From 83f3c5a53316c240b7f068195ddd00772a514af9 Mon Sep 17 00:00:00 2001 From: Dan Engelbrecht Date: Thu, 19 Feb 2026 07:44:53 +0100 Subject: 5.7.21-pre0 --- VERSION.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION.txt b/VERSION.txt index 4b5a784f6..e018afd57 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -5.7.20 \ No newline at end of file +5.7.21-pre0 \ No newline at end of file -- cgit v1.2.3 From 2d2781a03e3ab476dc45193b2bec72d8fd74d00d Mon Sep 17 00:00:00 2001 From: Dan Engelbrecht Date: Thu, 19 Feb 2026 15:06:17 +0100 Subject: 5.7.21 --- VERSION.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION.txt b/VERSION.txt index e018afd57..cf3060b3b 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -5.7.21-pre0 \ No newline at end of file +5.7.21 \ No newline at end of file -- cgit v1.2.3 From ee26e5af2ced0987fbdf666dc6bce7c2074e925f Mon Sep 17 00:00:00 2001 From: Stefan Boberg Date: Fri, 20 Feb 2026 09:05:23 +0100 Subject: GC - fix handling of attachment ranges, http access token expiration, lock file retry logic (#766) * GC - fix handling of attachment ranges * fix trace/log strings * fix HTTP access token expiration time logic * added missing lock retry in zenserver startup --- src/zenhttp/httpclientauth.cpp | 2 +- src/zenhttp/servers/httpparser.cpp | 9 ++++++--- src/zenserver/compute/computeserver.cpp | 6 +++--- src/zenserver/hub/zenhubserver.cpp | 2 +- src/zenserver/zenserver.cpp | 2 ++ src/zenstore/gc.cpp | 7 ++++--- src/zenstore/include/zenstore/gc.h | 2 +- 7 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/zenhttp/httpclientauth.cpp b/src/zenhttp/httpclientauth.cpp index 72df12d02..02e1b57e2 100644 --- a/src/zenhttp/httpclientauth.cpp +++ b/src/zenhttp/httpclientauth.cpp @@ -170,7 +170,7 @@ namespace zen { namespace httpclientauth { time_t UTCTime = timegm(&Time); HttpClientAccessToken::TimePoint ExpireTime = std::chrono::system_clock::from_time_t(UTCTime); - ExpireTime += std::chrono::microseconds(Millisecond); + ExpireTime += std::chrono::milliseconds(Millisecond); return HttpClientAccessToken{.Value = fmt::format("Bearer {}"sv, Token), .ExpireTime = ExpireTime}; } diff --git a/src/zenhttp/servers/httpparser.cpp b/src/zenhttp/servers/httpparser.cpp index be5befcd2..f0485aa25 100644 --- a/src/zenhttp/servers/httpparser.cpp +++ b/src/zenhttp/servers/httpparser.cpp @@ -226,6 +226,8 @@ NormalizeUrlPath(std::string_view InUrl, std::string& NormalizedUrl) NormalizedUrl.append(Url, UrlIndex); } + // NOTE: this check is redundant given the enclosing if, + // need to verify the intent of this code if (!LastCharWasSeparator) { NormalizedUrl.push_back('/'); @@ -310,6 +312,7 @@ HttpRequestParser::OnHeadersComplete() if (ContentLength) { + // TODO: should sanity-check content length here m_BodyBuffer = IoBuffer(ContentLength); } @@ -329,9 +332,9 @@ HttpRequestParser::OnHeadersComplete() int HttpRequestParser::OnBody(const char* Data, size_t Bytes) { - if (m_BodyPosition + Bytes > m_BodyBuffer.Size()) + if ((m_BodyPosition + Bytes) > m_BodyBuffer.Size()) { - ZEN_WARN("HTTP parser incoming body is larger than content size, need {} more bytes", + ZEN_WARN("HTTP parser incoming body is larger than content size, need {} more buffer bytes", (m_BodyPosition + Bytes) - m_BodyBuffer.Size()); return 1; } @@ -342,7 +345,7 @@ HttpRequestParser::OnBody(const char* Data, size_t Bytes) { if (m_BodyPosition != m_BodyBuffer.Size()) { - ZEN_WARN("Body mismatch! {} != {}", m_BodyPosition, m_BodyBuffer.Size()); + ZEN_WARN("Body size mismatch! {} != {}", m_BodyPosition, m_BodyBuffer.Size()); return 1; } } diff --git a/src/zenserver/compute/computeserver.cpp b/src/zenserver/compute/computeserver.cpp index 173f56386..0f9ef0287 100644 --- a/src/zenserver/compute/computeserver.cpp +++ b/src/zenserver/compute/computeserver.cpp @@ -82,7 +82,7 @@ ZenComputeServer::Initialize(const ZenComputeServerConfig& ServerConfig, ZenServ ZEN_TRACE_CPU("ZenComputeServer::Initialize"); ZEN_MEMSCOPE(GetZenserverTag()); - ZEN_INFO(ZEN_APP_NAME " initializing in HUB server mode"); + ZEN_INFO(ZEN_APP_NAME " initializing in COMPUTE server mode"); const int EffectiveBasePort = ZenServerBase::Initialize(ServerConfig, ServerEntry); if (EffectiveBasePort < 0) @@ -91,7 +91,7 @@ ZenComputeServer::Initialize(const ZenComputeServerConfig& ServerConfig, ZenServ } // This is a workaround to make sure we can have automated tests. Without - // this the ranges for different child zen hub processes could overlap with + // this the ranges for different child zen compute processes could overlap with // the main test range. ZenServerEnvironment::SetBaseChildId(1000); @@ -109,7 +109,7 @@ ZenComputeServer::Initialize(const ZenComputeServerConfig& ServerConfig, ZenServ void ZenComputeServer::Cleanup() { - ZEN_TRACE_CPU("ZenStorageServer::Cleanup"); + ZEN_TRACE_CPU("ZenComputeServer::Cleanup"); ZEN_INFO(ZEN_APP_NAME " cleaning up"); try { diff --git a/src/zenserver/hub/zenhubserver.cpp b/src/zenserver/hub/zenhubserver.cpp index 7a4ba951d..d0a0db417 100644 --- a/src/zenserver/hub/zenhubserver.cpp +++ b/src/zenserver/hub/zenhubserver.cpp @@ -105,7 +105,7 @@ ZenHubServer::Initialize(const ZenHubServerConfig& ServerConfig, ZenServerState: void ZenHubServer::Cleanup() { - ZEN_TRACE_CPU("ZenStorageServer::Cleanup"); + ZEN_TRACE_CPU("ZenHubServer::Cleanup"); ZEN_INFO(ZEN_APP_NAME " cleaning up"); try { diff --git a/src/zenserver/zenserver.cpp b/src/zenserver/zenserver.cpp index 7bf6126df..5fd35d9b4 100644 --- a/src/zenserver/zenserver.cpp +++ b/src/zenserver/zenserver.cpp @@ -617,6 +617,8 @@ ZenServerMain::Run() { ZEN_INFO(ZEN_APP_NAME " unable to grab lock at '{}' (reason: '{}'), retrying", LockFilePath, Ec.message()); Sleep(500); + + m_LockFile.Create(LockFilePath, MakeLockData(false), Ec); if (Ec) { ZEN_WARN(ZEN_APP_NAME " exiting, unable to grab lock at '{}' (reason: '{}')", LockFilePath, Ec.message()); diff --git a/src/zenstore/gc.cpp b/src/zenstore/gc.cpp index 14caa5abf..c3bdc59f0 100644 --- a/src/zenstore/gc.cpp +++ b/src/zenstore/gc.cpp @@ -1494,7 +1494,8 @@ GcManager::CollectGarbage(const GcSettings& Settings) GcReferenceValidatorStats& Stats = Result.ReferenceValidatorStats[It.second].second; try { - // Go through all the ReferenceCheckers to see if the list of Cids the collector selected are referenced or + // Go through all the ReferenceCheckers to see if the list of Cids the collector selected + // are referenced or not SCOPED_TIMER(Stats.ElapsedMS = std::chrono::milliseconds(Timer.GetElapsedTimeMs());); ReferenceValidator->Validate(Ctx, Stats); } @@ -1952,7 +1953,7 @@ GcScheduler::AppendGCLog(std::string_view Id, GcClock::TimePoint StartTime, cons Writer << "SingleThread"sv << Settings.SingleThread; Writer << "CompactBlockUsageThresholdPercent"sv << Settings.CompactBlockUsageThresholdPercent; Writer << "AttachmentRangeMin"sv << Settings.AttachmentRangeMin; - Writer << "AttachmentRangeMax"sv << Settings.AttachmentRangeMin; + Writer << "AttachmentRangeMax"sv << Settings.AttachmentRangeMax; Writer << "ForceStoreCacheAttachmentMetaData"sv << Settings.StoreCacheAttachmentMetaData; Writer << "ForceStoreProjectAttachmentMetaData"sv << Settings.StoreProjectAttachmentMetaData; Writer << "EnableValidation"sv << Settings.EnableValidation; @@ -2893,7 +2894,7 @@ GcScheduler::CollectGarbage(const GcClock::TimePoint& CacheExpireTime, { m_LastFullGCV2Result = Result; m_LastFullAttachmentRangeMin = AttachmentRangeMin; - m_LastFullAttachmentRangeMin = AttachmentRangeMax; + m_LastFullAttachmentRangeMax = AttachmentRangeMax; } Diff.DiskSize = Result.CompactStoresStatSum.RemovedDisk; Diff.MemorySize = Result.ReferencerStatSum.RemoveExpiredDataStats.FreedMemory; diff --git a/src/zenstore/include/zenstore/gc.h b/src/zenstore/include/zenstore/gc.h index 734d2e5a7..794f50d96 100644 --- a/src/zenstore/include/zenstore/gc.h +++ b/src/zenstore/include/zenstore/gc.h @@ -238,7 +238,7 @@ bool FilterReferences(GcCtx& Ctx, std::string_view Context, std::vector Date: Fri, 20 Feb 2026 09:07:00 +0100 Subject: fix MakeSafeAbsolutePathInPlace mis-spelling (#765) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (was MakeSafeAbsolutePathÍnPlace - note accent) Also fixed misleading comments on multiple functions in filesystem.h --- src/zen/authutils.cpp | 2 +- src/zen/cmds/builds_cmd.cpp | 44 ++++++++++++++++---------------- src/zen/cmds/print_cmd.cpp | 4 +-- src/zen/cmds/projectstore_cmd.cpp | 2 +- src/zen/cmds/wipe_cmd.cpp | 2 +- src/zen/cmds/workspaces_cmd.cpp | 2 +- src/zencore/filesystem.cpp | 4 +-- src/zencore/include/zencore/filesystem.h | 38 +++++++++++++-------------- 8 files changed, 49 insertions(+), 49 deletions(-) diff --git a/src/zen/authutils.cpp b/src/zen/authutils.cpp index 31db82efd..16427acf5 100644 --- a/src/zen/authutils.cpp +++ b/src/zen/authutils.cpp @@ -233,7 +233,7 @@ AuthCommandLineOptions::ParseOptions(cxxopts::Options& Ops, } else if (!m_AccessTokenPath.empty()) { - MakeSafeAbsolutePathÍnPlace(m_AccessTokenPath); + MakeSafeAbsolutePathInPlace(m_AccessTokenPath); std::string ResolvedAccessToken = ReadAccessTokenFromJsonFile(m_AccessTokenPath); if (!ResolvedAccessToken.empty()) { diff --git a/src/zen/cmds/builds_cmd.cpp b/src/zen/cmds/builds_cmd.cpp index 59b209384..8dfe1093f 100644 --- a/src/zen/cmds/builds_cmd.cpp +++ b/src/zen/cmds/builds_cmd.cpp @@ -2680,7 +2680,7 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) { m_SystemRootDir = PickDefaultSystemRootDirectory(); } - MakeSafeAbsolutePathÍnPlace(m_SystemRootDir); + MakeSafeAbsolutePathInPlace(m_SystemRootDir); }; ParseSystemOptions(); @@ -2729,7 +2729,7 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) { throw OptionParseException("'--host', '--url', '--override-host' or '--storage-path' is required", SubOption->help()); } - MakeSafeAbsolutePathÍnPlace(m_StoragePath); + MakeSafeAbsolutePathInPlace(m_StoragePath); }; auto ParseOutputOptions = [&]() { @@ -2947,7 +2947,7 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) { throw OptionParseException("'--local-path' is required", SubOption->help()); } - MakeSafeAbsolutePathÍnPlace(m_Path); + MakeSafeAbsolutePathInPlace(m_Path); }; auto ParseFileFilters = [&](std::vector& OutIncludeWildcards, std::vector& OutExcludeWildcards) { @@ -3004,7 +3004,7 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) { throw OptionParseException("'--compare-path' is required", SubOption->help()); } - MakeSafeAbsolutePathÍnPlace(m_DiffPath); + MakeSafeAbsolutePathInPlace(m_DiffPath); }; auto ParseBlobHash = [&]() -> IoHash { @@ -3105,7 +3105,7 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) if (!m_BuildMetadataPath.empty()) { - MakeSafeAbsolutePathÍnPlace(m_BuildMetadataPath); + MakeSafeAbsolutePathInPlace(m_BuildMetadataPath); IoBuffer MetaDataJson = ReadFile(m_BuildMetadataPath).Flatten(); std::string_view Json(reinterpret_cast(MetaDataJson.GetData()), MetaDataJson.GetSize()); std::string JsonError; @@ -3202,8 +3202,8 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) if (SubOption == &m_ListOptions) { - MakeSafeAbsolutePathÍnPlace(m_ListQueryPath); - MakeSafeAbsolutePathÍnPlace(m_ListResultPath); + MakeSafeAbsolutePathInPlace(m_ListQueryPath); + MakeSafeAbsolutePathInPlace(m_ListResultPath); if (!m_ListResultPath.empty()) { @@ -3255,7 +3255,7 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) { m_ZenFolderPath = std::filesystem::current_path() / ZenFolderName; } - MakeSafeAbsolutePathÍnPlace(m_ZenFolderPath); + MakeSafeAbsolutePathInPlace(m_ZenFolderPath); CreateDirectories(m_ZenFolderPath); auto _ = MakeGuard([this]() { CleanAndRemoveDirectory(GetSmallWorkerPool(EWorkloadType::Burst), m_ZenFolderPath); }); @@ -3294,7 +3294,7 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) if (SubOption == &m_ListBlocksOptions) { - MakeSafeAbsolutePathÍnPlace(m_ListResultPath); + MakeSafeAbsolutePathInPlace(m_ListResultPath); if (!m_ListResultPath.empty()) { @@ -3316,7 +3316,7 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) { m_ZenFolderPath = std::filesystem::current_path() / ZenFolderName; } - MakeSafeAbsolutePathÍnPlace(m_ZenFolderPath); + MakeSafeAbsolutePathInPlace(m_ZenFolderPath); CreateDirectories(m_ZenFolderPath); auto _ = MakeGuard([this]() { CleanAndRemoveDirectory(GetSmallWorkerPool(EWorkloadType::Burst), m_ZenFolderPath); }); @@ -3387,8 +3387,8 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) { m_ZenFolderPath = std::filesystem::current_path() / ZenFolderName; } - MakeSafeAbsolutePathÍnPlace(m_ZenFolderPath); - MakeSafeAbsolutePathÍnPlace(m_ChunkingCachePath); + MakeSafeAbsolutePathInPlace(m_ZenFolderPath); + MakeSafeAbsolutePathInPlace(m_ChunkingCachePath); CreateDirectories(m_ZenFolderPath); auto _ = MakeGuard([this, &Workers]() { CleanAndRemoveDirectory(Workers.GetIOWorkerPool(), m_ZenFolderPath); }); @@ -3532,7 +3532,7 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) { m_ZenFolderPath = m_Path / ZenFolderName; } - MakeSafeAbsolutePathÍnPlace(m_ZenFolderPath); + MakeSafeAbsolutePathInPlace(m_ZenFolderPath); BuildStorageBase::Statistics StorageStats; BuildStorageCache::Statistics StorageCacheStats; @@ -3632,7 +3632,7 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) { m_ZenFolderPath = m_Path / ZenFolderName; } - MakeSafeAbsolutePathÍnPlace(m_ZenFolderPath); + MakeSafeAbsolutePathInPlace(m_ZenFolderPath); BuildStorageBase::Statistics StorageStats; BuildStorageCache::Statistics StorageCacheStats; @@ -3652,7 +3652,7 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) std::unique_ptr StructuredOutput; if (!m_LsResultPath.empty()) { - MakeSafeAbsolutePathÍnPlace(m_LsResultPath); + MakeSafeAbsolutePathInPlace(m_LsResultPath); StructuredOutput = std::make_unique(); } @@ -3696,7 +3696,7 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) ParsePath(); ParseDiffPath(); - MakeSafeAbsolutePathÍnPlace(m_ChunkingCachePath); + MakeSafeAbsolutePathInPlace(m_ChunkingCachePath); std::vector ExcludeFolders = DefaultExcludeFolders; std::vector ExcludeExtensions = DefaultExcludeExtensions; @@ -3745,7 +3745,7 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) { m_ZenFolderPath = std::filesystem::current_path() / ZenFolderName; } - MakeSafeAbsolutePathÍnPlace(m_ZenFolderPath); + MakeSafeAbsolutePathInPlace(m_ZenFolderPath); CreateDirectories(m_ZenFolderPath); auto _ = MakeGuard([this, &Workers]() { CleanAndRemoveDirectory(Workers.GetIOWorkerPool(), m_ZenFolderPath); }); @@ -3828,7 +3828,7 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) { m_ZenFolderPath = std::filesystem::current_path() / ZenFolderName; } - MakeSafeAbsolutePathÍnPlace(m_ZenFolderPath); + MakeSafeAbsolutePathInPlace(m_ZenFolderPath); CreateDirectories(m_ZenFolderPath); auto _ = MakeGuard([this, &Workers]() { CleanAndRemoveDirectory(Workers.GetIOWorkerPool(), m_ZenFolderPath); }); @@ -3883,7 +3883,7 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) { m_ZenFolderPath = std::filesystem::current_path() / ZenFolderName; } - MakeSafeAbsolutePathÍnPlace(m_ZenFolderPath); + MakeSafeAbsolutePathInPlace(m_ZenFolderPath); CreateDirectories(m_ZenFolderPath); auto _ = MakeGuard([this, &Workers]() { CleanAndRemoveDirectory(Workers.GetIOWorkerPool(), m_ZenFolderPath); }); @@ -3933,7 +3933,7 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) { m_ZenFolderPath = m_Path / ZenFolderName; } - MakeSafeAbsolutePathÍnPlace(m_ZenFolderPath); + MakeSafeAbsolutePathInPlace(m_ZenFolderPath); EPartialBlockRequestMode PartialBlockRequestMode = ParseAllowPartialBlockRequests(); @@ -4083,8 +4083,8 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) { m_ZenFolderPath = m_Path / ZenFolderName; } - MakeSafeAbsolutePathÍnPlace(m_ZenFolderPath); - MakeSafeAbsolutePathÍnPlace(m_ChunkingCachePath); + MakeSafeAbsolutePathInPlace(m_ZenFolderPath); + MakeSafeAbsolutePathInPlace(m_ChunkingCachePath); StorageInstance Storage = CreateBuildStorage(StorageStats, StorageCacheStats, diff --git a/src/zen/cmds/print_cmd.cpp b/src/zen/cmds/print_cmd.cpp index 030cc8b66..c6b250fdf 100644 --- a/src/zen/cmds/print_cmd.cpp +++ b/src/zen/cmds/print_cmd.cpp @@ -84,7 +84,7 @@ PrintCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) } else { - MakeSafeAbsolutePathÍnPlace(m_Filename); + MakeSafeAbsolutePathInPlace(m_Filename); Fc = ReadFile(m_Filename); } @@ -244,7 +244,7 @@ PrintPackageCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** ar if (m_Filename.empty()) throw OptionParseException("'--source' is required", m_Options.help()); - MakeSafeAbsolutePathÍnPlace(m_Filename); + MakeSafeAbsolutePathInPlace(m_Filename); FileContents Fc = ReadFile(m_Filename); IoBuffer Data = Fc.Flatten(); CbPackage Package; diff --git a/src/zen/cmds/projectstore_cmd.cpp b/src/zen/cmds/projectstore_cmd.cpp index 4885fd363..4de6ad25c 100644 --- a/src/zen/cmds/projectstore_cmd.cpp +++ b/src/zen/cmds/projectstore_cmd.cpp @@ -2430,7 +2430,7 @@ OplogDownloadCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** a { m_SystemRootDir = PickDefaultSystemRootDirectory(); } - MakeSafeAbsolutePathÍnPlace(m_SystemRootDir); + MakeSafeAbsolutePathInPlace(m_SystemRootDir); }; ParseSystemOptions(); diff --git a/src/zen/cmds/wipe_cmd.cpp b/src/zen/cmds/wipe_cmd.cpp index adf0e61f0..a5029e1c5 100644 --- a/src/zen/cmds/wipe_cmd.cpp +++ b/src/zen/cmds/wipe_cmd.cpp @@ -549,7 +549,7 @@ WipeCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) ProgressMode = (IsVerbose || m_PlainProgress) ? ProgressBar::Mode::Plain : ProgressBar::Mode::Pretty; BoostWorkerThreads = m_BoostWorkerThreads; - MakeSafeAbsolutePathÍnPlace(m_Directory); + MakeSafeAbsolutePathInPlace(m_Directory); if (!IsDir(m_Directory)) { diff --git a/src/zen/cmds/workspaces_cmd.cpp b/src/zen/cmds/workspaces_cmd.cpp index 6e6f5d863..2661ac9da 100644 --- a/src/zen/cmds/workspaces_cmd.cpp +++ b/src/zen/cmds/workspaces_cmd.cpp @@ -398,7 +398,7 @@ WorkspaceShareCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** } else { - MakeSafeAbsolutePathÍnPlace(m_SystemRootDir); + MakeSafeAbsolutePathInPlace(m_SystemRootDir); } std::filesystem::path StatePath = m_SystemRootDir / "workspaces"; diff --git a/src/zencore/filesystem.cpp b/src/zencore/filesystem.cpp index 92a065707..1a4ee4b9b 100644 --- a/src/zencore/filesystem.cpp +++ b/src/zencore/filesystem.cpp @@ -3069,7 +3069,7 @@ SetFileReadOnly(const std::filesystem::path& Filename, bool ReadOnly) } void -MakeSafeAbsolutePathÍnPlace(std::filesystem::path& Path) +MakeSafeAbsolutePathInPlace(std::filesystem::path& Path) { if (!Path.empty()) { @@ -3091,7 +3091,7 @@ std::filesystem::path MakeSafeAbsolutePath(const std::filesystem::path& Path) { std::filesystem::path Tmp(Path); - MakeSafeAbsolutePathÍnPlace(Tmp); + MakeSafeAbsolutePathInPlace(Tmp); return Tmp; } diff --git a/src/zencore/include/zencore/filesystem.h b/src/zencore/include/zencore/filesystem.h index f28863679..16e2b59f8 100644 --- a/src/zencore/include/zencore/filesystem.h +++ b/src/zencore/include/zencore/filesystem.h @@ -64,80 +64,80 @@ std::filesystem::path PathFromHandle(void* NativeHandle, std::error_code& Ec); */ std::filesystem::path CanonicalPath(std::filesystem::path InPath, std::error_code& Ec); -/** Query file size +/** Check if a path exists and is a regular file (throws) */ bool IsFile(const std::filesystem::path& Path); -/** Query file size +/** Check if a path exists and is a regular file (does not throw) */ bool IsFile(const std::filesystem::path& Path, std::error_code& Ec); -/** Query file size +/** Check if a path exists and is a directory (throws) */ bool IsDir(const std::filesystem::path& Path); -/** Query file size +/** Check if a path exists and is a directory (does not throw) */ bool IsDir(const std::filesystem::path& Path, std::error_code& Ec); -/** Query file size +/** Delete file at path, if it exists (throws) */ bool RemoveFile(const std::filesystem::path& Path); -/** Query file size +/** Delete file at path, if it exists (does not throw) */ bool RemoveFile(const std::filesystem::path& Path, std::error_code& Ec); -/** Query file size +/** Delete directory at path, if it exists (throws) */ bool RemoveDir(const std::filesystem::path& Path); -/** Query file size +/** Delete directory at path, if it exists (does not throw) */ bool RemoveDir(const std::filesystem::path& Path, std::error_code& Ec); -/** Query file size +/** Query file size (throws) */ uint64_t FileSizeFromPath(const std::filesystem::path& Path); -/** Query file size +/** Query file size (does not throw) */ uint64_t FileSizeFromPath(const std::filesystem::path& Path, std::error_code& Ec); -/** Query file size from native file handle +/** Query file size from native file handle (throws) */ uint64_t FileSizeFromHandle(void* NativeHandle); -/** Query file size from native file handle +/** Query file size from native file handle (does not throw) */ uint64_t FileSizeFromHandle(void* NativeHandle, std::error_code& Ec); /** Get a native time tick of last modification time */ -uint64_t GetModificationTickFromHandle(void* NativeHandle, std::error_code& Ec); +uint64_t GetModificationTickFromPath(const std::filesystem::path& Filename); /** Get a native time tick of last modification time */ -uint64_t GetModificationTickFromPath(const std::filesystem::path& Filename); +uint64_t GetModificationTickFromHandle(void* NativeHandle, std::error_code& Ec); bool TryGetFileProperties(const std::filesystem::path& Path, uint64_t& OutSize, uint64_t& OutModificationTick, uint32_t& OutNativeModeOrAttributes); -/** Move a file, if the files are not on the same drive the function will fail +/** Move/rename a file, if the files are not on the same drive the function will fail (throws) */ void RenameFile(const std::filesystem::path& SourcePath, const std::filesystem::path& TargetPath); -/** Move a file, if the files are not on the same drive the function will fail +/** Move/rename a file, if the files are not on the same drive the function will fail */ void RenameFile(const std::filesystem::path& SourcePath, const std::filesystem::path& TargetPath, std::error_code& Ec); -/** Move a directory, if the files are not on the same drive the function will fail +/** Move/rename a directory, if the files are not on the same drive the function will fail (throws) */ void RenameDirectory(const std::filesystem::path& SourcePath, const std::filesystem::path& TargetPath); -/** Move a directory, if the files are not on the same drive the function will fail +/** Move/rename a directory, if the files are not on the same drive the function will fail */ void RenameDirectory(const std::filesystem::path& SourcePath, const std::filesystem::path& TargetPath, std::error_code& Ec); @@ -421,7 +421,7 @@ uint32_t MakeFileModeReadOnly(uint32_t FileMode, bool ReadOnly); bool SetFileReadOnly(const std::filesystem::path& Filename, bool ReadOnly, std::error_code& Ec); bool SetFileReadOnly(const std::filesystem::path& Filename, bool ReadOnly); -void MakeSafeAbsolutePathÍnPlace(std::filesystem::path& Path); +void MakeSafeAbsolutePathInPlace(std::filesystem::path& Path); [[nodiscard]] std::filesystem::path MakeSafeAbsolutePath(const std::filesystem::path& Path); class SharedMemory -- cgit v1.2.3 From 4032ceb35dbfc0ffb71789fb9ff3dfcf854ca2d3 Mon Sep 17 00:00:00 2001 From: Stefan Boberg Date: Fri, 20 Feb 2026 09:14:26 +0100 Subject: initial CLAUDE.md (#764) --- CLAUDE.md | 271 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 271 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000..757ce5d2a --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,271 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +Unreal Zen Storage Service (zenserver) is a high-performance local storage service for UE5, managing secondary data such as cooker output and local caches (DDC - Derived Data Cache). Can be deployed as a daemon on user machines or as a shared cache instance for build farms. + +## Build System + +This project uses **xmake** as its build system. xmake is stateful - run configuration before building. + +### Common Build Commands + +```bash +# Configure for debug (includes tests) +xmake config -m debug + +# Configure for release +xmake config -m release + +# Build everything +xmake + +# Build specific target +xmake build zenserver +xmake build zen + +# Run targets +xmake run zenserver +xmake run zen + +# Generate IDE project files +xmake sln # Windows: Visual Studio 2022 +xmake project -k xcode # macOS: Xcode +``` + +### Build Configuration Options + +- `--zensentry=yes|no` - Enable/disable Sentry crash reporting (default: yes) +- `--zenmimalloc=yes|no` - Use mimalloc for memory management (default: yes, disabled with ASAN) +- `--zenrpmalloc=yes|no` - Use rpmalloc for memory management (default: yes) +- `--httpsys=yes|no` - Enable http.sys server (Windows only, default: yes) +- `--zencompute=yes|no` - Enable compute services endpoint (default: yes) +- `--zenmemtrack=yes|no` - Enable UE Memory Trace support (Windows only, default: yes) +- `--zentrace=yes|no` - Enable UE Trace support (default: yes) + +### Testing + +```bash +# Tests are only built in debug mode +xmake config -m debug +xmake + +# Run all tests +xmake test --run=all + +# Run specific test suites +xmake test --run=core # zencore-test +xmake test --run=store # zenstore-test +xmake test --run=server # zenserver test command +xmake test --run=integration # zenserver-test +xmake test --run=http # zenhttp-test +xmake test --run=util # zenutil-test +xmake test --run=remotestore # zenremotestore-test + +# Run tests with JUnit reporting +xmake test --run=all --junit +``` + +Tests use the **doctest** framework. To run server tests: `xmake run zenserver test` + +### Code Formatting + +```bash +# Format all files (requires pre-commit) +xmake precommit + +# Or use pre-commit directly +pre-commit run --all-files +``` + +Install pre-commit hooks with `pre-commit install` to auto-format on commit. + +### Cleaning Build State + +When encountering build issues, clean all build state: + +**Windows:** +```cmd +rmdir /s /q .xmake build %LOCALAPPDATA%\.xmake %TEMP%\.xmake +``` + +**Linux/macOS:** +```bash +rm -rf .xmake build ~/.xmake +``` + +## Architecture + +### Module Structure + +The codebase is organized into layered modules with clear dependencies: + +**Core Libraries (Foundation Layer):** +- `zenbase` - Platform abstraction primitives +- `zencore` - Core utilities, memory management, logging, filesystem, crypto, threading +- `zenutil` - Higher-level utilities and common patterns + +**Protocol & Network Layer:** +- `zenhttp` - HTTP server implementations (http.sys on Windows, ASIO-based on Linux/Mac) +- `zennet` - Network utilities and protocols +- `transports` - Transport SDK and implementations + +**Storage Layer:** +- `zenstore` - Core storage engine and key-value store +- `zenvfs` - Virtual filesystem implementation +- `zenremotestore` - Remote storage client + +**Service Layer:** +- `zenserver` - Main server binary integrating all services +- `zencompute` - Compute services endpoint +- `zentelemetry` - Telemetry and metrics collection + +**Client Tools:** +- `zen` - CLI client utility for interacting with zenserver + - Commands are in `src/zen/cmds/` (e.g., `cache_cmd.h`, `status_cmd.h`, `ui_cmd.h`) + - Each command inherits from base command classes and registers with the CLI dispatcher + +**Test Projects:** +- `*-test` modules contain tests for their corresponding module (only built in debug mode) +- `zenserver-test` contains integration tests + +### Key Architectural Patterns + +**HTTP Server Implementations:** +- Windows: Uses http.sys kernel driver for highest throughput (requires elevation or URL reservation) +- Linux/macOS: ASIO-based HTTP server (also available on Windows) +- Server selection is compile-time based on platform but can be overridden on the command line via `--http=asio/httpsys/etc` + +**Storage Architecture:** +- zenserver manages multiple storage services (build store, cache, project store, object store) +- Content-addressable storage with deduplication on the lowest storage layer but this is mostly an internal implementation detail. + - Clients generally do not request content via content address. Instead they interface with the higher level storage services + - CAS content is garbage collected based on what is referenced from of higher level services + +**Frontend:** +- Web UI bundled as ZIP in `src/zenserver/frontend/*.zip` +- Dashboards for hub, orchestrator, and compute services are located in `src/zenserver/frontent/html/` + - These are the files which end up being bundled into the front-end zip mentioned above +- Update with `xmake updatefrontend` after modifying HTML/JS, and check in the resulting zip + +**Memory Management:** +- Can use mimalloc or rpmalloc for performance +- UE-style LLM (Low-Level Memory) tracking available on Windows +- Memory tracing support integrated with UE trace system + +**Tracing:** +- UE Trace integration for profiling and diagnostics +- Trace files use .utrace format +- Trace analysis tools in zentrace module (if available) +- Traces can be visualized using Unreal Insights, available in the UE5 code base + +## Coding Standards + +**Naming Conventions (UE-inspired with modifications):** +- Classes/Structs: `PascalCase` +- Functions/Methods: `PascalCase()` +- Member variables: `m_PascalCase` +- Global variables: `g_PascalCase` +- Static variables: `s_PascalCase` +- Thread-local variables: `t_PascalCase` + +**Note:** Unlike UE, no `F` prefix on structs/classes is required or encouraged. Also, no `b` prefix on booleans. + +**Code Style:** +- C++20 standard +- clang-format enforced via pre-commit hooks +- Use `std` containers; `eastl::fixed_vector` etc. for performance-critical paths +- Exceptions used only for unexpected errors, not flow control +- Logging is done via `ZEN_DEBUG(...)`, `ZEN_INFO(...)`, `ZEN_WARN`, `ZEN_ERROR` macros + - Logging macros use `fmt::format` for message formatting. The first argument is the format string, which + must be a string literal (turned into `std::string_view` in the macros) + - Logging channels can be overridden on a scope-by-scope basis (per-class or even per-function) by implementing + a `LoggerRef Log()` function + +**Includes:** +- Wrap third-party includes with `ZEN_THIRD_PARTY_INCLUDES_START` / `ZEN_THIRD_PARTY_INCLUDES_END` + - This helps avoid spurious compiler warnings due to the use of strict warnings-as-error policy + +**Platform Macros:** +- `ZEN_PLATFORM_WINDOWS`, `ZEN_PLATFORM_LINUX`, `ZEN_PLATFORM_MAC` +- Use `is_plat("windows")` etc. in xmake.lua files + +## Security Considerations + +**XSS in Web UI:** +Sanitize all dynamic data before inserting into innerHTML. Use `escapeHtml()` helper functions in JavaScript. + +**http.sys URL Reservation:** +On Windows, zenserver requires elevation or a URL reservation to bind http.sys to network interfaces: +```cmd +netsh http add urlacl url=http://*:8558/ user= +``` + +## Platform-Specific Notes + +**Windows:** +- Primary development platform +- Visual Studio 2022+ required (C++20 features) +- Static CRT linking by default (`/MT` in release, `/MTd` in debug) +- Recommended profilers: Superluminal Performance, Visual Studio profiler + +**Linux:** +- Requires GCC-11+ or Clang-12+ with libstdc++-11+ +- Set `CXX=g++-11` before running xmake if needed +- UE cross-compile toolchain support via `UE_TOOLCHAIN_DIR` environment variable + +**macOS:** +- Requires Xcode or Xcode command-line tools +- Supports both x86_64 and arm64 architectures + +## Dependencies + +Key third-party libraries (managed by xmake): +- EASTL - High-performance containers +- ASIO - Async I/O +- spdlog/fmt - Logging and formatting +- doctest - Testing framework +- cxxopts - Command-line parsing +- json11 - JSON parsing +- lz4 - Compression +- xxhash - Hashing +- OpenSSL (Linux/Mac) - Crypto operations +- Sentry - Crash reporting (optional) + +## Adding New Commands to `zen` CLI + +1. Create `src/zen/cmds/mycommand_cmd.h` and `src/zen/cmds/mycommand_cmd.cpp` +2. Inherit from appropriate base command class +3. Implement `Execute()` method +4. Add `#include "cmds/mycommand_cmd.h"` to `src/zen/zen.cpp` +5. Register command in `zen.cpp` command dispatcher. These should be ordered in alphabetical identifier order for consistent merging + +## Adding New Modules + +1. Create `src/mymodule/` directory structure +2. Add `include/` subdirectory for public headers +3. Create `xmake.lua` defining the target +4. Add `includes("src/mymodule")` to root `xmake.lua` +5. Add dependencies via `add_deps()` in the module's xmake.lua + +## Debugging + +**Visual Studio:** +- Use Debug configuration (includes test code) +- For http.sys debugging, run Visual Studio as Administrator or add URL reservation +- Enable child process debugging with Microsoft Child Process Debugging Power Tool + +**Multi-process Scenarios:** +When debugging zenserver-test or other multi-process scenarios, use child process debugging tools to attach to spawned processes automatically. + +## Bundle Creation + +```bash +# Create deployable ZIP bundle +xmake bundle + +# Update frontend ZIP after HTML changes +xmake updatefrontend +``` -- cgit v1.2.3 From 17898ec8a7ce42c0da27ac50c5c65aeb447c6374 Mon Sep 17 00:00:00 2001 From: Dan Engelbrecht Date: Fri, 20 Feb 2026 10:29:42 +0100 Subject: fix plain progress bar (#768) * fix plain progress not updating current state --- CHANGELOG.md | 3 +++ src/zen/progressbar.cpp | 1 + 2 files changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9fa4fe031..0098f08b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,7 @@ ## +- Bugfix: `--plain-progress` style progress bar should now show elapsed time correctly + +## 5.7.21 - Feature: Added `--security-config-path` option to zenserver to configure security settings - Expects a path to a .json file - Default is an empty path resulting in no extra security settings and legacy behavior diff --git a/src/zen/progressbar.cpp b/src/zen/progressbar.cpp index 83606df67..1ee1d1e71 100644 --- a/src/zen/progressbar.cpp +++ b/src/zen/progressbar.cpp @@ -245,6 +245,7 @@ ProgressBar::UpdateState(const State& NewState, bool DoLinebreak) const std::string Details = (!NewState.Details.empty()) ? fmt::format(": {}", NewState.Details) : ""; const std::string Output = fmt::format("{} {}% ({}){}\n", Task, PercentDone, NiceTimeSpanMs(ElapsedTimeMS), Details); OutputToConsoleRaw(Output); + m_State = NewState; } else if (m_Mode == Mode::Pretty) { -- cgit v1.2.3 From 80bc5a53fe9077bc20d287b912f6476db233110c Mon Sep 17 00:00:00 2001 From: Dan Engelbrecht Date: Fri, 20 Feb 2026 10:31:31 +0100 Subject: fix builds download indexing timer (#769) * fix build download indexing timer log --- CHANGELOG.md | 1 + src/zen/cmds/builds_cmd.cpp | 7 +++++++ src/zenremotestore/builds/buildstorageoperations.cpp | 7 ------- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0098f08b4..af2414682 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ## - Bugfix: `--plain-progress` style progress bar should now show elapsed time correctly +- Bugfix: Time spent indexing local and remote state during `zen builds download` now show the correct time ## 5.7.21 - Feature: Added `--security-config-path` option to zenserver to configure security settings diff --git a/src/zen/cmds/builds_cmd.cpp b/src/zen/cmds/builds_cmd.cpp index 8dfe1093f..849259013 100644 --- a/src/zen/cmds/builds_cmd.cpp +++ b/src/zen/cmds/builds_cmd.cpp @@ -1467,9 +1467,16 @@ namespace { ZEN_CONSOLE("Downloading build {}, parts:{} to '{}' ({})", BuildId, BuildPartString.ToView(), Path, NiceBytes(RawSize)); } + Stopwatch IndexTimer; + const ChunkedContentLookup LocalLookup = BuildChunkedContentLookup(LocalState.State.ChunkedContent); const ChunkedContentLookup RemoteLookup = BuildChunkedContentLookup(RemoteContent); + if (!IsQuiet) + { + ZEN_OPERATION_LOG_INFO(Output, "Indexed local and remote content in {}", NiceTimeSpanMs(IndexTimer.GetElapsedTimeMs())); + } + ProgressBar::SetLogOperationProgress(ProgressMode, TaskSteps::Download, TaskSteps::StepCount); BuildsOperationUpdateFolder Updater( diff --git a/src/zenremotestore/builds/buildstorageoperations.cpp b/src/zenremotestore/builds/buildstorageoperations.cpp index ade431393..72e06767a 100644 --- a/src/zenremotestore/builds/buildstorageoperations.cpp +++ b/src/zenremotestore/builds/buildstorageoperations.cpp @@ -579,13 +579,6 @@ BuildsOperationUpdateFolder::Execute(FolderContent& OutLocalFolderState) CreateDirectories(m_TempDownloadFolderPath); CreateDirectories(m_TempBlockFolderPath); - Stopwatch IndexTimer; - - if (!m_Options.IsQuiet) - { - ZEN_OPERATION_LOG_INFO(m_LogOutput, "Indexed local and remote content in {}", NiceTimeSpanMs(IndexTimer.GetElapsedTimeMs())); - } - Stopwatch CacheMappingTimer; std::vector> SequenceIndexChunksLeftToWriteCounters(m_RemoteContent.ChunkedContent.SequenceRawHashes.size()); -- cgit v1.2.3 From da4826d560a66b8a5f09158a93c83caa12348c7b Mon Sep 17 00:00:00 2001 From: Dan Engelbrecht Date: Fri, 20 Feb 2026 10:32:32 +0100 Subject: move partial chunk block anailsys to chunkblock.h/cpp (#767) --- .../builds/buildstorageoperations.cpp | 882 ++++++--------------- src/zenremotestore/chunking/chunkblock.cpp | 540 ++++++++++++- .../zenremotestore/builds/buildstorageoperations.h | 50 +- .../include/zenremotestore/chunking/chunkblock.h | 94 +++ 4 files changed, 887 insertions(+), 679 deletions(-) diff --git a/src/zenremotestore/builds/buildstorageoperations.cpp b/src/zenremotestore/builds/buildstorageoperations.cpp index 72e06767a..4f1b07c37 100644 --- a/src/zenremotestore/builds/buildstorageoperations.cpp +++ b/src/zenremotestore/builds/buildstorageoperations.cpp @@ -899,343 +899,213 @@ BuildsOperationUpdateFolder::Execute(FolderContent& OutLocalFolderState) CheckRequiredDiskSpace(RemotePathToRemoteIndex); + BlobsExistsResult ExistsResult; { - ZEN_TRACE_CPU("WriteChunks"); - - m_LogOutput.SetLogOperationProgress((uint32_t)TaskSteps::WriteChunks, (uint32_t)TaskSteps::StepCount); + ChunkBlockAnalyser BlockAnalyser(m_LogOutput, + m_BlockDescriptions, + ChunkBlockAnalyser::Options{.IsQuiet = m_Options.IsQuiet, .IsVerbose = m_Options.IsVerbose}); - Stopwatch WriteTimer; + std::vector NeededBlocks = BlockAnalyser.GetNeeded( + m_RemoteLookup.ChunkHashToChunkIndex, + [&](uint32_t RemoteChunkIndex) -> bool { return RemoteChunkIndexNeedsCopyFromSourceFlags[RemoteChunkIndex]; }); - FilteredRate FilteredDownloadedBytesPerSecond; - FilteredRate FilteredWrittenBytesPerSecond; - - std::unique_ptr WriteProgressBarPtr( - m_LogOutput.CreateProgressBar(m_Options.PrimeCacheOnly ? "Downloading" : "Writing")); - OperationLogOutput::ProgressBar& WriteProgressBar(*WriteProgressBarPtr); - ParallelWork Work(m_AbortFlag, m_PauseFlag, WorkerThreadPool::EMode::EnableBacklog); - - struct LooseChunkHashWorkData - { - std::vector ChunkTargetPtrs; - uint32_t RemoteChunkIndex = (uint32_t)-1; - }; - - std::vector LooseChunkHashWorks; - TotalPartWriteCount += CopyChunkDatas.size(); - TotalPartWriteCount += ScavengedSequenceCopyOperations.size(); + std::vector FetchBlockIndexes; + std::vector CachedChunkBlockIndexes; - for (const IoHash ChunkHash : m_LooseChunkHashes) { - auto RemoteChunkIndexIt = m_RemoteLookup.ChunkHashToChunkIndex.find(ChunkHash); - ZEN_ASSERT(RemoteChunkIndexIt != m_RemoteLookup.ChunkHashToChunkIndex.end()); - const uint32_t RemoteChunkIndex = RemoteChunkIndexIt->second; - if (RemoteChunkIndexNeedsCopyFromLocalFileFlags[RemoteChunkIndex]) + ZEN_TRACE_CPU("BlockCacheFileExists"); + for (const ChunkBlockAnalyser::NeededBlock& NeededBlock : NeededBlocks) { - if (m_Options.IsVerbose) + if (m_Options.PrimeCacheOnly) { - ZEN_OPERATION_LOG_INFO(m_LogOutput, "Skipping chunk {} due to cache reuse", ChunkHash); - } - continue; - } - bool NeedsCopy = true; - if (RemoteChunkIndexNeedsCopyFromSourceFlags[RemoteChunkIndex].compare_exchange_strong(NeedsCopy, false)) - { - std::vector ChunkTargetPtrs = - GetRemainingChunkTargets(SequenceIndexChunksLeftToWriteCounters, RemoteChunkIndex); - - if (ChunkTargetPtrs.empty()) - { - if (m_Options.IsVerbose) - { - ZEN_OPERATION_LOG_INFO(m_LogOutput, "Skipping chunk {} due to cache reuse", ChunkHash); - } + FetchBlockIndexes.push_back(NeededBlock.BlockIndex); } else { - TotalRequestCount++; - TotalPartWriteCount++; - LooseChunkHashWorks.push_back( - LooseChunkHashWorkData{.ChunkTargetPtrs = ChunkTargetPtrs, .RemoteChunkIndex = RemoteChunkIndex}); - } - } - } - - uint32_t BlockCount = gsl::narrow(m_BlockDescriptions.size()); - - std::vector ChunkIsPickedUpByBlock(m_RemoteContent.ChunkedContent.ChunkHashes.size(), false); - auto GetNeededChunkBlockIndexes = [this, &RemoteChunkIndexNeedsCopyFromSourceFlags, &ChunkIsPickedUpByBlock]( - const ChunkBlockDescription& BlockDescription) { - ZEN_TRACE_CPU("GetNeededChunkBlockIndexes"); - std::vector NeededBlockChunkIndexes; - for (uint32_t ChunkBlockIndex = 0; ChunkBlockIndex < BlockDescription.ChunkRawHashes.size(); ChunkBlockIndex++) - { - const IoHash& ChunkHash = BlockDescription.ChunkRawHashes[ChunkBlockIndex]; - if (auto It = m_RemoteLookup.ChunkHashToChunkIndex.find(ChunkHash); It != m_RemoteLookup.ChunkHashToChunkIndex.end()) - { - const uint32_t RemoteChunkIndex = It->second; - if (!ChunkIsPickedUpByBlock[RemoteChunkIndex]) + const ChunkBlockDescription& BlockDescription = m_BlockDescriptions[NeededBlock.BlockIndex]; + bool UsingCachedBlock = false; + if (auto It = CachedBlocksFound.find(BlockDescription.BlockHash); It != CachedBlocksFound.end()) { - if (RemoteChunkIndexNeedsCopyFromSourceFlags[RemoteChunkIndex]) + TotalPartWriteCount++; + + std::filesystem::path BlockPath = m_TempBlockFolderPath / BlockDescription.BlockHash.ToHexString(); + if (IsFile(BlockPath)) { - ChunkIsPickedUpByBlock[RemoteChunkIndex] = true; - NeededBlockChunkIndexes.push_back(ChunkBlockIndex); + CachedChunkBlockIndexes.push_back(NeededBlock.BlockIndex); + UsingCachedBlock = true; } } - } - else - { - ZEN_DEBUG("Chunk {} not found in block {}", ChunkHash, BlockDescription.BlockHash); + if (!UsingCachedBlock) + { + FetchBlockIndexes.push_back(NeededBlock.BlockIndex); + } } } - return NeededBlockChunkIndexes; - }; + } - std::vector CachedChunkBlockIndexes; - std::vector FetchBlockIndexes; - std::vector> AllBlockChunkIndexNeeded; + std::vector NeededLooseChunkIndexes; - for (uint32_t BlockIndex = 0; BlockIndex < BlockCount; BlockIndex++) { - const ChunkBlockDescription& BlockDescription = m_BlockDescriptions[BlockIndex]; - - std::vector BlockChunkIndexNeeded = GetNeededChunkBlockIndexes(BlockDescription); - if (!BlockChunkIndexNeeded.empty()) + NeededLooseChunkIndexes.reserve(m_LooseChunkHashes.size()); + for (uint32_t LooseChunkIndex = 0; LooseChunkIndex < m_LooseChunkHashes.size(); LooseChunkIndex++) { - if (m_Options.PrimeCacheOnly) + const IoHash& ChunkHash = m_LooseChunkHashes[LooseChunkIndex]; + auto RemoteChunkIndexIt = m_RemoteLookup.ChunkHashToChunkIndex.find(ChunkHash); + ZEN_ASSERT(RemoteChunkIndexIt != m_RemoteLookup.ChunkHashToChunkIndex.end()); + const uint32_t RemoteChunkIndex = RemoteChunkIndexIt->second; + + if (RemoteChunkIndexNeedsCopyFromLocalFileFlags[RemoteChunkIndex]) { - FetchBlockIndexes.push_back(BlockIndex); + if (m_Options.IsVerbose) + { + ZEN_OPERATION_LOG_INFO(m_LogOutput, + "Skipping chunk {} due to cache reuse", + m_RemoteContent.ChunkedContent.ChunkHashes[RemoteChunkIndex]); + } + continue; } - else + + bool NeedsCopy = true; + if (RemoteChunkIndexNeedsCopyFromSourceFlags[RemoteChunkIndex].compare_exchange_strong(NeedsCopy, false)) { - bool UsingCachedBlock = false; - if (auto It = CachedBlocksFound.find(BlockDescription.BlockHash); It != CachedBlocksFound.end()) + uint64_t WriteCount = GetChunkWriteCount(SequenceIndexChunksLeftToWriteCounters, RemoteChunkIndex); + if (WriteCount == 0) { - TotalPartWriteCount++; - - std::filesystem::path BlockPath = m_TempBlockFolderPath / BlockDescription.BlockHash.ToHexString(); - if (IsFile(BlockPath)) + if (m_Options.IsVerbose) { - CachedChunkBlockIndexes.push_back(BlockIndex); - UsingCachedBlock = true; + ZEN_OPERATION_LOG_INFO(m_LogOutput, + "Skipping chunk {} due to cache reuse", + m_RemoteContent.ChunkedContent.ChunkHashes[RemoteChunkIndex]); } } - if (!UsingCachedBlock) + else { - FetchBlockIndexes.push_back(BlockIndex); + NeededLooseChunkIndexes.push_back(LooseChunkIndex); } } } - AllBlockChunkIndexNeeded.emplace_back(std::move(BlockChunkIndexNeeded)); } - BlobsExistsResult ExistsResult; - if (m_Storage.BuildCacheStorage) { ZEN_TRACE_CPU("BlobCacheExistCheck"); Stopwatch Timer; - tsl::robin_set BlobHashesSet; + std::vector BlobHashes; + BlobHashes.reserve(NeededLooseChunkIndexes.size() + FetchBlockIndexes.size()); - BlobHashesSet.reserve(LooseChunkHashWorks.size() + FetchBlockIndexes.size()); - for (LooseChunkHashWorkData& LooseChunkHashWork : LooseChunkHashWorks) + for (const uint32_t LooseChunkIndex : NeededLooseChunkIndexes) { - BlobHashesSet.insert(m_RemoteContent.ChunkedContent.ChunkHashes[LooseChunkHashWork.RemoteChunkIndex]); + BlobHashes.push_back(m_LooseChunkHashes[LooseChunkIndex]); } + for (uint32_t BlockIndex : FetchBlockIndexes) { - const ChunkBlockDescription& BlockDescription = m_BlockDescriptions[BlockIndex]; - BlobHashesSet.insert(BlockDescription.BlockHash); + BlobHashes.push_back(m_BlockDescriptions[BlockIndex].BlockHash); } - if (!BlobHashesSet.empty()) - { - const std::vector BlobHashes(BlobHashesSet.begin(), BlobHashesSet.end()); - const std::vector CacheExistsResult = - m_Storage.BuildCacheStorage->BlobsExists(m_BuildId, BlobHashes); + const std::vector CacheExistsResult = + m_Storage.BuildCacheStorage->BlobsExists(m_BuildId, BlobHashes); - if (CacheExistsResult.size() == BlobHashes.size()) + if (CacheExistsResult.size() == BlobHashes.size()) + { + ExistsResult.ExistingBlobs.reserve(CacheExistsResult.size()); + for (size_t BlobIndex = 0; BlobIndex < BlobHashes.size(); BlobIndex++) { - ExistsResult.ExistingBlobs.reserve(CacheExistsResult.size()); - for (size_t BlobIndex = 0; BlobIndex < BlobHashes.size(); BlobIndex++) + if (CacheExistsResult[BlobIndex].HasBody) { - if (CacheExistsResult[BlobIndex].HasBody) - { - ExistsResult.ExistingBlobs.insert(BlobHashes[BlobIndex]); - } + ExistsResult.ExistingBlobs.insert(BlobHashes[BlobIndex]); } } - ExistsResult.ElapsedTimeMs = Timer.GetElapsedTimeMs(); - if (!ExistsResult.ExistingBlobs.empty() && !m_Options.IsQuiet) - { - ZEN_OPERATION_LOG_INFO(m_LogOutput, - "Remote cache : Found {} out of {} needed blobs in {}", - ExistsResult.ExistingBlobs.size(), - BlobHashes.size(), - NiceTimeSpanMs(ExistsResult.ElapsedTimeMs)); - } + } + ExistsResult.ElapsedTimeMs = Timer.GetElapsedTimeMs(); + if (!ExistsResult.ExistingBlobs.empty() && !m_Options.IsQuiet) + { + ZEN_OPERATION_LOG_INFO(m_LogOutput, + "Remote cache : Found {} out of {} needed blobs in {}", + ExistsResult.ExistingBlobs.size(), + BlobHashes.size(), + NiceTimeSpanMs(ExistsResult.ElapsedTimeMs)); } } - std::vector BlockRangeWorks; - std::vector FullBlockWorks; + std::vector BlockPartialDownloadModes; + if (m_Options.PartialBlockRequestMode == EPartialBlockRequestMode::Off) { - Stopwatch Timer; - - std::vector PartialBlockIndexes; - - for (uint32_t BlockIndex : FetchBlockIndexes) + BlockPartialDownloadModes.resize(m_BlockDescriptions.size(), ChunkBlockAnalyser::EPartialBlockDownloadMode::Off); + } + else if (m_Options.PartialBlockRequestMode == EPartialBlockRequestMode::All) + { + BlockPartialDownloadModes.resize(m_BlockDescriptions.size(), ChunkBlockAnalyser::EPartialBlockDownloadMode::On); + } + else + { + BlockPartialDownloadModes.reserve(m_BlockDescriptions.size()); + for (uint32_t BlockIndex = 0; BlockIndex < m_BlockDescriptions.size(); BlockIndex++) { - const ChunkBlockDescription& BlockDescription = m_BlockDescriptions[BlockIndex]; - - const std::vector BlockChunkIndexNeeded = std::move(AllBlockChunkIndexNeeded[BlockIndex]); - if (!BlockChunkIndexNeeded.empty()) + const bool BlockExistInCache = ExistsResult.ExistingBlobs.contains(m_BlockDescriptions[BlockIndex].BlockHash); + if (m_Options.PartialBlockRequestMode == EPartialBlockRequestMode::ZenCacheOnly) { - bool WantsToDoPartialBlockDownload = BlockChunkIndexNeeded.size() < BlockDescription.ChunkRawHashes.size(); - bool CanDoPartialBlockDownload = - (BlockDescription.HeaderSize > 0) && - (BlockDescription.ChunkCompressedLengths.size() == BlockDescription.ChunkRawHashes.size()); - - bool AllowedToDoPartialRequest = false; - bool BlockExistInCache = ExistsResult.ExistingBlobs.contains(BlockDescription.BlockHash); - switch (m_Options.PartialBlockRequestMode) - { - case EPartialBlockRequestMode::Off: - break; - case EPartialBlockRequestMode::ZenCacheOnly: - AllowedToDoPartialRequest = BlockExistInCache; - break; - case EPartialBlockRequestMode::Mixed: - case EPartialBlockRequestMode::All: - AllowedToDoPartialRequest = true; - break; - default: - ZEN_ASSERT(false); - break; - } + BlockPartialDownloadModes.push_back(BlockExistInCache ? ChunkBlockAnalyser::EPartialBlockDownloadMode::On + : ChunkBlockAnalyser::EPartialBlockDownloadMode::Off); + } + else if (m_Options.PartialBlockRequestMode == EPartialBlockRequestMode::Mixed) + { + BlockPartialDownloadModes.push_back(BlockExistInCache ? ChunkBlockAnalyser::EPartialBlockDownloadMode::On + : ChunkBlockAnalyser::EPartialBlockDownloadMode::SingleRange); + } + } + } + ZEN_ASSERT(BlockPartialDownloadModes.size() == m_BlockDescriptions.size()); - const uint32_t ChunkStartOffsetInBlock = - gsl::narrow(CompressedBuffer::GetHeaderSizeForNoneEncoder() + BlockDescription.HeaderSize); + ChunkBlockAnalyser::BlockResult PartialBlocks = + BlockAnalyser.CalculatePartialBlockDownloads(NeededBlocks, BlockPartialDownloadModes); - const uint64_t TotalBlockSize = std::accumulate(BlockDescription.ChunkCompressedLengths.begin(), - BlockDescription.ChunkCompressedLengths.end(), - std::uint64_t(ChunkStartOffsetInBlock)); + struct LooseChunkHashWorkData + { + std::vector ChunkTargetPtrs; + uint32_t RemoteChunkIndex = (uint32_t)-1; + }; - if (AllowedToDoPartialRequest && WantsToDoPartialBlockDownload && CanDoPartialBlockDownload) - { - ZEN_TRACE_CPU("PartialBlockAnalysis"); - - bool LimitToSingleRange = - BlockExistInCache ? false : m_Options.PartialBlockRequestMode == EPartialBlockRequestMode::Mixed; - uint64_t TotalWantedChunksSize = 0; - std::optional> MaybeBlockRanges = - CalculateBlockRanges(BlockIndex, - BlockDescription, - BlockChunkIndexNeeded, - LimitToSingleRange, - ChunkStartOffsetInBlock, - TotalBlockSize, - TotalWantedChunksSize); - ZEN_ASSERT(TotalWantedChunksSize <= TotalBlockSize); - - if (MaybeBlockRanges.has_value()) - { - const std::vector& BlockRanges = MaybeBlockRanges.value(); - ZEN_ASSERT(!BlockRanges.empty()); - BlockRangeWorks.insert(BlockRangeWorks.end(), BlockRanges.begin(), BlockRanges.end()); - TotalRequestCount += BlockRanges.size(); - TotalPartWriteCount += BlockRanges.size(); - - uint64_t RequestedSize = std::accumulate( - BlockRanges.begin(), - BlockRanges.end(), - uint64_t(0), - [](uint64_t Current, const BlockRangeDescriptor& Range) { return Current + Range.RangeLength; }); - PartialBlockIndexes.push_back(BlockIndex); - - if (RequestedSize > TotalWantedChunksSize) - { - if (m_Options.IsVerbose) - { - ZEN_OPERATION_LOG_INFO( - m_LogOutput, - "Requesting {} chunks ({}) from block {} ({}) using {} requests (extra bytes {})", - BlockChunkIndexNeeded.size(), - NiceBytes(RequestedSize), - BlockDescription.BlockHash, - NiceBytes(TotalBlockSize), - BlockRanges.size(), - NiceBytes(RequestedSize - TotalWantedChunksSize)); - } - } - } - else - { - FullBlockWorks.push_back(BlockIndex); - TotalRequestCount++; - TotalPartWriteCount++; - } - } - else - { - FullBlockWorks.push_back(BlockIndex); - TotalRequestCount++; - TotalPartWriteCount++; - } - } - } + TotalRequestCount += NeededLooseChunkIndexes.size(); + TotalPartWriteCount += NeededLooseChunkIndexes.size(); + TotalRequestCount += PartialBlocks.BlockRanges.size(); + TotalPartWriteCount += PartialBlocks.BlockRanges.size(); + TotalRequestCount += PartialBlocks.FullBlockIndexes.size(); + TotalPartWriteCount += PartialBlocks.FullBlockIndexes.size(); - if (!PartialBlockIndexes.empty()) - { - uint64_t TotalFullBlockRequestBytes = 0; - for (uint32_t BlockIndex : FullBlockWorks) - { - const ChunkBlockDescription& BlockDescription = m_BlockDescriptions[BlockIndex]; - uint32_t CurrentOffset = - gsl::narrow(CompressedBuffer::GetHeaderSizeForNoneEncoder() + BlockDescription.HeaderSize); + std::vector LooseChunkHashWorks; + for (uint32_t LooseChunkIndex : NeededLooseChunkIndexes) + { + const IoHash& ChunkHash = m_LooseChunkHashes[LooseChunkIndex]; + auto RemoteChunkIndexIt = m_RemoteLookup.ChunkHashToChunkIndex.find(ChunkHash); + ZEN_ASSERT(RemoteChunkIndexIt != m_RemoteLookup.ChunkHashToChunkIndex.end()); + const uint32_t RemoteChunkIndex = RemoteChunkIndexIt->second; - TotalFullBlockRequestBytes += std::accumulate(BlockDescription.ChunkCompressedLengths.begin(), - BlockDescription.ChunkCompressedLengths.end(), - std::uint64_t(CurrentOffset)); - } + std::vector ChunkTargetPtrs = + GetRemainingChunkTargets(SequenceIndexChunksLeftToWriteCounters, RemoteChunkIndex); - uint64_t TotalPartialBlockBytes = 0; - for (uint32_t BlockIndex : PartialBlockIndexes) - { - const ChunkBlockDescription& BlockDescription = m_BlockDescriptions[BlockIndex]; - uint32_t CurrentOffset = - gsl::narrow(CompressedBuffer::GetHeaderSizeForNoneEncoder() + BlockDescription.HeaderSize); + ZEN_ASSERT(!ChunkTargetPtrs.empty()); + LooseChunkHashWorks.push_back( + LooseChunkHashWorkData{.ChunkTargetPtrs = ChunkTargetPtrs, .RemoteChunkIndex = RemoteChunkIndex}); + } - TotalPartialBlockBytes += std::accumulate(BlockDescription.ChunkCompressedLengths.begin(), - BlockDescription.ChunkCompressedLengths.end(), - std::uint64_t(CurrentOffset)); - } + ZEN_TRACE_CPU("WriteChunks"); - uint64_t NonPartialTotalBlockBytes = TotalFullBlockRequestBytes + TotalPartialBlockBytes; + m_LogOutput.SetLogOperationProgress((uint32_t)TaskSteps::WriteChunks, (uint32_t)TaskSteps::StepCount); - const uint64_t TotalPartialBlockRequestBytes = - std::accumulate(BlockRangeWorks.begin(), - BlockRangeWorks.end(), - uint64_t(0), - [](uint64_t Current, const BlockRangeDescriptor& Range) { return Current + Range.RangeLength; }); - uint64_t TotalExtraPartialBlocksRequests = BlockRangeWorks.size() - PartialBlockIndexes.size(); + Stopwatch WriteTimer; - uint64_t TotalSavedBlocksSize = TotalPartialBlockBytes - TotalPartialBlockRequestBytes; - double SavedSizePercent = (TotalSavedBlocksSize * 100.0) / NonPartialTotalBlockBytes; + FilteredRate FilteredDownloadedBytesPerSecond; + FilteredRate FilteredWrittenBytesPerSecond; - if (!m_Options.IsQuiet) - { - ZEN_OPERATION_LOG_INFO(m_LogOutput, - "Analysis of partial block requests saves download of {} out of {} ({:.1f}%) using {} extra " - "requests. Completed in {}", - NiceBytes(TotalSavedBlocksSize), - NiceBytes(NonPartialTotalBlockBytes), - SavedSizePercent, - TotalExtraPartialBlocksRequests, - NiceTimeSpanMs(ExistsResult.ElapsedTimeMs)); - } - } - } + std::unique_ptr WriteProgressBarPtr( + m_LogOutput.CreateProgressBar(m_Options.PrimeCacheOnly ? "Downloading" : "Writing")); + OperationLogOutput::ProgressBar& WriteProgressBar(*WriteProgressBarPtr); + ParallelWork Work(m_AbortFlag, m_PauseFlag, WorkerThreadPool::EMode::EnableBacklog); + + TotalPartWriteCount += CopyChunkDatas.size(); + TotalPartWriteCount += ScavengedSequenceCopyOperations.size(); BufferedWriteFileCache WriteCache; @@ -1465,13 +1335,23 @@ BuildsOperationUpdateFolder::Execute(FolderContent& OutLocalFolderState) }); } - for (size_t BlockRangeIndex = 0; BlockRangeIndex < BlockRangeWorks.size(); BlockRangeIndex++) + for (size_t BlockRangeIndex = 0; BlockRangeIndex < PartialBlocks.BlockRanges.size();) { ZEN_ASSERT(!m_Options.PrimeCacheOnly); if (m_AbortFlag) { break; } + + size_t RangeCount = 1; + size_t RangesLeft = PartialBlocks.BlockRanges.size() - BlockRangeIndex; + const ChunkBlockAnalyser::BlockRangeDescriptor& CurrentBlockRange = PartialBlocks.BlockRanges[BlockRangeIndex]; + while (RangeCount < RangesLeft && + CurrentBlockRange.BlockIndex == PartialBlocks.BlockRanges[BlockRangeIndex + RangeCount].BlockIndex) + { + RangeCount++; + } + Work.ScheduleWork( m_NetworkPool, [this, @@ -1485,119 +1365,127 @@ BuildsOperationUpdateFolder::Execute(FolderContent& OutLocalFolderState) TotalPartWriteCount, &FilteredWrittenBytesPerSecond, &Work, - &BlockRangeWorks, - BlockRangeIndex](std::atomic&) { + &PartialBlocks, + BlockRangeStartIndex = BlockRangeIndex, + RangeCount](std::atomic&) { if (!m_AbortFlag) { - ZEN_TRACE_CPU("Async_GetPartialBlock"); - - const BlockRangeDescriptor& BlockRange = BlockRangeWorks[BlockRangeIndex]; + ZEN_TRACE_CPU("Async_GetPartialBlockRanges"); FilteredDownloadedBytesPerSecond.Start(); - DownloadPartialBlock( - BlockRange, - ExistsResult, - [this, - &RemoteChunkIndexNeedsCopyFromSourceFlags, - &SequenceIndexChunksLeftToWriteCounters, - &WritePartsComplete, - &WriteCache, - &Work, - TotalRequestCount, - TotalPartWriteCount, - &FilteredDownloadedBytesPerSecond, - &FilteredWrittenBytesPerSecond, - &BlockRange](IoBuffer&& InMemoryBuffer, const std::filesystem::path& OnDiskPath) { - if (m_DownloadStats.RequestsCompleteCount == TotalRequestCount) - { - FilteredDownloadedBytesPerSecond.Stop(); - } - - if (!m_AbortFlag) - { - Work.ScheduleWork( - m_IOWorkerPool, - [this, - &RemoteChunkIndexNeedsCopyFromSourceFlags, - &SequenceIndexChunksLeftToWriteCounters, - &WritePartsComplete, - &WriteCache, - &Work, - TotalPartWriteCount, - &FilteredWrittenBytesPerSecond, - &BlockRange, - BlockChunkPath = std::filesystem::path(OnDiskPath), - BlockPartialBuffer = std::move(InMemoryBuffer)](std::atomic&) mutable { - if (!m_AbortFlag) - { - ZEN_TRACE_CPU("Async_WritePartialBlock"); + for (size_t BlockRangeIndex = BlockRangeStartIndex; BlockRangeIndex < BlockRangeStartIndex + RangeCount; + BlockRangeIndex++) + { + ZEN_TRACE_CPU("GetPartialBlock"); - const uint32_t BlockIndex = BlockRange.BlockIndex; + const ChunkBlockAnalyser::BlockRangeDescriptor& BlockRange = PartialBlocks.BlockRanges[BlockRangeIndex]; - const ChunkBlockDescription& BlockDescription = m_BlockDescriptions[BlockIndex]; + DownloadPartialBlock( + BlockRange, + ExistsResult, + [this, + &RemoteChunkIndexNeedsCopyFromSourceFlags, + &SequenceIndexChunksLeftToWriteCounters, + &WritePartsComplete, + &WriteCache, + &Work, + TotalRequestCount, + TotalPartWriteCount, + &FilteredDownloadedBytesPerSecond, + &FilteredWrittenBytesPerSecond, + &BlockRange](IoBuffer&& InMemoryBuffer, const std::filesystem::path& OnDiskPath) { + if (m_DownloadStats.RequestsCompleteCount == TotalRequestCount) + { + FilteredDownloadedBytesPerSecond.Stop(); + } - if (BlockChunkPath.empty()) - { - ZEN_ASSERT(BlockPartialBuffer); - } - else + if (!m_AbortFlag) + { + Work.ScheduleWork( + m_IOWorkerPool, + [this, + &RemoteChunkIndexNeedsCopyFromSourceFlags, + &SequenceIndexChunksLeftToWriteCounters, + &WritePartsComplete, + &WriteCache, + &Work, + TotalPartWriteCount, + &FilteredWrittenBytesPerSecond, + &BlockRange, + BlockChunkPath = std::filesystem::path(OnDiskPath), + BlockPartialBuffer = std::move(InMemoryBuffer)](std::atomic&) mutable { + if (!m_AbortFlag) { - ZEN_ASSERT(!BlockPartialBuffer); - BlockPartialBuffer = IoBufferBuilder::MakeFromFile(BlockChunkPath); - if (!BlockPartialBuffer) + ZEN_TRACE_CPU("Async_WritePartialBlock"); + + const uint32_t BlockIndex = BlockRange.BlockIndex; + + const ChunkBlockDescription& BlockDescription = m_BlockDescriptions[BlockIndex]; + + if (BlockChunkPath.empty()) { - throw std::runtime_error( - fmt::format("Could not open downloaded block {} from {}", - BlockDescription.BlockHash, - BlockChunkPath)); + ZEN_ASSERT(BlockPartialBuffer); + } + else + { + ZEN_ASSERT(!BlockPartialBuffer); + BlockPartialBuffer = IoBufferBuilder::MakeFromFile(BlockChunkPath); + if (!BlockPartialBuffer) + { + throw std::runtime_error( + fmt::format("Could not open downloaded block {} from {}", + BlockDescription.BlockHash, + BlockChunkPath)); + } } - } - - FilteredWrittenBytesPerSecond.Start(); - if (!WritePartialBlockChunksToCache( - BlockDescription, - SequenceIndexChunksLeftToWriteCounters, - Work, - CompositeBuffer(std::move(BlockPartialBuffer)), - BlockRange.ChunkBlockIndexStart, - BlockRange.ChunkBlockIndexStart + BlockRange.ChunkBlockIndexCount - 1, - RemoteChunkIndexNeedsCopyFromSourceFlags, - WriteCache)) - { - std::error_code DummyEc; - RemoveFile(BlockChunkPath, DummyEc); - throw std::runtime_error( - fmt::format("Partial block {} is malformed", BlockDescription.BlockHash)); - } + FilteredWrittenBytesPerSecond.Start(); + + if (!WritePartialBlockChunksToCache( + BlockDescription, + SequenceIndexChunksLeftToWriteCounters, + Work, + CompositeBuffer(std::move(BlockPartialBuffer)), + BlockRange.ChunkBlockIndexStart, + BlockRange.ChunkBlockIndexStart + BlockRange.ChunkBlockIndexCount - 1, + RemoteChunkIndexNeedsCopyFromSourceFlags, + WriteCache)) + { + std::error_code DummyEc; + RemoveFile(BlockChunkPath, DummyEc); + throw std::runtime_error( + fmt::format("Partial block {} is malformed", BlockDescription.BlockHash)); + } - std::error_code Ec = TryRemoveFile(BlockChunkPath); - if (Ec) - { - ZEN_OPERATION_LOG_DEBUG(m_LogOutput, - "Failed removing file '{}', reason: ({}) {}", - BlockChunkPath, - Ec.value(), - Ec.message()); - } + std::error_code Ec = TryRemoveFile(BlockChunkPath); + if (Ec) + { + ZEN_OPERATION_LOG_DEBUG(m_LogOutput, + "Failed removing file '{}', reason: ({}) {}", + BlockChunkPath, + Ec.value(), + Ec.message()); + } - WritePartsComplete++; - if (WritePartsComplete == TotalPartWriteCount) - { - FilteredWrittenBytesPerSecond.Stop(); + WritePartsComplete++; + if (WritePartsComplete == TotalPartWriteCount) + { + FilteredWrittenBytesPerSecond.Stop(); + } } - } - }, - OnDiskPath.empty() ? WorkerThreadPool::EMode::DisableBacklog - : WorkerThreadPool::EMode::EnableBacklog); - } - }); + }, + OnDiskPath.empty() ? WorkerThreadPool::EMode::DisableBacklog + : WorkerThreadPool::EMode::EnableBacklog); + } + }); + } } }); + BlockRangeIndex += RangeCount; } - for (uint32_t BlockIndex : FullBlockWorks) + for (uint32_t BlockIndex : PartialBlocks.FullBlockIndexes) { if (m_AbortFlag) { @@ -3282,271 +3170,9 @@ BuildsOperationUpdateFolder::DownloadBuildBlob(uint32_t RemoteChunkInde } } -BuildsOperationUpdateFolder::BlockRangeDescriptor -BuildsOperationUpdateFolder::MergeBlockRanges(std::span Ranges) -{ - ZEN_ASSERT(Ranges.size() > 1); - const BlockRangeDescriptor& First = Ranges.front(); - const BlockRangeDescriptor& Last = Ranges.back(); - - return BlockRangeDescriptor{.BlockIndex = First.BlockIndex, - .RangeStart = First.RangeStart, - .RangeLength = Last.RangeStart + Last.RangeLength - First.RangeStart, - .ChunkBlockIndexStart = First.ChunkBlockIndexStart, - .ChunkBlockIndexCount = Last.ChunkBlockIndexStart + Last.ChunkBlockIndexCount - First.ChunkBlockIndexStart}; -} - -std::optional> -BuildsOperationUpdateFolder::MakeOptionalBlockRangeVector(uint64_t TotalBlockSize, const BlockRangeDescriptor& Range) -{ - if (Range.RangeLength == TotalBlockSize) - { - return {}; - } - else - { - return std::vector{Range}; - } -}; - -const BuildsOperationUpdateFolder::BlockRangeLimit* -BuildsOperationUpdateFolder::GetBlockRangeLimitForRange(std::span Limits, - uint64_t TotalBlockSize, - std::span Ranges) -{ - if (Ranges.size() > 1) - { - const std::uint64_t WantedSize = - std::accumulate(Ranges.begin(), Ranges.end(), uint64_t(0), [](uint64_t Current, const BlockRangeDescriptor& Range) { - return Current + Range.RangeLength; - }); - - const double RangeRequestedPercent = (WantedSize * 100.0) / TotalBlockSize; - - for (const BlockRangeLimit& Limit : Limits) - { - if (RangeRequestedPercent >= Limit.SizePercent && Ranges.size() > Limit.MaxRangeCount) - { - return &Limit; - } - } - } - return nullptr; -}; - -std::vector -BuildsOperationUpdateFolder::CollapseBlockRanges(const uint64_t AlwaysAcceptableGap, std::span BlockRanges) -{ - ZEN_ASSERT(BlockRanges.size() > 1); - std::vector CollapsedBlockRanges; - - auto BlockRangesIt = BlockRanges.begin(); - CollapsedBlockRanges.push_back(*BlockRangesIt++); - for (; BlockRangesIt != BlockRanges.end(); BlockRangesIt++) - { - BlockRangeDescriptor& LastRange = CollapsedBlockRanges.back(); - - const uint64_t BothRangeSize = BlockRangesIt->RangeLength + LastRange.RangeLength; - - const uint64_t Gap = BlockRangesIt->RangeStart - (LastRange.RangeStart + LastRange.RangeLength); - if (Gap <= Max(BothRangeSize / 16, AlwaysAcceptableGap)) - { - LastRange.ChunkBlockIndexCount = - (BlockRangesIt->ChunkBlockIndexStart + BlockRangesIt->ChunkBlockIndexCount) - LastRange.ChunkBlockIndexStart; - LastRange.RangeLength = (BlockRangesIt->RangeStart + BlockRangesIt->RangeLength) - LastRange.RangeStart; - } - else - { - CollapsedBlockRanges.push_back(*BlockRangesIt); - } - } - - return CollapsedBlockRanges; -}; - -uint64_t -BuildsOperationUpdateFolder::CalculateNextGap(std::span BlockRanges) -{ - ZEN_ASSERT(BlockRanges.size() > 1); - uint64_t AcceptableGap = (uint64_t)-1; - for (size_t RangeIndex = 0; RangeIndex < BlockRanges.size() - 1; RangeIndex++) - { - const BlockRangeDescriptor& Range = BlockRanges[RangeIndex]; - const BlockRangeDescriptor& NextRange = BlockRanges[RangeIndex + 1]; - - const uint64_t Gap = NextRange.RangeStart - (Range.RangeStart + Range.RangeLength); - AcceptableGap = Min(Gap, AcceptableGap); - } - AcceptableGap = RoundUp(AcceptableGap, 16u * 1024u); - return AcceptableGap; -}; - -std::optional> -BuildsOperationUpdateFolder::CalculateBlockRanges(uint32_t BlockIndex, - const ChunkBlockDescription& BlockDescription, - std::span BlockChunkIndexNeeded, - bool LimitToSingleRange, - const uint64_t ChunkStartOffsetInBlock, - const uint64_t TotalBlockSize, - uint64_t& OutTotalWantedChunksSize) -{ - ZEN_TRACE_CPU("CalculateBlockRanges"); - - std::vector BlockRanges; - { - uint64_t CurrentOffset = ChunkStartOffsetInBlock; - uint32_t ChunkBlockIndex = 0; - uint32_t NeedBlockChunkIndexOffset = 0; - BlockRangeDescriptor NextRange{.BlockIndex = BlockIndex}; - while (NeedBlockChunkIndexOffset < BlockChunkIndexNeeded.size() && ChunkBlockIndex < BlockDescription.ChunkRawHashes.size()) - { - const uint32_t ChunkCompressedLength = BlockDescription.ChunkCompressedLengths[ChunkBlockIndex]; - if (ChunkBlockIndex < BlockChunkIndexNeeded[NeedBlockChunkIndexOffset]) - { - if (NextRange.RangeLength > 0) - { - BlockRanges.push_back(NextRange); - NextRange = {.BlockIndex = BlockIndex}; - } - ChunkBlockIndex++; - CurrentOffset += ChunkCompressedLength; - } - else if (ChunkBlockIndex == BlockChunkIndexNeeded[NeedBlockChunkIndexOffset]) - { - if (NextRange.RangeLength == 0) - { - NextRange.RangeStart = CurrentOffset; - NextRange.ChunkBlockIndexStart = ChunkBlockIndex; - } - NextRange.RangeLength += ChunkCompressedLength; - NextRange.ChunkBlockIndexCount++; - ChunkBlockIndex++; - CurrentOffset += ChunkCompressedLength; - NeedBlockChunkIndexOffset++; - } - else - { - ZEN_ASSERT(false); - } - } - if (NextRange.RangeLength > 0) - { - BlockRanges.push_back(NextRange); - } - } - ZEN_ASSERT(!BlockRanges.empty()); - - OutTotalWantedChunksSize = - std::accumulate(BlockRanges.begin(), BlockRanges.end(), uint64_t(0), [](uint64_t Current, const BlockRangeDescriptor& Range) { - return Current + Range.RangeLength; - }); - - double RangeWantedPercent = (OutTotalWantedChunksSize * 100.0) / TotalBlockSize; - - if (BlockRanges.size() == 1) - { - if (m_Options.IsVerbose) - { - ZEN_OPERATION_LOG_INFO(m_LogOutput, - "Range request of {} ({:.2f}%) using single range from block {} ({}) as is", - NiceBytes(OutTotalWantedChunksSize), - RangeWantedPercent, - BlockDescription.BlockHash, - NiceBytes(TotalBlockSize)); - } - return BlockRanges; - } - - if (LimitToSingleRange) - { - const BlockRangeDescriptor MergedRange = MergeBlockRanges(BlockRanges); - if (m_Options.IsVerbose) - { - const double RangeRequestedPercent = (MergedRange.RangeLength * 100.0) / TotalBlockSize; - const double WastedPercent = ((MergedRange.RangeLength - OutTotalWantedChunksSize) * 100.0) / MergedRange.RangeLength; - - ZEN_OPERATION_LOG_INFO( - m_LogOutput, - "Range request of {} ({:.2f}%) using {} ranges from block {} ({}) limited to single block range {} ({:.2f}%) wasting " - "{:.2f}% ({})", - NiceBytes(OutTotalWantedChunksSize), - RangeWantedPercent, - BlockRanges.size(), - BlockDescription.BlockHash, - NiceBytes(TotalBlockSize), - NiceBytes(MergedRange.RangeLength), - RangeRequestedPercent, - WastedPercent, - NiceBytes(MergedRange.RangeLength - OutTotalWantedChunksSize)); - } - return MakeOptionalBlockRangeVector(TotalBlockSize, MergedRange); - } - - if (RangeWantedPercent > FullBlockRangePercentLimit) - { - const BlockRangeDescriptor MergedRange = MergeBlockRanges(BlockRanges); - if (m_Options.IsVerbose) - { - const double RangeRequestedPercent = (MergedRange.RangeLength * 100.0) / TotalBlockSize; - const double WastedPercent = ((MergedRange.RangeLength - OutTotalWantedChunksSize) * 100.0) / MergedRange.RangeLength; - - ZEN_OPERATION_LOG_INFO( - m_LogOutput, - "Range request of {} ({:.2f}%) using {} ranges from block {} ({}) exceeds {}%. Merged to single block range {} " - "({:.2f}%) wasting {:.2f}% ({})", - NiceBytes(OutTotalWantedChunksSize), - RangeWantedPercent, - BlockRanges.size(), - BlockDescription.BlockHash, - NiceBytes(TotalBlockSize), - FullBlockRangePercentLimit, - NiceBytes(MergedRange.RangeLength), - RangeRequestedPercent, - WastedPercent, - NiceBytes(MergedRange.RangeLength - OutTotalWantedChunksSize)); - } - return MakeOptionalBlockRangeVector(TotalBlockSize, MergedRange); - } - - std::vector CollapsedBlockRanges = CollapseBlockRanges(16u * 1024u, BlockRanges); - while (GetBlockRangeLimitForRange(ForceMergeLimits, TotalBlockSize, CollapsedBlockRanges)) - { - CollapsedBlockRanges = CollapseBlockRanges(CalculateNextGap(CollapsedBlockRanges), CollapsedBlockRanges); - } - - const std::uint64_t WantedCollapsedSize = - std::accumulate(CollapsedBlockRanges.begin(), - CollapsedBlockRanges.end(), - uint64_t(0), - [](uint64_t Current, const BlockRangeDescriptor& Range) { return Current + Range.RangeLength; }); - - const double CollapsedRangeRequestedPercent = (WantedCollapsedSize * 100.0) / TotalBlockSize; - - if (m_Options.IsVerbose) - { - const double WastedPercent = ((WantedCollapsedSize - OutTotalWantedChunksSize) * 100.0) / WantedCollapsedSize; - - ZEN_OPERATION_LOG_INFO( - m_LogOutput, - "Range request of {} ({:.2f}%) using {} ranges from block {} ({}) collapsed to {} {:.2f}% using {} ranges wasting {:.2f}% " - "({})", - NiceBytes(OutTotalWantedChunksSize), - RangeWantedPercent, - BlockRanges.size(), - BlockDescription.BlockHash, - NiceBytes(TotalBlockSize), - NiceBytes(WantedCollapsedSize), - CollapsedRangeRequestedPercent, - CollapsedBlockRanges.size(), - WastedPercent, - NiceBytes(WantedCollapsedSize - OutTotalWantedChunksSize)); - } - return CollapsedBlockRanges; -} - void BuildsOperationUpdateFolder::DownloadPartialBlock( - const BlockRangeDescriptor BlockRange, + const ChunkBlockAnalyser::BlockRangeDescriptor BlockRange, const BlobsExistsResult& ExistsResult, std::function&& OnDownloaded) { diff --git a/src/zenremotestore/chunking/chunkblock.cpp b/src/zenremotestore/chunking/chunkblock.cpp index c4d8653f4..06cedae3f 100644 --- a/src/zenremotestore/chunking/chunkblock.cpp +++ b/src/zenremotestore/chunking/chunkblock.cpp @@ -10,18 +10,17 @@ #include +#include #include ZEN_THIRD_PARTY_INCLUDES_START #include +#include ZEN_THIRD_PARTY_INCLUDES_END #if ZEN_WITH_TESTS # include # include - -# include -# include #endif // ZEN_WITH_TESTS namespace zen { @@ -455,6 +454,537 @@ FindReuseBlocks(OperationLogOutput& Output, return FilteredReuseBlockIndexes; } +ChunkBlockAnalyser::ChunkBlockAnalyser(OperationLogOutput& LogOutput, + std::span BlockDescriptions, + const Options& Options) +: m_LogOutput(LogOutput) +, m_BlockDescriptions(BlockDescriptions) +, m_Options(Options) +{ +} + +std::vector +ChunkBlockAnalyser::GetNeeded(const tsl::robin_map& ChunkHashToChunkIndex, + std::function&& NeedsBlockChunk) +{ + ZEN_TRACE_CPU("ChunkBlockAnalyser::GetNeeded"); + + std::vector Result; + + std::vector ChunkIsNeeded(ChunkHashToChunkIndex.size()); + for (uint32_t ChunkIndex = 0; ChunkIndex < ChunkHashToChunkIndex.size(); ChunkIndex++) + { + ChunkIsNeeded[ChunkIndex] = NeedsBlockChunk(ChunkIndex); + } + + std::vector BlockSlack(m_BlockDescriptions.size(), 0u); + for (uint32_t BlockIndex = 0; BlockIndex < m_BlockDescriptions.size(); BlockIndex++) + { + const ChunkBlockDescription& BlockDescription = m_BlockDescriptions[BlockIndex]; + + uint64_t BlockUsedSize = 0; + uint64_t BlockSize = 0; + + for (uint32_t ChunkBlockIndex = 0; ChunkBlockIndex < BlockDescription.ChunkRawHashes.size(); ChunkBlockIndex++) + { + const IoHash& ChunkHash = BlockDescription.ChunkRawHashes[ChunkBlockIndex]; + if (auto It = ChunkHashToChunkIndex.find(ChunkHash); It != ChunkHashToChunkIndex.end()) + { + const uint32_t RemoteChunkIndex = It->second; + if (ChunkIsNeeded[RemoteChunkIndex]) + { + BlockUsedSize += BlockDescription.ChunkCompressedLengths[ChunkBlockIndex]; + } + } + BlockSize += BlockDescription.ChunkCompressedLengths[ChunkBlockIndex]; + } + BlockSlack[BlockIndex] = BlockSize - BlockUsedSize; + } + + std::vector BlockOrder(m_BlockDescriptions.size()); + std::iota(BlockOrder.begin(), BlockOrder.end(), 0); + + std::sort(BlockOrder.begin(), BlockOrder.end(), [&BlockSlack](uint32_t Lhs, uint32_t Rhs) { + return BlockSlack[Lhs] < BlockSlack[Rhs]; + }); + + std::vector ChunkIsPickedUp(ChunkHashToChunkIndex.size(), false); + + for (uint32_t BlockIndex : BlockOrder) + { + const ChunkBlockDescription& BlockDescription = m_BlockDescriptions[BlockIndex]; + + std::vector BlockChunkIndexNeeded; + + for (uint32_t ChunkBlockIndex = 0; ChunkBlockIndex < BlockDescription.ChunkRawHashes.size(); ChunkBlockIndex++) + { + const IoHash& ChunkHash = BlockDescription.ChunkRawHashes[ChunkBlockIndex]; + if (auto It = ChunkHashToChunkIndex.find(ChunkHash); It != ChunkHashToChunkIndex.end()) + { + const uint32_t RemoteChunkIndex = It->second; + if (ChunkIsNeeded[RemoteChunkIndex]) + { + if (!ChunkIsPickedUp[RemoteChunkIndex]) + { + ChunkIsPickedUp[RemoteChunkIndex] = true; + BlockChunkIndexNeeded.push_back(ChunkBlockIndex); + } + } + } + else + { + ZEN_DEBUG("Chunk {} not found in block {}", ChunkHash, BlockDescription.BlockHash); + } + } + + if (!BlockChunkIndexNeeded.empty()) + { + Result.push_back(NeededBlock{.BlockIndex = BlockIndex, .ChunkIndexes = std::move(BlockChunkIndexNeeded)}); + } + } + return Result; +} + +ChunkBlockAnalyser::BlockResult +ChunkBlockAnalyser::CalculatePartialBlockDownloads(std::span NeededBlocks, + std::span BlockPartialDownloadModes) +{ + ZEN_TRACE_CPU("ChunkBlockAnalyser::CalculatePartialBlockDownloads"); + + Stopwatch PartialAnalisysTimer; + + ChunkBlockAnalyser::BlockResult Result; + + uint64_t IdealDownloadTotalSize = 0; + uint64_t AllBlocksTotalBlocksSize = 0; + + for (const NeededBlock& NeededBlock : NeededBlocks) + { + const ChunkBlockDescription& BlockDescription = m_BlockDescriptions[NeededBlock.BlockIndex]; + + std::span BlockChunkIndexNeeded(NeededBlock.ChunkIndexes); + if (!NeededBlock.ChunkIndexes.empty()) + { + bool WantsToDoPartialBlockDownload = NeededBlock.ChunkIndexes.size() < BlockDescription.ChunkRawHashes.size(); + bool CanDoPartialBlockDownload = (BlockDescription.HeaderSize > 0) && + (BlockDescription.ChunkCompressedLengths.size() == BlockDescription.ChunkRawHashes.size()); + + EPartialBlockDownloadMode PartialBlockDownloadMode = BlockPartialDownloadModes[NeededBlock.BlockIndex]; + + const uint32_t ChunkStartOffsetInBlock = + gsl::narrow(CompressedBuffer::GetHeaderSizeForNoneEncoder() + BlockDescription.HeaderSize); + + const uint64_t TotalBlockSize = std::accumulate(BlockDescription.ChunkCompressedLengths.begin(), + BlockDescription.ChunkCompressedLengths.end(), + std::uint64_t(ChunkStartOffsetInBlock)); + + AllBlocksTotalBlocksSize += TotalBlockSize; + + if ((PartialBlockDownloadMode != EPartialBlockDownloadMode::Off) && WantsToDoPartialBlockDownload && CanDoPartialBlockDownload) + { + ZEN_TRACE_CPU("PartialBlockAnalysis"); + + uint64_t TotalWantedChunksSize = 0; + std::optional> MaybeBlockRanges = CalculateBlockRanges(NeededBlock.BlockIndex, + BlockDescription, + NeededBlock.ChunkIndexes, + PartialBlockDownloadMode, + ChunkStartOffsetInBlock, + TotalBlockSize, + TotalWantedChunksSize); + ZEN_ASSERT(TotalWantedChunksSize <= TotalBlockSize); + IdealDownloadTotalSize += TotalWantedChunksSize; + + if (MaybeBlockRanges.has_value()) + { + const std::vector& BlockRanges = MaybeBlockRanges.value(); + ZEN_ASSERT(!BlockRanges.empty()); + + uint64_t RequestedSize = + std::accumulate(BlockRanges.begin(), + BlockRanges.end(), + uint64_t(0), + [](uint64_t Current, const BlockRangeDescriptor& Range) { return Current + Range.RangeLength; }); + + if ((PartialBlockDownloadMode != EPartialBlockDownloadMode::Exact) && ((RequestedSize * 100) / TotalBlockSize) >= 200) + { + if (m_Options.IsVerbose) + { + ZEN_OPERATION_LOG_INFO(m_LogOutput, + "Requesting {} chunks ({}) from block {} ({}) using full block request (extra bytes {})", + NeededBlock.ChunkIndexes.size(), + NiceBytes(RequestedSize), + BlockDescription.BlockHash, + NiceBytes(TotalBlockSize), + NiceBytes(TotalBlockSize - TotalWantedChunksSize)); + } + Result.FullBlockIndexes.push_back(NeededBlock.BlockIndex); + } + else + { + Result.BlockRanges.insert(Result.BlockRanges.end(), BlockRanges.begin(), BlockRanges.end()); + + if (RequestedSize > TotalWantedChunksSize) + { + if (m_Options.IsVerbose) + { + ZEN_OPERATION_LOG_INFO(m_LogOutput, + "Requesting {} chunks ({}) from block {} ({}) using {} requests (extra bytes {})", + NeededBlock.ChunkIndexes.size(), + NiceBytes(RequestedSize), + BlockDescription.BlockHash, + NiceBytes(TotalBlockSize), + BlockRanges.size(), + NiceBytes(RequestedSize - TotalWantedChunksSize)); + } + } + } + } + else + { + Result.FullBlockIndexes.push_back(NeededBlock.BlockIndex); + } + } + else + { + Result.FullBlockIndexes.push_back(NeededBlock.BlockIndex); + IdealDownloadTotalSize += TotalBlockSize; + } + } + } + + if (!Result.BlockRanges.empty() && !m_Options.IsQuiet) + { + tsl::robin_set PartialBlockIndexes; + uint64_t PartialBlocksTotalSize = std::accumulate(Result.BlockRanges.begin(), + Result.BlockRanges.end(), + uint64_t(0u), + [&](uint64_t Current, const BlockRangeDescriptor& Range) { + PartialBlockIndexes.insert(Range.BlockIndex); + return Current + Range.RangeLength; + }); + + uint64_t FullBlocksTotalSize = + std::accumulate(Result.FullBlockIndexes.begin(), + Result.FullBlockIndexes.end(), + uint64_t(0u), + [&](uint64_t Current, uint32_t BlockIndex) { + const ChunkBlockDescription& BlockDescription = m_BlockDescriptions[BlockIndex]; + uint32_t CurrentOffset = + gsl::narrow(CompressedBuffer::GetHeaderSizeForNoneEncoder() + BlockDescription.HeaderSize); + + return Current + std::accumulate(BlockDescription.ChunkCompressedLengths.begin(), + BlockDescription.ChunkCompressedLengths.end(), + std::uint64_t(CurrentOffset)); + }); + + uint64_t PartialBlockRequestCount = Result.BlockRanges.size(); + uint64_t PartialBlockCount = PartialBlockIndexes.size(); + + uint64_t TotalExtraPartialBlocksRequestCount = PartialBlockRequestCount - PartialBlockCount; + uint64_t ActualPartialDownloadTotalSize = FullBlocksTotalSize + PartialBlocksTotalSize; + + uint64_t IdealSkippedSize = AllBlocksTotalBlocksSize - IdealDownloadTotalSize; + uint64_t ActualSkippedSize = AllBlocksTotalBlocksSize - ActualPartialDownloadTotalSize; + + double PercentOfIdealPartialSkippedSize = (ActualSkippedSize * 100.0) / IdealSkippedSize; + + ZEN_OPERATION_LOG_INFO(m_LogOutput, + "Analysis of partial block requests saves download of {} out of {}, {:.1f}% of possible {} using {} extra " + "requests. Completed in {}", + NiceBytes(ActualSkippedSize), + NiceBytes(AllBlocksTotalBlocksSize), + PercentOfIdealPartialSkippedSize, + NiceBytes(IdealSkippedSize), + TotalExtraPartialBlocksRequestCount, + NiceTimeSpanMs(PartialAnalisysTimer.GetElapsedTimeMs())); + } + + return Result; +} + +ChunkBlockAnalyser::BlockRangeDescriptor +ChunkBlockAnalyser::MergeBlockRanges(std::span Ranges) +{ + ZEN_ASSERT(Ranges.size() > 1); + const BlockRangeDescriptor& First = Ranges.front(); + const BlockRangeDescriptor& Last = Ranges.back(); + + return BlockRangeDescriptor{.BlockIndex = First.BlockIndex, + .RangeStart = First.RangeStart, + .RangeLength = Last.RangeStart + Last.RangeLength - First.RangeStart, + .ChunkBlockIndexStart = First.ChunkBlockIndexStart, + .ChunkBlockIndexCount = Last.ChunkBlockIndexStart + Last.ChunkBlockIndexCount - First.ChunkBlockIndexStart}; +} + +std::optional> +ChunkBlockAnalyser::MakeOptionalBlockRangeVector(uint64_t TotalBlockSize, const BlockRangeDescriptor& Range) +{ + if (Range.RangeLength == TotalBlockSize) + { + return {}; + } + else + { + return std::vector{Range}; + } +}; + +const ChunkBlockAnalyser::BlockRangeLimit* +ChunkBlockAnalyser::GetBlockRangeLimitForRange(std::span Limits, + uint64_t TotalBlockSize, + std::span Ranges) +{ + if (Ranges.size() > 1) + { + const std::uint64_t WantedSize = + std::accumulate(Ranges.begin(), Ranges.end(), uint64_t(0), [](uint64_t Current, const BlockRangeDescriptor& Range) { + return Current + Range.RangeLength; + }); + + const double RangeRequestedPercent = (WantedSize * 100.0) / TotalBlockSize; + + for (const BlockRangeLimit& Limit : Limits) + { + if (RangeRequestedPercent >= Limit.SizePercent && Ranges.size() > Limit.MaxRangeCount) + { + return &Limit; + } + } + } + return nullptr; +}; + +std::vector +ChunkBlockAnalyser::CollapseBlockRanges(const uint64_t AlwaysAcceptableGap, std::span BlockRanges) +{ + ZEN_ASSERT(BlockRanges.size() > 1); + std::vector CollapsedBlockRanges; + + auto BlockRangesIt = BlockRanges.begin(); + CollapsedBlockRanges.push_back(*BlockRangesIt++); + for (; BlockRangesIt != BlockRanges.end(); BlockRangesIt++) + { + BlockRangeDescriptor& LastRange = CollapsedBlockRanges.back(); + + const uint64_t BothRangeSize = BlockRangesIt->RangeLength + LastRange.RangeLength; + + const uint64_t Gap = BlockRangesIt->RangeStart - (LastRange.RangeStart + LastRange.RangeLength); + if (Gap <= Max(BothRangeSize / 16, AlwaysAcceptableGap)) + { + LastRange.ChunkBlockIndexCount = + (BlockRangesIt->ChunkBlockIndexStart + BlockRangesIt->ChunkBlockIndexCount) - LastRange.ChunkBlockIndexStart; + LastRange.RangeLength = (BlockRangesIt->RangeStart + BlockRangesIt->RangeLength) - LastRange.RangeStart; + } + else + { + CollapsedBlockRanges.push_back(*BlockRangesIt); + } + } + + return CollapsedBlockRanges; +}; + +uint64_t +ChunkBlockAnalyser::CalculateNextGap(std::span BlockRanges) +{ + ZEN_ASSERT(BlockRanges.size() > 1); + uint64_t AcceptableGap = (uint64_t)-1; + for (size_t RangeIndex = 0; RangeIndex < BlockRanges.size() - 1; RangeIndex++) + { + const BlockRangeDescriptor& Range = BlockRanges[RangeIndex]; + const BlockRangeDescriptor& NextRange = BlockRanges[RangeIndex + 1]; + + const uint64_t Gap = NextRange.RangeStart - (Range.RangeStart + Range.RangeLength); + AcceptableGap = Min(Gap, AcceptableGap); + } + AcceptableGap = RoundUp(AcceptableGap, 16u * 1024u); + return AcceptableGap; +}; + +std::optional> +ChunkBlockAnalyser::CalculateBlockRanges(uint32_t BlockIndex, + const ChunkBlockDescription& BlockDescription, + std::span BlockChunkIndexNeeded, + EPartialBlockDownloadMode PartialBlockDownloadMode, + const uint64_t ChunkStartOffsetInBlock, + const uint64_t TotalBlockSize, + uint64_t& OutTotalWantedChunksSize) +{ + ZEN_TRACE_CPU("CalculateBlockRanges"); + + if (PartialBlockDownloadMode == EPartialBlockDownloadMode::Off) + { + return {}; + } + + std::vector BlockRanges; + { + uint64_t CurrentOffset = ChunkStartOffsetInBlock; + uint32_t ChunkBlockIndex = 0; + uint32_t NeedBlockChunkIndexOffset = 0; + BlockRangeDescriptor NextRange{.BlockIndex = BlockIndex}; + while (NeedBlockChunkIndexOffset < BlockChunkIndexNeeded.size() && ChunkBlockIndex < BlockDescription.ChunkRawHashes.size()) + { + const uint32_t ChunkCompressedLength = BlockDescription.ChunkCompressedLengths[ChunkBlockIndex]; + if (ChunkBlockIndex < BlockChunkIndexNeeded[NeedBlockChunkIndexOffset]) + { + if (NextRange.RangeLength > 0) + { + BlockRanges.push_back(NextRange); + NextRange = {.BlockIndex = BlockIndex}; + } + ChunkBlockIndex++; + CurrentOffset += ChunkCompressedLength; + } + else if (ChunkBlockIndex == BlockChunkIndexNeeded[NeedBlockChunkIndexOffset]) + { + if (NextRange.RangeLength == 0) + { + NextRange.RangeStart = CurrentOffset; + NextRange.ChunkBlockIndexStart = ChunkBlockIndex; + } + NextRange.RangeLength += ChunkCompressedLength; + NextRange.ChunkBlockIndexCount++; + ChunkBlockIndex++; + CurrentOffset += ChunkCompressedLength; + NeedBlockChunkIndexOffset++; + } + else + { + ZEN_ASSERT(false); + } + } + if (NextRange.RangeLength > 0) + { + BlockRanges.push_back(NextRange); + } + } + ZEN_ASSERT(!BlockRanges.empty()); + + OutTotalWantedChunksSize = + std::accumulate(BlockRanges.begin(), BlockRanges.end(), uint64_t(0), [](uint64_t Current, const BlockRangeDescriptor& Range) { + return Current + Range.RangeLength; + }); + + double RangeWantedPercent = (OutTotalWantedChunksSize * 100.0) / TotalBlockSize; + + if (BlockRanges.size() == 1) + { + if (m_Options.IsVerbose) + { + ZEN_OPERATION_LOG_INFO(m_LogOutput, + "Range request of {} ({:.2f}%) using single range from block {} ({}) as is", + NiceBytes(OutTotalWantedChunksSize), + RangeWantedPercent, + BlockDescription.BlockHash, + NiceBytes(TotalBlockSize)); + } + return BlockRanges; + } + + if (PartialBlockDownloadMode == EPartialBlockDownloadMode::Exact) + { + if (m_Options.IsVerbose) + { + ZEN_OPERATION_LOG_INFO(m_LogOutput, + "Range request of {} ({:.2f}%) using {} ranges from block {} ({})", + NiceBytes(OutTotalWantedChunksSize), + RangeWantedPercent, + BlockRanges.size(), + BlockDescription.BlockHash, + NiceBytes(TotalBlockSize)); + } + return BlockRanges; + } + + if (PartialBlockDownloadMode == EPartialBlockDownloadMode::SingleRange) + { + const BlockRangeDescriptor MergedRange = MergeBlockRanges(BlockRanges); + if (m_Options.IsVerbose) + { + const double RangeRequestedPercent = (MergedRange.RangeLength * 100.0) / TotalBlockSize; + const double WastedPercent = ((MergedRange.RangeLength - OutTotalWantedChunksSize) * 100.0) / MergedRange.RangeLength; + + ZEN_OPERATION_LOG_INFO( + m_LogOutput, + "Range request of {} ({:.2f}%) using {} ranges from block {} ({}) limited to single block range {} ({:.2f}%) wasting " + "{:.2f}% ({})", + NiceBytes(OutTotalWantedChunksSize), + RangeWantedPercent, + BlockRanges.size(), + BlockDescription.BlockHash, + NiceBytes(TotalBlockSize), + NiceBytes(MergedRange.RangeLength), + RangeRequestedPercent, + WastedPercent, + NiceBytes(MergedRange.RangeLength - OutTotalWantedChunksSize)); + } + return MakeOptionalBlockRangeVector(TotalBlockSize, MergedRange); + } + + if (RangeWantedPercent > FullBlockRangePercentLimit) + { + const BlockRangeDescriptor MergedRange = MergeBlockRanges(BlockRanges); + if (m_Options.IsVerbose) + { + const double RangeRequestedPercent = (MergedRange.RangeLength * 100.0) / TotalBlockSize; + const double WastedPercent = ((MergedRange.RangeLength - OutTotalWantedChunksSize) * 100.0) / MergedRange.RangeLength; + + ZEN_OPERATION_LOG_INFO( + m_LogOutput, + "Range request of {} ({:.2f}%) using {} ranges from block {} ({}) exceeds {}%. Merged to single block range {} " + "({:.2f}%) wasting {:.2f}% ({})", + NiceBytes(OutTotalWantedChunksSize), + RangeWantedPercent, + BlockRanges.size(), + BlockDescription.BlockHash, + NiceBytes(TotalBlockSize), + FullBlockRangePercentLimit, + NiceBytes(MergedRange.RangeLength), + RangeRequestedPercent, + WastedPercent, + NiceBytes(MergedRange.RangeLength - OutTotalWantedChunksSize)); + } + return MakeOptionalBlockRangeVector(TotalBlockSize, MergedRange); + } + + std::vector CollapsedBlockRanges = CollapseBlockRanges(16u * 1024u, BlockRanges); + while (GetBlockRangeLimitForRange(ForceMergeLimits, TotalBlockSize, CollapsedBlockRanges)) + { + CollapsedBlockRanges = CollapseBlockRanges(CalculateNextGap(CollapsedBlockRanges), CollapsedBlockRanges); + } + + const std::uint64_t WantedCollapsedSize = + std::accumulate(CollapsedBlockRanges.begin(), + CollapsedBlockRanges.end(), + uint64_t(0), + [](uint64_t Current, const BlockRangeDescriptor& Range) { return Current + Range.RangeLength; }); + + const double CollapsedRangeRequestedPercent = (WantedCollapsedSize * 100.0) / TotalBlockSize; + + if (m_Options.IsVerbose) + { + const double WastedPercent = ((WantedCollapsedSize - OutTotalWantedChunksSize) * 100.0) / WantedCollapsedSize; + + ZEN_OPERATION_LOG_INFO( + m_LogOutput, + "Range request of {} ({:.2f}%) using {} ranges from block {} ({}) collapsed to {} {:.2f}% using {} ranges wasting {:.2f}% " + "({})", + NiceBytes(OutTotalWantedChunksSize), + RangeWantedPercent, + BlockRanges.size(), + BlockDescription.BlockHash, + NiceBytes(TotalBlockSize), + NiceBytes(WantedCollapsedSize), + CollapsedRangeRequestedPercent, + CollapsedBlockRanges.size(), + WastedPercent, + NiceBytes(WantedCollapsedSize - OutTotalWantedChunksSize)); + } + return CollapsedBlockRanges; +} + #if ZEN_WITH_TESTS namespace testutils { @@ -476,7 +1006,7 @@ namespace testutils { } // namespace testutils -TEST_CASE("project.store.block") +TEST_CASE("chunkblock.block") { using namespace std::literals; using namespace testutils; @@ -504,7 +1034,7 @@ TEST_CASE("project.store.block") HeaderSize)); } -TEST_CASE("project.store.reuseblocks") +TEST_CASE("chunkblock.reuseblocks") { using namespace std::literals; using namespace testutils; diff --git a/src/zenremotestore/include/zenremotestore/builds/buildstorageoperations.h b/src/zenremotestore/include/zenremotestore/builds/buildstorageoperations.h index 9e5bf8d91..6800444e0 100644 --- a/src/zenremotestore/include/zenremotestore/builds/buildstorageoperations.h +++ b/src/zenremotestore/include/zenremotestore/builds/buildstorageoperations.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -218,33 +219,6 @@ private: uint64_t ElapsedTimeMs = 0; }; - struct BlockRangeDescriptor - { - uint32_t BlockIndex = (uint32_t)-1; - uint64_t RangeStart = 0; - uint64_t RangeLength = 0; - uint32_t ChunkBlockIndexStart = 0; - uint32_t ChunkBlockIndexCount = 0; - }; - - struct BlockRangeLimit - { - uint16_t SizePercent; - uint16_t MaxRangeCount; - }; - - static constexpr uint16_t FullBlockRangePercentLimit = 95; - - static constexpr BuildsOperationUpdateFolder::BlockRangeLimit ForceMergeLimits[] = { - {.SizePercent = FullBlockRangePercentLimit, .MaxRangeCount = 1}, - {.SizePercent = 90, .MaxRangeCount = 2}, - {.SizePercent = 85, .MaxRangeCount = 8}, - {.SizePercent = 80, .MaxRangeCount = 16}, - {.SizePercent = 70, .MaxRangeCount = 32}, - {.SizePercent = 60, .MaxRangeCount = 48}, - {.SizePercent = 2, .MaxRangeCount = 56}, - {.SizePercent = 0, .MaxRangeCount = 64}}; - void ScanCacheFolder(tsl::robin_map& OutCachedChunkHashesFound, tsl::robin_map& OutCachedSequenceHashesFound); void ScanTempBlocksFolder(tsl::robin_map& OutCachedBlocksFound); @@ -299,25 +273,9 @@ private: ParallelWork& Work, std::function&& OnDownloaded); - BlockRangeDescriptor MergeBlockRanges(std::span Ranges); - std::optional> MakeOptionalBlockRangeVector(uint64_t TotalBlockSize, - const BlockRangeDescriptor& Range); - const BlockRangeLimit* GetBlockRangeLimitForRange(std::span Limits, - uint64_t TotalBlockSize, - std::span Ranges); - std::vector CollapseBlockRanges(const uint64_t AlwaysAcceptableGap, - std::span BlockRanges); - uint64_t CalculateNextGap(std::span BlockRanges); - std::optional> CalculateBlockRanges(uint32_t BlockIndex, - const ChunkBlockDescription& BlockDescription, - std::span BlockChunkIndexNeeded, - bool LimitToSingleRange, - const uint64_t ChunkStartOffsetInBlock, - const uint64_t TotalBlockSize, - uint64_t& OutTotalWantedChunksSize); - void DownloadPartialBlock(const BlockRangeDescriptor BlockRange, - const BlobsExistsResult& ExistsResult, - std::function&& OnDownloaded); + void DownloadPartialBlock(const ChunkBlockAnalyser::BlockRangeDescriptor BlockRange, + const BlobsExistsResult& ExistsResult, + std::function&& OnDownloaded); std::vector WriteLocalChunkToCache(CloneQueryInterface* CloneQuery, const CopyChunkData& CopyData, diff --git a/src/zenremotestore/include/zenremotestore/chunking/chunkblock.h b/src/zenremotestore/include/zenremotestore/chunking/chunkblock.h index d339b0f94..57710fcf5 100644 --- a/src/zenremotestore/include/zenremotestore/chunking/chunkblock.h +++ b/src/zenremotestore/include/zenremotestore/chunking/chunkblock.h @@ -7,6 +7,10 @@ #include #include +ZEN_THIRD_PARTY_INCLUDES_START +#include +ZEN_THIRD_PARTY_INCLUDES_END + #include #include @@ -73,6 +77,96 @@ std::vector FindReuseBlocks(OperationLogOutput& Output, std::span ChunkIndexes, std::vector& OutUnusedChunkIndexes); +class ChunkBlockAnalyser +{ +public: + struct Options + { + bool IsQuiet = false; + bool IsVerbose = false; + }; + + ChunkBlockAnalyser(OperationLogOutput& LogOutput, std::span BlockDescriptions, const Options& Options); + + struct BlockRangeDescriptor + { + uint32_t BlockIndex = (uint32_t)-1; + uint64_t RangeStart = 0; + uint64_t RangeLength = 0; + uint32_t ChunkBlockIndexStart = 0; + uint32_t ChunkBlockIndexCount = 0; + }; + + struct NeededBlock + { + uint32_t BlockIndex; + std::vector ChunkIndexes; + }; + + std::vector GetNeeded(const tsl::robin_map& ChunkHashToChunkIndex, + std::function&& NeedsBlockChunk); + + enum EPartialBlockDownloadMode + { + Off, + SingleRange, + On, + Exact + }; + + struct BlockResult + { + std::vector BlockRanges; + std::vector FullBlockIndexes; + }; + + BlockResult CalculatePartialBlockDownloads(std::span NeededBlocks, + std::span BlockPartialDownloadModes); + +private: + struct BlockRangeLimit + { + uint16_t SizePercent; + uint16_t MaxRangeCount; + }; + + static constexpr uint16_t FullBlockRangePercentLimit = 95; + + static constexpr BlockRangeLimit ForceMergeLimits[] = {{.SizePercent = FullBlockRangePercentLimit, .MaxRangeCount = 1}, + {.SizePercent = 90, .MaxRangeCount = 2}, + {.SizePercent = 85, .MaxRangeCount = 8}, + {.SizePercent = 80, .MaxRangeCount = 16}, + {.SizePercent = 75, .MaxRangeCount = 32}, + {.SizePercent = 70, .MaxRangeCount = 48}, + {.SizePercent = 4, .MaxRangeCount = 82}, + {.SizePercent = 0, .MaxRangeCount = 96}}; + + BlockRangeDescriptor MergeBlockRanges(std::span Ranges); + std::optional> MakeOptionalBlockRangeVector(uint64_t TotalBlockSize, + const BlockRangeDescriptor& Range); + const BlockRangeLimit* GetBlockRangeLimitForRange(std::span Limits, + uint64_t TotalBlockSize, + std::span Ranges); + std::vector CollapseBlockRanges(const uint64_t AlwaysAcceptableGap, + std::span BlockRanges); + uint64_t CalculateNextGap(std::span BlockRanges); + std::optional> CalculateBlockRanges(uint32_t BlockIndex, + const ChunkBlockDescription& BlockDescription, + std::span BlockChunkIndexNeeded, + EPartialBlockDownloadMode PartialBlockDownloadMode, + const uint64_t ChunkStartOffsetInBlock, + const uint64_t TotalBlockSize, + uint64_t& OutTotalWantedChunksSize); + + OperationLogOutput& m_LogOutput; + const std::span m_BlockDescriptions; + const Options m_Options; +}; + +#if ZEN_WITH_TESTS + +class CbWriter; void chunkblock_forcelink(); +#endif // ZEN_WITH_TESTS } // namespace zen -- cgit v1.2.3 From 606eb90fa55185a033923d310dc92a78a4a2d0f8 Mon Sep 17 00:00:00 2001 From: Stefan Boberg Date: Fri, 20 Feb 2026 13:50:27 +0100 Subject: update .gitignore to exclude .claude/ --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 3d98ecff8..eaf1656a6 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore .DS_Store +.claude/ # User-specific files *.suo -- cgit v1.2.3 From b927d006e8d33fcf8d2f5c1bce6b3c052839d32a Mon Sep 17 00:00:00 2001 From: Stefan Boberg Date: Sun, 22 Feb 2026 21:03:33 +0100 Subject: disable msys logic in blake3 to fix Git Bash build issues --- thirdparty/xmake.lua | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/thirdparty/xmake.lua b/thirdparty/xmake.lua index 07605a016..6fead7b50 100644 --- a/thirdparty/xmake.lua +++ b/thirdparty/xmake.lua @@ -92,9 +92,11 @@ target("blake3") end if is_arch("x86_64", "x64") then - if is_subhost("msys", "cygwin") then - add_files("blake3/c/*x86-64_windows_gnu.S") - elseif is_plat("windows") then + -- sbo: this breaks when using MINGW on windows (which is what you get in Git Bash), so just disable it + -- if is_subhost("msys", "cygwin") then + -- add_files("blake3/c/*x86-64_windows_gnu.S") + -- elseif is_plat("windows") then + if is_plat("windows") then add_files("blake3/c/*x86-64_windows_msvc.asm") else add_files("blake3/c/*x86-64_unix.S") -- cgit v1.2.3 From 73f3eb4feedf3bca0ddc832a89a05f09813c6858 Mon Sep 17 00:00:00 2001 From: Stefan Boberg Date: Mon, 23 Feb 2026 11:08:24 +0100 Subject: implemented base64 decoding (#777) Co-authored-by: Stefan Boberg --- src/zencore/base64.cpp | 192 ++++++++++++++++++++++++++++++++++- src/zencore/include/zencore/base64.h | 4 + 2 files changed, 194 insertions(+), 2 deletions(-) diff --git a/src/zencore/base64.cpp b/src/zencore/base64.cpp index 1f56ee6c3..fdf5f2d66 100644 --- a/src/zencore/base64.cpp +++ b/src/zencore/base64.cpp @@ -1,6 +1,10 @@ // Copyright Epic Games, Inc. All Rights Reserved. #include +#include +#include + +#include namespace zen { @@ -11,7 +15,6 @@ static const uint8_t EncodingAlphabet[64] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'}; /** The table used to convert an ascii character into a 6 bit value */ -#if 0 static const uint8_t DecodingAlphabet[256] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x00-0x0f 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x10-0x1f @@ -30,7 +33,6 @@ static const uint8_t DecodingAlphabet[256] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xe0-0xef 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF // 0xf0-0xff }; -#endif // 0 template uint32_t @@ -104,4 +106,190 @@ Base64::Encode(const uint8_t* Source, uint32_t Length, CharType* Dest) template uint32_t Base64::Encode(const uint8_t* Source, uint32_t Length, char* Dest); template uint32_t Base64::Encode(const uint8_t* Source, uint32_t Length, wchar_t* Dest); +template +bool +Base64::Decode(const CharType* Source, uint32_t Length, uint8_t* Dest, uint32_t& OutLength) +{ + // Length must be a multiple of 4 + if (Length % 4 != 0) + { + OutLength = 0; + return false; + } + + uint8_t* DecodedBytes = Dest; + + // Process 4 encoded characters at a time, producing 3 decoded bytes + while (Length > 0) + { + // Count padding characters at the end + uint32_t PadCount = 0; + if (Source[3] == '=') + { + PadCount++; + if (Source[2] == '=') + { + PadCount++; + } + } + + // Look up each character in the decoding table + uint8_t A = DecodingAlphabet[static_cast(Source[0])]; + uint8_t B = DecodingAlphabet[static_cast(Source[1])]; + uint8_t C = (PadCount >= 2) ? 0 : DecodingAlphabet[static_cast(Source[2])]; + uint8_t D = (PadCount >= 1) ? 0 : DecodingAlphabet[static_cast(Source[3])]; + + // Check for invalid characters (0xFF means not in the base64 alphabet) + if (A == 0xFF || B == 0xFF || C == 0xFF || D == 0xFF) + { + OutLength = 0; + return false; + } + + // Reconstruct the 24-bit value from 4 6-bit chunks + uint32_t ByteTriplet = (A << 18) | (B << 12) | (C << 6) | D; + + // Extract the 3 bytes + *DecodedBytes++ = static_cast(ByteTriplet >> 16); + if (PadCount < 2) + { + *DecodedBytes++ = static_cast((ByteTriplet >> 8) & 0xFF); + } + if (PadCount < 1) + { + *DecodedBytes++ = static_cast(ByteTriplet & 0xFF); + } + + Source += 4; + Length -= 4; + } + + OutLength = uint32_t(DecodedBytes - Dest); + return true; +} + +template bool Base64::Decode(const char* Source, uint32_t Length, uint8_t* Dest, uint32_t& OutLength); +template bool Base64::Decode(const wchar_t* Source, uint32_t Length, uint8_t* Dest, uint32_t& OutLength); + +////////////////////////////////////////////////////////////////////////// +// +// Testing related code follows... +// + +#if ZEN_WITH_TESTS + +using namespace std::string_literals; + +TEST_CASE("Base64") +{ + auto EncodeString = [](std::string_view Input) -> std::string { + std::string Result; + Result.resize(Base64::GetEncodedDataSize(uint32_t(Input.size()))); + Base64::Encode(reinterpret_cast(Input.data()), uint32_t(Input.size()), Result.data()); + return Result; + }; + + auto DecodeString = [](std::string_view Input) -> std::string { + std::string Result; + Result.resize(Base64::GetMaxDecodedDataSize(uint32_t(Input.size()))); + uint32_t DecodedLength = 0; + bool Success = Base64::Decode(Input.data(), uint32_t(Input.size()), reinterpret_cast(Result.data()), DecodedLength); + CHECK(Success); + Result.resize(DecodedLength); + return Result; + }; + + SUBCASE("Encode") + { + CHECK(EncodeString("") == ""s); + CHECK(EncodeString("f") == "Zg=="s); + CHECK(EncodeString("fo") == "Zm8="s); + CHECK(EncodeString("foo") == "Zm9v"s); + CHECK(EncodeString("foob") == "Zm9vYg=="s); + CHECK(EncodeString("fooba") == "Zm9vYmE="s); + CHECK(EncodeString("foobar") == "Zm9vYmFy"s); + } + + SUBCASE("Decode") + { + CHECK(DecodeString("") == ""s); + CHECK(DecodeString("Zg==") == "f"s); + CHECK(DecodeString("Zm8=") == "fo"s); + CHECK(DecodeString("Zm9v") == "foo"s); + CHECK(DecodeString("Zm9vYg==") == "foob"s); + CHECK(DecodeString("Zm9vYmE=") == "fooba"s); + CHECK(DecodeString("Zm9vYmFy") == "foobar"s); + } + + SUBCASE("RoundTrip") + { + auto RoundTrip = [&](const std::string& Input) { + std::string Encoded = EncodeString(Input); + std::string Decoded = DecodeString(Encoded); + CHECK(Decoded == Input); + }; + + RoundTrip("Hello, World!"); + RoundTrip("Base64 encoding test with various lengths"); + RoundTrip("A"); + RoundTrip("AB"); + RoundTrip("ABC"); + RoundTrip("ABCD"); + RoundTrip("\x00\x01\x02\xff\xfe\xfd"s); + } + + SUBCASE("BinaryRoundTrip") + { + // Test with all byte values 0-255 + uint8_t AllBytes[256]; + for (int i = 0; i < 256; ++i) + { + AllBytes[i] = static_cast(i); + } + + char Encoded[Base64::GetEncodedDataSize(256) + 1]; + Base64::Encode(AllBytes, 256, Encoded); + + uint8_t Decoded[256]; + uint32_t DecodedLength = 0; + bool Success = Base64::Decode(Encoded, uint32_t(strlen(Encoded)), Decoded, DecodedLength); + CHECK(Success); + CHECK(DecodedLength == 256); + CHECK(memcmp(AllBytes, Decoded, 256) == 0); + } + + SUBCASE("DecodeInvalidInput") + { + uint8_t Dest[64]; + uint32_t OutLength = 0; + + // Length not a multiple of 4 + CHECK_FALSE(Base64::Decode("abc", 3u, Dest, OutLength)); + + // Invalid character + CHECK_FALSE(Base64::Decode("ab!d", 4u, Dest, OutLength)); + } + + SUBCASE("EncodedDataSize") + { + CHECK(Base64::GetEncodedDataSize(0) == 0); + CHECK(Base64::GetEncodedDataSize(1) == 4); + CHECK(Base64::GetEncodedDataSize(2) == 4); + CHECK(Base64::GetEncodedDataSize(3) == 4); + CHECK(Base64::GetEncodedDataSize(4) == 8); + CHECK(Base64::GetEncodedDataSize(5) == 8); + CHECK(Base64::GetEncodedDataSize(6) == 8); + } + + SUBCASE("MaxDecodedDataSize") + { + CHECK(Base64::GetMaxDecodedDataSize(0) == 0); + CHECK(Base64::GetMaxDecodedDataSize(4) == 3); + CHECK(Base64::GetMaxDecodedDataSize(8) == 6); + CHECK(Base64::GetMaxDecodedDataSize(12) == 9); + } +} + +#endif + } // namespace zen diff --git a/src/zencore/include/zencore/base64.h b/src/zencore/include/zencore/base64.h index 4d78b085f..08d9f3043 100644 --- a/src/zencore/include/zencore/base64.h +++ b/src/zencore/include/zencore/base64.h @@ -11,7 +11,11 @@ struct Base64 template static uint32_t Encode(const uint8_t* Source, uint32_t Length, CharType* Dest); + template + static bool Decode(const CharType* Source, uint32_t Length, uint8_t* Dest, uint32_t& OutLength); + static inline constexpr int32_t GetEncodedDataSize(uint32_t Size) { return ((Size + 2) / 3) * 4; } + static inline constexpr int32_t GetMaxDecodedDataSize(uint32_t Length) { return (Length / 4) * 3; } }; } // namespace zen -- cgit v1.2.3 From 01445315564ab527566ec200e0182d8968a80d6f Mon Sep 17 00:00:00 2001 From: Stefan Boberg Date: Mon, 23 Feb 2026 11:09:11 +0100 Subject: changed command names and descriptions to use class members instead of string literals in zen.cpp (#776) --- src/zen/cmds/admin_cmd.h | 40 +++++++++++++++---- src/zen/cmds/bench_cmd.h | 5 ++- src/zen/cmds/cache_cmd.h | 20 ++++++++-- src/zen/cmds/copy_cmd.h | 5 ++- src/zen/cmds/dedup_cmd.h | 5 ++- src/zen/cmds/info_cmd.h | 5 ++- src/zen/cmds/print_cmd.h | 10 ++++- src/zen/cmds/projectstore_cmd.h | 58 ++++++++++++++++++++------- src/zen/cmds/rpcreplay_cmd.h | 15 +++++-- src/zen/cmds/run_cmd.h | 5 ++- src/zen/cmds/serve_cmd.h | 5 ++- src/zen/cmds/status_cmd.h | 5 ++- src/zen/cmds/top_cmd.h | 10 ++++- src/zen/cmds/trace_cmd.h | 7 ++-- src/zen/cmds/up_cmd.h | 15 +++++-- src/zen/cmds/vfs_cmd.h | 5 ++- src/zen/zen.cpp | 86 ++++++++++++++++++++--------------------- 17 files changed, 211 insertions(+), 90 deletions(-) diff --git a/src/zen/cmds/admin_cmd.h b/src/zen/cmds/admin_cmd.h index 87ef8091b..83bcf8893 100644 --- a/src/zen/cmds/admin_cmd.h +++ b/src/zen/cmds/admin_cmd.h @@ -13,6 +13,9 @@ namespace zen { class ScrubCommand : public StorageCommand { public: + static constexpr char Name[] = "scrub"; + static constexpr char Description[] = "Scrub zen storage (verify data integrity)"; + ScrubCommand(); ~ScrubCommand(); @@ -20,7 +23,7 @@ public: virtual cxxopts::Options& Options() override { return m_Options; } private: - cxxopts::Options m_Options{"scrub", "Scrub zen storage"}; + cxxopts::Options m_Options{Name, Description}; std::string m_HostName; bool m_DryRun = false; bool m_NoGc = false; @@ -33,6 +36,9 @@ private: class GcCommand : public StorageCommand { public: + static constexpr char Name[] = "gc"; + static constexpr char Description[] = "Garbage collect zen storage"; + GcCommand(); ~GcCommand(); @@ -40,7 +46,7 @@ public: virtual cxxopts::Options& Options() override { return m_Options; } private: - cxxopts::Options m_Options{"gc", "Garbage collect zen storage"}; + cxxopts::Options m_Options{Name, Description}; std::string m_HostName; bool m_SmallObjects{false}; bool m_SkipCid{false}; @@ -62,6 +68,9 @@ private: class GcStatusCommand : public StorageCommand { public: + static constexpr char Name[] = "gc-status"; + static constexpr char Description[] = "Garbage collect zen storage status check"; + GcStatusCommand(); ~GcStatusCommand(); @@ -69,7 +78,7 @@ public: virtual cxxopts::Options& Options() override { return m_Options; } private: - cxxopts::Options m_Options{"gc-status", "Garbage collect zen storage status check"}; + cxxopts::Options m_Options{Name, Description}; std::string m_HostName; bool m_Details = false; }; @@ -77,6 +86,9 @@ private: class GcStopCommand : public StorageCommand { public: + static constexpr char Name[] = "gc-stop"; + static constexpr char Description[] = "Request cancel of running garbage collection in zen storage"; + GcStopCommand(); ~GcStopCommand(); @@ -84,7 +96,7 @@ public: virtual cxxopts::Options& Options() override { return m_Options; } private: - cxxopts::Options m_Options{"gc-stop", "Request cancel of running garbage collection in zen storage"}; + cxxopts::Options m_Options{Name, Description}; std::string m_HostName; }; @@ -93,6 +105,9 @@ private: class JobCommand : public ZenCmdBase { public: + static constexpr char Name[] = "jobs"; + static constexpr char Description[] = "Show/cancel zen background jobs"; + JobCommand(); ~JobCommand(); @@ -100,7 +115,7 @@ public: virtual cxxopts::Options& Options() override { return m_Options; } private: - cxxopts::Options m_Options{"jobs", "Show/cancel zen background jobs"}; + cxxopts::Options m_Options{Name, Description}; std::string m_HostName; std::uint64_t m_JobId = 0; bool m_Cancel = 0; @@ -111,6 +126,9 @@ private: class LoggingCommand : public ZenCmdBase { public: + static constexpr char Name[] = "logs"; + static constexpr char Description[] = "Show/control zen logging"; + LoggingCommand(); ~LoggingCommand(); @@ -118,7 +136,7 @@ public: virtual cxxopts::Options& Options() override { return m_Options; } private: - cxxopts::Options m_Options{"logs", "Show/control zen logging"}; + cxxopts::Options m_Options{Name, Description}; std::string m_HostName; std::string m_CacheWriteLog; std::string m_CacheAccessLog; @@ -133,6 +151,9 @@ private: class FlushCommand : public StorageCommand { public: + static constexpr char Name[] = "flush"; + static constexpr char Description[] = "Flush storage"; + FlushCommand(); ~FlushCommand(); @@ -140,7 +161,7 @@ public: virtual cxxopts::Options& Options() override { return m_Options; } private: - cxxopts::Options m_Options{"flush", "Flush zen storage"}; + cxxopts::Options m_Options{Name, Description}; std::string m_HostName; }; @@ -149,6 +170,9 @@ private: class CopyStateCommand : public StorageCommand { public: + static constexpr char Name[] = "copy-state"; + static constexpr char Description[] = "Copy zen server disk state"; + CopyStateCommand(); ~CopyStateCommand(); @@ -156,7 +180,7 @@ public: virtual cxxopts::Options& Options() override { return m_Options; } private: - cxxopts::Options m_Options{"copy-state", "Copy zen server disk state"}; + cxxopts::Options m_Options{Name, Description}; std::filesystem::path m_DataPath; std::filesystem::path m_TargetPath; bool m_SkipLogs = false; diff --git a/src/zen/cmds/bench_cmd.h b/src/zen/cmds/bench_cmd.h index ed123be75..7fbf85340 100644 --- a/src/zen/cmds/bench_cmd.h +++ b/src/zen/cmds/bench_cmd.h @@ -9,6 +9,9 @@ namespace zen { class BenchCommand : public ZenCmdBase { public: + static constexpr char Name[] = "bench"; + static constexpr char Description[] = "Utility command for benchmarking"; + BenchCommand(); ~BenchCommand(); @@ -17,7 +20,7 @@ public: virtual ZenCmdCategory& CommandCategory() const override { return g_UtilitiesCategory; } private: - cxxopts::Options m_Options{"bench", "Benchmarking utility command"}; + cxxopts::Options m_Options{Name, Description}; bool m_PurgeStandbyLists = false; bool m_SingleProcess = false; }; diff --git a/src/zen/cmds/cache_cmd.h b/src/zen/cmds/cache_cmd.h index 4dc05bbdc..4f5b90f4d 100644 --- a/src/zen/cmds/cache_cmd.h +++ b/src/zen/cmds/cache_cmd.h @@ -9,6 +9,9 @@ namespace zen { class DropCommand : public CacheStoreCommand { public: + static constexpr char Name[] = "drop"; + static constexpr char Description[] = "Drop cache namespace or bucket"; + DropCommand(); ~DropCommand(); @@ -16,7 +19,7 @@ public: virtual cxxopts::Options& Options() override { return m_Options; } private: - cxxopts::Options m_Options{"drop", "Drop cache namespace or bucket"}; + cxxopts::Options m_Options{Name, Description}; std::string m_HostName; std::string m_NamespaceName; std::string m_BucketName; @@ -25,13 +28,16 @@ private: class CacheInfoCommand : public CacheStoreCommand { public: + static constexpr char Name[] = "cache-info"; + static constexpr char Description[] = "Info on cache, namespace or bucket"; + CacheInfoCommand(); ~CacheInfoCommand(); virtual void Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) override; virtual cxxopts::Options& Options() override { return m_Options; } private: - cxxopts::Options m_Options{"cache-info", "Info on cache, namespace or bucket"}; + cxxopts::Options m_Options{Name, Description}; std::string m_HostName; std::string m_NamespaceName; std::string m_SizeInfoBucketNames; @@ -42,26 +48,32 @@ private: class CacheStatsCommand : public CacheStoreCommand { public: + static constexpr char Name[] = "cache-stats"; + static constexpr char Description[] = "Stats on cache"; + CacheStatsCommand(); ~CacheStatsCommand(); virtual void Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) override; virtual cxxopts::Options& Options() override { return m_Options; } private: - cxxopts::Options m_Options{"cache-stats", "Stats info on cache"}; + cxxopts::Options m_Options{Name, Description}; std::string m_HostName; }; class CacheDetailsCommand : public CacheStoreCommand { public: + static constexpr char Name[] = "cache-details"; + static constexpr char Description[] = "Details on cache"; + CacheDetailsCommand(); ~CacheDetailsCommand(); virtual void Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) override; virtual cxxopts::Options& Options() override { return m_Options; } private: - cxxopts::Options m_Options{"cache-details", "Detailed info on cache"}; + cxxopts::Options m_Options{Name, Description}; std::string m_HostName; bool m_CSV = false; bool m_Details = false; diff --git a/src/zen/cmds/copy_cmd.h b/src/zen/cmds/copy_cmd.h index e1a5dcb82..757a8e691 100644 --- a/src/zen/cmds/copy_cmd.h +++ b/src/zen/cmds/copy_cmd.h @@ -11,6 +11,9 @@ namespace zen { class CopyCommand : public ZenCmdBase { public: + static constexpr char Name[] = "copy"; + static constexpr char Description[] = "Copy file(s)"; + CopyCommand(); ~CopyCommand(); @@ -19,7 +22,7 @@ public: virtual ZenCmdCategory& CommandCategory() const override { return g_UtilitiesCategory; } private: - cxxopts::Options m_Options{"copy", "Copy files efficiently"}; + cxxopts::Options m_Options{Name, Description}; std::filesystem::path m_CopySource; std::filesystem::path m_CopyTarget; bool m_NoClone = false; diff --git a/src/zen/cmds/dedup_cmd.h b/src/zen/cmds/dedup_cmd.h index 5b8387dd2..835b35e92 100644 --- a/src/zen/cmds/dedup_cmd.h +++ b/src/zen/cmds/dedup_cmd.h @@ -11,6 +11,9 @@ namespace zen { class DedupCommand : public ZenCmdBase { public: + static constexpr char Name[] = "dedup"; + static constexpr char Description[] = "Dedup files"; + DedupCommand(); ~DedupCommand(); @@ -19,7 +22,7 @@ public: virtual ZenCmdCategory& CommandCategory() const override { return g_UtilitiesCategory; } private: - cxxopts::Options m_Options{"dedup", "Deduplicate files"}; + cxxopts::Options m_Options{Name, Description}; std::vector m_Positional; std::filesystem::path m_DedupSource; std::filesystem::path m_DedupTarget; diff --git a/src/zen/cmds/info_cmd.h b/src/zen/cmds/info_cmd.h index 231565bfd..dc108b8a2 100644 --- a/src/zen/cmds/info_cmd.h +++ b/src/zen/cmds/info_cmd.h @@ -9,6 +9,9 @@ namespace zen { class InfoCommand : public ZenCmdBase { public: + static constexpr char Name[] = "info"; + static constexpr char Description[] = "Show high level Zen server information"; + InfoCommand(); ~InfoCommand(); @@ -17,7 +20,7 @@ public: // virtual ZenCmdCategory& CommandCategory() const override { return g_UtilitiesCategory; } private: - cxxopts::Options m_Options{"info", "Show high level zen store information"}; + cxxopts::Options m_Options{Name, Description}; std::string m_HostName; }; diff --git a/src/zen/cmds/print_cmd.h b/src/zen/cmds/print_cmd.h index 6c1529b7c..f4a97e218 100644 --- a/src/zen/cmds/print_cmd.h +++ b/src/zen/cmds/print_cmd.h @@ -11,6 +11,9 @@ namespace zen { class PrintCommand : public ZenCmdBase { public: + static constexpr char Name[] = "print"; + static constexpr char Description[] = "Print compact binary object"; + PrintCommand(); ~PrintCommand(); @@ -19,7 +22,7 @@ public: virtual ZenCmdCategory& CommandCategory() const override { return g_UtilitiesCategory; } private: - cxxopts::Options m_Options{"print", "Print compact binary object"}; + cxxopts::Options m_Options{Name, Description}; std::filesystem::path m_Filename; bool m_ShowCbObjectTypeInfo = false; }; @@ -29,6 +32,9 @@ private: class PrintPackageCommand : public ZenCmdBase { public: + static constexpr char Name[] = "printpackage"; + static constexpr char Description[] = "Print compact binary package"; + PrintPackageCommand(); ~PrintPackageCommand(); @@ -37,7 +43,7 @@ public: virtual ZenCmdCategory& CommandCategory() const override { return g_UtilitiesCategory; } private: - cxxopts::Options m_Options{"printpkg", "Print compact binary package"}; + cxxopts::Options m_Options{Name, Description}; std::filesystem::path m_Filename; bool m_ShowCbObjectTypeInfo = false; }; diff --git a/src/zen/cmds/projectstore_cmd.h b/src/zen/cmds/projectstore_cmd.h index 56ef858f5..e415b41b7 100644 --- a/src/zen/cmds/projectstore_cmd.h +++ b/src/zen/cmds/projectstore_cmd.h @@ -16,6 +16,9 @@ class ProjectStoreCommand : public ZenCmdBase class DropProjectCommand : public ProjectStoreCommand { public: + static constexpr char Name[] = "project-drop"; + static constexpr char Description[] = "Drop project or project oplog"; + DropProjectCommand(); ~DropProjectCommand(); @@ -23,7 +26,7 @@ public: virtual cxxopts::Options& Options() override { return m_Options; } private: - cxxopts::Options m_Options{"project-drop", "Drop project or project oplog"}; + cxxopts::Options m_Options{Name, Description}; std::string m_HostName; std::string m_ProjectName; std::string m_OplogName; @@ -33,13 +36,16 @@ private: class ProjectInfoCommand : public ProjectStoreCommand { public: + static constexpr char Name[] = "project-info"; + static constexpr char Description[] = "Info on project or project oplog"; + ProjectInfoCommand(); ~ProjectInfoCommand(); virtual void Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) override; virtual cxxopts::Options& Options() override { return m_Options; } private: - cxxopts::Options m_Options{"project-info", "Info on project or project oplog"}; + cxxopts::Options m_Options{Name, Description}; std::string m_HostName; std::string m_ProjectName; std::string m_OplogName; @@ -48,6 +54,9 @@ private: class CreateProjectCommand : public ProjectStoreCommand { public: + static constexpr char Name[] = "project-create"; + static constexpr char Description[] = "Create a project"; + CreateProjectCommand(); ~CreateProjectCommand(); @@ -55,7 +64,7 @@ public: virtual cxxopts::Options& Options() override { return m_Options; } private: - cxxopts::Options m_Options{"project-create", "Create project, the project must not already exist."}; + cxxopts::Options m_Options{Name, Description}; std::string m_HostName; std::string m_ProjectId; std::string m_RootDir; @@ -68,6 +77,9 @@ private: class CreateOplogCommand : public ProjectStoreCommand { public: + static constexpr char Name[] = "oplog-create"; + static constexpr char Description[] = "Create a project oplog"; + CreateOplogCommand(); ~CreateOplogCommand(); @@ -75,7 +87,7 @@ public: virtual cxxopts::Options& Options() override { return m_Options; } private: - cxxopts::Options m_Options{"oplog-create", "Create oplog in an existing project, the oplog must not already exist."}; + cxxopts::Options m_Options{Name, Description}; std::string m_HostName; std::string m_ProjectId; std::string m_OplogId; @@ -86,6 +98,9 @@ private: class ExportOplogCommand : public ProjectStoreCommand { public: + static constexpr char Name[] = "oplog-export"; + static constexpr char Description[] = "Export project store oplog"; + ExportOplogCommand(); ~ExportOplogCommand(); @@ -93,8 +108,7 @@ public: virtual cxxopts::Options& Options() override { return m_Options; } private: - cxxopts::Options m_Options{"oplog-export", - "Export project store oplog to cloud (--cloud), file system (--file) or other Zen instance (--zen)"}; + cxxopts::Options m_Options{Name, Description}; std::string m_HostName; std::string m_ProjectName; std::string m_OplogName; @@ -145,6 +159,9 @@ private: class ImportOplogCommand : public ProjectStoreCommand { public: + static constexpr char Name[] = "oplog-import"; + static constexpr char Description[] = "Import project store oplog"; + ImportOplogCommand(); ~ImportOplogCommand(); @@ -152,8 +169,7 @@ public: virtual cxxopts::Options& Options() override { return m_Options; } private: - cxxopts::Options m_Options{"oplog-import", - "Import project store oplog from cloud (--cloud), file system (--file) or other Zen instance (--zen)"}; + cxxopts::Options m_Options{Name, Description}; std::string m_HostName; std::string m_ProjectName; std::string m_OplogName; @@ -198,14 +214,16 @@ private: class SnapshotOplogCommand : public ProjectStoreCommand { public: + static constexpr char Name[] = "oplog-snapshot"; + static constexpr char Description[] = "Snapshot project store oplog"; + SnapshotOplogCommand(); ~SnapshotOplogCommand(); - virtual void Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) override; virtual cxxopts::Options& Options() override { return m_Options; } private: - cxxopts::Options m_Options{"oplog-snapshot", "Snapshot external file references in project store oplog into zen"}; + cxxopts::Options m_Options{Name, Description}; std::string m_HostName; std::string m_ProjectName; std::string m_OplogName; @@ -214,26 +232,32 @@ private: class ProjectStatsCommand : public ProjectStoreCommand { public: + static constexpr char Name[] = "project-stats"; + static constexpr char Description[] = "Stats on project store"; + ProjectStatsCommand(); ~ProjectStatsCommand(); virtual void Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) override; virtual cxxopts::Options& Options() override { return m_Options; } private: - cxxopts::Options m_Options{"project-stats", "Stats info on project store"}; + cxxopts::Options m_Options{Name, Description}; std::string m_HostName; }; class ProjectOpDetailsCommand : public ProjectStoreCommand { public: + static constexpr char Name[] = "project-op-details"; + static constexpr char Description[] = "Detail info on ops inside a project store oplog"; + ProjectOpDetailsCommand(); ~ProjectOpDetailsCommand(); virtual void Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) override; virtual cxxopts::Options& Options() override { return m_Options; } private: - cxxopts::Options m_Options{"project-op-details", "Detail info on ops inside a project store oplog"}; + cxxopts::Options m_Options{Name, Description}; std::string m_HostName; bool m_Details = false; bool m_OpDetails = false; @@ -247,13 +271,16 @@ private: class OplogMirrorCommand : public ProjectStoreCommand { public: + static constexpr char Name[] = "oplog-mirror"; + static constexpr char Description[] = "Mirror project store oplog to file system"; + OplogMirrorCommand(); ~OplogMirrorCommand(); virtual void Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) override; virtual cxxopts::Options& Options() override { return m_Options; } private: - cxxopts::Options m_Options{"oplog-mirror", "Mirror oplog to file system"}; + cxxopts::Options m_Options{Name, Description}; std::string m_HostName; std::string m_ProjectName; std::string m_OplogName; @@ -268,13 +295,16 @@ private: class OplogValidateCommand : public ProjectStoreCommand { public: + static constexpr char Name[] = "oplog-validate"; + static constexpr char Description[] = "Validate oplog for missing references"; + OplogValidateCommand(); ~OplogValidateCommand(); virtual void Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) override; virtual cxxopts::Options& Options() override { return m_Options; } private: - cxxopts::Options m_Options{"oplog-validate", "Validate oplog for missing references"}; + cxxopts::Options m_Options{Name, Description}; std::string m_HostName; std::string m_ProjectName; std::string m_OplogName; diff --git a/src/zen/cmds/rpcreplay_cmd.h b/src/zen/cmds/rpcreplay_cmd.h index a6363b614..332a3126c 100644 --- a/src/zen/cmds/rpcreplay_cmd.h +++ b/src/zen/cmds/rpcreplay_cmd.h @@ -9,6 +9,9 @@ namespace zen { class RpcStartRecordingCommand : public CacheStoreCommand { public: + static constexpr char Name[] = "rpc-record-start"; + static constexpr char Description[] = "Starts recording of cache rpc requests on a host"; + RpcStartRecordingCommand(); ~RpcStartRecordingCommand(); @@ -16,7 +19,7 @@ public: virtual cxxopts::Options& Options() override { return m_Options; } private: - cxxopts::Options m_Options{"rpc-record-start", "Starts recording of cache rpc requests on a host"}; + cxxopts::Options m_Options{Name, Description}; std::string m_HostName; std::string m_RecordingPath; }; @@ -24,6 +27,9 @@ private: class RpcStopRecordingCommand : public CacheStoreCommand { public: + static constexpr char Name[] = "rpc-record-stop"; + static constexpr char Description[] = "Stops recording of cache rpc requests on a host"; + RpcStopRecordingCommand(); ~RpcStopRecordingCommand(); @@ -31,13 +37,16 @@ public: virtual cxxopts::Options& Options() override { return m_Options; } private: - cxxopts::Options m_Options{"rpc-record-stop", "Stops recording of cache rpc requests on a host"}; + cxxopts::Options m_Options{Name, Description}; std::string m_HostName; }; class RpcReplayCommand : public CacheStoreCommand { public: + static constexpr char Name[] = "rpc-record-replay"; + static constexpr char Description[] = "Replays a previously recorded session of rpc requests"; + RpcReplayCommand(); ~RpcReplayCommand(); @@ -45,7 +54,7 @@ public: virtual cxxopts::Options& Options() override { return m_Options; } private: - cxxopts::Options m_Options{"rpc-record-replay", "Replays a previously recorded session of cache rpc requests to a target host"}; + cxxopts::Options m_Options{Name, Description}; std::string m_HostName; std::string m_RecordingPath; bool m_OnHost = false; diff --git a/src/zen/cmds/run_cmd.h b/src/zen/cmds/run_cmd.h index 570a2e63a..300c08c5b 100644 --- a/src/zen/cmds/run_cmd.h +++ b/src/zen/cmds/run_cmd.h @@ -9,6 +9,9 @@ namespace zen { class RunCommand : public ZenCmdBase { public: + static constexpr char Name[] = "run"; + static constexpr char Description[] = "Run command with special options"; + RunCommand(); ~RunCommand(); @@ -17,7 +20,7 @@ public: virtual ZenCmdCategory& CommandCategory() const override { return g_UtilitiesCategory; } private: - cxxopts::Options m_Options{"run", "Run executable"}; + cxxopts::Options m_Options{Name, Description}; int m_RunCount = 0; int m_RunTime = -1; std::string m_BaseDirectory; diff --git a/src/zen/cmds/serve_cmd.h b/src/zen/cmds/serve_cmd.h index ac74981f2..22f430948 100644 --- a/src/zen/cmds/serve_cmd.h +++ b/src/zen/cmds/serve_cmd.h @@ -11,6 +11,9 @@ namespace zen { class ServeCommand : public ZenCmdBase { public: + static constexpr char Name[] = "serve"; + static constexpr char Description[] = "Serve files from a directory"; + ServeCommand(); ~ServeCommand(); @@ -18,7 +21,7 @@ public: virtual cxxopts::Options& Options() override { return m_Options; } private: - cxxopts::Options m_Options{"serve", "Serve files from a tree"}; + cxxopts::Options m_Options{Name, Description}; std::string m_HostName; std::string m_ProjectName; std::string m_OplogName; diff --git a/src/zen/cmds/status_cmd.h b/src/zen/cmds/status_cmd.h index dc103a196..df5df3066 100644 --- a/src/zen/cmds/status_cmd.h +++ b/src/zen/cmds/status_cmd.h @@ -11,6 +11,9 @@ namespace zen { class StatusCommand : public ZenCmdBase { public: + static constexpr char Name[] = "status"; + static constexpr char Description[] = "Show zen status"; + StatusCommand(); ~StatusCommand(); @@ -20,7 +23,7 @@ public: private: int GetLockFileEffectivePort() const; - cxxopts::Options m_Options{"status", "Show zen status"}; + cxxopts::Options m_Options{Name, Description}; uint16_t m_Port = 0; std::filesystem::path m_DataDir; }; diff --git a/src/zen/cmds/top_cmd.h b/src/zen/cmds/top_cmd.h index 74167ecfd..aeb196558 100644 --- a/src/zen/cmds/top_cmd.h +++ b/src/zen/cmds/top_cmd.h @@ -9,6 +9,9 @@ namespace zen { class TopCommand : public ZenCmdBase { public: + static constexpr char Name[] = "top"; + static constexpr char Description[] = "Monitor zen server activity"; + TopCommand(); ~TopCommand(); @@ -16,12 +19,15 @@ public: virtual cxxopts::Options& Options() override { return m_Options; } private: - cxxopts::Options m_Options{"top", "Show dev UI"}; + cxxopts::Options m_Options{Name, Description}; }; class PsCommand : public ZenCmdBase { public: + static constexpr char Name[] = "ps"; + static constexpr char Description[] = "Enumerate running zen server instances"; + PsCommand(); ~PsCommand(); @@ -29,7 +35,7 @@ public: virtual cxxopts::Options& Options() override { return m_Options; } private: - cxxopts::Options m_Options{"ps", "Enumerate running Zen server instances"}; + cxxopts::Options m_Options{Name, Description}; }; } // namespace zen diff --git a/src/zen/cmds/trace_cmd.h b/src/zen/cmds/trace_cmd.h index a6c9742b7..6eb0ba22b 100644 --- a/src/zen/cmds/trace_cmd.h +++ b/src/zen/cmds/trace_cmd.h @@ -6,11 +6,12 @@ namespace zen { -/** Scrub storage - */ class TraceCommand : public ZenCmdBase { public: + static constexpr char Name[] = "trace"; + static constexpr char Description[] = "Control zen realtime tracing"; + TraceCommand(); ~TraceCommand(); @@ -18,7 +19,7 @@ public: virtual cxxopts::Options& Options() override { return m_Options; } private: - cxxopts::Options m_Options{"trace", "Control zen realtime tracing"}; + cxxopts::Options m_Options{Name, Description}; std::string m_HostName; bool m_Stop = false; std::string m_TraceHost; diff --git a/src/zen/cmds/up_cmd.h b/src/zen/cmds/up_cmd.h index 2e822d5fc..270db7f88 100644 --- a/src/zen/cmds/up_cmd.h +++ b/src/zen/cmds/up_cmd.h @@ -11,6 +11,9 @@ namespace zen { class UpCommand : public ZenCmdBase { public: + static constexpr char Name[] = "up"; + static constexpr char Description[] = "Bring zen server up"; + UpCommand(); ~UpCommand(); @@ -18,7 +21,7 @@ public: virtual cxxopts::Options& Options() override { return m_Options; } private: - cxxopts::Options m_Options{"up", "Bring up zen service"}; + cxxopts::Options m_Options{Name, Description}; uint16_t m_Port = 0; bool m_ShowConsole = false; bool m_ShowLog = false; @@ -28,6 +31,9 @@ private: class AttachCommand : public ZenCmdBase { public: + static constexpr char Name[] = "attach"; + static constexpr char Description[] = "Add a sponsor process to a running zen service"; + AttachCommand(); ~AttachCommand(); @@ -35,7 +41,7 @@ public: virtual cxxopts::Options& Options() override { return m_Options; } private: - cxxopts::Options m_Options{"attach", "Add a sponsor process to a running zen service"}; + cxxopts::Options m_Options{Name, Description}; uint16_t m_Port = 0; int m_OwnerPid = 0; std::filesystem::path m_DataDir; @@ -44,6 +50,9 @@ private: class DownCommand : public ZenCmdBase { public: + static constexpr char Name[] = "down"; + static constexpr char Description[] = "Bring zen server down"; + DownCommand(); ~DownCommand(); @@ -51,7 +60,7 @@ public: virtual cxxopts::Options& Options() override { return m_Options; } private: - cxxopts::Options m_Options{"down", "Bring down zen service"}; + cxxopts::Options m_Options{Name, Description}; uint16_t m_Port = 0; bool m_ForceTerminate = false; std::filesystem::path m_ProgramBaseDir; diff --git a/src/zen/cmds/vfs_cmd.h b/src/zen/cmds/vfs_cmd.h index 5deaa02fa..9009c774b 100644 --- a/src/zen/cmds/vfs_cmd.h +++ b/src/zen/cmds/vfs_cmd.h @@ -9,6 +9,9 @@ namespace zen { class VfsCommand : public StorageCommand { public: + static constexpr char Name[] = "vfs"; + static constexpr char Description[] = "Manage virtual file system"; + VfsCommand(); ~VfsCommand(); @@ -16,7 +19,7 @@ public: virtual cxxopts::Options& Options() override { return m_Options; } private: - cxxopts::Options m_Options{"vfs", "Manage virtual file system"}; + cxxopts::Options m_Options{Name, Description}; std::string m_Verb; std::string m_HostName; diff --git a/src/zen/zen.cpp b/src/zen/zen.cpp index 018f77738..bdc2b4003 100644 --- a/src/zen/zen.cpp +++ b/src/zen/zen.cpp @@ -379,56 +379,56 @@ main(int argc, char** argv) const char* CmdSummary; } Commands[] = { // clang-format off - {"attach", &AttachCmd, "Add a sponsor process to a running zen service"}, - {"bench", &BenchCmd, "Utility command for benchmarking"}, - {BuildsCommand::Name, &BuildsCmd, BuildsCommand::Description}, - {"cache-details", &CacheDetailsCmd, "Details on cache"}, - {"cache-info", &CacheInfoCmd, "Info on cache, namespace or bucket"}, + {AttachCommand::Name, &AttachCmd, AttachCommand::Description}, + {BenchCommand::Name, &BenchCmd, BenchCommand::Description}, + {BuildsCommand::Name, &BuildsCmd, BuildsCommand::Description}, + {CacheDetailsCommand::Name, &CacheDetailsCmd, CacheDetailsCommand::Description}, + {CacheInfoCommand::Name, &CacheInfoCmd, CacheInfoCommand::Description}, {CacheGetCommand::Name, &CacheGetCmd, CacheGetCommand::Description}, {CacheGenerateCommand::Name, &CacheGenerateCmd, CacheGenerateCommand::Description}, - {"cache-stats", &CacheStatsCmd, "Stats on cache"}, - {"copy", &CopyCmd, "Copy file(s)"}, - {"copy-state", &CopyStateCmd, "Copy zen server disk state"}, - {"dedup", &DedupCmd, "Dedup files"}, - {"down", &DownCmd, "Bring zen server down"}, - {"drop", &DropCmd, "Drop cache namespace or bucket"}, + {CacheStatsCommand::Name, &CacheStatsCmd, CacheStatsCommand::Description}, + {CopyCommand::Name, &CopyCmd, CopyCommand::Description}, + {CopyStateCommand::Name, &CopyStateCmd, CopyStateCommand::Description}, + {DedupCommand::Name, &DedupCmd, DedupCommand::Description}, + {DownCommand::Name, &DownCmd, DownCommand::Description}, + {DropCommand::Name, &DropCmd, DropCommand::Description}, #if ZEN_WITH_COMPUTE_SERVICES {ExecCommand::Name, &ExecCmd, ExecCommand::Description}, #endif - {"gc-status", &GcStatusCmd, "Garbage collect zen storage status check"}, - {"gc-stop", &GcStopCmd, "Request cancel of running garbage collection in zen storage"}, - {"gc", &GcCmd, "Garbage collect zen storage"}, - {"info", &InfoCmd, "Show high level Zen server information"}, - {"jobs", &JobCmd, "Show/cancel zen background jobs"}, - {"logs", &LoggingCmd, "Show/control zen logging"}, - {"oplog-create", &CreateOplogCmd, "Create a project oplog"}, - {"oplog-export", &ExportOplogCmd, "Export project store oplog"}, - {"oplog-import", &ImportOplogCmd, "Import project store oplog"}, - {"oplog-mirror", &OplogMirrorCmd, "Mirror project store oplog to file system"}, - {"oplog-snapshot", &SnapshotOplogCmd, "Snapshot project store oplog"}, + {GcStatusCommand::Name, &GcStatusCmd, GcStatusCommand::Description}, + {GcStopCommand::Name, &GcStopCmd, GcStopCommand::Description}, + {GcCommand::Name, &GcCmd, GcCommand::Description}, + {InfoCommand::Name, &InfoCmd, InfoCommand::Description}, + {JobCommand::Name, &JobCmd, JobCommand::Description}, + {LoggingCommand::Name, &LoggingCmd, LoggingCommand::Description}, + {CreateOplogCommand::Name, &CreateOplogCmd, CreateOplogCommand::Description}, + {ExportOplogCommand::Name, &ExportOplogCmd, ExportOplogCommand::Description}, + {ImportOplogCommand::Name, &ImportOplogCmd, ImportOplogCommand::Description}, + {OplogMirrorCommand::Name, &OplogMirrorCmd, OplogMirrorCommand::Description}, + {SnapshotOplogCommand::Name, &SnapshotOplogCmd, SnapshotOplogCommand::Description}, {OplogDownloadCommand::Name, &OplogDownload, OplogDownloadCommand::Description}, - {"oplog-validate", &OplogValidateCmd, "Validate oplog for missing references"}, - {"print", &PrintCmd, "Print compact binary object"}, - {"printpackage", &PrintPkgCmd, "Print compact binary package"}, - {"project-create", &CreateProjectCmd, "Create a project"}, - {"project-op-details", &ProjectOpDetailsCmd, "Detail info on ops inside a project store oplog"}, - {"project-drop", &ProjectDropCmd, "Drop project or project oplog"}, - {"project-info", &ProjectInfoCmd, "Info on project or project oplog"}, - {"project-stats", &ProjectStatsCmd, "Stats on project store"}, - {"ps", &PsCmd, "Enumerate running zen server instances"}, - {"rpc-record-replay", &RpcReplayCmd, "Replays a previously recorded session of rpc requests"}, - {"rpc-record-start", &RpcStartRecordingCmd, "Starts recording of cache rpc requests on a host"}, - {"rpc-record-stop", &RpcStopRecordingCmd, "Stops recording of cache rpc requests on a host"}, - {"run", &RunCmd, "Run command with special options"}, - {"scrub", &ScrubCmd, "Scrub zen storage (verify data integrity)"}, - {"serve", &ServeCmd, "Serve files from a directory"}, - {"status", &StatusCmd, "Show zen status"}, - {"top", &TopCmd, "Monitor zen server activity"}, - {"trace", &TraceCmd, "Control zen realtime tracing"}, - {"up", &UpCmd, "Bring zen server up"}, + {OplogValidateCommand::Name, &OplogValidateCmd, OplogValidateCommand::Description}, + {PrintCommand::Name, &PrintCmd, PrintCommand::Description}, + {PrintPackageCommand::Name, &PrintPkgCmd, PrintPackageCommand::Description}, + {CreateProjectCommand::Name, &CreateProjectCmd, CreateProjectCommand::Description}, + {ProjectOpDetailsCommand::Name, &ProjectOpDetailsCmd, ProjectOpDetailsCommand::Description}, + {DropProjectCommand::Name, &ProjectDropCmd, DropProjectCommand::Description}, + {ProjectInfoCommand::Name, &ProjectInfoCmd, ProjectInfoCommand::Description}, + {ProjectStatsCommand::Name, &ProjectStatsCmd, ProjectStatsCommand::Description}, + {PsCommand::Name, &PsCmd, PsCommand::Description}, + {RpcReplayCommand::Name, &RpcReplayCmd, RpcReplayCommand::Description}, + {RpcStartRecordingCommand::Name, &RpcStartRecordingCmd, RpcStartRecordingCommand::Description}, + {RpcStopRecordingCommand::Name, &RpcStopRecordingCmd, RpcStopRecordingCommand::Description}, + {RunCommand::Name, &RunCmd, RunCommand::Description}, + {ScrubCommand::Name, &ScrubCmd, ScrubCommand::Description}, + {ServeCommand::Name, &ServeCmd, ServeCommand::Description}, + {StatusCommand::Name, &StatusCmd, StatusCommand::Description}, + {TopCommand::Name, &TopCmd, TopCommand::Description}, + {TraceCommand::Name, &TraceCmd, TraceCommand::Description}, + {UpCommand::Name, &UpCmd, UpCommand::Description}, {VersionCommand::Name, &VersionCmd, VersionCommand::Description}, - {"vfs", &VfsCmd, "Manage virtual file system"}, - {"flush", &FlushCmd, "Flush storage"}, + {VfsCommand::Name, &VfsCmd, VfsCommand::Description}, + {FlushCommand::Name, &FlushCmd, FlushCommand::Description}, {WipeCommand::Name, &WipeCmd, WipeCommand::Description}, {WorkspaceCommand::Name, &WorkspaceCmd, WorkspaceCommand::Description}, {WorkspaceShareCommand::Name, &WorkspaceShareCmd, WorkspaceShareCommand::Description}, -- cgit v1.2.3 From 9aac0fd369b87e965fb34b5168646387de7ea1cd Mon Sep 17 00:00:00 2001 From: Stefan Boberg Date: Mon, 23 Feb 2026 11:19:52 +0100 Subject: implement yaml generation (#774) this implements a yaml generation strategy similar to the JSON generation where we just build a string instead of building a ryml tree. This also removes the dependency on ryml for reduced binary/build times. --- src/zencore/compactbinaryyaml.cpp | 427 +- src/zencore/xmake.lua | 2 - thirdparty/ryml/.github/codeql.yml | 3 - thirdparty/ryml/.github/release.sh | 127 - thirdparty/ryml/.github/reqs.sh | 315 - thirdparty/ryml/.github/setenv.sh | 434 -- thirdparty/ryml/.github/workflows/benchmarks.yml | 147 - thirdparty/ryml/.github/workflows/clang.yml | 262 - thirdparty/ryml/.github/workflows/clang_tidy.yml | 72 - thirdparty/ryml/.github/workflows/codeql.yml | 44 - thirdparty/ryml/.github/workflows/coverage.yml | 94 - thirdparty/ryml/.github/workflows/emscripten.yml | 71 - thirdparty/ryml/.github/workflows/gcc.yml | 168 - thirdparty/ryml/.github/workflows/install.yml | 105 - thirdparty/ryml/.github/workflows/macosx.yml | 103 - thirdparty/ryml/.github/workflows/rarearchs.yml | 123 - thirdparty/ryml/.github/workflows/release.yml | 366 -- thirdparty/ryml/.github/workflows/samples.yml | 60 - thirdparty/ryml/.github/workflows/windows.yml | 130 - thirdparty/ryml/.gitignore | 51 - thirdparty/ryml/.gitmodules | 3 - thirdparty/ryml/.lgtm.yml | 2 - thirdparty/ryml/CONTRIBUTING.md | 18 - thirdparty/ryml/LICENSE.txt | 20 - thirdparty/ryml/MANIFEST.in | 3 - thirdparty/ryml/README.md | 1136 ---- thirdparty/ryml/ROADMAP.md | 18 - thirdparty/ryml/api/python/.gitignore | 141 - thirdparty/ryml/api/python/Makefile | 94 - thirdparty/ryml/api/python/bm/bm_parse.py | 237 - thirdparty/ryml/api/python/requirements.txt | 5 - thirdparty/ryml/api/python/ryml/__init__.py | 2 - thirdparty/ryml/api/python/tests/test_parse.py | 488 -- thirdparty/ryml/api/ryml.i | 662 --- thirdparty/ryml/changelog/0.1.0.md | 44 - thirdparty/ryml/changelog/0.2.0.md | 29 - thirdparty/ryml/changelog/0.2.1.md | 235 - thirdparty/ryml/changelog/0.2.2.md | 1 - thirdparty/ryml/changelog/0.2.3.md | 285 - thirdparty/ryml/changelog/0.3.0.md | 104 - thirdparty/ryml/changelog/0.4.0.md | 229 - thirdparty/ryml/changelog/0.4.1.md | 3 - thirdparty/ryml/changelog/0.5.0.md | 174 - thirdparty/ryml/cmake/uninstall.cmake | 24 - thirdparty/ryml/compat.cmake | 11 - thirdparty/ryml/ext/c4core/.github/release.sh | 129 - thirdparty/ryml/ext/c4core/.github/reqs.sh | 314 - thirdparty/ryml/ext/c4core/.github/setenv.sh | 443 -- .../ryml/ext/c4core/.github/vagrant/Vagrantfile | 80 - .../ext/c4core/.github/vagrant/macos/Vagrantfile | 71 - .../c4core/.github/vagrant/vagrant-provision.sh | 71 - .../ryml/ext/c4core/.github/workflows/arch.yml | 116 - .../ext/c4core/.github/workflows/benchmarks.yml | 250 - .../ryml/ext/c4core/.github/workflows/clang.yml | 230 - .../ext/c4core/.github/workflows/clang_tidy.yml | 97 - .../ryml/ext/c4core/.github/workflows/codeql.yml | 43 - .../ryml/ext/c4core/.github/workflows/coverage.yml | 150 - .../ext/c4core/.github/workflows/emscripten.yml | 99 - .../ryml/ext/c4core/.github/workflows/gcc.yml | 181 - .../ryml/ext/c4core/.github/workflows/libcxx.yml | 111 - .../ryml/ext/c4core/.github/workflows/macosx.yml | 103 - .../ryml/ext/c4core/.github/workflows/release.yml | 197 - .../ext/c4core/.github/workflows/test_install.yml | 104 - .../ryml/ext/c4core/.github/workflows/windows.yml | 157 - thirdparty/ryml/ext/c4core/.gitignore | 34 - thirdparty/ryml/ext/c4core/.gitmodules | 9 - thirdparty/ryml/ext/c4core/LICENSE-BOOST.txt | 26 - thirdparty/ryml/ext/c4core/LICENSE.txt | 20 - thirdparty/ryml/ext/c4core/README.md | 381 -- thirdparty/ryml/ext/c4core/ROADMAP.md | 23 - thirdparty/ryml/ext/c4core/bm/bm.yml | 32 - thirdparty/ryml/ext/c4core/bm/bm_atox.cpp | 478 -- thirdparty/ryml/ext/c4core/bm/bm_charconv.cpp | 1617 ----- thirdparty/ryml/ext/c4core/bm/bm_charconv.hpp | 454 -- thirdparty/ryml/ext/c4core/bm/bm_format.cpp | 900 --- thirdparty/ryml/ext/c4core/bm/bm_itoa_threads.cpp | 356 -- thirdparty/ryml/ext/c4core/bm/bm_plot_c4core.py | 266 - thirdparty/ryml/ext/c4core/bm/bm_xtoa.cpp | 1538 ----- thirdparty/ryml/ext/c4core/bm/float/measure.py | 65 - thirdparty/ryml/ext/c4core/bm/float/read.cpp | 170 - thirdparty/ryml/ext/c4core/bm/ryu.cmake | 37 - thirdparty/ryml/ext/c4core/changelog/0.1.0.md | 3 - thirdparty/ryml/ext/c4core/changelog/0.1.1.md | 5 - thirdparty/ryml/ext/c4core/changelog/0.1.10.md | 106 - thirdparty/ryml/ext/c4core/changelog/0.1.11.md | 59 - thirdparty/ryml/ext/c4core/changelog/0.1.2.md | 4 - thirdparty/ryml/ext/c4core/changelog/0.1.3.md | 1 - thirdparty/ryml/ext/c4core/changelog/0.1.4.md | 6 - thirdparty/ryml/ext/c4core/changelog/0.1.5.md | 2 - thirdparty/ryml/ext/c4core/changelog/0.1.6.md | 2 - thirdparty/ryml/ext/c4core/changelog/0.1.7.md | 5 - thirdparty/ryml/ext/c4core/changelog/0.1.8.md | 45 - thirdparty/ryml/ext/c4core/changelog/0.1.9.md | 31 - thirdparty/ryml/ext/c4core/changelog/current.md | 0 thirdparty/ryml/ext/c4core/cmake/.gitignore | 1 - .../ryml/ext/c4core/cmake/ConfigurationTypes.cmake | 120 - .../ryml/ext/c4core/cmake/CreateSourceGroup.cmake | 31 - thirdparty/ryml/ext/c4core/cmake/Doxyfile.full.in | 2566 -------- thirdparty/ryml/ext/c4core/cmake/Doxyfile.in | 2566 -------- .../ext/c4core/cmake/ExternalProjectUtils.cmake | 215 - thirdparty/ryml/ext/c4core/cmake/FindD3D12.cmake | 75 - thirdparty/ryml/ext/c4core/cmake/FindDX12.cmake | 76 - thirdparty/ryml/ext/c4core/cmake/GetFlags.cmake | 53 - thirdparty/ryml/ext/c4core/cmake/GetNames.cmake | 51 - thirdparty/ryml/ext/c4core/cmake/LICENSE.txt | 20 - thirdparty/ryml/ext/c4core/cmake/PVS-Studio.cmake | 275 - thirdparty/ryml/ext/c4core/cmake/PatchUtils.cmake | 25 - thirdparty/ryml/ext/c4core/cmake/PrintVar.cmake | 27 - thirdparty/ryml/ext/c4core/cmake/README.md | 25 - .../ryml/ext/c4core/cmake/TargetArchitecture.cmake | 180 - .../ext/c4core/cmake/Toolchain-Arm-ubuntu.cmake | 29 - .../ryml/ext/c4core/cmake/Toolchain-Armv7.cmake | 84 - .../ryml/ext/c4core/cmake/Toolchain-PS4.cmake | 73 - .../ryml/ext/c4core/cmake/Toolchain-XBoxOne.cmake | 93 - .../ryml/ext/c4core/cmake/amalgamate_utils.py | 219 - thirdparty/ryml/ext/c4core/cmake/bm-xp/.gitignore | 1 - thirdparty/ryml/ext/c4core/cmake/bm-xp/README.md | 7 - thirdparty/ryml/ext/c4core/cmake/bm-xp/bm.js | 475 -- thirdparty/ryml/ext/c4core/cmake/bm-xp/bm_plot.py | 746 --- thirdparty/ryml/ext/c4core/cmake/bm-xp/bm_run.py | 248 - thirdparty/ryml/ext/c4core/cmake/bm-xp/bm_serve.py | 502 -- thirdparty/ryml/ext/c4core/cmake/bm-xp/bm_util.py | 147 - .../ryml/ext/c4core/cmake/bm-xp/example_c4core.py | 1061 ---- .../ryml/ext/c4core/cmake/bm-xp/example_mintm.py | 1061 ---- .../ryml/ext/c4core/cmake/bm-xp/requirements.txt | 14 - .../ext/c4core/cmake/bm-xp/template/index.html | 45 - .../ryml/ext/c4core/cmake/c4CatSources.cmake | 105 - thirdparty/ryml/ext/c4core/cmake/c4Doxygen.cmake | 121 - .../ryml/ext/c4core/cmake/c4DoxygenConfig.cmake | 24 - .../cmake/c4GetTargetPropertyRecursive.cmake | 186 - thirdparty/ryml/ext/c4core/cmake/c4Project.cmake | 3691 ------------ .../ryml/ext/c4core/cmake/c4SanitizeTarget.cmake | 292 - .../ryml/ext/c4core/cmake/c4StaticAnalysis.cmake | 154 - .../ryml/ext/c4core/cmake/c4stlAddTarget.cmake | 5 - .../ryml/ext/c4core/cmake/compat/c4/gcc-4.8.hpp | 69 - .../ext/c4core/cmake/compat/gtest_gcc-4.8.patch | 97 - .../ryml/ext/c4core/cmake/requirements_doc.txt | 3 - thirdparty/ryml/ext/c4core/compat.cmake | 16 - thirdparty/ryml/ext/c4core/src/c4/allocator.hpp | 405 -- thirdparty/ryml/ext/c4core/src/c4/base64.cpp | 220 - thirdparty/ryml/ext/c4core/src/c4/base64.hpp | 98 - thirdparty/ryml/ext/c4core/src/c4/bitmask.hpp | 330 - thirdparty/ryml/ext/c4core/src/c4/blob.hpp | 50 - thirdparty/ryml/ext/c4core/src/c4/c4_pop.hpp | 19 - thirdparty/ryml/ext/c4core/src/c4/c4_push.hpp | 37 - thirdparty/ryml/ext/c4core/src/c4/c4core.natvis | 168 - thirdparty/ryml/ext/c4core/src/c4/char_traits.cpp | 10 - thirdparty/ryml/ext/c4core/src/c4/char_traits.hpp | 98 - thirdparty/ryml/ext/c4core/src/c4/charconv.hpp | 2407 -------- thirdparty/ryml/ext/c4core/src/c4/common.hpp | 15 - thirdparty/ryml/ext/c4core/src/c4/compiler.hpp | 117 - thirdparty/ryml/ext/c4core/src/c4/config.hpp | 39 - thirdparty/ryml/ext/c4core/src/c4/cpu.hpp | 139 - thirdparty/ryml/ext/c4core/src/c4/ctor_dtor.hpp | 462 -- thirdparty/ryml/ext/c4core/src/c4/dump.hpp | 579 -- thirdparty/ryml/ext/c4core/src/c4/enum.hpp | 276 - thirdparty/ryml/ext/c4core/src/c4/error.cpp | 227 - thirdparty/ryml/ext/c4core/src/c4/error.hpp | 432 -- thirdparty/ryml/ext/c4core/src/c4/export.hpp | 18 - .../ext/c4core/src/c4/ext/debugbreak/.gitignore | 10 - .../ryml/ext/c4core/src/c4/ext/debugbreak/COPYING | 23 - .../ext/c4core/src/c4/ext/debugbreak/GNUmakefile | 28 - .../ext/debugbreak/HOW-TO-USE-DEBUGBREAK-GDB-PY.md | 33 - .../ext/c4core/src/c4/ext/debugbreak/README.md | 127 - .../c4core/src/c4/ext/debugbreak/debugbreak-gdb.py | 183 - .../ext/c4core/src/c4/ext/debugbreak/debugbreak.h | 174 - .../c4core/src/c4/ext/debugbreak/test/break-c++.cc | 9 - .../ext/c4core/src/c4/ext/debugbreak/test/break.c | 9 - .../c4core/src/c4/ext/debugbreak/test/break.gdb | 2 - .../ext/c4core/src/c4/ext/debugbreak/test/fib.c | 21 - .../ext/c4core/src/c4/ext/debugbreak/test/fib.gdb | 2 - .../src/c4/ext/debugbreak/test/test-debugbreak.gdb | 6 - .../ext/c4core/src/c4/ext/debugbreak/test/trap.c | 8 - .../ext/c4core/src/c4/ext/debugbreak/test/trap.gdb | 3 - .../ryml/ext/c4core/src/c4/ext/fast_float.hpp | 28 - .../ext/c4core/src/c4/ext/fast_float/.cirrus.yml | 22 - .../c4/ext/fast_float/.github/workflows/alpine.yml | 27 - .../.github/workflows/amalgamate-ubuntu20.yml | 25 - .../fast_float/.github/workflows/msys2-clang.yml | 39 - .../c4/ext/fast_float/.github/workflows/msys2.yml | 45 - .../ext/fast_float/.github/workflows/ubuntu18.yml | 35 - .../.github/workflows/ubuntu20-cxx20.yml | 19 - .../ext/fast_float/.github/workflows/ubuntu20.yml | 29 - .../ext/fast_float/.github/workflows/vs15-ci.yml | 29 - .../fast_float/.github/workflows/vs16-arm-ci.yml | 21 - .../ext/fast_float/.github/workflows/vs16-ci.yml | 29 - .../fast_float/.github/workflows/vs16-clang-ci.yml | 27 - .../fast_float/.github/workflows/vs16-cxx20.yml | 24 - .../ext/c4core/src/c4/ext/fast_float/.gitignore | 4 - .../ext/c4core/src/c4/ext/fast_float/.travis.yml | 242 - .../ryml/ext/c4core/src/c4/ext/fast_float/AUTHORS | 2 - .../ext/c4core/src/c4/ext/fast_float/CONTRIBUTORS | 6 - .../c4core/src/c4/ext/fast_float/LICENSE-APACHE | 201 - .../ext/c4core/src/c4/ext/fast_float/LICENSE-MIT | 23 - .../ext/c4core/src/c4/ext/fast_float/README.md | 216 - .../ext/c4core/src/c4/ext/fast_float/ci/script.sh | 18 - .../src/c4/ext/fast_float/cmake/config.cmake.in | 4 - .../fast_float/include/fast_float/ascii_number.h | 231 - .../c4/ext/fast_float/include/fast_float/bigint.h | 590 -- .../include/fast_float/decimal_to_binary.h | 194 - .../include/fast_float/digit_comparison.h | 423 -- .../ext/fast_float/include/fast_float/fast_float.h | 63 - .../ext/fast_float/include/fast_float/fast_table.h | 699 --- .../fast_float/include/fast_float/float_common.h | 362 -- .../fast_float/include/fast_float/parse_number.h | 113 - .../include/fast_float/simple_decimal_conversion.h | 360 -- .../src/c4/ext/fast_float/script/amalgamate.py | 56 - .../src/c4/ext/fast_float/script/analysis.py | 36 - .../c4/ext/fast_float/script/table_generation.py | 31 - .../src/c4/ext/fast_float/tests/basictest.cpp | 704 --- .../fast_float/tests/build_tests/issue72/foo.cpp | 2 - .../fast_float/tests/build_tests/issue72/main.cpp | 2 - .../fast_float/tests/build_tests/issue72/test.h | 2 - .../c4/ext/fast_float/tests/example_comma_test.cpp | 15 - .../src/c4/ext/fast_float/tests/example_test.cpp | 14 - .../src/c4/ext/fast_float/tests/exhaustive32.cpp | 63 - .../c4/ext/fast_float/tests/exhaustive32_64.cpp | 78 - .../ext/fast_float/tests/exhaustive32_midpoint.cpp | 148 - .../c4/ext/fast_float/tests/long_exhaustive32.cpp | 63 - .../ext/fast_float/tests/long_exhaustive32_64.cpp | 66 - .../src/c4/ext/fast_float/tests/long_random64.cpp | 106 - .../src/c4/ext/fast_float/tests/long_test.cpp | 58 - .../fast_float/tests/powersoffive_hardround.cpp | 134 - .../src/c4/ext/fast_float/tests/random64.cpp | 109 - .../src/c4/ext/fast_float/tests/random_string.cpp | 240 - .../ext/fast_float/tests/short_random_string.cpp | 234 - .../src/c4/ext/fast_float/tests/string_test.cpp | 279 - .../ryml/ext/c4core/src/c4/ext/fast_float_all.h | 2947 --------- thirdparty/ryml/ext/c4core/src/c4/ext/rng/rng.hpp | 192 - .../ryml/ext/c4core/src/c4/ext/sg14/README.md | 1 - .../ext/c4core/src/c4/ext/sg14/inplace_function.h | 347 -- thirdparty/ryml/ext/c4core/src/c4/format.cpp | 56 - thirdparty/ryml/ext/c4core/src/c4/format.hpp | 900 --- thirdparty/ryml/ext/c4core/src/c4/hash.hpp | 95 - thirdparty/ryml/ext/c4core/src/c4/language.cpp | 16 - thirdparty/ryml/ext/c4core/src/c4/language.hpp | 275 - .../ryml/ext/c4core/src/c4/memory_resource.cpp | 338 -- .../ryml/ext/c4core/src/c4/memory_resource.hpp | 568 -- thirdparty/ryml/ext/c4core/src/c4/memory_util.cpp | 30 - thirdparty/ryml/ext/c4core/src/c4/memory_util.hpp | 774 --- thirdparty/ryml/ext/c4core/src/c4/platform.hpp | 44 - thirdparty/ryml/ext/c4core/src/c4/preprocessor.hpp | 123 - thirdparty/ryml/ext/c4core/src/c4/restrict.hpp | 51 - thirdparty/ryml/ext/c4core/src/c4/span.hpp | 517 -- thirdparty/ryml/ext/c4core/src/c4/std/std.hpp | 10 - thirdparty/ryml/ext/c4core/src/c4/std/std_fwd.hpp | 10 - thirdparty/ryml/ext/c4core/src/c4/std/string.hpp | 97 - .../ryml/ext/c4core/src/c4/std/string_fwd.hpp | 56 - thirdparty/ryml/ext/c4core/src/c4/std/tuple.hpp | 184 - thirdparty/ryml/ext/c4core/src/c4/std/vector.hpp | 88 - .../ryml/ext/c4core/src/c4/std/vector_fwd.hpp | 60 - thirdparty/ryml/ext/c4core/src/c4/substr.hpp | 2246 ------- thirdparty/ryml/ext/c4core/src/c4/substr_fwd.hpp | 16 - thirdparty/ryml/ext/c4core/src/c4/szconv.hpp | 64 - thirdparty/ryml/ext/c4core/src/c4/type_name.hpp | 125 - thirdparty/ryml/ext/c4core/src/c4/types.hpp | 492 -- thirdparty/ryml/ext/c4core/src/c4/unrestrict.hpp | 17 - thirdparty/ryml/ext/c4core/src/c4/utf.cpp | 56 - thirdparty/ryml/ext/c4core/src/c4/utf.hpp | 16 - thirdparty/ryml/ext/c4core/src/c4/windows.hpp | 10 - thirdparty/ryml/ext/c4core/src/c4/windows_pop.hpp | 41 - thirdparty/ryml/ext/c4core/src/c4/windows_push.hpp | 102 - thirdparty/ryml/ext/c4core/tbump.toml | 48 - .../ryml/ext/c4core/test/c4/libtest/archetypes.cpp | 9 - .../ryml/ext/c4core/test/c4/libtest/archetypes.hpp | 551 -- .../ext/c4core/test/c4/libtest/supprwarn_pop.hpp | 12 - .../ext/c4core/test/c4/libtest/supprwarn_push.hpp | 48 - .../ryml/ext/c4core/test/c4/libtest/test.cpp | 7 - thirdparty/ryml/ext/c4core/test/c4/main.cpp | 3 - thirdparty/ryml/ext/c4core/test/c4/test.hpp | 324 - thirdparty/ryml/ext/c4core/test/printintegers.py | 107 - thirdparty/ryml/ext/c4core/test/test_allocator.cpp | 246 - thirdparty/ryml/ext/c4core/test/test_base64.cpp | 265 - thirdparty/ryml/ext/c4core/test/test_bitmask.cpp | 385 -- thirdparty/ryml/ext/c4core/test/test_blob.cpp | 43 - .../ryml/ext/c4core/test/test_char_traits.cpp | 67 - thirdparty/ryml/ext/c4core/test/test_charconv.cpp | 2743 --------- thirdparty/ryml/ext/c4core/test/test_ctor_dtor.cpp | 306 - thirdparty/ryml/ext/c4core/test/test_dump.cpp | 1220 ---- thirdparty/ryml/ext/c4core/test/test_enum.cpp | 158 - .../ryml/ext/c4core/test/test_enum_common.hpp | 213 - thirdparty/ryml/ext/c4core/test/test_error.cpp | 635 -- .../ryml/ext/c4core/test/test_error_exception.cpp | 108 - thirdparty/ryml/ext/c4core/test/test_format.cpp | 1054 ---- thirdparty/ryml/ext/c4core/test/test_log.cpp | 70 - .../ryml/ext/c4core/test/test_memory_resource.cpp | 255 - .../ryml/ext/c4core/test/test_memory_util.cpp | 415 -- thirdparty/ryml/ext/c4core/test/test_numbers.hpp | 1863 ------ .../ryml/ext/c4core/test/test_preprocessor.cpp | 55 - .../test_singleheader/libc4core_singleheader.cpp | 2 - thirdparty/ryml/ext/c4core/test/test_span.cpp | 944 --- .../ryml/ext/c4core/test/test_std_string.cpp | 125 - .../ryml/ext/c4core/test/test_std_vector.cpp | 133 - thirdparty/ryml/ext/c4core/test/test_substr.cpp | 4507 -------------- thirdparty/ryml/ext/c4core/test/test_szconv.cpp | 166 - thirdparty/ryml/ext/c4core/test/test_type_name.cpp | 49 - thirdparty/ryml/ext/c4core/test/test_types.cpp | 81 - thirdparty/ryml/ext/c4core/test/test_utf.cpp | 48 - thirdparty/ryml/ext/c4core/test/utfchars.inc | 6274 -------------------- thirdparty/ryml/ext/c4core/tools/amalgamate.py | 143 - thirdparty/ryml/ext/testbm.cmake | 4 - thirdparty/ryml/img/first_comparison_yaml_cpp.png | Bin 25969 -> 0 bytes thirdparty/ryml/pyproject.toml | 8 - thirdparty/ryml/requirements.txt | 8 - thirdparty/ryml/samples/add_subdirectory/run.sh | 10 - thirdparty/ryml/samples/custom_c4core/run.sh | 10 - thirdparty/ryml/samples/fetch_content/run.sh | 12 - thirdparty/ryml/samples/find_package/run.sh | 26 - thirdparty/ryml/samples/quickstart.cpp | 4161 ------------- .../ryml/samples/singleheader/amalgamate.cmake | 18 - thirdparty/ryml/samples/singleheader/run.sh | 10 - thirdparty/ryml/samples/singleheaderlib/lib.cpp | 2 - .../ryml/samples/singleheaderlib/run_shared.sh | 10 - .../ryml/samples/singleheaderlib/run_static.sh | 10 - thirdparty/ryml/setup.py | 125 - thirdparty/ryml/src/c4/yml/common.cpp | 117 - thirdparty/ryml/src/c4/yml/common.hpp | 278 - thirdparty/ryml/src/c4/yml/detail/checks.hpp | 200 - thirdparty/ryml/src/c4/yml/detail/parser_dbg.hpp | 137 - thirdparty/ryml/src/c4/yml/detail/print.hpp | 128 - thirdparty/ryml/src/c4/yml/detail/stack.hpp | 274 - thirdparty/ryml/src/c4/yml/emit.def.hpp | 960 --- thirdparty/ryml/src/c4/yml/emit.hpp | 490 -- thirdparty/ryml/src/c4/yml/export.hpp | 18 - thirdparty/ryml/src/c4/yml/node.cpp | 30 - thirdparty/ryml/src/c4/yml/node.hpp | 1276 ---- thirdparty/ryml/src/c4/yml/parse.cpp | 5724 ------------------ thirdparty/ryml/src/c4/yml/parse.hpp | 706 --- thirdparty/ryml/src/c4/yml/preprocess.cpp | 110 - thirdparty/ryml/src/c4/yml/preprocess.hpp | 99 - thirdparty/ryml/src/c4/yml/std/map.hpp | 45 - thirdparty/ryml/src/c4/yml/std/std.hpp | 8 - thirdparty/ryml/src/c4/yml/std/string.hpp | 9 - thirdparty/ryml/src/c4/yml/std/vector.hpp | 53 - thirdparty/ryml/src/c4/yml/tree.cpp | 2183 ------- thirdparty/ryml/src/c4/yml/tree.hpp | 1495 ----- thirdparty/ryml/src/c4/yml/writer.hpp | 229 - thirdparty/ryml/src/c4/yml/yml.hpp | 10 - thirdparty/ryml/src/ryml-gdbtypes.py | 391 -- thirdparty/ryml/src/ryml.hpp | 11 - thirdparty/ryml/src/ryml.natvis | 194 - thirdparty/ryml/src/ryml_std.hpp | 6 - thirdparty/ryml/tbump.toml | 56 - thirdparty/ryml/test/callbacks_tester.hpp | 77 - thirdparty/ryml/test/test_basic.cpp | 304 - thirdparty/ryml/test/test_block_folded.cpp | 1574 ----- thirdparty/ryml/test/test_block_literal.cpp | 1261 ---- thirdparty/ryml/test/test_callbacks.cpp | 356 -- thirdparty/ryml/test/test_case.cpp | 898 --- thirdparty/ryml/test/test_case.hpp | 533 -- thirdparty/ryml/test/test_double_quoted.cpp | 610 -- thirdparty/ryml/test/test_emit.cpp | 491 -- thirdparty/ryml/test/test_empty_file.cpp | 79 - thirdparty/ryml/test/test_empty_map.cpp | 43 - thirdparty/ryml/test/test_empty_scalar.cpp | 353 -- thirdparty/ryml/test/test_empty_seq.cpp | 40 - thirdparty/ryml/test/test_explicit_key.cpp | 419 -- thirdparty/ryml/test/test_generic_map.cpp | 89 - thirdparty/ryml/test/test_generic_seq.cpp | 47 - thirdparty/ryml/test/test_github_issues.cpp | 590 -- thirdparty/ryml/test/test_group.cpp | 732 --- thirdparty/ryml/test/test_group.hpp | 210 - thirdparty/ryml/test/test_indentation.cpp | 340 -- thirdparty/ryml/test/test_json.cpp | 516 -- thirdparty/ryml/test/test_location.cpp | 720 --- thirdparty/ryml/test/test_map_of_seq.cpp | 201 - thirdparty/ryml/test/test_merge.cpp | 225 - thirdparty/ryml/test/test_nested_mapx2.cpp | 73 - thirdparty/ryml/test/test_nested_mapx3.cpp | 103 - thirdparty/ryml/test/test_nested_mapx4.cpp | 190 - thirdparty/ryml/test/test_nested_seqx2.cpp | 133 - thirdparty/ryml/test/test_nested_seqx3.cpp | 187 - thirdparty/ryml/test/test_nested_seqx4.cpp | 124 - thirdparty/ryml/test/test_noderef.cpp | 813 --- thirdparty/ryml/test/test_null_val.cpp | 519 -- thirdparty/ryml/test/test_number.cpp | 217 - thirdparty/ryml/test/test_parser.cpp | 566 -- thirdparty/ryml/test/test_plain_scalar.cpp | 800 --- thirdparty/ryml/test/test_preprocess.cpp | 53 - thirdparty/ryml/test/test_scalar_names.cpp | 94 - thirdparty/ryml/test/test_seq_of_map.cpp | 348 -- thirdparty/ryml/test/test_serialize.cpp | 499 -- thirdparty/ryml/test/test_simple_anchor.cpp | 1405 ----- thirdparty/ryml/test/test_simple_doc.cpp | 526 -- thirdparty/ryml/test/test_simple_map.cpp | 1050 ---- thirdparty/ryml/test/test_simple_seq.cpp | 695 --- thirdparty/ryml/test/test_simple_set.cpp | 144 - thirdparty/ryml/test/test_single_quoted.cpp | 356 -- .../test_singleheader/libryml_singleheader.cpp | 3 - thirdparty/ryml/test/test_stack.cpp | 857 --- thirdparty/ryml/test/test_style.cpp | 616 -- thirdparty/ryml/test/test_suite.cpp | 612 -- .../ryml/test/test_suite/test_suite_common.hpp | 44 - .../ryml/test/test_suite/test_suite_events.cpp | 607 -- .../ryml/test/test_suite/test_suite_events.hpp | 45 - .../test/test_suite/test_suite_events_emitter.cpp | 289 - .../ryml/test/test_suite/test_suite_parts.cpp | 220 - .../ryml/test/test_suite/test_suite_parts.hpp | 28 - thirdparty/ryml/test/test_tag_property.cpp | 1149 ---- thirdparty/ryml/test/test_tree.cpp | 3924 ------------ thirdparty/ryml/test/test_yaml_events.cpp | 467 -- thirdparty/ryml/tools/amalgamate.py | 130 - thirdparty/ryml/tools/parse_emit.cpp | 116 - thirdparty/ryml/tools/test_suite/Dockerfile | 33 - thirdparty/ryml/tools/test_suite/run_test_suite.sh | 18 - thirdparty/ryml/tools/yaml_events.cpp | 92 - thirdparty/xmake.lua | 15 - 407 files changed, 302 insertions(+), 128804 deletions(-) delete mode 100644 thirdparty/ryml/.github/codeql.yml delete mode 100644 thirdparty/ryml/.github/release.sh delete mode 100644 thirdparty/ryml/.github/reqs.sh delete mode 100644 thirdparty/ryml/.github/setenv.sh delete mode 100644 thirdparty/ryml/.github/workflows/benchmarks.yml delete mode 100644 thirdparty/ryml/.github/workflows/clang.yml delete mode 100644 thirdparty/ryml/.github/workflows/clang_tidy.yml delete mode 100644 thirdparty/ryml/.github/workflows/codeql.yml delete mode 100644 thirdparty/ryml/.github/workflows/coverage.yml delete mode 100644 thirdparty/ryml/.github/workflows/emscripten.yml delete mode 100644 thirdparty/ryml/.github/workflows/gcc.yml delete mode 100644 thirdparty/ryml/.github/workflows/install.yml delete mode 100644 thirdparty/ryml/.github/workflows/macosx.yml delete mode 100644 thirdparty/ryml/.github/workflows/rarearchs.yml delete mode 100644 thirdparty/ryml/.github/workflows/release.yml delete mode 100644 thirdparty/ryml/.github/workflows/samples.yml delete mode 100644 thirdparty/ryml/.github/workflows/windows.yml delete mode 100644 thirdparty/ryml/.gitignore delete mode 100644 thirdparty/ryml/.gitmodules delete mode 100644 thirdparty/ryml/.lgtm.yml delete mode 100644 thirdparty/ryml/CONTRIBUTING.md delete mode 100644 thirdparty/ryml/LICENSE.txt delete mode 100644 thirdparty/ryml/MANIFEST.in delete mode 100644 thirdparty/ryml/README.md delete mode 100644 thirdparty/ryml/ROADMAP.md delete mode 100644 thirdparty/ryml/api/python/.gitignore delete mode 100644 thirdparty/ryml/api/python/Makefile delete mode 100644 thirdparty/ryml/api/python/bm/bm_parse.py delete mode 100644 thirdparty/ryml/api/python/requirements.txt delete mode 100644 thirdparty/ryml/api/python/ryml/__init__.py delete mode 100644 thirdparty/ryml/api/python/tests/test_parse.py delete mode 100644 thirdparty/ryml/api/ryml.i delete mode 100644 thirdparty/ryml/changelog/0.1.0.md delete mode 100644 thirdparty/ryml/changelog/0.2.0.md delete mode 100644 thirdparty/ryml/changelog/0.2.1.md delete mode 100644 thirdparty/ryml/changelog/0.2.2.md delete mode 100644 thirdparty/ryml/changelog/0.2.3.md delete mode 100644 thirdparty/ryml/changelog/0.3.0.md delete mode 100644 thirdparty/ryml/changelog/0.4.0.md delete mode 100644 thirdparty/ryml/changelog/0.4.1.md delete mode 100644 thirdparty/ryml/changelog/0.5.0.md delete mode 100644 thirdparty/ryml/cmake/uninstall.cmake delete mode 100644 thirdparty/ryml/compat.cmake delete mode 100644 thirdparty/ryml/ext/c4core/.github/release.sh delete mode 100644 thirdparty/ryml/ext/c4core/.github/reqs.sh delete mode 100644 thirdparty/ryml/ext/c4core/.github/setenv.sh delete mode 100644 thirdparty/ryml/ext/c4core/.github/vagrant/Vagrantfile delete mode 100644 thirdparty/ryml/ext/c4core/.github/vagrant/macos/Vagrantfile delete mode 100755 thirdparty/ryml/ext/c4core/.github/vagrant/vagrant-provision.sh delete mode 100644 thirdparty/ryml/ext/c4core/.github/workflows/arch.yml delete mode 100644 thirdparty/ryml/ext/c4core/.github/workflows/benchmarks.yml delete mode 100644 thirdparty/ryml/ext/c4core/.github/workflows/clang.yml delete mode 100644 thirdparty/ryml/ext/c4core/.github/workflows/clang_tidy.yml delete mode 100644 thirdparty/ryml/ext/c4core/.github/workflows/codeql.yml delete mode 100644 thirdparty/ryml/ext/c4core/.github/workflows/coverage.yml delete mode 100644 thirdparty/ryml/ext/c4core/.github/workflows/emscripten.yml delete mode 100644 thirdparty/ryml/ext/c4core/.github/workflows/gcc.yml delete mode 100644 thirdparty/ryml/ext/c4core/.github/workflows/libcxx.yml delete mode 100644 thirdparty/ryml/ext/c4core/.github/workflows/macosx.yml delete mode 100644 thirdparty/ryml/ext/c4core/.github/workflows/release.yml delete mode 100644 thirdparty/ryml/ext/c4core/.github/workflows/test_install.yml delete mode 100644 thirdparty/ryml/ext/c4core/.github/workflows/windows.yml delete mode 100644 thirdparty/ryml/ext/c4core/.gitignore delete mode 100644 thirdparty/ryml/ext/c4core/.gitmodules delete mode 100644 thirdparty/ryml/ext/c4core/LICENSE-BOOST.txt delete mode 100644 thirdparty/ryml/ext/c4core/LICENSE.txt delete mode 100644 thirdparty/ryml/ext/c4core/README.md delete mode 100644 thirdparty/ryml/ext/c4core/ROADMAP.md delete mode 100644 thirdparty/ryml/ext/c4core/bm/bm.yml delete mode 100644 thirdparty/ryml/ext/c4core/bm/bm_atox.cpp delete mode 100644 thirdparty/ryml/ext/c4core/bm/bm_charconv.cpp delete mode 100644 thirdparty/ryml/ext/c4core/bm/bm_charconv.hpp delete mode 100644 thirdparty/ryml/ext/c4core/bm/bm_format.cpp delete mode 100644 thirdparty/ryml/ext/c4core/bm/bm_itoa_threads.cpp delete mode 100644 thirdparty/ryml/ext/c4core/bm/bm_plot_c4core.py delete mode 100644 thirdparty/ryml/ext/c4core/bm/bm_xtoa.cpp delete mode 100644 thirdparty/ryml/ext/c4core/bm/float/measure.py delete mode 100644 thirdparty/ryml/ext/c4core/bm/float/read.cpp delete mode 100644 thirdparty/ryml/ext/c4core/bm/ryu.cmake delete mode 100644 thirdparty/ryml/ext/c4core/changelog/0.1.0.md delete mode 100644 thirdparty/ryml/ext/c4core/changelog/0.1.1.md delete mode 100644 thirdparty/ryml/ext/c4core/changelog/0.1.10.md delete mode 100644 thirdparty/ryml/ext/c4core/changelog/0.1.11.md delete mode 100644 thirdparty/ryml/ext/c4core/changelog/0.1.2.md delete mode 100644 thirdparty/ryml/ext/c4core/changelog/0.1.3.md delete mode 100644 thirdparty/ryml/ext/c4core/changelog/0.1.4.md delete mode 100644 thirdparty/ryml/ext/c4core/changelog/0.1.5.md delete mode 100644 thirdparty/ryml/ext/c4core/changelog/0.1.6.md delete mode 100644 thirdparty/ryml/ext/c4core/changelog/0.1.7.md delete mode 100644 thirdparty/ryml/ext/c4core/changelog/0.1.8.md delete mode 100644 thirdparty/ryml/ext/c4core/changelog/0.1.9.md delete mode 100644 thirdparty/ryml/ext/c4core/changelog/current.md delete mode 100644 thirdparty/ryml/ext/c4core/cmake/.gitignore delete mode 100644 thirdparty/ryml/ext/c4core/cmake/ConfigurationTypes.cmake delete mode 100644 thirdparty/ryml/ext/c4core/cmake/CreateSourceGroup.cmake delete mode 100644 thirdparty/ryml/ext/c4core/cmake/Doxyfile.full.in delete mode 100644 thirdparty/ryml/ext/c4core/cmake/Doxyfile.in delete mode 100644 thirdparty/ryml/ext/c4core/cmake/ExternalProjectUtils.cmake delete mode 100644 thirdparty/ryml/ext/c4core/cmake/FindD3D12.cmake delete mode 100644 thirdparty/ryml/ext/c4core/cmake/FindDX12.cmake delete mode 100644 thirdparty/ryml/ext/c4core/cmake/GetFlags.cmake delete mode 100644 thirdparty/ryml/ext/c4core/cmake/GetNames.cmake delete mode 100644 thirdparty/ryml/ext/c4core/cmake/LICENSE.txt delete mode 100644 thirdparty/ryml/ext/c4core/cmake/PVS-Studio.cmake delete mode 100644 thirdparty/ryml/ext/c4core/cmake/PatchUtils.cmake delete mode 100644 thirdparty/ryml/ext/c4core/cmake/PrintVar.cmake delete mode 100644 thirdparty/ryml/ext/c4core/cmake/README.md delete mode 100644 thirdparty/ryml/ext/c4core/cmake/TargetArchitecture.cmake delete mode 100644 thirdparty/ryml/ext/c4core/cmake/Toolchain-Arm-ubuntu.cmake delete mode 100644 thirdparty/ryml/ext/c4core/cmake/Toolchain-Armv7.cmake delete mode 100644 thirdparty/ryml/ext/c4core/cmake/Toolchain-PS4.cmake delete mode 100644 thirdparty/ryml/ext/c4core/cmake/Toolchain-XBoxOne.cmake delete mode 100644 thirdparty/ryml/ext/c4core/cmake/amalgamate_utils.py delete mode 100644 thirdparty/ryml/ext/c4core/cmake/bm-xp/.gitignore delete mode 100644 thirdparty/ryml/ext/c4core/cmake/bm-xp/README.md delete mode 100644 thirdparty/ryml/ext/c4core/cmake/bm-xp/bm.js delete mode 100644 thirdparty/ryml/ext/c4core/cmake/bm-xp/bm_plot.py delete mode 100644 thirdparty/ryml/ext/c4core/cmake/bm-xp/bm_run.py delete mode 100644 thirdparty/ryml/ext/c4core/cmake/bm-xp/bm_serve.py delete mode 100644 thirdparty/ryml/ext/c4core/cmake/bm-xp/bm_util.py delete mode 100644 thirdparty/ryml/ext/c4core/cmake/bm-xp/example_c4core.py delete mode 100644 thirdparty/ryml/ext/c4core/cmake/bm-xp/example_mintm.py delete mode 100644 thirdparty/ryml/ext/c4core/cmake/bm-xp/requirements.txt delete mode 100644 thirdparty/ryml/ext/c4core/cmake/bm-xp/template/index.html delete mode 100644 thirdparty/ryml/ext/c4core/cmake/c4CatSources.cmake delete mode 100644 thirdparty/ryml/ext/c4core/cmake/c4Doxygen.cmake delete mode 100644 thirdparty/ryml/ext/c4core/cmake/c4DoxygenConfig.cmake delete mode 100644 thirdparty/ryml/ext/c4core/cmake/c4GetTargetPropertyRecursive.cmake delete mode 100644 thirdparty/ryml/ext/c4core/cmake/c4Project.cmake delete mode 100644 thirdparty/ryml/ext/c4core/cmake/c4SanitizeTarget.cmake delete mode 100644 thirdparty/ryml/ext/c4core/cmake/c4StaticAnalysis.cmake delete mode 100644 thirdparty/ryml/ext/c4core/cmake/c4stlAddTarget.cmake delete mode 100644 thirdparty/ryml/ext/c4core/cmake/compat/c4/gcc-4.8.hpp delete mode 100644 thirdparty/ryml/ext/c4core/cmake/compat/gtest_gcc-4.8.patch delete mode 100644 thirdparty/ryml/ext/c4core/cmake/requirements_doc.txt delete mode 100644 thirdparty/ryml/ext/c4core/compat.cmake delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/allocator.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/base64.cpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/base64.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/bitmask.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/blob.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/c4_pop.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/c4_push.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/c4core.natvis delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/char_traits.cpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/char_traits.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/charconv.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/common.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/compiler.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/config.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/cpu.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ctor_dtor.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/dump.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/enum.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/error.cpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/error.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/export.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/.gitignore delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/COPYING delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/GNUmakefile delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/HOW-TO-USE-DEBUGBREAK-GDB-PY.md delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/README.md delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/debugbreak-gdb.py delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/debugbreak.h delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/test/break-c++.cc delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/test/break.c delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/test/break.gdb delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/test/fib.c delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/test/fib.gdb delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/test/test-debugbreak.gdb delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/test/trap.c delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/test/trap.gdb delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.cirrus.yml delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/alpine.yml delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/amalgamate-ubuntu20.yml delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/msys2-clang.yml delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/msys2.yml delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/ubuntu18.yml delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/ubuntu20-cxx20.yml delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/ubuntu20.yml delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/vs15-ci.yml delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/vs16-arm-ci.yml delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/vs16-ci.yml delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/vs16-clang-ci.yml delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/vs16-cxx20.yml delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.gitignore delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.travis.yml delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/AUTHORS delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/CONTRIBUTORS delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/LICENSE-APACHE delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/LICENSE-MIT delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/README.md delete mode 100755 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/ci/script.sh delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/cmake/config.cmake.in delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/include/fast_float/ascii_number.h delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/include/fast_float/bigint.h delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/include/fast_float/decimal_to_binary.h delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/include/fast_float/digit_comparison.h delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/include/fast_float/fast_float.h delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/include/fast_float/fast_table.h delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/include/fast_float/float_common.h delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/include/fast_float/parse_number.h delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/include/fast_float/simple_decimal_conversion.h delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/script/amalgamate.py delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/script/analysis.py delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/script/table_generation.py delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/basictest.cpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/build_tests/issue72/foo.cpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/build_tests/issue72/main.cpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/build_tests/issue72/test.h delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/example_comma_test.cpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/example_test.cpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/exhaustive32.cpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/exhaustive32_64.cpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/exhaustive32_midpoint.cpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/long_exhaustive32.cpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/long_exhaustive32_64.cpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/long_random64.cpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/long_test.cpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/powersoffive_hardround.cpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/random64.cpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/random_string.cpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/short_random_string.cpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/string_test.cpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/fast_float_all.h delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/rng/rng.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/sg14/README.md delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/ext/sg14/inplace_function.h delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/format.cpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/format.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/hash.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/language.cpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/language.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/memory_resource.cpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/memory_resource.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/memory_util.cpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/memory_util.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/platform.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/preprocessor.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/restrict.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/span.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/std/std.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/std/std_fwd.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/std/string.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/std/string_fwd.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/std/tuple.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/std/vector.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/std/vector_fwd.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/substr.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/substr_fwd.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/szconv.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/type_name.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/types.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/unrestrict.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/utf.cpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/utf.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/windows.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/windows_pop.hpp delete mode 100644 thirdparty/ryml/ext/c4core/src/c4/windows_push.hpp delete mode 100644 thirdparty/ryml/ext/c4core/tbump.toml delete mode 100644 thirdparty/ryml/ext/c4core/test/c4/libtest/archetypes.cpp delete mode 100644 thirdparty/ryml/ext/c4core/test/c4/libtest/archetypes.hpp delete mode 100644 thirdparty/ryml/ext/c4core/test/c4/libtest/supprwarn_pop.hpp delete mode 100644 thirdparty/ryml/ext/c4core/test/c4/libtest/supprwarn_push.hpp delete mode 100644 thirdparty/ryml/ext/c4core/test/c4/libtest/test.cpp delete mode 100644 thirdparty/ryml/ext/c4core/test/c4/main.cpp delete mode 100644 thirdparty/ryml/ext/c4core/test/c4/test.hpp delete mode 100644 thirdparty/ryml/ext/c4core/test/printintegers.py delete mode 100644 thirdparty/ryml/ext/c4core/test/test_allocator.cpp delete mode 100644 thirdparty/ryml/ext/c4core/test/test_base64.cpp delete mode 100644 thirdparty/ryml/ext/c4core/test/test_bitmask.cpp delete mode 100644 thirdparty/ryml/ext/c4core/test/test_blob.cpp delete mode 100644 thirdparty/ryml/ext/c4core/test/test_char_traits.cpp delete mode 100644 thirdparty/ryml/ext/c4core/test/test_charconv.cpp delete mode 100644 thirdparty/ryml/ext/c4core/test/test_ctor_dtor.cpp delete mode 100644 thirdparty/ryml/ext/c4core/test/test_dump.cpp delete mode 100644 thirdparty/ryml/ext/c4core/test/test_enum.cpp delete mode 100644 thirdparty/ryml/ext/c4core/test/test_enum_common.hpp delete mode 100644 thirdparty/ryml/ext/c4core/test/test_error.cpp delete mode 100644 thirdparty/ryml/ext/c4core/test/test_error_exception.cpp delete mode 100644 thirdparty/ryml/ext/c4core/test/test_format.cpp delete mode 100644 thirdparty/ryml/ext/c4core/test/test_log.cpp delete mode 100644 thirdparty/ryml/ext/c4core/test/test_memory_resource.cpp delete mode 100644 thirdparty/ryml/ext/c4core/test/test_memory_util.cpp delete mode 100644 thirdparty/ryml/ext/c4core/test/test_numbers.hpp delete mode 100644 thirdparty/ryml/ext/c4core/test/test_preprocessor.cpp delete mode 100644 thirdparty/ryml/ext/c4core/test/test_singleheader/libc4core_singleheader.cpp delete mode 100644 thirdparty/ryml/ext/c4core/test/test_span.cpp delete mode 100644 thirdparty/ryml/ext/c4core/test/test_std_string.cpp delete mode 100644 thirdparty/ryml/ext/c4core/test/test_std_vector.cpp delete mode 100644 thirdparty/ryml/ext/c4core/test/test_substr.cpp delete mode 100644 thirdparty/ryml/ext/c4core/test/test_szconv.cpp delete mode 100644 thirdparty/ryml/ext/c4core/test/test_type_name.cpp delete mode 100644 thirdparty/ryml/ext/c4core/test/test_types.cpp delete mode 100644 thirdparty/ryml/ext/c4core/test/test_utf.cpp delete mode 100644 thirdparty/ryml/ext/c4core/test/utfchars.inc delete mode 100644 thirdparty/ryml/ext/c4core/tools/amalgamate.py delete mode 100644 thirdparty/ryml/ext/testbm.cmake delete mode 100644 thirdparty/ryml/img/first_comparison_yaml_cpp.png delete mode 100644 thirdparty/ryml/pyproject.toml delete mode 100644 thirdparty/ryml/requirements.txt delete mode 100755 thirdparty/ryml/samples/add_subdirectory/run.sh delete mode 100755 thirdparty/ryml/samples/custom_c4core/run.sh delete mode 100755 thirdparty/ryml/samples/fetch_content/run.sh delete mode 100755 thirdparty/ryml/samples/find_package/run.sh delete mode 100644 thirdparty/ryml/samples/quickstart.cpp delete mode 100644 thirdparty/ryml/samples/singleheader/amalgamate.cmake delete mode 100755 thirdparty/ryml/samples/singleheader/run.sh delete mode 100644 thirdparty/ryml/samples/singleheaderlib/lib.cpp delete mode 100755 thirdparty/ryml/samples/singleheaderlib/run_shared.sh delete mode 100755 thirdparty/ryml/samples/singleheaderlib/run_static.sh delete mode 100644 thirdparty/ryml/setup.py delete mode 100644 thirdparty/ryml/src/c4/yml/common.cpp delete mode 100644 thirdparty/ryml/src/c4/yml/common.hpp delete mode 100644 thirdparty/ryml/src/c4/yml/detail/checks.hpp delete mode 100644 thirdparty/ryml/src/c4/yml/detail/parser_dbg.hpp delete mode 100644 thirdparty/ryml/src/c4/yml/detail/print.hpp delete mode 100644 thirdparty/ryml/src/c4/yml/detail/stack.hpp delete mode 100644 thirdparty/ryml/src/c4/yml/emit.def.hpp delete mode 100644 thirdparty/ryml/src/c4/yml/emit.hpp delete mode 100644 thirdparty/ryml/src/c4/yml/export.hpp delete mode 100644 thirdparty/ryml/src/c4/yml/node.cpp delete mode 100644 thirdparty/ryml/src/c4/yml/node.hpp delete mode 100644 thirdparty/ryml/src/c4/yml/parse.cpp delete mode 100644 thirdparty/ryml/src/c4/yml/parse.hpp delete mode 100644 thirdparty/ryml/src/c4/yml/preprocess.cpp delete mode 100644 thirdparty/ryml/src/c4/yml/preprocess.hpp delete mode 100644 thirdparty/ryml/src/c4/yml/std/map.hpp delete mode 100644 thirdparty/ryml/src/c4/yml/std/std.hpp delete mode 100644 thirdparty/ryml/src/c4/yml/std/string.hpp delete mode 100644 thirdparty/ryml/src/c4/yml/std/vector.hpp delete mode 100644 thirdparty/ryml/src/c4/yml/tree.cpp delete mode 100644 thirdparty/ryml/src/c4/yml/tree.hpp delete mode 100644 thirdparty/ryml/src/c4/yml/writer.hpp delete mode 100644 thirdparty/ryml/src/c4/yml/yml.hpp delete mode 100644 thirdparty/ryml/src/ryml-gdbtypes.py delete mode 100644 thirdparty/ryml/src/ryml.hpp delete mode 100644 thirdparty/ryml/src/ryml.natvis delete mode 100644 thirdparty/ryml/src/ryml_std.hpp delete mode 100644 thirdparty/ryml/tbump.toml delete mode 100644 thirdparty/ryml/test/callbacks_tester.hpp delete mode 100644 thirdparty/ryml/test/test_basic.cpp delete mode 100644 thirdparty/ryml/test/test_block_folded.cpp delete mode 100644 thirdparty/ryml/test/test_block_literal.cpp delete mode 100644 thirdparty/ryml/test/test_callbacks.cpp delete mode 100644 thirdparty/ryml/test/test_case.cpp delete mode 100644 thirdparty/ryml/test/test_case.hpp delete mode 100644 thirdparty/ryml/test/test_double_quoted.cpp delete mode 100644 thirdparty/ryml/test/test_emit.cpp delete mode 100644 thirdparty/ryml/test/test_empty_file.cpp delete mode 100644 thirdparty/ryml/test/test_empty_map.cpp delete mode 100644 thirdparty/ryml/test/test_empty_scalar.cpp delete mode 100644 thirdparty/ryml/test/test_empty_seq.cpp delete mode 100644 thirdparty/ryml/test/test_explicit_key.cpp delete mode 100644 thirdparty/ryml/test/test_generic_map.cpp delete mode 100644 thirdparty/ryml/test/test_generic_seq.cpp delete mode 100644 thirdparty/ryml/test/test_github_issues.cpp delete mode 100644 thirdparty/ryml/test/test_group.cpp delete mode 100644 thirdparty/ryml/test/test_group.hpp delete mode 100644 thirdparty/ryml/test/test_indentation.cpp delete mode 100644 thirdparty/ryml/test/test_json.cpp delete mode 100644 thirdparty/ryml/test/test_location.cpp delete mode 100644 thirdparty/ryml/test/test_map_of_seq.cpp delete mode 100644 thirdparty/ryml/test/test_merge.cpp delete mode 100644 thirdparty/ryml/test/test_nested_mapx2.cpp delete mode 100644 thirdparty/ryml/test/test_nested_mapx3.cpp delete mode 100644 thirdparty/ryml/test/test_nested_mapx4.cpp delete mode 100644 thirdparty/ryml/test/test_nested_seqx2.cpp delete mode 100644 thirdparty/ryml/test/test_nested_seqx3.cpp delete mode 100644 thirdparty/ryml/test/test_nested_seqx4.cpp delete mode 100644 thirdparty/ryml/test/test_noderef.cpp delete mode 100644 thirdparty/ryml/test/test_null_val.cpp delete mode 100644 thirdparty/ryml/test/test_number.cpp delete mode 100644 thirdparty/ryml/test/test_parser.cpp delete mode 100644 thirdparty/ryml/test/test_plain_scalar.cpp delete mode 100644 thirdparty/ryml/test/test_preprocess.cpp delete mode 100644 thirdparty/ryml/test/test_scalar_names.cpp delete mode 100644 thirdparty/ryml/test/test_seq_of_map.cpp delete mode 100644 thirdparty/ryml/test/test_serialize.cpp delete mode 100644 thirdparty/ryml/test/test_simple_anchor.cpp delete mode 100644 thirdparty/ryml/test/test_simple_doc.cpp delete mode 100644 thirdparty/ryml/test/test_simple_map.cpp delete mode 100644 thirdparty/ryml/test/test_simple_seq.cpp delete mode 100644 thirdparty/ryml/test/test_simple_set.cpp delete mode 100644 thirdparty/ryml/test/test_single_quoted.cpp delete mode 100644 thirdparty/ryml/test/test_singleheader/libryml_singleheader.cpp delete mode 100644 thirdparty/ryml/test/test_stack.cpp delete mode 100644 thirdparty/ryml/test/test_style.cpp delete mode 100644 thirdparty/ryml/test/test_suite.cpp delete mode 100644 thirdparty/ryml/test/test_suite/test_suite_common.hpp delete mode 100644 thirdparty/ryml/test/test_suite/test_suite_events.cpp delete mode 100644 thirdparty/ryml/test/test_suite/test_suite_events.hpp delete mode 100644 thirdparty/ryml/test/test_suite/test_suite_events_emitter.cpp delete mode 100644 thirdparty/ryml/test/test_suite/test_suite_parts.cpp delete mode 100644 thirdparty/ryml/test/test_suite/test_suite_parts.hpp delete mode 100644 thirdparty/ryml/test/test_tag_property.cpp delete mode 100644 thirdparty/ryml/test/test_tree.cpp delete mode 100644 thirdparty/ryml/test/test_yaml_events.cpp delete mode 100644 thirdparty/ryml/tools/amalgamate.py delete mode 100644 thirdparty/ryml/tools/parse_emit.cpp delete mode 100644 thirdparty/ryml/tools/test_suite/Dockerfile delete mode 100755 thirdparty/ryml/tools/test_suite/run_test_suite.sh delete mode 100644 thirdparty/ryml/tools/yaml_events.cpp diff --git a/src/zencore/compactbinaryyaml.cpp b/src/zencore/compactbinaryyaml.cpp index 5122e952a..b308af418 100644 --- a/src/zencore/compactbinaryyaml.cpp +++ b/src/zencore/compactbinaryyaml.cpp @@ -14,11 +14,6 @@ #include #include -ZEN_THIRD_PARTY_INCLUDES_START -#include -#include -ZEN_THIRD_PARTY_INCLUDES_END - namespace zen { ////////////////////////////////////////////////////////////////////////// @@ -26,193 +21,349 @@ namespace zen { class CbYamlWriter { public: - explicit CbYamlWriter(StringBuilderBase& InBuilder) : m_StrBuilder(InBuilder) { m_NodeStack.push_back(m_Tree.rootref()); } + explicit CbYamlWriter(StringBuilderBase& InBuilder) : m_Builder(InBuilder) {} void WriteField(CbFieldView Field) { - ryml::NodeRef Node; + CbValue Accessor = Field.GetValue(); + CbFieldType Type = Accessor.GetType(); - if (m_IsFirst) + switch (Type) { - Node = Top(); + case CbFieldType::Object: + case CbFieldType::UniformObject: + WriteMapEntries(Field, 0); + break; + case CbFieldType::Array: + case CbFieldType::UniformArray: + WriteSeqEntries(Field, 0); + break; + default: + WriteScalarValue(Field); + m_Builder << '\n'; + break; + } + } + + void WriteMapEntry(CbFieldView Field, int32_t Indent) + { + WriteIndent(Indent); + WriteMapEntryContent(Field, Indent); + } + + void WriteSeqEntry(CbFieldView Field, int32_t Indent) + { + CbValue Accessor = Field.GetValue(); + CbFieldType Type = Accessor.GetType(); - m_IsFirst = false; + if (Type == CbFieldType::Object || Type == CbFieldType::UniformObject) + { + bool First = true; + for (CbFieldView MapChild : Field) + { + if (First) + { + WriteIndent(Indent); + m_Builder << "- "; + First = false; + } + else + { + WriteIndent(Indent + 1); + } + WriteMapEntryContent(MapChild, Indent + 1); + } + } + else if (Type == CbFieldType::Array || Type == CbFieldType::UniformArray) + { + WriteIndent(Indent); + m_Builder << "-\n"; + WriteSeqEntries(Field, Indent + 1); } else { - Node = Top().append_child(); + WriteIndent(Indent); + m_Builder << "- "; + WriteScalarValue(Field); + m_Builder << '\n'; } + } - if (std::u8string_view Name = Field.GetU8Name(); !Name.empty()) +private: + void WriteMapEntries(CbFieldView MapField, int32_t Indent) + { + for (CbFieldView Child : MapField) { - Node.set_key_serialized(ryml::csubstr((const char*)Name.data(), Name.size())); + WriteIndent(Indent); + WriteMapEntryContent(Child, Indent); } + } + + void WriteMapEntryContent(CbFieldView Field, int32_t Indent) + { + std::u8string_view Name = Field.GetU8Name(); + m_Builder << std::string_view(reinterpret_cast(Name.data()), Name.size()); - switch (CbValue Accessor = Field.GetValue(); Accessor.GetType()) + CbValue Accessor = Field.GetValue(); + CbFieldType Type = Accessor.GetType(); + + if (IsContainer(Type)) { - case CbFieldType::Null: - Node.set_val("null"); - break; - case CbFieldType::Object: - case CbFieldType::UniformObject: - Node |= ryml::MAP; - m_NodeStack.push_back(Node); - for (CbFieldView It : Field) + m_Builder << ":\n"; + WriteFieldValue(Field, Indent + 1); + } + else + { + m_Builder << ": "; + WriteScalarValue(Field); + m_Builder << '\n'; + } + } + + void WriteSeqEntries(CbFieldView SeqField, int32_t Indent) + { + for (CbFieldView Child : SeqField) + { + CbValue Accessor = Child.GetValue(); + CbFieldType Type = Accessor.GetType(); + + if (Type == CbFieldType::Object || Type == CbFieldType::UniformObject) + { + bool First = true; + for (CbFieldView MapChild : Child) { - WriteField(It); + if (First) + { + WriteIndent(Indent); + m_Builder << "- "; + First = false; + } + else + { + WriteIndent(Indent + 1); + } + WriteMapEntryContent(MapChild, Indent + 1); } - m_NodeStack.pop_back(); + } + else if (Type == CbFieldType::Array || Type == CbFieldType::UniformArray) + { + WriteIndent(Indent); + m_Builder << "-\n"; + WriteSeqEntries(Child, Indent + 1); + } + else + { + WriteIndent(Indent); + m_Builder << "- "; + WriteScalarValue(Child); + m_Builder << '\n'; + } + } + } + + void WriteFieldValue(CbFieldView Field, int32_t Indent) + { + CbValue Accessor = Field.GetValue(); + CbFieldType Type = Accessor.GetType(); + + switch (Type) + { + case CbFieldType::Object: + case CbFieldType::UniformObject: + WriteMapEntries(Field, Indent); break; case CbFieldType::Array: case CbFieldType::UniformArray: - Node |= ryml::SEQ; - m_NodeStack.push_back(Node); - for (CbFieldView It : Field) - { - WriteField(It); - } - m_NodeStack.pop_back(); + WriteSeqEntries(Field, Indent); break; - case CbFieldType::Binary: - { - ExtendableStringBuilder<256> Builder; - const MemoryView Value = Accessor.AsBinary(); - ZEN_ASSERT(Value.GetSize() <= 512 * 1024 * 1024); - const uint32_t EncodedSize = Base64::GetEncodedDataSize(uint32_t(Value.GetSize())); - const size_t EncodedIndex = Builder.AddUninitialized(size_t(EncodedSize)); - Base64::Encode(static_cast(Value.GetData()), uint32_t(Value.GetSize()), Builder.Data() + EncodedIndex); - - Node.set_key_serialized(Builder.c_str()); - } + case CbFieldType::CustomById: + WriteCustomById(Field.GetValue().AsCustomById(), Indent); break; - case CbFieldType::String: - { - const std::u8string_view U8String = Accessor.AsU8String(); - Node.set_val(ryml::csubstr((const char*)U8String.data(), U8String.size())); - } + case CbFieldType::CustomByName: + WriteCustomByName(Field.GetValue().AsCustomByName(), Indent); + break; + default: + WriteScalarValue(Field); + m_Builder << '\n'; + break; + } + } + + void WriteScalarValue(CbFieldView Field) + { + CbValue Accessor = Field.GetValue(); + switch (Accessor.GetType()) + { + case CbFieldType::Null: + m_Builder << "null"; + break; + case CbFieldType::BoolFalse: + m_Builder << "false"; + break; + case CbFieldType::BoolTrue: + m_Builder << "true"; break; case CbFieldType::IntegerPositive: - Node << Accessor.AsIntegerPositive(); + m_Builder << Accessor.AsIntegerPositive(); break; case CbFieldType::IntegerNegative: - Node << Accessor.AsIntegerNegative(); + m_Builder << Accessor.AsIntegerNegative(); break; case CbFieldType::Float32: if (const float Value = Accessor.AsFloat32(); std::isfinite(Value)) - { - Node << Value; - } + m_Builder.Append(fmt::format("{}", Value)); else - { - Node << "null"; - } + m_Builder << "null"; break; case CbFieldType::Float64: if (const double Value = Accessor.AsFloat64(); std::isfinite(Value)) - { - Node << Value; - } + m_Builder.Append(fmt::format("{}", Value)); else + m_Builder << "null"; + break; + case CbFieldType::String: { - Node << "null"; + const std::u8string_view U8String = Accessor.AsU8String(); + WriteString(std::string_view(reinterpret_cast(U8String.data()), U8String.size())); } break; - case CbFieldType::BoolFalse: - Node << "false"; - break; - case CbFieldType::BoolTrue: - Node << "true"; + case CbFieldType::Hash: + WriteString(Accessor.AsHash().ToHexString()); break; case CbFieldType::ObjectAttachment: case CbFieldType::BinaryAttachment: - Node << Accessor.AsAttachment().ToHexString(); - break; - case CbFieldType::Hash: - Node << Accessor.AsHash().ToHexString(); + WriteString(Accessor.AsAttachment().ToHexString()); break; case CbFieldType::Uuid: - Node << fmt::format("{}", Accessor.AsUuid()); + WriteString(fmt::format("{}", Accessor.AsUuid())); break; case CbFieldType::DateTime: - Node << DateTime(Accessor.AsDateTimeTicks()).ToIso8601(); + WriteString(DateTime(Accessor.AsDateTimeTicks()).ToIso8601()); break; case CbFieldType::TimeSpan: if (const TimeSpan Span(Accessor.AsTimeSpanTicks()); Span.GetDays() == 0) - { - Node << Span.ToString("%h:%m:%s.%n"); - } + WriteString(Span.ToString("%h:%m:%s.%n")); else - { - Node << Span.ToString("%d.%h:%m:%s.%n"); - } + WriteString(Span.ToString("%d.%h:%m:%s.%n")); break; case CbFieldType::ObjectId: - Node << fmt::format("{}", Accessor.AsObjectId()); + WriteString(fmt::format("{}", Accessor.AsObjectId())); break; - case CbFieldType::CustomById: - { - CbCustomById Custom = Accessor.AsCustomById(); + case CbFieldType::Binary: + WriteBase64(Accessor.AsBinary()); + break; + default: + ZEN_ASSERT_FORMAT(false, "invalid field type: {}", uint8_t(Accessor.GetType())); + break; + } + } - Node |= ryml::MAP; + void WriteCustomById(CbCustomById Custom, int32_t Indent) + { + WriteIndent(Indent); + m_Builder << "Id: "; + m_Builder.Append(fmt::format("{}", Custom.Id)); + m_Builder << '\n'; + + WriteIndent(Indent); + m_Builder << "Data: "; + WriteBase64(Custom.Data); + m_Builder << '\n'; + } - ryml::NodeRef IdNode = Node.append_child(); - IdNode.set_key("Id"); - IdNode.set_val_serialized(fmt::format("{}", Custom.Id)); + void WriteCustomByName(CbCustomByName Custom, int32_t Indent) + { + WriteIndent(Indent); + m_Builder << "Name: "; + WriteString(std::string_view(reinterpret_cast(Custom.Name.data()), Custom.Name.size())); + m_Builder << '\n'; + + WriteIndent(Indent); + m_Builder << "Data: "; + WriteBase64(Custom.Data); + m_Builder << '\n'; + } - ryml::NodeRef DataNode = Node.append_child(); - DataNode.set_key("Data"); + void WriteBase64(MemoryView Value) + { + ZEN_ASSERT(Value.GetSize() <= 512 * 1024 * 1024); + ExtendableStringBuilder<256> Buf; + const uint32_t EncodedSize = Base64::GetEncodedDataSize(uint32_t(Value.GetSize())); + const size_t EncodedIndex = Buf.AddUninitialized(size_t(EncodedSize)); + Base64::Encode(static_cast(Value.GetData()), uint32_t(Value.GetSize()), Buf.Data() + EncodedIndex); + WriteString(Buf.ToView()); + } - ExtendableStringBuilder<256> Builder; - const MemoryView& Value = Custom.Data; - const uint32_t EncodedSize = Base64::GetEncodedDataSize(uint32_t(Value.GetSize())); - const size_t EncodedIndex = Builder.AddUninitialized(size_t(EncodedSize)); - Base64::Encode(static_cast(Value.GetData()), uint32_t(Value.GetSize()), Builder.Data() + EncodedIndex); + void WriteString(std::string_view Str) + { + if (NeedsQuoting(Str)) + { + m_Builder << '\''; + for (char C : Str) + { + if (C == '\'') + m_Builder << "''"; + else + m_Builder << C; + } + m_Builder << '\''; + } + else + { + m_Builder << Str; + } + } - DataNode.set_val_serialized(Builder.c_str()); - } - break; - case CbFieldType::CustomByName: - { - CbCustomByName Custom = Accessor.AsCustomByName(); + void WriteIndent(int32_t Indent) + { + for (int32_t I = 0; I < Indent; ++I) + m_Builder << " "; + } - Node |= ryml::MAP; + static bool NeedsQuoting(std::string_view Str) + { + if (Str.empty()) + return false; - ryml::NodeRef NameNode = Node.append_child(); - NameNode.set_key("Name"); - std::string_view Name = std::string_view((const char*)Custom.Name.data(), Custom.Name.size()); - NameNode.set_val_serialized(std::string(Name)); + char First = Str[0]; + if (First == ' ' || First == '\n' || First == '\t' || First == '\r' || First == '*' || First == '&' || First == '%' || + First == '@' || First == '`') + return true; - ryml::NodeRef DataNode = Node.append_child(); - DataNode.set_key("Data"); + if (Str.size() >= 2 && Str[0] == '<' && Str[1] == '<') + return true; - ExtendableStringBuilder<256> Builder; - const MemoryView& Value = Custom.Data; - const uint32_t EncodedSize = Base64::GetEncodedDataSize(uint32_t(Value.GetSize())); - const size_t EncodedIndex = Builder.AddUninitialized(size_t(EncodedSize)); - Base64::Encode(static_cast(Value.GetData()), uint32_t(Value.GetSize()), Builder.Data() + EncodedIndex); + char Last = Str.back(); + if (Last == ' ' || Last == '\n' || Last == '\t' || Last == '\r') + return true; - DataNode.set_val_serialized(Builder.c_str()); - } - break; - default: - ZEN_ASSERT_FORMAT(false, "invalid field type: {}", uint8_t(Accessor.GetType())); - break; + for (char C : Str) + { + if (C == '#' || C == ':' || C == '-' || C == '?' || C == ',' || C == '\n' || C == '{' || C == '}' || C == '[' || C == ']' || + C == '\'' || C == '"') + return true; } - if (m_NodeStack.size() == 1) + return false; + } + + static bool IsContainer(CbFieldType Type) + { + switch (Type) { - std::string Yaml = ryml::emitrs_yaml(m_Tree); - m_StrBuilder << Yaml; + case CbFieldType::Object: + case CbFieldType::UniformObject: + case CbFieldType::Array: + case CbFieldType::UniformArray: + case CbFieldType::CustomById: + case CbFieldType::CustomByName: + return true; + default: + return false; } } -private: - StringBuilderBase& m_StrBuilder; - bool m_IsFirst = true; - - ryml::Tree m_Tree; - std::vector m_NodeStack; - ryml::NodeRef& Top() { return m_NodeStack.back(); } + StringBuilderBase& m_Builder; }; void @@ -229,6 +380,32 @@ CompactBinaryToYaml(const CbArrayView& Array, StringBuilderBase& Builder) Writer.WriteField(Array.AsFieldView()); } +void +CompactBinaryToYaml(MemoryView Data, StringBuilderBase& InBuilder) +{ + std::vector Fields = ReadCompactBinaryStream(Data); + if (Fields.empty()) + return; + + CbYamlWriter Writer(InBuilder); + if (Fields.size() == 1) + { + Writer.WriteField(Fields[0]); + return; + } + + if (Fields[0].HasName()) + { + for (const CbFieldView& Field : Fields) + Writer.WriteMapEntry(Field, 0); + } + else + { + for (const CbFieldView& Field : Fields) + Writer.WriteSeqEntry(Field, 0); + } +} + #if ZEN_WITH_TESTS void cbyaml_forcelink() diff --git a/src/zencore/xmake.lua b/src/zencore/xmake.lua index a3fd4dacb..9a67175a0 100644 --- a/src/zencore/xmake.lua +++ b/src/zencore/xmake.lua @@ -33,8 +33,6 @@ target('zencore') add_deps("timesinceprocessstart") add_deps("doctest") add_deps("fmt") - add_deps("ryml") - add_packages("json11") if is_plat("linux", "macosx") then diff --git a/thirdparty/ryml/.github/codeql.yml b/thirdparty/ryml/.github/codeql.yml deleted file mode 100644 index fa58c1d8b..000000000 --- a/thirdparty/ryml/.github/codeql.yml +++ /dev/null @@ -1,3 +0,0 @@ -query-filters: - - exclude: - id: cpp/unsigned-comparison-zero diff --git a/thirdparty/ryml/.github/release.sh b/thirdparty/ryml/.github/release.sh deleted file mode 100644 index 43eb6e71b..000000000 --- a/thirdparty/ryml/.github/release.sh +++ /dev/null @@ -1,127 +0,0 @@ -#!/bin/bash - - -# useful to iterate when fixing the release: -# ver=0.2.1 ; ( set -x ; git tag -d v$ver ; git push origin :v$ver ) ; (set -x ; set -e ; tbump --only-patch --non-interactive $ver ; git add -u ; git commit --amend --no-edit ; git tag --annotate --message "v$ver" "v$ver" ; git push -f --tags origin ) - - -function c4_release_create() -{ - ( \ - set -euxo pipefail ; \ - ver=$(_c4_validate_ver $1) ; \ - branch=$(_c4_validate_branch) ; \ - c4_release_bump $ver ; \ - c4_release_commit $ver $branch \ - ) -} - -function c4_release_redo() -{ - ( \ - set -euxo pipefail ; \ - ver=$(_c4_validate_ver $1) ; \ - branch=$(_c4_validate_branch) ; \ - c4_release_delete $ver ; \ - c4_release_bump $ver ; \ - c4_release_amend $ver $branch \ - ) -} - -function c4_release_bump() -{ - ( \ - set -euxo pipefail ; \ - ver=$(_c4_validate_ver $1) ; \ - tbump --non-interactive --only-patch $ver \ - ) -} - -function c4_release_commit() -{ - ( \ - set -euxo pipefail ; \ - ver=$(_c4_validate_ver $1) ; \ - branch=$(_c4_validate_branch) ; \ - tag=v$ver ; \ - git add -u ; \ - git commit -m $tag ; \ - git tag --annotate --message $tag $tag ; \ - ) -} - -function c4_release_amend() -{ - ( \ - set -euxo pipefail ; \ - ver=$(_c4_validate_ver $1) ; \ - branch=$(_c4_validate_branch) ; \ - tag=v$ver ; \ - git add -u ; \ - git commit --amend -m $tag ; \ - git tag --annotate --message $tag $tag ; \ - ) -} - -function c4_release_delete() -{ - ( \ - set -euxo pipefail ; \ - ver=$(_c4_validate_ver $1) ; \ - git tag -d v$ver ; \ - git push origin :v$ver \ - ) -} - -function c4_release_push() -{ - ( \ - set -euxo pipefail ; \ - ver=$(_c4_validate_ver $1) ; \ - branch=$(_c4_validate_branch) ; \ - tag=v$ver ; \ - git push origin $branch ; \ - git push --tags origin $tag \ - ) -} - -function c4_release_force_push() -{ - ( \ - set -euxo pipefail ; \ - ver=$(_c4_validate_ver $1) ; \ - branch=$(_c4_validate_branch) ; \ - tag=v$ver ; \ - git push -f origin $branch ; \ - git push -f --tags origin $tag \ - ) -} - -function _c4_validate_ver() -{ - ver=$1 - if [ -z "$ver" ] ; then \ - exit 1 - fi - ver=$(echo $ver | sed "s:v\(.*\):\1:") - #sver=$(echo $ver | sed "s:\([0-9]*\.[0-9]*\..[0-9]*\).*:\1:") - if [ ! -f changelog/$ver.md ] ; then \ - if [ -f changelog/current.md ] ; then - git mv changelog/current.md changelog/$ver.md - else - echo "ERROR: could not find changelog/$ver.md or changelog/current.md" - exit 1 - fi - fi - echo $ver -} - -function _c4_validate_branch() -{ - branch=$(git rev-parse --abbrev-ref HEAD) - if [ "$branch" != "master" ] ; then - echo "ERROR: release branch must be master" - exit 1 - fi - echo $branch -} diff --git a/thirdparty/ryml/.github/reqs.sh b/thirdparty/ryml/.github/reqs.sh deleted file mode 100644 index b1747747c..000000000 --- a/thirdparty/ryml/.github/reqs.sh +++ /dev/null @@ -1,315 +0,0 @@ -#!/usr/bin/env bash - -set -x - -# input environment variables: -# OS: the operating system -# CXX_: the compiler version. eg, g++-9 or clang++-6.0 -# BT: the build type -# VG: whether to install valgrind -# ARM: whether to arm cross-compiler and emulator -# GITHUB_WORKFLOW: when run from github -# API: whether to install swig -# CMANY: whether to install cmany - - - -#------------------------------------------------------------------------------- - -function c4_install_test_requirements() -{ - os=$1 - case "$os" in - ubuntu*) - c4_install_test_requirements_ubuntu - return 0 - ;; - macos*) - c4_install_test_requirements_macos - return 0 - ;; - win*) - c4_install_test_requirements_windows - return 0 - ;; - *) - return 0 - ;; - esac -} - -function c4_install_test_requirements_windows() -{ - if [ "$CMANY" == "ON" ] ; then - pip install cmany - fi - if [ "$API" == "ON" ] ; then - choco install swig - which swig - fi - # ensure chocolatey does not override cmake's cpack - which cpack - choco_cpack="/c/ProgramData/Chocolatey/bin/cpack.exe" - if [ -f $choco_cpack ] ; then - newname=$(echo $choco_cpack | sed 's:cpack:choco-cpack:') - mv -vf $choco_cpack $newname - fi - which cpack -} - -function c4_install_test_requirements_macos() -{ - if [ "$CMANY" == "ON" ] ; then - sudo pip3 install cmany - fi -} - -function c4_install_test_requirements_ubuntu() -{ - UBUNTU_RELEASE=$(lsb_release -rs) - UBUNTU_RELEASE_NAME=$(lsb_release -cs) - APT_PKG="" # all - PIP_PKG="" - c4_gather_test_requirements_ubuntu - echo "apt packages: $APT_PKG" - echo "pip packages: $PIP_PKG" - c4_install_test_requirements_ubuntu_impl - echo 'INSTALL COMPLETE!' -} - - -function c4_install_all_possible_requirements_ubuntu() -{ - export CXX_=all - export BT=Coverage - APT_PKG="" # all - PIP_PKG="" - sudo dpkg --add-architecture i386 - c4_gather_test_requirements_ubuntu - _c4_add_arm_compilers - echo "apt packages: $APT_PKG" - echo "pip packages: $PIP_PKG" - c4_install_test_requirements_ubuntu_impl - echo 'INSTALL COMPLETE!' -} - - -function c4_gather_test_requirements_ubuntu() -{ - if [ "$GITHUB_WORKFLOW" != "" ] ; then - sudo dpkg --add-architecture i386 - else - _add_apt build-essential - _add_apt cmake - fi - - _add_apt linux-libc-dev:i386 - _add_apt libc6:i386 - _add_apt libc6-dev:i386 - _add_apt libc6-dbg:i386 - - _c4_gather_compilers "$CXX_" - - _add_apt python3-setuptools - _add_apt python3-pip - - #_add_apt iwyu - #_add_apt cppcheck - #_add_pip cpplint - # oclint? - if [ "$VG" == "ON" ] ; then - _add_apt valgrind - fi - - if [ "$BT" == "Coverage" ]; then - _add_apt lcov - _add_apt libffi-dev - _add_apt libssl-dev - _add_pip requests[security] - _add_pip pyopenssl - _add_pip ndg-httpsclient - _add_pip pyasn1 - _add_pip cpp-coveralls - fi - - if [ "$CMANY" != "" ] ; then - _add_pip cmany - fi - - case "$CXX_" in - arm*) - _c4_add_arm_compilers - ;; - esac -} - - -function c4_install_test_requirements_ubuntu_impl() -{ - wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key 2>/dev/null | sudo apt-key add - - wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | sudo apt-key add - - sudo -E apt-add-repository --yes "deb https://apt.kitware.com/ubuntu/ $UBUNTU_RELEASE_NAME main" - sudo -E add-apt-repository --yes ppa:ubuntu-toolchain-r/test - - if [ "$APT_PKG" != "" ] ; then - #sudo -E apt-get clean - sudo -E apt-get update - sudo -E apt-get install -y --force-yes $APT_PKG - fi - - if [ "$PIP_PKG" != "" ]; then - sudo pip3 install $PIP_PKG - fi -} - - -#------------------------------------------------------------------------------- - -function _c4_add_arm_compilers() -{ - # this is going to be deprecated: - # https://askubuntu.com/questions/1243252/how-to-install-arm-none-eabi-gdb-on-ubuntu-20-04-lts-focal-fossa - sudo -E add-apt-repository --yes ppa:team-gcc-arm-embedded/ppa - - _add_apt gcc-arm-embedded - _add_apt g++-arm-linux-gnueabihf - _add_apt g++-multilib-arm-linux-gnueabihf - _add_apt qemu -} - - -function _c4_gather_compilers() -{ - cxx=$1 - case $cxx in - g++-12 ) _c4_addgcc 12 ;; - g++-11 ) _c4_addgcc 11 ;; - g++-10 ) _c4_addgcc 10 ;; - g++-9 ) _c4_addgcc 9 ;; - g++-8 ) _c4_addgcc 8 ;; - g++-7 ) _c4_addgcc 7 ;; - g++-6 ) _c4_addgcc 6 ;; - g++-5 ) _c4_addgcc 5 ;; - #g++-4.9 ) _c4_addgcc 4.9 ;; # https://askubuntu.com/questions/1036108/install-gcc-4-9-at-ubuntu-18-04 - g++-4.8 ) _c4_addgcc 4.8 ;; - clang++-14 ) _c4_addclang 14 ;; - clang++-13 ) _c4_addclang 13 ;; - clang++-12 ) _c4_addclang 12 ;; - clang++-11 ) _c4_addclang 11 ;; - clang++-10 ) _c4_addclang 10 ;; - clang++-9 ) _c4_addclang 9 ;; - clang++-8 ) _c4_addclang 8 ;; - clang++-7 ) _c4_addclang 7 ;; - clang++-6.0) _c4_addclang 6.0 ;; - clang++-5.0) _c4_addclang 5.0 ;; - clang++-4.0) _c4_addclang 4.0 ;; - clang++-3.9) _c4_addclang 3.9 ;; - all) - all="g++-12 g++-11 g++-10 g++-9 g++-8 g++-7 g++-6 g++-5 clang++-14 clang++-13 clang++-12 clang++-11 clang++-10 clang++-9 clang++-8 clang++-7 clang++-6.0 clang++-5.0 clang++-4.0 clang++-3.9" - echo "installing all compilers: $all" - for cxx in $all ; do - _c4_gather_compilers $cxx - done - ;; - "") - # use default compiler - ;; - arm*) - ;; - *) - echo "unknown compiler: $cxx" - exit 1 - ;; - esac -} - -# add a gcc compiler -function _c4_addgcc() -{ - gccversion=$1 - case $gccversion in - 5 ) - _add_apt gcc-5 "deb http://dk.archive.ubuntu.com/ubuntu/ xenial main" - _add_apt gcc-5 "deb http://dk.archive.ubuntu.com/ubuntu/ xenial universe" - ;; - *) - ;; - esac - _add_apt g++-$gccversion - _add_apt g++-$gccversion-multilib - _add_apt libstdc++-$gccversion-dev - _add_apt lib32stdc++-$gccversion-dev -} - -# add a clang compiler -function _c4_addclang() -{ - clversion=$1 - case $clversion in - # in 18.04, clang9 and later require PPAs - 9 | 10 | 11 | 12 | 13 | 14) - _add_apt clang-$clversion "deb http://apt.llvm.org/$UBUNTU_RELEASE_NAME/ llvm-toolchain-$UBUNTU_RELEASE_NAME-$clversion main" - # libstdc++ is required - #_c4_addgcc 12 - _c4_addgcc 11 - _c4_addgcc 10 - _c4_addgcc 9 - ;; - "") - _add_apt clang - ;; - *) - _add_apt clang-$clversion - ;; - esac - _add_apt g++-multilib # this is required for 32 bit https://askubuntu.com/questions/1057341/unable-to-find-stl-headers-in-ubuntu-18-04 - _add_apt clang-tidy-$clversion -} - -# add libc++ -function _c4_addlibcxx() -{ - _add_apt clang - _add_apt libc++1 - _add_apt libc++abi-dev - _add_apt libc++-dev - #_add_apt libc++1:i386 - #_add_apt libc++abi-dev:i386 - #_add_apt libc++-dev:i386 -} - - -#------------------------------------------------------------------------------- - -# add a pip package to the list -function _add_pip() -{ - pkgs=$* - PIP_PKG="$PIP_PKG $pkgs" - echo "adding to pip packages: $pkgs" -} - -# add a debian package to the list -function _add_apt() -{ - pkgs=$1 - sourceslist=$2 - APT_PKG="$APT_PKG $pkgs" - echo "adding to apt packages: $pkgs" - _add_src "$sourceslist" "# for packages: $pkgs" -} - -# add an apt source -function _add_src() -{ - sourceslist=$1 - comment=$2 - if [ ! -z "$sourceslist" ] ; then - echo "adding apt source: $sourceslist" - sudo bash -c "cat >> /etc/apt/sources.list < $coverage_service" - cmake --build $build_dir --config $BT --target ${PROJ_PFX_TARGET}coverage-submit-$coverage_service -} - -# WIP -function c4_run_static_analysis() -{ - if _c4skipbitlink "$1" ; then return 0 ; fi - id=$1 - linktype=$(_c4linktype $id) - build_dir=`pwd`/build/$id - # https://blog.kitware.com/static-checks-with-cmake-cdash-iwyu-clang-tidy-lwyu-cpplint-and-cppcheck/ - pushd $PROJ_DIR -} - -function c4_cfg_test() -{ - if _c4skipbitlink "$1" ; then return 0 ; fi - id=$1 - # - build_dir=`pwd`/build/$id - install_dir=`pwd`/install/$id - mkdir -p $build_dir - mkdir -p $install_dir - # - if [ "$TOOLCHAIN" != "" ] ; then - toolchain_file=`pwd`/$TOOLCHAIN - if [ ! -f "$toolchain_file" ] ; then - echo "ERROR: toolchain not found: $toolchain_file" - exit 1 - fi - _addcmkflags -DCMAKE_TOOLCHAIN_FILE=$toolchain_file - else - bits=$(_c4bits $id) - linktype=$(_c4linktype $id) - case "$linktype" in - static) _addcmkflags -DBUILD_SHARED_LIBS=OFF ;; - shared) _addcmkflags -DBUILD_SHARED_LIBS=ON ;; - *) - echo "ERROR: unknown linktype: $linktype" - exit 1 - ;; - esac - fi - if [ "$STD" != "" ] ; then - _addcmkflags -DC4_CXX_STANDARD=$STD - _addprojflags CXX_STANDARD=$STD - fi - if [ "$LIBCXX" != "" ] ; then - _addprojflags USE_LIBCXX=$LIBCXX - fi - # - if [ "$DEV" != "OFF" ] ; then - _addprojflags DEV=ON - fi - case "$LINT" in - all ) _addprojflags LINT=ON LINT_TESTS=ON LINT_CLANG_TIDY=ON LINT_PVS_STUDIO=ON ;; - clang-tidy) _addprojflags LINT=ON LINT_TESTS=ON LINT_CLANG_TIDY=ON LINT_PVS_STUDIO=OFF ;; - pvs-studio) _addprojflags LINT=ON LINT_TESTS=ON LINT_CLANG_TIDY=OFF LINT_PVS_STUDIO=ON ;; - * ) _addprojflags LINT=OFF ;; - esac - case "$SAN" in - ALL) _addprojflags SANITIZE=ON ;; - A ) _addprojflags SANITIZE=ON ASAN=ON TSAN=OFF MSAN=OFF UBSAN=OFF ;; - T ) _addprojflags SANITIZE=ON ASAN=OFF TSAN=ON MSAN=OFF UBSAN=OFF ;; - M ) _addprojflags SANITIZE=ON ASAN=OFF TSAN=OFF MSAN=ON UBSAN=OFF ;; - UB ) _addprojflags SANITIZE=ON ASAN=OFF TSAN=OFF MSAN=OFF UBSAN=ON ;; - * ) _addprojflags SANITIZE=OFF ;; - esac - case "$SAN_ONLY" in - ON) _addprojflags SANITIZE_ONLY=ON ;; - * ) _addprojflags SANITIZE_ONLY=OFF ;; - esac - case "$VG" in - ON) _addprojflags VALGRIND=ON VALGRIND_SGCHECK=OFF ;; # FIXME SGCHECK should be ON - * ) _addprojflags VALGRIND=OFF VALGRIND_SGCHECK=OFF ;; - esac - case "$BM" in - ON) _addprojflags BUILD_BENCHMARKS=ON ;; - * ) _addprojflags BUILD_BENCHMARKS=OFF ;; - esac - if [ "$BT" == "Coverage" ] ; then - # the coverage repo tokens can be set in the travis environment: - # export CODECOV_TOKEN=....... - # export COVERALLS_REPO_TOKEN=....... - _addprojflags COVERAGE_CODECOV=ON COVERAGE_CODECOV_SILENT=ON - _addprojflags COVERAGE_COVERALLS=ON COVERAGE_COVERALLS_SILENT=OFF - fi - if [ ! -z "$VERBOSE_MAKEFILES" ] ; then - _addcmkflags -DCMAKE_VERBOSE_MAKEFILES=$VERBOSE_MAKEFILES - fi - _addcmkflags -DCMAKE_EXPORT_COMPILE_COMMANDS=ON - if [ ! -z "$CMAKE_FLAGS" ] ; then - _addcmkflags $CMAKE_FLAGS - fi - - echo "building with additional cmake flags: $CMFLAGS" - - export C4_EXTERN_DIR=`pwd`/build/extern - mkdir -p $C4_EXTERN_DIR - - cmake --version - pwd - - # - # bash quote handling is a fiasco, and I could not find a way of storing - # quoted strings in variables and then expand the variables with correct quotes - # so we have to do this precious jewell of chicanery: - case "$CXX_" in - vs2022) - g='Visual Studio 17 2022' - case "$bits" in - 64) a=x64 ;; - 32) a=Win32 ;; - esac - cmake -S $PROJ_DIR -B $build_dir -DCMAKE_INSTALL_PREFIX="$install_dir" \ - -DCMAKE_BUILD_TYPE=$BT -G "$g" -A $a $CMFLAGS - ;; - vs2019) - g='Visual Studio 16 2019' - case "$bits" in - 64) a=x64 ;; - 32) a=Win32 ;; - esac - cmake -S $PROJ_DIR -B $build_dir -DCMAKE_INSTALL_PREFIX="$install_dir" \ - -DCMAKE_BUILD_TYPE=$BT -G "$g" -A $a $CMFLAGS - ;; - vs2017) - case "$bits" in - 64) g="Visual Studio 15 2017 Win64" ;; - 32) g="Visual Studio 15 2017" ;; - esac - cmake -S $PROJ_DIR -B $build_dir -DCMAKE_INSTALL_PREFIX="$install_dir" \ - -DCMAKE_BUILD_TYPE=$BT -G "$g" $CMFLAGS - ;; - xcode) - g=Xcode - case "$bits" in - 64) a="x86_64" ;; - 32) a="i386" - exit 1 # i386 is deprecated in xcode - ;; - esac - cmake -S $PROJ_DIR -B $build_dir -DCMAKE_INSTALL_PREFIX="$install_dir" \ - -DCMAKE_BUILD_TYPE=$BT -G "$g" -DCMAKE_OSX_ARCHITECTURES=$a $CMFLAGS - ;; - arm*|"") # make sure arm* comes before *g++ or *gcc* - cmake -S $PROJ_DIR -B $build_dir -DCMAKE_INSTALL_PREFIX="$install_dir" \ - -DCMAKE_BUILD_TYPE=$BT $CMFLAGS - ;; - *mingw*) - export CC_=$(echo "$CXX_" | sed 's:clang++:clang:g' | sed 's:g++:gcc:g') - cmake -S $PROJ_DIR -B $build_dir -DCMAKE_INSTALL_PREFIX="$install_dir" \ - -G "MinGW Makefiles" \ - -DCMAKE_BUILD_TYPE=$BT $CMFLAGS \ - -DCMAKE_C_COMPILER=$CC_ -DCMAKE_CXX_COMPILER=$CXX_ \ - -DCMAKE_C_FLAGS="-m$bits" -DCMAKE_CXX_FLAGS="-m$bits" - cmake --build $build_dir --target help | sed 1d | sort - ;; - *g++*|*gcc*|*clang*) - export CC_=$(echo "$CXX_" | sed 's:clang++:clang:g' | sed 's:g++:gcc:g') - _c4_choose_clang_tidy $CXX_ - cmake -S $PROJ_DIR -B $build_dir -DCMAKE_INSTALL_PREFIX="$install_dir" \ - -DCMAKE_BUILD_TYPE=$BT $CMFLAGS \ - -DCMAKE_C_COMPILER=$CC_ -DCMAKE_CXX_COMPILER=$CXX_ \ - -DCMAKE_C_FLAGS="-m$bits" -DCMAKE_CXX_FLAGS="-m$bits" - cmake --build $build_dir --target help | sed 1d | sort - ;; - em++) - emcmake cmake -S $PROJ_DIR -B $build_dir -DCMAKE_INSTALL_PREFIX="$install_dir" \ - -DCMAKE_BUILD_TYPE=$BT $CMFLAGS \ - -DCMAKE_CXX_FLAGS="-s DISABLE_EXCEPTION_CATCHING=0" \ - -DRYML_TEST_TOOLS=OFF - ;; - *) - echo "unknown compiler" - exit 1 - ;; - esac -} - -function _c4_choose_clang_tidy() -{ - cxx=$1 - # only for clang compilers. - case $cxx in - clang*) - # try with version first - clang_tidy_ver=$(echo $cxx | sed "s:++:-tidy:") - clang_tidy=$(echo $cxx | sed "s:++.*:-tidy:") - for n in $clang_tidy_ver $clang_tidy ; do - exe=$(which $n) - echo "searching for $n: $exe" - if [ -z "$exe" ] ; then - echo "could not find $clang_tidy" - else - _addcmkflags "-DCLANG_TIDY=$exe" - return 0 - fi - done - echo "error: could not find clang-tidy for $cxx" - exit 1 - ;; - esac -} - -# add cmake flags without project prefix -function _addcmkflags() -{ - for f in $* ; do - CMFLAGS="$CMFLAGS ${f}" - done -} - -# add cmake flags with project prefix -function _addprojflags() -{ - for f in $* ; do - CMFLAGS="$CMFLAGS -D${PROJ_PFX_CMAKE}${f}" - done -} - -function _c4_parallel_build_flags() -{ - case "$CXX_" in - vs2022|vs2019|vs2017|vs2015) - # https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild-command-line-reference?view=vs-2019 - # https://stackoverflow.com/questions/2619198/how-to-get-number-of-cores-in-win32 - if [ -z "$NUM_JOBS_BUILD" ] ; then - echo "/maxcpucount:$NUMBER_OF_PROCESSORS" - else - echo "/maxcpucount:$NUM_JOBS_BUILD" - fi - ;; - xcode) - # https://stackoverflow.com/questions/5417835/how-to-modify-the-number-of-parallel-compilation-with-xcode - # https://gist.github.com/nlutsenko/ee245fbd239087d22137 - if [ -z "$NUM_JOBS_BUILD" ] ; then - echo "-IDEBuildOperationMaxNumberOfConcurrentCompileTasks=$(sysctl -n hw.ncpu)" - else - echo "-IDEBuildOperationMaxNumberOfConcurrentCompileTasks=$NUM_JOBS_BUILD" - fi - ;; - *g++*|*gcc*|*clang*|em++) - if [ -z "$NUM_JOBS_BUILD" ] ; then - echo "-j $(nproc)" - else - echo "-j $NUM_JOBS_BUILD" - fi - ;; - "") # allow empty compiler - ;; - *) - echo "unknown compiler" - exit 1 - ;; - esac -} - -function _c4_generator_build_flags() -{ - case "$CXX_" in - vs2022|vs2019|vs2017|vs2015) - ;; - xcode) - # WTF??? - # https://github.com/biojppm/rapidyaml/pull/97/checks?check_run_id=1504677928#step:7:964 - # https://stackoverflow.com/questions/51153525/xcode-10-unable-to-attach-db-error - echo "-UseModernBuildSystem=NO" - ;; - *g++*|*gcc*|*clang*|em++) - ;; - "") # allow empty compiler - ;; - *) - echo "unknown compiler" - exit 1 - ;; - esac -} diff --git a/thirdparty/ryml/.github/workflows/benchmarks.yml b/thirdparty/ryml/.github/workflows/benchmarks.yml deleted file mode 100644 index 61654643f..000000000 --- a/thirdparty/ryml/.github/workflows/benchmarks.yml +++ /dev/null @@ -1,147 +0,0 @@ -name: benchmarks - -defaults: - run: - # Use a bash shell so we can use the same syntax for environment variable - # access regardless of the host operating system - shell: bash -e -x {0} - -on: - # https://github.community/t/how-to-trigger-an-action-on-push-or-pull-request-but-not-both/16662 - workflow_dispatch: - push: - branches: - - master - pull_request: - branches: - - master - -env: - PROJ_PFX_TARGET: ryml- - PROJ_PFX_CMAKE: RYML_ - CMAKE_FLAGS: -DRYML_TEST_SUITE=ON - NUM_JOBS_BUILD: # 4 - - -jobs: - - gettag: - runs-on: ubuntu-latest - steps: - # use fetch-depth to ensure all tags are fetched - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive, fetch-depth: 0}} - - name: Variables (from tag) - if: contains(github.ref, 'tags/v') - run: | - # https://github.community/t/how-to-get-just-the-tag-name/16241/11 - SRC_TAG=${GITHUB_REF#refs/tags/} - SRC_VERSION=${GITHUB_REF#refs/tags/v} - cat < vars.sh - export SRC_TAG=$SRC_TAG - export SRC_VERSION=$SRC_VERSION - EOF - - name: Variables (from commit, no tag) - if: ${{ !contains(github.ref, 'tags/v') }} - run: | - set -x - branch_name=${GITHUB_REF#refs/heads/} - # builds triggered from PRs have the branch_name like this: refs/pull/150/merge - # so filter to eg pr0150_merge - branch_name=`echo $branch_name | sed "s:refs/pull/\([0-9]*\)/\(.*\):pr0\1_\2:"` - # sanitize the branch name; eg merge/foo-bar -> merge_foo_bar - branch_name=`echo $branch_name | sed 's:[/.-]:_:g'` - git config --global --add safe.directory $(pwd) - SRC_TAG=$(git describe || git rev-parse --short HEAD) # eg v0.2.0-110-gda837e0 - SRC_VERSION="${branch_name}-${SRC_TAG}" - cat < vars.sh - export SRC_TAG=$SRC_TAG - export SRC_VERSION=$SRC_VERSION - EOF - - name: Verify vars.sh - run: cat vars.sh ; source vars.sh ; echo $SRC_TAG ; echo $SRC_VERSION - - name: Save vars.sh - uses: actions/upload-artifact@v3 - with: {name: vars.sh, path: ./vars.sh} - - benchmarks: - name: bm/c++${{matrix.std}}/${{matrix.cxx}}/${{matrix.bt}} - needs: gettag - if: | - (!contains(github.event.head_commit.message, 'skip all')) || - (!contains(github.event.head_commit.message, 'skip benchmarks')) || - contains(github.event.head_commit.message, 'only benchmarks') - continue-on-error: true - runs-on: ${{matrix.os}} - strategy: - fail-fast: false - matrix: - include: - - {std: 11, cxx: g++-10, bt: Release, os: ubuntu-20.04, bitlinks: static64 static32} - - {std: 17, cxx: g++-10, bt: Release, os: ubuntu-20.04, bitlinks: static64 static32} - - {std: 20, cxx: g++-10, bt: Release, os: ubuntu-20.04, bitlinks: static64 static32} - # - - {std: 17, cxx: vs2019, bt: Release, os: windows-2019, bitlinks: static64 static32} - - {std: 20, cxx: vs2019, bt: Release, os: windows-2019, bitlinks: static64 static32} - - {std: 17, cxx: vs2022, bt: Release, os: windows-2022, bitlinks: static64 static32} - - {std: 20, cxx: vs2022, bt: Release, os: windows-2022, bitlinks: static64 static32} - # - - {std: 17, cxx: xcode, xcver: 13, bt: Release, os: macos-11, bitlinks: static64} - env: {BM: ON, STD: "${{matrix.std}}", CXX_: "${{matrix.cxx}}", BT: "${{matrix.bt}}", BITLINKS: "${{matrix.bitlinks}}", VG: "${{matrix.vg}}", SAN: "${{matrix.san}}", LINT: "${{matrix.lint}}", OS: "${{matrix.os}}"} - steps: - # use fetch-depth to ensure all tags are fetched - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive, fetch-depth: 0}} - - {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS} - - name: Download vars.sh - uses: actions/download-artifact@v3 - with: {name: vars.sh, path: ./} - - {name: show info, run: source .github/setenv.sh && c4_show_info} - - name: Install python 3.10 for plotting - uses: actions/setup-python@v4 - with: { python-version: '3.10' } - - name: install benchmark plotting dependencies - run: | - which python - which pip - python --version - pip --version - pip install -v -r ext/c4core/cmake/bm-xp/requirements.txt - python -c 'import munch ; print("ok!") ; exit(0)' - echo $? - - name: shared64-configure--------------------------------------------------- - run: export CMAKE_FLAGS="-DPython_EXECUTABLE=$(which python)" && source .github/setenv.sh && c4_cfg_test shared64 - - {name: shared64-build, run: source .github/setenv.sh && c4_build_target shared64 ryml-bm-build} - - {name: shared64-run, run: export NUM_JOBS_BUILD=1 && source .github/setenv.sh && c4_run_target shared64 ryml-bm-run} - - {name: shared64-plot, run: export NUM_JOBS_BUILD=1 && source .github/setenv.sh && c4_run_target shared64 ryml-bm-plot} - - name: static64-configure--------------------------------------------------- - run: export CMAKE_FLAGS="-DPython_EXECUTABLE=$(which python)" && source .github/setenv.sh && c4_cfg_test static64 - - {name: static64-build, run: source .github/setenv.sh && c4_build_target static64 ryml-bm-build} - - {name: static64-run, run: export NUM_JOBS_BUILD=1 && source .github/setenv.sh && c4_run_target static64 ryml-bm-run} - - {name: static64-plot, run: export NUM_JOBS_BUILD=1 && source .github/setenv.sh && c4_run_target static64 ryml-bm-plot} - - name: static32-configure--------------------------------------------------- - run: export CMAKE_FLAGS="-DPython_EXECUTABLE=$(which python)" && source .github/setenv.sh && c4_cfg_test static32 - - {name: static32-build, run: source .github/setenv.sh && c4_build_target static32 ryml-bm-build} - - {name: static32-run, run: export NUM_JOBS_BUILD=1 && source .github/setenv.sh && c4_run_target static32 ryml-bm-run} - - {name: static32-plot, run: export NUM_JOBS_BUILD=1 && source .github/setenv.sh && c4_run_target static32 ryml-bm-plot} - - name: shared32-configure--------------------------------------------------- - run: export CMAKE_FLAGS="-DPython_EXECUTABLE=$(which python)" && source .github/setenv.sh && c4_cfg_test shared32 - - {name: shared32-build, run: source .github/setenv.sh && c4_build_target shared32 ryml-bm-build} - - {name: shared32-run, run: export NUM_JOBS_BUILD=1 && source .github/setenv.sh && c4_run_target shared32 ryml-bm-run} - - {name: shared32-plot, run: export NUM_JOBS_BUILD=1 && source .github/setenv.sh && c4_run_target shared32 ryml-bm-plot} - - name: gather benchmark results - run: | - set -x - source vars.sh - echo SRC_TAG=$SRC_TAG - echo SRC_VERSION=$SRC_VERSION - desc=$SRC_TAG - for bl in ${{matrix.bitlinks}} ; do - dst=$(echo ryml-benchmark_results/$desc/x86_64/${{matrix.cxx}}-${{matrix.bt}}-c++${{matrix.std}}-$bl | sed 's:++-:xx:g' | sed 's:+:x:g') - mkdir -p $dst - find build -name bm-results - mv -vf build/$bl/bm/bm-results/* $dst/. - done - - name: upload benchmark result artifacts - uses: actions/upload-artifact@v3 - with: - name: ryml-benchmark_results - path: ryml-benchmark_results/ diff --git a/thirdparty/ryml/.github/workflows/clang.yml b/thirdparty/ryml/.github/workflows/clang.yml deleted file mode 100644 index f0b7ad009..000000000 --- a/thirdparty/ryml/.github/workflows/clang.yml +++ /dev/null @@ -1,262 +0,0 @@ -name: clang - -defaults: - run: - # Use a bash shell so we can use the same syntax for environment variable - # access regardless of the host operating system - shell: bash -e -x {0} - -on: - # https://github.community/t/how-to-trigger-an-action-on-push-or-pull-request-but-not-both/16662 - workflow_dispatch: - push: - branches: - - master - pull_request: - branches: - - master - -env: - PROJ_PFX_TARGET: ryml- - PROJ_PFX_CMAKE: RYML_ - CMAKE_FLAGS: -DRYML_TEST_SUITE=ON - NUM_JOBS_BUILD: # 4 - - -jobs: - clang_canary: - name: ${{matrix.cxx}}/canary/c++${{matrix.std}}/${{matrix.bt}} - if: | - (!contains(github.event.head_commit.message, 'skip all')) || - (!contains(github.event.head_commit.message, 'skip clang')) || - contains(github.event.head_commit.message, 'only clang') - continue-on-error: true - runs-on: ${{matrix.os}} - strategy: - fail-fast: false - matrix: - include: - - {std: 17, cxx: clang++-10 , bt: Debug , os: ubuntu-20.04, bitlinks: shared64 static32} - - {std: 17, cxx: clang++-10 , bt: Release, os: ubuntu-20.04, bitlinks: shared64 static32} - - {std: 20, cxx: clang++-10 , bt: Debug , os: ubuntu-20.04, bitlinks: shared64 static32} - - {std: 20, cxx: clang++-10 , bt: Release, os: ubuntu-20.04, bitlinks: shared64 static32} - - {std: 11, cxx: clang++-6.0, bt: Debug , os: ubuntu-20.04, bitlinks: shared64 static32} - - {std: 11, cxx: clang++-6.0, bt: Release, os: ubuntu-20.04, bitlinks: shared64 static32} - env: {STD: "${{matrix.std}}", CXX_: "${{matrix.cxx}}", BT: "${{matrix.bt}}", BITLINKS: "${{matrix.bitlinks}}", - CMAKE_FLAGS: "${{matrix.cmkflags}}", - VG: "${{matrix.vg}}", SAN: "${{matrix.san}}", LINT: "${{matrix.lint}}", OS: "${{matrix.os}}"} - steps: - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} - - {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS} - - {name: show info, run: source .github/setenv.sh && c4_show_info} - - name: shared64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared64 - - {name: shared64-build, run: source .github/setenv.sh && c4_build_test shared64} - - {name: shared64-run, run: source .github/setenv.sh && c4_run_test shared64} - - {name: shared64-pack, run: source .github/setenv.sh && c4_package shared64} - - name: static64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static64 - - {name: static64-build, run: source .github/setenv.sh && c4_build_test static64} - - {name: static64-run, run: source .github/setenv.sh && c4_run_test static64} - - {name: static64-pack, run: source .github/setenv.sh && c4_package static64} - - name: static32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static32 - - {name: static32-build, run: source .github/setenv.sh && c4_build_test static32} - - {name: static32-run, run: source .github/setenv.sh && c4_run_test static32} - - {name: static32-pack, run: source .github/setenv.sh && c4_package static32} - - name: shared32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared32 - - {name: shared32-build, run: source .github/setenv.sh && c4_build_test shared32} - - {name: shared32-run, run: source .github/setenv.sh && c4_run_test shared32} - - {name: shared32-pack, run: source .github/setenv.sh && c4_package shared32} - - clang_canary_tabtokens: - name: tabtokens/${{matrix.cxx}}/canary/c++${{matrix.std}}/${{matrix.bt}} - if: | - (!contains(github.event.head_commit.message, 'skip all')) || - (!contains(github.event.head_commit.message, 'skip clang')) || - contains(github.event.head_commit.message, 'only clang') - continue-on-error: true - runs-on: ${{matrix.os}} - strategy: - fail-fast: false - matrix: - include: - - {std: 17, cxx: clang++-10 , bt: Debug , os: ubuntu-20.04, bitlinks: static64, cmkflags: "-DRYML_WITH_TAB_TOKENS=ON"} - - {std: 17, cxx: clang++-10 , bt: Release, os: ubuntu-20.04, bitlinks: static64, cmkflags: "-DRYML_WITH_TAB_TOKENS=ON"} - - {std: 20, cxx: clang++-10 , bt: Debug , os: ubuntu-20.04, bitlinks: static64, cmkflags: "-DRYML_WITH_TAB_TOKENS=ON"} - - {std: 20, cxx: clang++-10 , bt: Release, os: ubuntu-20.04, bitlinks: static64, cmkflags: "-DRYML_WITH_TAB_TOKENS=ON"} - - {std: 11, cxx: clang++-6.0, bt: Debug , os: ubuntu-20.04, bitlinks: static64, cmkflags: "-DRYML_WITH_TAB_TOKENS=ON"} - - {std: 11, cxx: clang++-6.0, bt: Release, os: ubuntu-20.04, bitlinks: static64, cmkflags: "-DRYML_WITH_TAB_TOKENS=ON"} - env: {STD: "${{matrix.std}}", CXX_: "${{matrix.cxx}}", BT: "${{matrix.bt}}", BITLINKS: "${{matrix.bitlinks}}", - CMAKE_FLAGS: "${{matrix.cmkflags}}", - VG: "${{matrix.vg}}", SAN: "${{matrix.san}}", LINT: "${{matrix.lint}}", OS: "${{matrix.os}}"} - steps: - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} - - {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS} - - {name: show info, run: source .github/setenv.sh && c4_show_info} - - name: shared64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared64 - - {name: shared64-build, run: source .github/setenv.sh && c4_build_test shared64} - - {name: shared64-run, run: source .github/setenv.sh && c4_run_test shared64} - - {name: shared64-pack, run: source .github/setenv.sh && c4_package shared64} - - name: static64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static64 - - {name: static64-build, run: source .github/setenv.sh && c4_build_test static64} - - {name: static64-run, run: source .github/setenv.sh && c4_run_test static64} - - {name: static64-pack, run: source .github/setenv.sh && c4_package static64} - - name: static32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static32 - - {name: static32-build, run: source .github/setenv.sh && c4_build_test static32} - - {name: static32-run, run: source .github/setenv.sh && c4_run_test static32} - - {name: static32-pack, run: source .github/setenv.sh && c4_package static32} - - name: shared32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared32 - - {name: shared32-build, run: source .github/setenv.sh && c4_build_test shared32} - - {name: shared32-run, run: source .github/setenv.sh && c4_run_test shared32} - - {name: shared32-pack, run: source .github/setenv.sh && c4_package shared32} - - #---------------------------------------------------------------------------- - clang_extended: - name: ${{matrix.cxx}}/extended/c++${{matrix.std}}/${{matrix.bt}} - needs: clang_canary - if: | - (!contains(github.event.head_commit.message, 'skip all')) || - (!contains(github.event.head_commit.message, 'skip clang')) || - contains(github.event.head_commit.message, 'only clang') - continue-on-error: true - runs-on: ${{matrix.os}} - strategy: - fail-fast: false - matrix: - include: - - {std: 11, cxx: clang++-10 , bt: Debug , vg: on, os: ubuntu-20.04} - - {std: 11, cxx: clang++-10 , bt: Release, vg: on, os: ubuntu-20.04} - env: {STD: "${{matrix.std}}", CXX_: "${{matrix.cxx}}", BT: "${{matrix.bt}}", BITLINKS: "${{matrix.bitlinks}}", - CMAKE_FLAGS: "${{matrix.cmkflags}}", - VG: "${{matrix.vg}}", SAN: "${{matrix.san}}", LINT: "${{matrix.lint}}", OS: "${{matrix.os}}"} - steps: - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} - - {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS} - - {name: show info, run: source .github/setenv.sh && c4_show_info} - - name: shared64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared64 - - {name: shared64-build, run: source .github/setenv.sh && c4_build_test shared64} - - {name: shared64-run, run: source .github/setenv.sh && c4_run_test shared64} - - {name: shared64-pack, run: source .github/setenv.sh && c4_package shared64} - - name: static64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static64 - - {name: static64-build, run: source .github/setenv.sh && c4_build_test static64} - - {name: static64-run, run: source .github/setenv.sh && c4_run_test static64} - - {name: static64-pack, run: source .github/setenv.sh && c4_package static64} - - name: static32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static32 - - {name: static32-build, run: source .github/setenv.sh && c4_build_test static32} - - {name: static32-run, run: source .github/setenv.sh && c4_run_test static32} - - {name: static32-pack, run: source .github/setenv.sh && c4_package static32} - - name: shared32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared32 - - {name: shared32-build, run: source .github/setenv.sh && c4_build_test shared32} - - {name: shared32-run, run: source .github/setenv.sh && c4_run_test shared32} - - {name: shared32-pack, run: source .github/setenv.sh && c4_package shared32} - - #---------------------------------------------------------------------------- - clang_sanitize: - name: ${{matrix.cxx}}/san/c++${{matrix.std}}/${{matrix.bt}} - needs: clang_canary - if: | - (!contains(github.event.head_commit.message, 'skip all')) || - (!contains(github.event.head_commit.message, 'skip clang')) || - contains(github.event.head_commit.message, 'only clang') - continue-on-error: true - runs-on: ${{matrix.os}} - strategy: - fail-fast: false - matrix: - include: - # these jobs take much longer, so run only one bitlink pair per job to profit from parallelism - - {std: 11, cxx: clang++-10, bt: Debug , vg: ON, san: ALL, bitlinks: shared64, os: ubuntu-20.04} - - {std: 11, cxx: clang++-10, bt: Debug , vg: ON, san: ALL, bitlinks: static64, os: ubuntu-20.04} - - {std: 11, cxx: clang++-10, bt: Debug , vg: ON, san: ALL, bitlinks: shared32, os: ubuntu-20.04} - - {std: 11, cxx: clang++-10, bt: Debug , vg: ON, san: ALL, bitlinks: static32, os: ubuntu-20.04} - - {std: 11, cxx: clang++-10, bt: Release, vg: ON, san: ALL, bitlinks: shared64, os: ubuntu-20.04} - - {std: 11, cxx: clang++-10, bt: Release, vg: ON, san: ALL, bitlinks: static64, os: ubuntu-20.04} - - {std: 11, cxx: clang++-10, bt: Release, vg: ON, san: ALL, bitlinks: shared32, os: ubuntu-20.04} - - {std: 11, cxx: clang++-10, bt: Release, vg: ON, san: ALL, bitlinks: static32, os: ubuntu-20.04} - - {std: 17, cxx: clang++-10, bt: Debug , vg: ON, san: ALL, bitlinks: shared64, os: ubuntu-20.04} - - {std: 17, cxx: clang++-10, bt: Debug , vg: ON, san: ALL, bitlinks: static64, os: ubuntu-20.04} - - {std: 17, cxx: clang++-10, bt: Debug , vg: ON, san: ALL, bitlinks: shared32, os: ubuntu-20.04} - - {std: 17, cxx: clang++-10, bt: Debug , vg: ON, san: ALL, bitlinks: static32, os: ubuntu-20.04} - - {std: 17, cxx: clang++-10, bt: Release, vg: ON, san: ALL, bitlinks: shared64, os: ubuntu-20.04} - - {std: 17, cxx: clang++-10, bt: Release, vg: ON, san: ALL, bitlinks: static64, os: ubuntu-20.04} - - {std: 17, cxx: clang++-10, bt: Release, vg: ON, san: ALL, bitlinks: shared32, os: ubuntu-20.04} - - {std: 17, cxx: clang++-10, bt: Release, vg: ON, san: ALL, bitlinks: static32, os: ubuntu-20.04} - - {std: 20, cxx: clang++-10, bt: Debug , vg: ON, san: ALL, bitlinks: shared64, os: ubuntu-20.04} - - {std: 20, cxx: clang++-10, bt: Debug , vg: ON, san: ALL, bitlinks: static64, os: ubuntu-20.04} - - {std: 20, cxx: clang++-10, bt: Debug , vg: ON, san: ALL, bitlinks: shared32, os: ubuntu-20.04} - - {std: 20, cxx: clang++-10, bt: Debug , vg: ON, san: ALL, bitlinks: static32, os: ubuntu-20.04} - - {std: 20, cxx: clang++-10, bt: Release, vg: ON, san: ALL, bitlinks: shared64, os: ubuntu-20.04} - - {std: 20, cxx: clang++-10, bt: Release, vg: ON, san: ALL, bitlinks: static64, os: ubuntu-20.04} - - {std: 20, cxx: clang++-10, bt: Release, vg: ON, san: ALL, bitlinks: shared32, os: ubuntu-20.04} - - {std: 20, cxx: clang++-10, bt: Release, vg: ON, san: ALL, bitlinks: static32, os: ubuntu-20.04} - env: {STD: "${{matrix.std}}", CXX_: "${{matrix.cxx}}", BT: "${{matrix.bt}}", BITLINKS: "${{matrix.bitlinks}}", VG: "${{matrix.vg}}", SAN: "${{matrix.san}}", LINT: "${{matrix.lint}}", OS: "${{matrix.os}}"} - steps: - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} - - {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS} - - {name: show info, run: source .github/setenv.sh && c4_show_info} - - name: shared64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared64 - - {name: shared64-build, run: source .github/setenv.sh && c4_build_test shared64} - - {name: shared64-run, run: source .github/setenv.sh && c4_run_test shared64} - - {name: shared64-pack, run: source .github/setenv.sh && c4_package shared64} - - name: static64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static64 - - {name: static64-build, run: source .github/setenv.sh && c4_build_test static64} - - {name: static64-run, run: source .github/setenv.sh && c4_run_test static64} - - {name: static64-pack, run: source .github/setenv.sh && c4_package static64} - - name: static32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static32 - - {name: static32-build, run: source .github/setenv.sh && c4_build_test static32} - - {name: static32-run, run: source .github/setenv.sh && c4_run_test static32} - - {name: static32-pack, run: source .github/setenv.sh && c4_package static32} - - name: shared32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared32 - - {name: shared32-build, run: source .github/setenv.sh && c4_build_test shared32} - - {name: shared32-run, run: source .github/setenv.sh && c4_run_test shared32} - - {name: shared32-pack, run: source .github/setenv.sh && c4_package shared32} - -# #---------------------------------------------------------------------------- -# # https://blog.kitware.com/static-checks-with-cmake-cdash-iwyu-clang-tidy-lwyu-cpplint-and-cppcheck/ -# static_analysis: -# if: | -# (!contains(github.event.head_commit.message, 'skip all')) || -# (!contains(github.event.head_commit.message, 'skip clang')) || -# contains(github.event.head_commit.message, 'only clang') -# continue-on-error: true -# runs-on: ${{matrix.os}} -# strategy: -# fail-fast: false -# matrix: -# include: -# # these jobs take much longer, so run only one bitlink pair per job to profit from parallelism -# - {std: 11, cxx: clang++-10, bt: Debug , bitlinks: shared64, os: ubuntu-20.04} -# - {std: 11, cxx: clang++-10, bt: Release, bitlinks: shared64, os: ubuntu-20.04} -# - {std: 14, cxx: clang++-10, bt: Debug , bitlinks: shared64, os: ubuntu-20.04} -# - {std: 14, cxx: clang++-10, bt: Release, bitlinks: shared64, os: ubuntu-20.04} -# - {std: 17, cxx: clang++-10, bt: Debug , bitlinks: shared64, os: ubuntu-20.04} -# - {std: 17, cxx: clang++-10, bt: Release, bitlinks: shared64, os: ubuntu-20.04} -# - {std: 20, cxx: clang++-10, bt: Debug , bitlinks: shared64, os: ubuntu-20.04} -# - {std: 20, cxx: clang++-10, bt: Release, bitlinks: shared64, os: ubuntu-20.04} -# env: {STD: "${{matrix.std}}", CXX_: "${{matrix.cxx}}", BT: "${{matrix.bt}}", BITLINKS: "${{matrix.bitlinks}}", VG: "${{matrix.vg}}", SAN: "${{matrix.san}}", LINT: "${{matrix.lint}}", OS: "${{matrix.os}}"} -# steps: -# - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} -# - {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS} -# - {name: show info, run: source .github/setenv.sh && c4_show_info} -# - name: shared64-configure--------------------------------------------------- -# run: source .github/setenv.sh && c4_cfg_test shared64 -# - {name: shared64-build, run: source .github/setenv.sh && c4_build_test shared64} -# - {name: clang-tidy, run: cmake "-DCMAKE_CXX_CLANG_TIDY=/usr/bin/clang-tidy-3.9;-checks=*" ../path/to/source} -# - {name: cppcheck, run: cmake "-DCMAKE_CXX_CPPCHECK=/usr/bin/cppcheck;--std=c++11" ../path/to/source} -# - {name: cpplint, run: cmake "-DCMAKE_CXX_CPPLINT=/usr/local/bin/cpplint;--linelength=179" ..} -# - {name: include-what-you-use, run: cmake "-DCMAKE_CXX_INCLUDE_WHAT_YOU_USE=/usr/bin/iwyu;--transitive_includes_only" ..} -# - {name: link-what-you-use, run: cmake -DCMAKE_LINK_WHAT_YOU_USE=TRUE ..} diff --git a/thirdparty/ryml/.github/workflows/clang_tidy.yml b/thirdparty/ryml/.github/workflows/clang_tidy.yml deleted file mode 100644 index 5c9a7d872..000000000 --- a/thirdparty/ryml/.github/workflows/clang_tidy.yml +++ /dev/null @@ -1,72 +0,0 @@ -name: clang_tidy - -defaults: - run: - # Use a bash shell so we can use the same syntax for environment variable - # access regardless of the host operating system - shell: bash -e -x {0} - -on: - # https://github.community/t/how-to-trigger-an-action-on-push-or-pull-request-but-not-both/16662 - workflow_dispatch: - push: - branches: - - master - pull_request: - branches: - - master - -env: - PROJ_PFX_TARGET: ryml- - PROJ_PFX_CMAKE: RYML_ - CMAKE_FLAGS: -DRYML_TEST_SUITE=ON - NUM_JOBS_BUILD: # 4 - - -jobs: - clang_tidy: - name: ${{matrix.cxx}}/tidy/c++${{matrix.std}}/${{matrix.bt}} - if: | - (!contains(github.event.head_commit.message, 'skip all')) || - (!contains(github.event.head_commit.message, 'skip clang')) || - contains(github.event.head_commit.message, 'only clang') - continue-on-error: false - runs-on: ${{matrix.os}} - strategy: - fail-fast: false - matrix: - include: - # clang tidy takes a long time, so don't do multiple bits/linktypes - - {std: 11, cxx: clang++-10, bt: Debug , lint: clang-tidy, bitlinks: shared64, os: ubuntu-20.04} - - {std: 11, cxx: clang++-10, bt: Debug , lint: clang-tidy, bitlinks: static64, os: ubuntu-20.04} - - {std: 11, cxx: clang++-10, bt: Debug , lint: clang-tidy, bitlinks: shared32, os: ubuntu-20.04} - - {std: 11, cxx: clang++-10, bt: Debug , lint: clang-tidy, bitlinks: static32, os: ubuntu-20.04} - - {std: 11, cxx: clang++-10, bt: ReleaseWithDebInfo, lint: clang-tidy, bitlinks: shared64, os: ubuntu-20.04} - - {std: 11, cxx: clang++-10, bt: ReleaseWithDebInfo, lint: clang-tidy, bitlinks: static64, os: ubuntu-20.04} - - {std: 11, cxx: clang++-10, bt: ReleaseWithDebInfo, lint: clang-tidy, bitlinks: shared32, os: ubuntu-20.04} - - {std: 11, cxx: clang++-10, bt: ReleaseWithDebInfo, lint: clang-tidy, bitlinks: static32, os: ubuntu-20.04} - env: {STD: "${{matrix.std}}", CXX_: "${{matrix.cxx}}", BT: "${{matrix.bt}}", BITLINKS: "${{matrix.bitlinks}}", VG: "${{matrix.vg}}", SAN: "${{matrix.san}}", LINT: "${{matrix.lint}}", OS: "${{matrix.os}}"} - steps: - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} - - {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS} - - {name: show info, run: source .github/setenv.sh && c4_show_info} - - name: shared64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared64 - - {name: shared64-build, run: source .github/setenv.sh && c4_build_test shared64} - - {name: shared64-run, run: source .github/setenv.sh && c4_run_test shared64} - - {name: shared64-pack, run: source .github/setenv.sh && c4_package shared64} - - name: static64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static64 - - {name: static64-build, run: source .github/setenv.sh && c4_build_test static64} - - {name: static64-run, run: source .github/setenv.sh && c4_run_test static64} - - {name: static64-pack, run: source .github/setenv.sh && c4_package static64} - - name: static32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static32 - - {name: static32-build, run: source .github/setenv.sh && c4_build_test static32} - - {name: static32-run, run: source .github/setenv.sh && c4_run_test static32} - - {name: static32-pack, run: source .github/setenv.sh && c4_package static32} - - name: shared32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared32 - - {name: shared32-build, run: source .github/setenv.sh && c4_build_test shared32} - - {name: shared32-run, run: source .github/setenv.sh && c4_run_test shared32} - - {name: shared32-pack, run: source .github/setenv.sh && c4_package shared32} diff --git a/thirdparty/ryml/.github/workflows/codeql.yml b/thirdparty/ryml/.github/workflows/codeql.yml deleted file mode 100644 index 3ad8a5819..000000000 --- a/thirdparty/ryml/.github/workflows/codeql.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: "CodeQL" - -on: - push: - branches: [ "master" ] - pull_request: - branches: [ "master" ] - schedule: - - cron: "41 14 * * 5" - -jobs: - analyze: - name: Analyze - runs-on: ubuntu-latest - permissions: - actions: read - contents: read - security-events: write - - strategy: - fail-fast: false - matrix: - language: [ cpp ] - - steps: - - name: Checkout - uses: actions/checkout@v3 - with: - submodules: recursive - - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: ${{ matrix.language }} - config-file: ./.github/codeql.yml - queries: +security-and-quality - - - name: Autobuild - uses: github/codeql-action/autobuild@v2 - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 - with: - category: "/language:${{ matrix.language }}" diff --git a/thirdparty/ryml/.github/workflows/coverage.yml b/thirdparty/ryml/.github/workflows/coverage.yml deleted file mode 100644 index 52da02c56..000000000 --- a/thirdparty/ryml/.github/workflows/coverage.yml +++ /dev/null @@ -1,94 +0,0 @@ -name: coverage - -defaults: - run: - # Use a bash shell so we can use the same syntax for environment variable - # access regardless of the host operating system - shell: bash -e -x {0} - -on: - # https://github.community/t/how-to-trigger-an-action-on-push-or-pull-request-but-not-both/16662 - workflow_dispatch: - push: - branches: - - master - pull_request: - branches: - - master - -env: - PROJ_PFX_TARGET: ryml- - PROJ_PFX_CMAKE: RYML_ - CMAKE_FLAGS: -DRYML_TEST_SUITE=ON - NUM_JOBS_BUILD: # 4 - - -jobs: - #---------------------------------------------------------------------------- - coverage: - name: coverage/c++${{matrix.std}} - if: | - (!contains(github.event.head_commit.message, 'skip all')) || - (!contains(github.event.head_commit.message, 'skip coverage')) || - contains(github.event.head_commit.message, 'only coverage') - continue-on-error: true - runs-on: ${{matrix.os}} - strategy: - fail-fast: false - matrix: - include: - - {std: 11, cxx: g++-9, bt: Coverage, os: ubuntu-20.04} - - {std: 17, cxx: g++-9, bt: Coverage, os: ubuntu-20.04} - env: {STD: "${{matrix.std}}", CXX_: "${{matrix.cxx}}", BT: "${{matrix.bt}}", BITLINKS: "${{matrix.bitlinks}}", VG: "${{matrix.vg}}", SAN: "${{matrix.san}}", LINT: "${{matrix.lint}}", OS: "${{matrix.os}}", - CODECOV_TOKEN: "${{secrets.CODECOV_TOKEN}}", - COVERALLS_REPO_TOKEN: "${{secrets.COVERALLS_REPO_TOKEN}}", - # coveralls disabled: https://github.com/lemurheavy/coveralls-public/issues/1665 - # https://docs.coveralls.io/parallel-build-webhook - #COVERALLS_PARALLEL: true - } - steps: - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} - - {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS} - - {name: show info, run: source .github/setenv.sh && c4_show_info} - - name: static64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static64 - - {name: static64-build, run: source .github/setenv.sh && c4_build_test static64} - - {name: static64-coverage, run: source .github/setenv.sh && c4_run_target static64 ryml-coverage} - - name: static64-coverage-artifacts - uses: actions/upload-artifact@v3 - with: - name: coverage-static64-cxx${{matrix.std}} - path: | - build/static64/lcov - build/static64/coverage3-final_filtered.lcov - - {name: static64-submit-codecov, run: source .github/setenv.sh && c4_submit_coverage static64 codecov} - # coveralls disabled: https://github.com/lemurheavy/coveralls-public/issues/1665 - #- {name: static64-submit-coveralls, run: "if [ \"${{matrix.std}}\" == \"17\" ] ; then ( source .github/setenv.sh && c4_submit_coverage static64 coveralls ) ; fi" } - - name: static32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static32 - - {name: static32-build, run: source .github/setenv.sh && c4_build_test static32} - - {name: static32-coverage, run: source .github/setenv.sh && c4_run_target static32 ryml-coverage} - - name: static32-coverage-artifacts - uses: actions/upload-artifact@v3 - with: - name: coverage-static32-cxx${{matrix.std}} - path: | - build/static32/lcov - build/static32/coverage3-final_filtered.lcov - - {name: static32-submit-codecov, run: source .github/setenv.sh && c4_submit_coverage static32 codecov} - # coveralls disabled: https://github.com/lemurheavy/coveralls-public/issues/1665 - #- {name: static32-submit-coveralls, run: source .github/setenv.sh && c4_submit_coverage static32 coveralls} - - # coveralls disabled: https://github.com/lemurheavy/coveralls-public/issues/1665 - # https://github.com/lemurheavy/coveralls-public/issues/1665 - #coveralls_finish: - # needs: [coverage] - # runs-on: ubuntu-latest - # steps: - # - name: coveralls-notify - # #continue-on-error: true - # uses: coverallsapp/github-action@master - # with: - # github-token: ${{ secrets.github_token }} - # parallel-finished: true - diff --git a/thirdparty/ryml/.github/workflows/emscripten.yml b/thirdparty/ryml/.github/workflows/emscripten.yml deleted file mode 100644 index bc920d7ca..000000000 --- a/thirdparty/ryml/.github/workflows/emscripten.yml +++ /dev/null @@ -1,71 +0,0 @@ -name: emscripten - -defaults: - run: - # Use a bash shell so we can use the same syntax for environment variable - # access regardless of the host operating system - shell: bash -e -x {0} - -on: - # https://github.community/t/how-to-trigger-an-action-on-push-or-pull-request-but-not-both/16662 - workflow_dispatch: - push: - branches: - - master - pull_request: - branches: - - master - -env: - PROJ_PFX_TARGET: ryml- - PROJ_PFX_CMAKE: RYML_ - CMAKE_FLAGS: '-DRYML_TEST_SUITE=OFF' - NUM_JOBS_BUILD: # 4 - EMSCRIPTEN_CACHE_FOLDER: 'emsdk-cache' - -jobs: - - #---------------------------------------------------------------------------- - emscripten: - if: | - (!contains(github.event.head_commit.message, 'skip all')) || - (!contains(github.event.head_commit.message, 'skip emscripten')) || - contains(github.event.head_commit.message, 'only emscripten') - name: emscripten/${{matrix.emver}}/c++${{matrix.std}}/${{matrix.bt}} - continue-on-error: true - runs-on: ${{matrix.os}} - strategy: - fail-fast: false - matrix: - include: - #- {std: 11, cxx: em++, emver: 2.0.34, bt: Debug , os: ubuntu-latest, bitlinks: static32} - - {std: 11, cxx: em++, emver: 2.0.34, bt: Release, os: ubuntu-latest, bitlinks: static32} - #- {std: 20, cxx: em++, emver: 2.0.34, bt: Debug , os: ubuntu-latest, bitlinks: static32} - - {std: 20, cxx: em++, emver: 2.0.34, bt: Release, os: ubuntu-latest, bitlinks: static32} - #- {std: 11, cxx: em++, emver: 3.0.0 , bt: Debug , os: ubuntu-latest, bitlinks: static32} - - {std: 11, cxx: em++, emver: 3.0.0 , bt: Release, os: ubuntu-latest, bitlinks: static32} - #- {std: 20, cxx: em++, emver: 3.0.0 , bt: Debug , os: ubuntu-latest, bitlinks: static32} - - {std: 20, cxx: em++, emver: 3.0.0 , bt: Release, os: ubuntu-latest, bitlinks: static32} - env: - STD: "${{matrix.std}}" - CXX_: "${{matrix.cxx}}" - BT: "${{matrix.bt}}" - BITLINKS: "${{matrix.bitlinks}}" - VG: "${{matrix.vg}}" - SAN: "${{matrix.san}}" - LINT: "${{matrix.lint}}" - OS: "${{matrix.os}}" - steps: - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} - - name: setup emscripten cache - id: cache-system-libraries - uses: actions/cache@v3 - with: {path: "${{env.EMSCRIPTEN_CACHE_FOLDER}}", key: "${{matrix.emver}}-${{runner.os}}"} - - name: setup emscripten - uses: mymindstorm/setup-emsdk@v11 - with: {version: "${{matrix.emver}}", actions-cache-folder: "${{env.EMSCRIPTEN_CACHE_FOLDER}}"} - - {name: show info, run: source .github/setenv.sh && c4_show_info} - - name: static32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static32 - - {name: static32-build, run: source .github/setenv.sh && c4_build_test static32} - - {name: static32-run, run: source .github/setenv.sh && c4_run_test static32} diff --git a/thirdparty/ryml/.github/workflows/gcc.yml b/thirdparty/ryml/.github/workflows/gcc.yml deleted file mode 100644 index fd0337ed7..000000000 --- a/thirdparty/ryml/.github/workflows/gcc.yml +++ /dev/null @@ -1,168 +0,0 @@ -name: gcc - -defaults: - run: - # Use a bash shell so we can use the same syntax for environment variable - # access regardless of the host operating system - shell: bash -e -x {0} - -on: - # https://github.community/t/how-to-trigger-an-action-on-push-or-pull-request-but-not-both/16662 - workflow_dispatch: - push: - branches: - - master - pull_request: - branches: - - master - -env: - PROJ_PFX_TARGET: ryml- - PROJ_PFX_CMAKE: RYML_ - CMAKE_FLAGS: -DRYML_TEST_SUITE=ON - NUM_JOBS_BUILD: # 4 - - -jobs: - gcc_canary: - name: ${{matrix.cxx}}/canary/${{matrix.bt}} - if: | - (!contains(github.event.head_commit.message, 'skip all')) || - (!contains(github.event.head_commit.message, 'skip gcc')) || - contains(github.event.head_commit.message, 'only gcc') - continue-on-error: true - runs-on: ${{matrix.os}} - strategy: - fail-fast: false - matrix: - include: - - {std: 11, cxx: g++-7 , bt: Debug , os: ubuntu-20.04, bitlinks: shared64 static32} - - {std: 11, cxx: g++-7 , bt: Release, os: ubuntu-20.04, bitlinks: shared64 static32} - - {std: 20, cxx: g++-10 , bt: Debug , os: ubuntu-20.04, bitlinks: shared64 static32} - - {std: 20, cxx: g++-10 , bt: Release, os: ubuntu-20.04, bitlinks: shared64 static32} - - {std: 11, cxx: g++-5 , bt: Debug , os: ubuntu-20.04, bitlinks: shared64 static32} - - {std: 11, cxx: g++-5 , bt: Release, os: ubuntu-20.04, bitlinks: shared64 static32} - - {std: 11, cxx: g++-4.8 , bt: Debug, os: ubuntu-18.04, bitlinks: shared64 static32} - - {std: 11, cxx: g++-4.8 , bt: Release, os: ubuntu-18.04, bitlinks: shared64 static32} - env: {STD: "${{matrix.std}}", CXX_: "${{matrix.cxx}}", BT: "${{matrix.bt}}", BITLINKS: "${{matrix.bitlinks}}", VG: "${{matrix.vg}}", SAN: "${{matrix.san}}", LINT: "${{matrix.lint}}", OS: "${{matrix.os}}"} - steps: - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} - - {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS} - - {name: show info, run: source .github/setenv.sh && c4_show_info} - - name: shared64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared64 - - {name: shared64-build, run: source .github/setenv.sh && c4_build_test shared64} - - {name: shared64-run, run: source .github/setenv.sh && c4_run_test shared64} - - {name: shared64-pack, run: source .github/setenv.sh && c4_package shared64} - - name: static64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static64 - - {name: static64-build, run: source .github/setenv.sh && c4_build_test static64} - - {name: static64-run, run: source .github/setenv.sh && c4_run_test static64} - - {name: static64-pack, run: source .github/setenv.sh && c4_package static64} - - name: static32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static32 - - {name: static32-build, run: source .github/setenv.sh && c4_build_test static32} - - {name: static32-run, run: source .github/setenv.sh && c4_run_test static32} - - {name: static32-pack, run: source .github/setenv.sh && c4_package static32} - - name: shared32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared32 - - {name: shared32-build, run: source .github/setenv.sh && c4_build_test shared32} - - {name: shared32-run, run: source .github/setenv.sh && c4_run_test shared32} - - {name: shared32-pack, run: source .github/setenv.sh && c4_package shared32} - - gcc_tabtokens: - name: tabtokens/${{matrix.cxx}}/canary/${{matrix.bt}} - if: | - (!contains(github.event.head_commit.message, 'skip all')) || - (!contains(github.event.head_commit.message, 'skip gcc')) || - contains(github.event.head_commit.message, 'only gcc') - continue-on-error: true - runs-on: ${{matrix.os}} - strategy: - fail-fast: false - matrix: - include: - - {std: 11, cxx: g++-7 , bt: Debug , os: ubuntu-20.04, bitlinks: shared64 static32, cmkflags: "-DRYML_WITH_TAB_TOKENS=ON"} - - {std: 11, cxx: g++-7 , bt: Release, os: ubuntu-20.04, bitlinks: shared64 static32, cmkflags: "-DRYML_WITH_TAB_TOKENS=ON"} - - {std: 20, cxx: g++-10 , bt: Debug , os: ubuntu-20.04, bitlinks: shared64 static32, cmkflags: "-DRYML_WITH_TAB_TOKENS=ON"} - - {std: 20, cxx: g++-10 , bt: Release, os: ubuntu-20.04, bitlinks: shared64 static32, cmkflags: "-DRYML_WITH_TAB_TOKENS=ON"} - - {std: 11, cxx: g++-5 , bt: Debug , os: ubuntu-20.04, bitlinks: shared64 static32, cmkflags: "-DRYML_WITH_TAB_TOKENS=ON"} - - {std: 11, cxx: g++-5 , bt: Release, os: ubuntu-20.04, bitlinks: shared64 static32, cmkflags: "-DRYML_WITH_TAB_TOKENS=ON"} - env: {STD: "${{matrix.std}}", CXX_: "${{matrix.cxx}}", BT: "${{matrix.bt}}", BITLINKS: "${{matrix.bitlinks}}", - CMAKE_FLAGS: "${{matrix.cmkflags}}", - VG: "${{matrix.vg}}", SAN: "${{matrix.san}}", LINT: "${{matrix.lint}}", OS: "${{matrix.os}}"} - steps: - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} - - {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS} - - {name: show info, run: source .github/setenv.sh && c4_show_info} - - name: shared64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared64 - - {name: shared64-build, run: source .github/setenv.sh && c4_build_test shared64} - - {name: shared64-run, run: source .github/setenv.sh && c4_run_test shared64} - - {name: shared64-pack, run: source .github/setenv.sh && c4_package shared64} - - name: static64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static64 - - {name: static64-build, run: source .github/setenv.sh && c4_build_test static64} - - {name: static64-run, run: source .github/setenv.sh && c4_run_test static64} - - {name: static64-pack, run: source .github/setenv.sh && c4_package static64} - - name: static32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static32 - - {name: static32-build, run: source .github/setenv.sh && c4_build_test static32} - - {name: static32-run, run: source .github/setenv.sh && c4_run_test static32} - - {name: static32-pack, run: source .github/setenv.sh && c4_package static32} - - name: shared32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared32 - - {name: shared32-build, run: source .github/setenv.sh && c4_build_test shared32} - - {name: shared32-run, run: source .github/setenv.sh && c4_run_test shared32} - - {name: shared32-pack, run: source .github/setenv.sh && c4_package shared32} - - #---------------------------------------------------------------------------- - gcc_extended: - name: ${{matrix.cxx}}/extended/${{matrix.bt}} - needs: gcc_canary - if: | - (!contains(github.event.head_commit.message, 'skip all')) || - (!contains(github.event.head_commit.message, 'skip gcc')) || - contains(github.event.head_commit.message, 'only gcc') - continue-on-error: true - runs-on: ${{matrix.os}} - strategy: - fail-fast: false - matrix: - include: - # VALGRIND - - {std: 11, cxx: g++-10, bt: Debug , vg: ON, os: ubuntu-20.04} - - {std: 11, cxx: g++-10, bt: Release, vg: ON, os: ubuntu-20.04} - - {std: 14, cxx: g++-10, bt: Debug , vg: ON, os: ubuntu-20.04} - - {std: 14, cxx: g++-10, bt: Release, vg: ON, os: ubuntu-20.04} - - {std: 17, cxx: g++-10, bt: Debug , vg: ON, os: ubuntu-20.04} - - {std: 17, cxx: g++-10, bt: Release, vg: ON, os: ubuntu-20.04} - - {std: 20, cxx: g++-10, bt: Debug , vg: ON, os: ubuntu-20.04} - - {std: 20, cxx: g++-10, bt: Release, vg: ON, os: ubuntu-20.04} - - {std: 11, cxx: g++-4.8, bt: Debug, vg: ON, os: ubuntu-18.04} - - {std: 11, cxx: g++-4.8, bt: Release, vg: ON, os: ubuntu-18.04} - env: {STD: "${{matrix.std}}", CXX_: "${{matrix.cxx}}", BT: "${{matrix.bt}}", BITLINKS: "${{matrix.bitlinks}}", VG: "${{matrix.vg}}", SAN: "${{matrix.san}}", LINT: "${{matrix.lint}}", OS: "${{matrix.os}}"} - steps: - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} - - {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS} - - {name: show info, run: source .github/setenv.sh && c4_show_info} - - name: shared64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared64 - - {name: shared64-build, run: source .github/setenv.sh && c4_build_test shared64} - - {name: shared64-run, run: source .github/setenv.sh && c4_run_test shared64} - - {name: shared64-pack, run: source .github/setenv.sh && c4_package shared64} - - name: static64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static64 - - {name: static64-build, run: source .github/setenv.sh && c4_build_test static64} - - {name: static64-run, run: source .github/setenv.sh && c4_run_test static64} - - {name: static64-pack, run: source .github/setenv.sh && c4_package static64} - - name: static32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static32 - - {name: static32-build, run: source .github/setenv.sh && c4_build_test static32} - - {name: static32-run, run: source .github/setenv.sh && c4_run_test static32} - - {name: static32-pack, run: source .github/setenv.sh && c4_package static32} - - name: shared32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared32 - - {name: shared32-build, run: source .github/setenv.sh && c4_build_test shared32} - - {name: shared32-run, run: source .github/setenv.sh && c4_run_test shared32} - - {name: shared32-pack, run: source .github/setenv.sh && c4_package shared32} diff --git a/thirdparty/ryml/.github/workflows/install.yml b/thirdparty/ryml/.github/workflows/install.yml deleted file mode 100644 index b8b74c682..000000000 --- a/thirdparty/ryml/.github/workflows/install.yml +++ /dev/null @@ -1,105 +0,0 @@ -name: test_install - -defaults: - run: - # Use a bash shell so we can use the same syntax for environment variable - # access regardless of the host operating system - shell: bash -e -x {0} - -on: - # https://github.community/t/how-to-trigger-an-action-on-push-or-pull-request-but-not-both/16662 - workflow_dispatch: - push: - branches: - - master - pull_request: - branches: - - master - -env: - PROJ_PFX_TARGET: ryml- - PROJ_PFX_CMAKE: RYML_ - CMAKE_FLAGS: - NUM_JOBS_BUILD: # 4 - -jobs: - - #---------------------------------------------------------------------------- - install_tests: - if: | - (!contains(github.event.head_commit.message, 'skip all')) || - (!contains(github.event.head_commit.message, 'skip test_install')) || - contains(github.event.head_commit.message, 'only test_install') - name: ${{matrix.name}}/${{matrix.bt}} - continue-on-error: true - runs-on: ${{matrix.os}} - strategy: - fail-fast: false - matrix: - include: - - {name: find_package/linux , sdir: test/test_install , os: ubuntu-20.04, cxx: g++-10 , gen: "-DCMAKE_CXX_COMPILER=g++-10" , tgt: all , bt: Release, vars: "-Dryml_DIR=$GITHUB_WORKSPACE/$PDIR/lib/cmake/ryml -DRYML_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: } - - {name: find_package/linux , sdir: test/test_install , os: ubuntu-20.04, cxx: g++-10 , gen: "-DCMAKE_CXX_COMPILER=g++-10" , tgt: all , bt: Debug , vars: "-Dryml_DIR=$GITHUB_WORKSPACE/$PDIR/lib/cmake/ryml -DRYML_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: } - - {name: find_package/linux/libcxx, sdir: test/test_install , os: ubuntu-20.04, cxx: clang++-9, gen: "-DCMAKE_CXX_COMPILER=clang++-9" , tgt: all , bt: Release, vars: "-Dryml_DIR=$GITHUB_WORKSPACE/$PDIR/lib/cmake/ryml -DRYML_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: "-DRYML_USE_LIBCXX=ON"} - - {name: find_package/linux/libcxx, sdir: test/test_install , os: ubuntu-20.04, cxx: clang++-9, gen: "-DCMAKE_CXX_COMPILER=clang++-9" , tgt: all , bt: Debug , vars: "-Dryml_DIR=$GITHUB_WORKSPACE/$PDIR/lib/cmake/ryml -DRYML_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: "-DRYML_USE_LIBCXX=ON"} - - {name: find_package/macos , sdir: test/test_install , os: macos-11.0 , cxx: xcode , gen: "-G Xcode -DCMAKE_OSX_ARCHITECTURES=x86_64", tgt: ALL_BUILD, bt: Release, vars: "-Dryml_DIR=$GITHUB_WORKSPACE/$PDIR/lib/cmake/ryml -DRYML_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: } - - {name: find_package/macos , sdir: test/test_install , os: macos-11.0 , cxx: xcode , gen: "-G Xcode -DCMAKE_OSX_ARCHITECTURES=x86_64", tgt: ALL_BUILD, bt: Debug , vars: "-Dryml_DIR=$GITHUB_WORKSPACE/$PDIR/lib/cmake/ryml -DRYML_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: } - - {name: find_package/win , sdir: test/test_install , os: windows-2019, cxx: vs2019 , gen: "-G 'Visual Studio 16 2019' -A x64" , tgt: ALL_BUILD, bt: Release, vars: "-Dryml_DIR=$GITHUB_WORKSPACE/$PDIR/cmake -DRYML_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: } - - {name: find_package/win , sdir: test/test_install , os: windows-2019, cxx: vs2019 , gen: "-G 'Visual Studio 16 2019' -A x64" , tgt: ALL_BUILD, bt: Debug , vars: "-Dryml_DIR=$GITHUB_WORKSPACE/$PDIR/cmake -DRYML_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: } - # - - {name: find_library/linux , sdir: test/test_install , os: ubuntu-20.04, cxx: g++-10 , gen: "-DCMAKE_CXX_COMPILER=g++-10" , tgt: all , bt: Release, vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DRYML_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: } - - {name: find_library/linux , sdir: test/test_install , os: ubuntu-20.04, cxx: g++-10 , gen: "-DCMAKE_CXX_COMPILER=g++-10" , tgt: all , bt: Debug , vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DRYML_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: } - - {name: find_library/linux/libcxx, sdir: test/test_install , os: ubuntu-20.04, cxx: clang++-9, gen: "-DCMAKE_CXX_COMPILER=clang++-9" , tgt: all , bt: Release, vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DRYML_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: "-DRYML_USE_LIBCXX=ON"} - - {name: find_library/linux/libcxx, sdir: test/test_install , os: ubuntu-20.04, cxx: clang++-9, gen: "-DCMAKE_CXX_COMPILER=clang++-9" , tgt: all , bt: Debug , vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DRYML_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: "-DRYML_USE_LIBCXX=ON"} - - {name: find_library/macos , sdir: test/test_install , os: macos-11.0 , cxx: xcode , gen: "-G Xcode -DCMAKE_OSX_ARCHITECTURES=x86_64", tgt: ALL_BUILD, bt: Release, vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DRYML_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: } - - {name: find_library/macos , sdir: test/test_install , os: macos-11.0 , cxx: xcode , gen: "-G Xcode -DCMAKE_OSX_ARCHITECTURES=x86_64", tgt: ALL_BUILD, bt: Debug , vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DRYML_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: } - - {name: find_library/win , sdir: test/test_install , os: windows-2019, cxx: vs2019 , gen: "-G 'Visual Studio 16 2019' -A x64" , tgt: ALL_BUILD, bt: Release, vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DRYML_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: } - - {name: find_library/win , sdir: test/test_install , os: windows-2019, cxx: vs2019 , gen: "-G 'Visual Studio 16 2019' -A x64" , tgt: ALL_BUILD, bt: Debug , vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DRYML_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: } - # - - {name: singleheader/linux , sdir: test/test_singleheader, os: ubuntu-20.04, cxx: g++-10 , gen: "-DCMAKE_CXX_COMPILER=g++-10" , tgt: all , bt: Release, vars: , commonvars: } - - {name: singleheader/linux , sdir: test/test_singleheader, os: ubuntu-20.04, cxx: g++-10 , gen: "-DCMAKE_CXX_COMPILER=g++-10" , tgt: all , bt: Debug , vars: , commonvars: } - - {name: singleheader/linux/libcxx, sdir: test/test_singleheader, os: ubuntu-20.04, cxx: clang++-9, gen: "-DCMAKE_CXX_COMPILER=clang++-9" , tgt: all , bt: Release, vars: , commonvars: "-DRYML_USE_LIBCXX=ON"} - - {name: singleheader/linux/libcxx, sdir: test/test_singleheader, os: ubuntu-20.04, cxx: clang++-9, gen: "-DCMAKE_CXX_COMPILER=clang++-9" , tgt: all , bt: Debug , vars: , commonvars: "-DRYML_USE_LIBCXX=ON"} - - {name: singleheader/macos , sdir: test/test_singleheader, os: macos-11.0 , cxx: xcode , gen: "-G Xcode -DCMAKE_OSX_ARCHITECTURES=x86_64", tgt: ALL_BUILD, bt: Release, vars: , commonvars: } - - {name: singleheader/macos , sdir: test/test_singleheader, os: macos-11.0 , cxx: xcode , gen: "-G Xcode -DCMAKE_OSX_ARCHITECTURES=x86_64", tgt: ALL_BUILD, bt: Debug , vars: , commonvars: } - - {name: singleheader/win , sdir: test/test_singleheader, os: windows-2019, cxx: vs2019 , gen: "-G 'Visual Studio 16 2019' -A x64" , tgt: ALL_BUILD, bt: Release, vars: , commonvars: } - - {name: singleheader/win , sdir: test/test_singleheader, os: windows-2019, cxx: vs2019 , gen: "-G 'Visual Studio 16 2019' -A x64" , tgt: ALL_BUILD, bt: Debug , vars: , commonvars: } - env: - CXX_: "${{matrix.cxx}}" - BT: "${{matrix.bt}}" - OS: "${{matrix.os}}" - BDIR: "build/${{matrix.name}}-${{matrix.bt}}" - IDIR: "install/${{matrix.name}}-${{matrix.bt}}" - PDIR: "prefix/${{matrix.name}}-${{matrix.bt}}" - steps: - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} - - {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS} - - {name: show info, run: source .github/setenv.sh && c4_show_info} - - name: Install python 3.9 - uses: actions/setup-python@v4 - with: { python-version: 3.9 } - - name: preinstall - run: | - if [ "${{matrix.sdir}}" == "test/test_install" ] ; then - mkdir -p $BDIR-staging - cmake -S . -B $BDIR-staging -DCMAKE_INSTALL_PREFIX=$PDIR -DCMAKE_BUILD_TYPE=${{matrix.bt}} ${{matrix.gen}} ${{matrix.commonvars}} - cmake --build $BDIR-staging --config ${{matrix.bt}} --target ${{matrix.tgt}} -j - cmake --build $BDIR-staging --config ${{matrix.bt}} --target install - fi - - name: configure - run: | - mkdir -p $BDIR - mkdir -p $IDIR - cmake -S ${{matrix.sdir}} -B $BDIR \ - -DRYML_BUILD_TESTS=ON \ - -DRYML_VALGRIND=OFF \ - -DCMAKE_BUILD_TYPE=${{matrix.bt}} \ - -DCMAKE_INSTALL_PREFIX=$IDIR \ - ${{matrix.gen}} \ - ${{matrix.vars}} \ - ${{matrix.commonvars}} - - name: build - run: | - cmake --build $BDIR --config ${{matrix.bt}} --target ryml-test-build -j - - name: run - run: | - cmake --build $BDIR --config ${{matrix.bt}} --target ryml-test-run diff --git a/thirdparty/ryml/.github/workflows/macosx.yml b/thirdparty/ryml/.github/workflows/macosx.yml deleted file mode 100644 index a9fb97ffb..000000000 --- a/thirdparty/ryml/.github/workflows/macosx.yml +++ /dev/null @@ -1,103 +0,0 @@ -name: macosx - -defaults: - run: - # Use a bash shell so we can use the same syntax for environment variable - # access regardless of the host operating system - shell: bash -e -x {0} - -on: - # https://github.community/t/how-to-trigger-an-action-on-push-or-pull-request-but-not-both/16662 - workflow_dispatch: - push: - branches: - - master - pull_request: - branches: - - master - -env: - PROJ_PFX_TARGET: ryml- - PROJ_PFX_CMAKE: RYML_ - CMAKE_FLAGS: -DRYML_TEST_SUITE=ON - NUM_JOBS_BUILD: # 4 - - -# ubuntu-20.04: -# # https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu2004-README.md -# gcc: 7.5.0, 8.4.0, 9.3.0, 10.2.0 -# clang: 8.0.1, 9.0.1, 10.0.0 -# ubuntu-18.04: -# # https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu1804-README.md -# gcc: 7.5.0, 8.4.0, 9.3.0, 10.1.0 -# clang: 6.0.0, 8.0.0, 9.0.0 -# macos-11.0: macOS Big Sur 11.0 -# # https://github.com/actions/virtual-environments/blob/main/images/macos/macos-11.0-Readme.md -# Xcode 12.1 11.7 -# clang/LLVM 10.0.1 -# gcc-8 gcc-9 -# macos-10.15: macOS Catalina 10.15 -# # https://github.com/actions/virtual-environments/blob/main/images/macos/macos-10.15-Readme.md -# Xcode 12.1 11.7 -# clang/LLVM 11.0.0 -# gcc-8 gcc-9 -# windows-2019: -# # https://github.com/actions/virtual-environments/blob/main/images/win/Windows2019-Readme.md -# vs2019 -# windows-2016: -# # https://github.com/actions/virtual-environments/blob/main/images/win/Windows2016-Readme.md -# vs2017 -jobs: - - #---------------------------------------------------------------------------- - macosx: - if: | - (!contains(github.event.head_commit.message, 'skip all')) || - (!contains(github.event.head_commit.message, 'skip macosx')) || - contains(github.event.head_commit.message, 'only macosx') - continue-on-error: true - runs-on: ${{matrix.os}} - strategy: - fail-fast: false - matrix: - include: - - {std: 11, cxx: xcode, xcver: 13, bt: Debug , os: macos-11, bitlinks: shared64 static64} - - {std: 11, cxx: xcode, xcver: 13, bt: Release, os: macos-11, bitlinks: shared64 static64} - - {std: 17, cxx: xcode, xcver: 13, bt: Debug , os: macos-11, bitlinks: shared64 static64} - - {std: 17, cxx: xcode, xcver: 13, bt: Release, os: macos-11, bitlinks: shared64 static64} - # - - {std: 11, cxx: xcode, xcver: 12, bt: Debug , os: macos-11, bitlinks: shared64 static64} - - {std: 11, cxx: xcode, xcver: 12, bt: Release, os: macos-11, bitlinks: shared64 static64} - - {std: 17, cxx: xcode, xcver: 12, bt: Debug , os: macos-11, bitlinks: shared64 static64} - - {std: 17, cxx: xcode, xcver: 12, bt: Release, os: macos-11, bitlinks: shared64 static64} - # - - {std: 11, cxx: xcode, xcver: 11, bt: Debug , os: macos-11, bitlinks: shared64 static64} - - {std: 11, cxx: xcode, xcver: 11, bt: Release, os: macos-11, bitlinks: shared64 static64} - - {std: 17, cxx: xcode, xcver: 11, bt: Debug , os: macos-11, bitlinks: shared64 static64} - - {std: 17, cxx: xcode, xcver: 11, bt: Release, os: macos-11, bitlinks: shared64 static64} - env: {STD: "${{matrix.std}}", CXX_: "${{matrix.cxx}}", BT: "${{matrix.bt}}", BITLINKS: "${{matrix.bitlinks}}", VG: "${{matrix.vg}}", SAN: "${{matrix.san}}", LINT: "${{matrix.lint}}", OS: "${{matrix.os}}"} - steps: - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} - - {name: xcode, uses: maxim-lobanov/setup-xcode@v1, with: {xcode-version: "${{matrix.xcver}}" }} - - {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS} - - {name: show info, run: source .github/setenv.sh && c4_show_info} - - name: shared64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared64 - - {name: shared64-build, run: source .github/setenv.sh && c4_build_test shared64} - - {name: shared64-run, run: source .github/setenv.sh && c4_run_test shared64} - - {name: shared64-pack, run: source .github/setenv.sh && c4_package shared64} - - name: static64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static64 - - {name: static64-build, run: source .github/setenv.sh && c4_build_test static64} - - {name: static64-run, run: source .github/setenv.sh && c4_run_test static64} - - {name: static64-pack, run: source .github/setenv.sh && c4_package static64} - - name: shared32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared32 - - {name: shared32-build, run: source .github/setenv.sh && c4_build_test shared32} - - {name: shared32-run, run: source .github/setenv.sh && c4_run_test shared32} - - {name: shared32-pack, run: source .github/setenv.sh && c4_package shared32} - - name: static32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static32 - - {name: static32-build, run: source .github/setenv.sh && c4_build_test static32} - - {name: static32-run, run: source .github/setenv.sh && c4_run_test static32} - - {name: static32-pack, run: source .github/setenv.sh && c4_package static32} diff --git a/thirdparty/ryml/.github/workflows/rarearchs.yml b/thirdparty/ryml/.github/workflows/rarearchs.yml deleted file mode 100644 index 8306b54ae..000000000 --- a/thirdparty/ryml/.github/workflows/rarearchs.yml +++ /dev/null @@ -1,123 +0,0 @@ -name: rarearchs - -defaults: - run: - # Use a bash shell so we can use the same syntax for environment variable - # access regardless of the host operating system - shell: bash -e -x {0} - -on: - # https://github.community/t/how-to-trigger-an-action-on-push-or-pull-request-but-not-both/16662 - workflow_dispatch: - push: - branches: - - master - pull_request: - branches: - - master - -jobs: - rarearchs: - if: | - (!contains(github.event.head_commit.message, 'skip all')) || - (!contains(github.event.head_commit.message, 'skip rarearchs')) || - contains(github.event.head_commit.message, 'only rarearchs') - name: ${{matrix.arch}}/c++${{matrix.std}}/${{matrix.bt}} - continue-on-error: true - runs-on: ubuntu-20.04 - strategy: - fail-fast: false - matrix: - include: - - {std: 11, bt: Debug , arch: aarch64, distro: ubuntu20.04} - - {std: 11, bt: Release, arch: aarch64, distro: ubuntu20.04} - - {std: 14, bt: Debug , arch: aarch64, distro: ubuntu20.04} - - {std: 14, bt: Release, arch: aarch64, distro: ubuntu20.04} - - {std: 17, bt: Debug , arch: aarch64, distro: ubuntu20.04} - - {std: 17, bt: Release, arch: aarch64, distro: ubuntu20.04} - # - - {std: 11, bt: Debug , arch: ppc64le, distro: ubuntu20.04} - - {std: 11, bt: Release, arch: ppc64le, distro: ubuntu20.04} - - {std: 14, bt: Debug , arch: ppc64le, distro: ubuntu20.04} - - {std: 14, bt: Release, arch: ppc64le, distro: ubuntu20.04} - - {std: 17, bt: Debug , arch: ppc64le, distro: ubuntu20.04} - - {std: 17, bt: Release, arch: ppc64le, distro: ubuntu20.04} - # - - {std: 11, bt: Debug , arch: s390x , distro: ubuntu20.04} - - {std: 11, bt: Release, arch: s390x , distro: ubuntu20.04} - - {std: 14, bt: Debug , arch: s390x , distro: ubuntu20.04} - - {std: 14, bt: Release, arch: s390x , distro: ubuntu20.04} - - {std: 17, bt: Debug , arch: s390x , distro: ubuntu20.04} - - {std: 17, bt: Release, arch: s390x , distro: ubuntu20.04} - # - #- {std: 11, bt: Debug , arch: armv6 , distro: bullseye} - #- {std: 11, bt: Release, arch: armv6 , distro: bullseye} - #- {std: 14, bt: Debug , arch: armv6 , distro: bullseye} - #- {std: 14, bt: Release, arch: armv6 , distro: bullseye} - #- {std: 17, bt: Debug , arch: armv6 , distro: bullseye} - #- {std: 17, bt: Release, arch: armv6 , distro: bullseye} - # - #- {std: 11, bt: Debug , arch: armv7 , distro: ubuntu20.04} - #- {std: 11, bt: Release, arch: armv7 , distro: ubuntu20.04} - #- {std: 14, bt: Debug , arch: armv7 , distro: ubuntu20.04} - #- {std: 14, bt: Release, arch: armv7 , distro: ubuntu20.04} - #- {std: 17, bt: Debug , arch: armv7 , distro: ubuntu20.04} - #- {std: 17, bt: Release, arch: armv7 , distro: ubuntu20.04} - steps: - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} - - name: test - uses: uraimo/run-on-arch-action@v2.3.0 - with: - arch: ${{matrix.arch}} - distro: ${{matrix.distro}} - install: | - set -x - start_time=$SECONDS - time apt-get update -y - time apt-get install -y \ - git \ - build-essential - # arm platforms need an up-to-date cmake: - # https://gitlab.kitware.com/cmake/cmake/-/issues/20568 - if [ "${{matrix.arch}}" == "armv6" ] || [ "${{matrix.arch}}" == "armv7" ] ; then - time apt-get install -y \ - gpg \ - wget \ - apt-transport-https - wget --no-check-certificate -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | tee /usr/share/keyrings/kitware-archive-keyring.gpg >/dev/null - echo 'deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ focal main' | tee /etc/apt/sources.list.d/kitware.list >/dev/null - time apt-get update -y - rm /usr/share/keyrings/kitware-archive-keyring.gpg - time apt-get install kitware-archive-keyring - time apt-get update -y - fi - time apt-get install -y cmake cmake-data - cmake --version - echo "install took $((SECONDS - start_time))" - run: | - set -x - start_time=$SECONDS - uname -a - pwd - ls -lFhp . - # - bdir=build_${{matrix.arch}}_${{matrix.bt}}_${{matrix.std}} - idir=install_${{matrix.arch}}_${{matrix.bt}}_${{matrix.std}} - mkdir -p $bdir - # - time cmake -S . -B $bdir \ - -DCMAKE_INSTALL_PREFIX=$idir \ - -DCMAKE_BUILD_TYPE=${{matrix.bt}} \ - -DC4_CXX_STANDARD=${{matrix.std}} \ - -DCXX_STANDARD=${{matrix.std}} \ - -DRYML_DEV=ON \ - -DRYML_TEST_SUITE=ON \ - -DRYML_BUILD_BENCHMARKS=OFF \ - -DRYML_SANITIZE=OFF \ - -DRYML_LINT=OFF \ - -DRYML_VALGRIND=OFF - # - time cmake --build $bdir -j 3 --target ryml-test-build - # - time cmake --build $bdir -j 3 --target ryml-test-run - echo "run took $((SECONDS - start_time))" diff --git a/thirdparty/ryml/.github/workflows/release.yml b/thirdparty/ryml/.github/workflows/release.yml deleted file mode 100644 index 3797359b8..000000000 --- a/thirdparty/ryml/.github/workflows/release.yml +++ /dev/null @@ -1,366 +0,0 @@ -name: release - -defaults: - run: - # Use a bash shell so we can use the same syntax for environment variable - # access regardless of the host operating system - shell: bash -e -x {0} - -on: - # https://github.community/t/how-to-trigger-an-action-on-push-or-pull-request-but-not-both/16662 - workflow_dispatch: - push: - tags: - - v0.* - - v1.* - - v2.* - branches: - - master - pull_request: - branches: - - master - -env: - PROJ_PKG_NAME: rapidyaml- - PROJ_PFX_TARGET: ryml- - PROJ_PFX_CMAKE: RYML_ - CMAKE_FLAGS: -DRYML_TEST_SUITE=OFF - NUM_JOBS_BUILD: # 4 - - -# useful to iterate when fixing the release: -# ver=0.2.1 ; ( set -x ; git tag -d v$ver ; git push origin :v$ver ) ; (set -x ; set -e ; tbump --only-patch --non-interactive $ver ; git add -u ; git commit --amend --no-edit ; git tag --annotate --message "v$ver" "v$ver" ; git push -f --tags origin ) - -jobs: - - gettag: - if: | - (!contains(github.event.head_commit.message, 'skip all')) || - (!contains(github.event.head_commit.message, 'skip release')) || - contains(github.event.head_commit.message, 'only release') - runs-on: ubuntu-latest - steps: - # use fetch-depth to ensure all tags are fetched - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive, fetch-depth: 0}} - - name: Variables (from tag) - if: contains(github.ref, 'tags/v') - run: | - # https://github.community/t/how-to-get-just-the-tag-name/16241/11 - SRC_TAG=${GITHUB_REF#refs/tags/} - SRC_VERSION=${GITHUB_REF#refs/tags/v} - cat < vars.sh - export SRC_TAG=$SRC_TAG - export SRC_VERSION=$SRC_VERSION - EOF - - name: Variables (from commit, no tag) - if: ${{ !contains(github.ref, 'tags/v') }} - run: | - set -x - branch_name=${GITHUB_REF#refs/heads/} - # builds triggered from PRs have the branch_name like this: refs/pull/150/merge - # so filter to eg pr0150_merge - branch_name=`echo $branch_name | sed "s:refs/pull/\([0-9]*\)/\(.*\):pr0\1_\2:"` - # sanitize the branch name; eg merge/foo-bar -> merge_foo_bar - branch_name=`echo $branch_name | sed 's:[/.-]:_:g'` - SRC_TAG=$(git describe || git rev-parse --short HEAD) # eg v0.2.0-110-gda837e0 - SRC_VERSION="${branch_name}-${SRC_TAG}" - cat < vars.sh - export SRC_TAG=$SRC_TAG - export SRC_VERSION=$SRC_VERSION - EOF - - name: Verify vars.sh - run: cat vars.sh ; source vars.sh ; echo $SRC_TAG ; echo $SRC_VERSION - - name: Save vars.sh - uses: actions/upload-artifact@v3 - with: {name: vars.sh, path: ./vars.sh} - - #---------------------------------------------------------------------------- - # create source packages - src: - if: | - (!contains(github.event.head_commit.message, 'skip all')) || - (!contains(github.event.head_commit.message, 'skip release')) || - contains(github.event.head_commit.message, 'only release') - needs: gettag - runs-on: ubuntu-latest - steps: - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} - - name: Download vars.sh - uses: actions/download-artifact@v3 - with: {name: vars.sh, path: ./} - - name: Install python 3.9 - uses: actions/setup-python@v4 - with: { python-version: 3.9 } - - name: Install requirements - run: | - sudo -E pip install git-archive-all - - name: Create source packages - run: | - pwd - ls -lFhp - source vars.sh - echo SRC_TAG=$SRC_TAG - echo SRC_VERSION=$SRC_VERSION - id=${PROJ_PKG_NAME}${SRC_VERSION} - name=${id}-src - mkdir -p assets - git-archive-all --prefix $name assets/$name.tgz - git-archive-all --prefix $name assets/$name.zip - python --version - python tools/amalgamate.py assets/$id.hpp - - name: Save source artifacts - uses: actions/upload-artifact@v3 - with: {name: assets, path: assets} - - #---------------------------------------------------------------------------- - # create c++ packages - cpp: - if: | - (!contains(github.event.head_commit.message, 'skip all')) || - (!contains(github.event.head_commit.message, 'skip release')) || - contains(github.event.head_commit.message, 'only release') - name: cpp/${{matrix.config.os}}/${{matrix.config.gen}} - needs: gettag - runs-on: ${{matrix.config.os}} - env: {DEV: OFF, BT: Release, OS: "${{matrix.config.os}}", CXX_: "${{matrix.config.cxx}}", GEN: "${{matrix.config.gen}}"} - strategy: - fail-fast: false - matrix: - config: - # name of the artifact | suffix (gen) | suffix (package) | cpack gen | mime type | os | cxx - - {name: Ubuntu 20.04 deb , sfxg: unix64.deb, sfxp: ubuntu-20.04.deb , gen: DEB , mime: vnd.debian.binary-package, os: ubuntu-20.04 } - #- {name: Ubuntu 18.04 deb , sfxg: unix64.deb, sfxp: ubuntu-18.04.deb , gen: DEB , mime: vnd.debian.binary-package, os: ubuntu-18.04 } - - {name: Windows VS2019 zip, sfxg: win64.zip , sfxp: windows-vs2019.zip , gen: ZIP , mime: zip , os: windows-2019, cxx: vs2019} - - {name: MacOSX sh , sfxg: apple64.sh, sfxp: macosx-xcode.sh , gen: STGZ , mime: x-sh , os: macos-11.0 , cxx: xcode } - steps: - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} - - name: Download vars.sh - uses: actions/download-artifact@v3 - with: {name: vars.sh, path: ./} - - {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS} - - {name: show info, run: source .github/setenv.sh && c4_show_info } - - name: shared64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared64 - - {name: shared64-build, run: source .github/setenv.sh && c4_build_target shared64} - - name: shared64-pack - run: source .github/setenv.sh && c4_package shared64 $GEN - - name: shared64-normalize - run: | - set -x - source vars.sh - mkdir -p assets - asset_src=`ls -1 ./build/shared64/*-${{matrix.config.sfxg}}` - asset_dst=./assets/${PROJ_PKG_NAME}${SRC_VERSION}-${{matrix.config.sfxp}} - [ ! -f $asset_src ] && exit 1 - cp -fav $asset_src $asset_dst - - name: Save artifacts - uses: actions/upload-artifact@v3 - with: {name: assets, path: assets} - - #---------------------------------------------------------------------------- - # create python packages - # adapted from https://github.com/pikepdf/pikepdf/blob/master/.github/workflows/build_wheels.yml - - python_src: - if: | - (!contains(github.event.head_commit.message, 'skip all')) || - (!contains(github.event.head_commit.message, 'skip release')) || - contains(github.event.head_commit.message, 'only release') - name: python/src - runs-on: ubuntu-latest - steps: - # use fetch-depth to ensure all tags are fetched - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive, fetch-depth: 0}} - - name: install python 3.9 - uses: actions/setup-python@v4 - with: { python-version: 3.9 } - - name: package python src packages - run: | - python --version - pip install -v -r requirements.txt - python setup.py sdist --formats=zip - - name: normalize src package names - run: | - sdist_orig=`find dist -type f -name 'rapidyaml-*.zip'` - [ ! -f $sdist_orig ] && exit 1 - sdist=`echo $sdist_orig | sed 's:\.zip:-python_src.zip:'` - mv -fv $sdist_orig $sdist - - name: Save artifacts - uses: actions/upload-artifact@v3 - with: {name: dist, path: dist} - - python_wheels: - if: | - (!contains(github.event.head_commit.message, 'skip all')) || - (!contains(github.event.head_commit.message, 'skip release')) || - contains(github.event.head_commit.message, 'only release') - name: python/${{matrix.config.cibw_pyv}}/${{matrix.config.osname}}/${{matrix.config.cibw_arch}} - runs-on: ${{matrix.config.os}} - env: - CMAKE_FLAGS: "${{matrix.config.cmakeflags}} -DRYML_DEV=OFF -DRYML_BUILD_API=ON -DRYML_API_TESTS=OFF -DRYML_API_BENCHMARKS=OFF" - CIBW_BUILD: "cp${{matrix.config.cibw_pyv}}-${{matrix.config.cibw_platform}}" - CIBW_ARCHS: "${{matrix.config.cibw_arch}}" - strategy: - fail-fast: false - matrix: - config: - # the 3-digit versions NEED to be quoted to prevent the version being read as float. (!) - - {pythonv: '3.11', cibw_pyv: 311, cibw_arch: x86_64, cibw_platform: manylinux_x86_64, osname: linux, os: ubuntu-20.04} - - {pythonv: '3.11', cibw_pyv: 311, cibw_arch: i686 , cibw_platform: manylinux_i686 , osname: linux, os: ubuntu-20.04} - - {pythonv: '3.10', cibw_pyv: 310, cibw_arch: x86_64, cibw_platform: manylinux_x86_64, osname: linux, os: ubuntu-20.04} - - {pythonv: '3.10', cibw_pyv: 310, cibw_arch: i686 , cibw_platform: manylinux_i686 , osname: linux, os: ubuntu-20.04} - - {pythonv: 3.9 , cibw_pyv: 39 , cibw_arch: x86_64, cibw_platform: manylinux_x86_64, osname: linux, os: ubuntu-20.04} - - {pythonv: 3.9 , cibw_pyv: 39 , cibw_arch: i686 , cibw_platform: manylinux_i686 , osname: linux, os: ubuntu-20.04} - - {pythonv: 3.8 , cibw_pyv: 38 , cibw_arch: x86_64, cibw_platform: manylinux_x86_64, osname: linux, os: ubuntu-20.04} - - {pythonv: 3.8 , cibw_pyv: 38 , cibw_arch: i686 , cibw_platform: manylinux_i686 , osname: linux, os: ubuntu-20.04} - - {pythonv: 3.7 , cibw_pyv: 37 , cibw_arch: x86_64, cibw_platform: manylinux_x86_64, osname: linux, os: ubuntu-20.04} - - {pythonv: 3.7 , cibw_pyv: 37 , cibw_arch: i686 , cibw_platform: manylinux_i686 , osname: linux, os: ubuntu-20.04} - - {pythonv: 3.6 , cibw_pyv: 36 , cibw_arch: x86_64, cibw_platform: manylinux_x86_64, osname: linux, os: ubuntu-20.04} - - {pythonv: 3.6 , cibw_pyv: 36 , cibw_arch: i686 , cibw_platform: manylinux_i686 , osname: linux, os: ubuntu-20.04} - # the windows builds are disabled because they are causing problems and preventing the release. - # the problems are related to CMakeExtension forcing the use of Ninja - # which does not play well with the -G 'Visual Studio...' option used below. - # fixing this looks like it will be time-intensive. - #- {pythonv: '3.11', cibw_pyv: 311, cibw_arch: AMD64 , cibw_platform: win_amd64, osname: win , os: windows-2019, cxx: vs2019} #, cmakeflags: '-G "Visual Studio 16 2019" -A x64'} - #- {pythonv: '3.11', cibw_pyv: 311, cibw_arch: x86 , cibw_platform: win32 , osname: win , os: windows-2019, cxx: vs2019} #, cmakeflags: '-G "Visual Studio 16 2019" -A Win32'} - #- {pythonv: '3.10', cibw_pyv: 310, cibw_arch: AMD64 , cibw_platform: win_amd64, osname: win , os: windows-2019, cxx: vs2019} #, cmakeflags: '-G "Visual Studio 16 2019" -A x64'} - #- {pythonv: '3.10', cibw_pyv: 310, cibw_arch: x86 , cibw_platform: win32 , osname: win , os: windows-2019, cxx: vs2019} #, cmakeflags: '-G "Visual Studio 16 2019" -A Win32'} - #- {pythonv: 3.9 , cibw_pyv: 39 , cibw_arch: AMD64 , cibw_platform: win_amd64, osname: win , os: windows-2019, cxx: vs2019} #, cmakeflags: '-G "Visual Studio 16 2019" -A x64'} - #- {pythonv: 3.9 , cibw_pyv: 39 , cibw_arch: x86 , cibw_platform: win32 , osname: win , os: windows-2019, cxx: vs2019} #, cmakeflags: '-G "Visual Studio 16 2019" -A Win32'} - #- {pythonv: 3.8 , cibw_pyv: 38 , cibw_arch: AMD64 , cibw_platform: win_amd64, osname: win , os: windows-2019, cxx: vs2019} #, cmakeflags: '-G "Visual Studio 16 2019" -A x64'} - #- {pythonv: 3.8 , cibw_pyv: 38 , cibw_arch: x86 , cibw_platform: win32 , osname: win , os: windows-2019, cxx: vs2019} #, cmakeflags: '-G "Visual Studio 16 2019" -A Win32'} - - {pythonv: 3.7 , cibw_pyv: 37 , cibw_arch: AMD64 , cibw_platform: win_amd64, osname: win , os: windows-2019, cxx: vs2019} #, cmakeflags: '-G "Visual Studio 16 2019" -A x64'} - #- {pythonv: 3.7 , cibw_pyv: 37 , cibw_arch: x86 , cibw_platform: win32 , osname: win , os: windows-2019, cxx: vs2019} #, cmakeflags: '-G "Visual Studio 16 2019" -A Win32'} - - {pythonv: 3.6 , cibw_pyv: 36 , cibw_arch: AMD64 , cibw_platform: win_amd64, osname: win , os: windows-2019, cxx: vs2019} #, cmakeflags: '-G "Visual Studio 16 2019" -A x64'} - #- {pythonv: 3.6 , cibw_pyv: 36 , cibw_arch: x86 , cibw_platform: win32 , osname: win , os: windows-2019, cxx: vs2019} #, cmakeflags: '-G "Visual Studio 16 2019" -A Win32'} - ## macosx builds are generating a SIGSEGV when importing. (!) - ## https://github.com/biojppm/rapidyaml/actions/runs/3062528713/jobs/4943611397#step:7:269 - #- {pythonv: '3.11', cibw_pyv: 311, cibw_arch: x86_64, cibw_platform: macosx_x86_64, osname: macos, os: macos-10.15} - #- {pythonv: '3.10', cibw_pyv: 310, cibw_arch: x86_64, cibw_platform: macosx_x86_64, osname: macos, os: macos-10.15} - #- {pythonv: 3.9 , cibw_pyv: 39 , cibw_arch: x86_64, cibw_platform: macosx_x86_64, osname: macos, os: macos-10.15} - #- {pythonv: 3.8 , cibw_pyv: 38 , cibw_arch: x86_64, cibw_platform: macosx_x86_64, osname: macos, os: macos-10.15} - #- {pythonv: 3.7 , cibw_pyv: 37 , cibw_arch: x86_64, cibw_platform: macosx_x86_64, osname: macos, os: macos-10.15} - #- {pythonv: 3.6 , cibw_pyv: 36 , cibw_arch: x86_64, cibw_platform: macosx_x86_64, osname: macos, os: macos-10.15} - steps: - # use fetch-depth to ensure all tags are fetched - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive, fetch-depth: 0}} - - name: create wheel - uses: joerick/cibuildwheel@v2.9.0 - - name: rename wheelhouse -> dist - run: | - mv -fv wheelhouse dist - ls -lFhp dist/ - - name: Save artifacts for publishing to PyPI - uses: actions/upload-artifact@v3 - with: {name: dist, path: dist} - # run the tests - - name: install python ${{matrix.config.pythonv}} - uses: actions/setup-python@v4 - with: - python-version: '${{matrix.config.pythonv}}' - - name: test with python ${{matrix.config.pythonv}} - run: | - set -x - echo "python ${{matrix.config.pythonv}} ${{matrix.config.py_arch}} ${{matrix.config.cibw_arch}}" - # skip 32 bit tests, as Python 32 bits are not available in ubuntu - arch="${{matrix.config.cibw_arch}}" - if [ "$arch" == "x86" ] || [ "$arch" == "i686" ] ; then - exit 0 - fi - python --version - python -c 'import sys ; import struct ; print("python:", sys.version, struct.calcsize("P") * 8, "bits")' - pip --version - pip install -v -r requirements.txt - pip install -v -r api/python/requirements.txt - for whl in dist/* ; do - pip install -v $whl - pip show -f rapidyaml - python -c 'import ryml ; print("ryml", ryml.version, ryml.version_tuple)' - python -c 'import ryml ; tree = ryml.parse_in_arena(b"{foo: bar}") ; assert tree.key(1) == b"foo" ; assert tree.val(1) == b"bar" ; print(str(tree.key(1), "utf8")) ; print(str(tree.val(1), "utf8"))' - python -m pytest -vvv api/python/tests - pip uninstall -y -v rapidyaml - done - - - #---------------------------------------------------------------------------- - release: - if: | - (!contains(github.event.head_commit.message, 'skip all')) || - (!contains(github.event.head_commit.message, 'skip release')) || - contains(github.event.head_commit.message, 'only release') - runs-on: ubuntu-latest - needs: - - src - - cpp - - python_src - - python_wheels - steps: - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} - - name: Gather artifacts - ./assets - uses: actions/download-artifact@v3 - with: {name: assets, path: assets} - - name: Gather artifacts - ./dist - uses: actions/download-artifact@v3 - with: {name: dist, path: dist} - - name: Verify existing artifacts - run: | - ls -lFhp assets/ - ls -lFhp dist/ - # - # Github - - name: Restore vars.sh - if: contains(github.ref, 'tags/v') - uses: actions/download-artifact@v3 - with: {name: vars.sh, path: ./} - - name: Save vars for following steps - if: contains(github.ref, 'tags/v') - id: vars - run: | - source vars.sh - version_body=${{github.workspace}}/changelog/$SRC_VERSION.md - if [ ! -f $version_body ] ; then - echo "version body file was not found: $version_body" - exit 1 - fi - echo "VERSION=$SRC_VERSION >> $GITHUB_OUTPUT" - echo "VERSION_BODY=$version_body >> $GITHUB_OUTPUT" - - name: Move Python packages to assets folder - if: contains(github.ref, 'tags/v') - run: mv -fv dist/*src.zip assets/. - - name: Create Github Release - if: contains(github.ref, 'tags/v') - id: create_release - uses: actions/create-release@v1 - env: { GITHUB_TOKEN: "${{secrets.GITHUB_TOKEN}}" } - with: - tag_name: ${{github.ref}} - release_name: Release ${{steps.vars.outputs.VERSION}} - body_path: ${{steps.vars.outputs.VERSION_BODY}} - draft: true - prerelease: ${{contains(github.ref, 'rc')}} - - name: Upload assets to Github Release - if: contains(github.ref, 'tags/v') - uses: dwenegar/upload-release-assets@v1 - env: { GITHUB_TOKEN: "${{secrets.GITHUB_TOKEN}}" } - with: - release_id: ${{steps.create_release.outputs.id}} - assets_path: ./assets/ - # - # PyPI (test) - - name: Publish python packages to test PyPI - uses: pypa/gh-action-pypi-publish@v1.4.2 - with: - repository_url: https://test.pypi.org/legacy/ - user: __token__ - password: ${{secrets.PYPI_TOKEN_TEST}} - verbose: true - skip_existing: true - # - # PyPI (production) - - name: Publish python packages to production PyPI - if: contains(github.ref, 'tags/v') - uses: pypa/gh-action-pypi-publish@v1.4.2 - with: - user: __token__ - password: ${{secrets.PYPI_TOKEN}} - verbose: true diff --git a/thirdparty/ryml/.github/workflows/samples.yml b/thirdparty/ryml/.github/workflows/samples.yml deleted file mode 100644 index d4ad65494..000000000 --- a/thirdparty/ryml/.github/workflows/samples.yml +++ /dev/null @@ -1,60 +0,0 @@ -name: samples - -defaults: - run: - # Use a bash shell so we can use the same syntax for environment variable - # access regardless of the host operating system - shell: bash -e -x {0} - -on: - # https://github.community/t/how-to-trigger-an-action-on-push-or-pull-request-but-not-both/16662 - workflow_dispatch: - push: - branches: - - master - pull_request: - branches: - - master - -env: - PROJ_PFX_TARGET: ryml- - PROJ_PFX_CMAKE: RYML_ - CMAKE_FLAGS: -DRYML_TEST_SUITE=ON - NUM_JOBS_BUILD: # 4 - -jobs: - - #---------------------------------------------------------------------------- - samples: - if: | - (!contains(github.event.head_commit.message, 'skip all')) || - (!contains(github.event.head_commit.message, 'skip samples')) || - contains(github.event.head_commit.message, 'only samples') - continue-on-error: true - runs-on: ${{matrix.os}} - strategy: - fail-fast: false - matrix: - include: - - {bt: Debug , os: ubuntu-20.04} - - {bt: Release, os: ubuntu-20.04} - - {bt: Debug , os: windows-2019} - - {bt: Release, os: windows-2019} - - {bt: Debug , os: macos-latest} - - {bt: Release, os: macos-latest} - env: {STD: "${{matrix.std}}", CXX_: "${{matrix.cxx}}", BT: "${{matrix.bt}}", BITLINKS: "${{matrix.bitlinks}}", - VG: "${{matrix.vg}}", SAN: "${{matrix.san}}", LINT: "${{matrix.lint}}", OS: "${{matrix.os}}", - CMANY: ON, RYMLSHA: "${{github.event.pull_request.head.sha}}" } - steps: - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive, fetch-depth: 0 } } # use fetch-depth to ensure all tags are fetched - - {name: python3, uses: actions/setup-python@v4, with: {python-version: 3.7}} - - {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS} - - {name: show info, run: source .github/setenv.sh && c4_show_info } - # - - {name: singleheader, run: cd samples/singleheader && ./run.sh $BT } - - {name: singleheaderlib-static, run: cd samples/singleheaderlib && ./run_static.sh $BT } - - {name: singleheaderlib-shared, run: cd samples/singleheaderlib && ./run_shared.sh $BT } - - {name: add_subdirectory, run: cd samples/add_subdirectory && ./run.sh $BT } - - {name: find_package, run: cd samples/find_package && ./run.sh $BT } - - {name: custom_c4core, run: cd samples/custom_c4core && ./run.sh $BT } - - {name: fetch_content, run: cd samples/fetch_content && ./run.sh $BT $RYMLSHA } diff --git a/thirdparty/ryml/.github/workflows/windows.yml b/thirdparty/ryml/.github/workflows/windows.yml deleted file mode 100644 index f39c6e19d..000000000 --- a/thirdparty/ryml/.github/workflows/windows.yml +++ /dev/null @@ -1,130 +0,0 @@ -name: windows - -defaults: - run: - # Use a bash shell so we can use the same syntax for environment variable - # access regardless of the host operating system - shell: bash -e -x {0} - -on: - # https://github.community/t/how-to-trigger-an-action-on-push-or-pull-request-but-not-both/16662 - workflow_dispatch: - push: - branches: - - master - pull_request: - branches: - - master - -env: - PROJ_PFX_TARGET: ryml- - PROJ_PFX_CMAKE: RYML_ - CMAKE_FLAGS: -DRYML_TEST_SUITE=ON - NUM_JOBS_BUILD: # 4 - - -jobs: - vs: - name: ${{matrix.cxx}}/c++${{matrix.std}}/${{matrix.bt}} - if: | - (!contains(github.event.head_commit.message, 'skip all')) || - (!contains(github.event.head_commit.message, 'skip windows')) || - contains(github.event.head_commit.message, 'only windows') - continue-on-error: true - runs-on: ${{matrix.os}} - strategy: - fail-fast: false - matrix: - include: - # vs2017 is only availble in windows-2016 - #- {std: 11, cxx: vs2017, bt: Debug , os: windows-2016, bitlinks: shared64 static32} - #- {std: 11, cxx: vs2017, bt: Release, os: windows-2016, bitlinks: shared64 static32} - #- {std: 14, cxx: vs2017, bt: Debug , os: windows-2016, bitlinks: shared64 static32} - #- {std: 14, cxx: vs2017, bt: Release, os: windows-2016, bitlinks: shared64 static32} - # - - {std: 11, cxx: vs2019, bt: Debug , os: windows-2019, bitlinks: shared64 static32} - - {std: 11, cxx: vs2019, bt: Release, os: windows-2019, bitlinks: shared64 static32} - - {std: 17, cxx: vs2019, bt: Debug , os: windows-2019, bitlinks: shared64 static32} - - {std: 17, cxx: vs2019, bt: Release, os: windows-2019, bitlinks: shared64 static32} - # - - {std: 11, cxx: vs2022, bt: Debug , os: windows-2022, bitlinks: shared64 static32} - - {std: 11, cxx: vs2022, bt: Release, os: windows-2022, bitlinks: shared64 static32} - - {std: 17, cxx: vs2022, bt: Debug , os: windows-2022, bitlinks: shared64 static32} - - {std: 17, cxx: vs2022, bt: Release, os: windows-2022, bitlinks: shared64 static32} - - {std: 20, cxx: vs2022, bt: Debug , os: windows-2022, bitlinks: shared64 static32} - - {std: 20, cxx: vs2022, bt: Release, os: windows-2022, bitlinks: shared64 static32} - env: {STD: "${{matrix.std}}", CXX_: "${{matrix.cxx}}", BT: "${{matrix.bt}}", BITLINKS: "${{matrix.bitlinks}}", VG: "${{matrix.vg}}", SAN: "${{matrix.san}}", LINT: "${{matrix.lint}}", OS: "${{matrix.os}}"} - steps: - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} - - {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS} - - {name: show info, run: source .github/setenv.sh && c4_show_info} - - name: shared64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared64 - - {name: shared64-build, run: source .github/setenv.sh && c4_build_test shared64} - - {name: shared64-run, run: source .github/setenv.sh && c4_run_test shared64} - - {name: shared64-pack, run: source .github/setenv.sh && c4_package shared64} - - name: static64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static64 - - {name: static64-build, run: source .github/setenv.sh && c4_build_test static64} - - {name: static64-run, run: source .github/setenv.sh && c4_run_test static64} - - {name: static64-pack, run: source .github/setenv.sh && c4_package static64} - - name: shared32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared32 - - {name: shared32-build, run: source .github/setenv.sh && c4_build_test shared32} - - {name: shared32-run, run: source .github/setenv.sh && c4_run_test shared32} - - {name: shared32-pack, run: source .github/setenv.sh && c4_package shared32} - - name: static32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static32 - - {name: static32-build, run: source .github/setenv.sh && c4_build_test static32} - - {name: static32-run, run: source .github/setenv.sh && c4_run_test static32} - - {name: static32-pack, run: source .github/setenv.sh && c4_package static32} - -# TODO: -# mingw: -# name: mingw/${{matrix.platform}}/c++${{matrix.std}}/${{matrix.bt}} -# if: | -# (!contains(github.event.head_commit.message, 'skip all')) || -# (!contains(github.event.head_commit.message, 'skip windows')) || -# contains(github.event.head_commit.message, 'only windows') -# continue-on-error: true -# runs-on: ${{matrix.os}} -# strategy: -# fail-fast: false -# matrix: -# include: -# - {std: 11, platform: x86, cxx: i686-w64-mingw32-g++, bt: Debug , os: windows-latest, bitlinks: shared32 static32} -# - {std: 11, platform: x64, cxx: x86_64-w64-mingw32-g++, bt: Debug , os: windows-latest, bitlinks: shared64 static64} -# - {std: 11, platform: x86, cxx: i686-w64-mingw32-g++, bt: Release, os: windows-latest, bitlinks: shared32 static32} -# - {std: 11, platform: x64, cxx: x86_64-w64-mingw32-g++, bt: Release, os: windows-latest, bitlinks: shared64 static64} -# - {std: 17, platform: x86, cxx: i686-w64-mingw32-g++, bt: Debug , os: windows-latest, bitlinks: shared32 static32} -# - {std: 17, platform: x64, cxx: x86_64-w64-mingw32-g++, bt: Debug , os: windows-latest, bitlinks: shared64 static64} -# - {std: 17, platform: x86, cxx: i686-w64-mingw32-g++, bt: Release, os: windows-latest, bitlinks: shared32 static32} -# - {std: 17, platform: x64, cxx: x86_64-w64-mingw32-g++, bt: Release, os: windows-latest, bitlinks: shared64 static64} -# env: {STD: "${{matrix.std}}", CXX_: "${{matrix.cxx}}", BT: "${{matrix.bt}}", BITLINKS: "${{matrix.bitlinks}}", VG: "${{matrix.vg}}", SAN: "${{matrix.san}}", LINT: "${{matrix.lint}}", OS: "${{matrix.os}}"} -# steps: -# - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} -# - {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS} -# - name: install mingw -# uses: egor-tensin/setup-mingw@v2 -# with: -# platform: "${{matrix.platform}}" -# - name: shared64-configure--------------------------------------------------- -# run: source .github/setenv.sh && c4_cfg_test shared64 -# - {name: shared64-build, run: source .github/setenv.sh && c4_build_test shared64} -# - {name: shared64-run, run: source .github/setenv.sh && c4_run_test shared64} -# - {name: shared64-pack, run: source .github/setenv.sh && c4_package shared64} -# - name: static64-configure--------------------------------------------------- -# run: source .github/setenv.sh && c4_cfg_test static64 -# - {name: static64-build, run: source .github/setenv.sh && c4_build_test static64} -# - {name: static64-run, run: source .github/setenv.sh && c4_run_test static64} -# - {name: static64-pack, run: source .github/setenv.sh && c4_package static64} -# - name: shared32-configure--------------------------------------------------- -# run: source .github/setenv.sh && c4_cfg_test shared32 -# - {name: shared32-build, run: source .github/setenv.sh && c4_build_test shared32} -# - {name: shared32-run, run: source .github/setenv.sh && c4_run_test shared32} -# - {name: shared32-pack, run: source .github/setenv.sh && c4_package shared32} -# - name: static32-configure--------------------------------------------------- -# run: source .github/setenv.sh && c4_cfg_test static32 -# - {name: static32-build, run: source .github/setenv.sh && c4_build_test static32} -# - {name: static32-run, run: source .github/setenv.sh && c4_run_test static32} -# - {name: static32-pack, run: source .github/setenv.sh && c4_package static32} diff --git a/thirdparty/ryml/.gitignore b/thirdparty/ryml/.gitignore deleted file mode 100644 index 641b684ab..000000000 --- a/thirdparty/ryml/.gitignore +++ /dev/null @@ -1,51 +0,0 @@ -# text editor files -*.bck -\#* -*~ -.cquery_cached_index/ -.clangd/ -.ccls-cache/ -.cache/ -__pycache__/ - -# gdb files -.gdbinit -setup.gdb - -# valgrind files -callgrind* -vgcore* - -# Visual Studio files -.vs/ -.vscode/ -# QtCreator files -CMakeLists.txt.user* -# Eclipse -.project -.cproject -/.settings/ -# KDevelop files -*.kdev4 - -# build files -build/ -install/ -.python-version -compile_commands.json - -# test files -/Testing/ - -# python packaging -.eggs/ -dist/ -rapidyaml.egg-info/ -wheelhouse/ - -# continuous integration files -.ci/.vagrant - -# amalgamation files -src/c4/c4core_all.hpp -src_singleheader/ diff --git a/thirdparty/ryml/.gitmodules b/thirdparty/ryml/.gitmodules deleted file mode 100644 index b8f0b0ef4..000000000 --- a/thirdparty/ryml/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "extern/c4core"] - path = ext/c4core - url = https://github.com/biojppm/c4core diff --git a/thirdparty/ryml/.lgtm.yml b/thirdparty/ryml/.lgtm.yml deleted file mode 100644 index c1376d236..000000000 --- a/thirdparty/ryml/.lgtm.yml +++ /dev/null @@ -1,2 +0,0 @@ -queries: -- exclude: cpp/unsigned-comparison-zero diff --git a/thirdparty/ryml/CONTRIBUTING.md b/thirdparty/ryml/CONTRIBUTING.md deleted file mode 100644 index c8e847bfa..000000000 --- a/thirdparty/ryml/CONTRIBUTING.md +++ /dev/null @@ -1,18 +0,0 @@ -# Contributing - -Thanks for your contribution! - -* Make sure to clone the project with `git clone --recursive` so that - the submodules are initialized correctly. -* To enable both tests and benchmarks, configure ryml with `-DRYML_DEV=ON` - when calling cmake. To enable only tests, use `-DRYML_BUILD_TESTS=ON`; to - enable only benchmarks use `-DRYML_BUILD_BENCHMARKS=ON`. All these flags - are disabled by default. -* Code style for pull requests should respect the existing code style: - ```c++ - if(foo) // no space before parens - { // curly brackets on next line - // no tabs; indent with 4 spaces - bar(); - } - ``` diff --git a/thirdparty/ryml/LICENSE.txt b/thirdparty/ryml/LICENSE.txt deleted file mode 100644 index 47b6b4394..000000000 --- a/thirdparty/ryml/LICENSE.txt +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2018, Joao Paulo Magalhaes - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. - diff --git a/thirdparty/ryml/MANIFEST.in b/thirdparty/ryml/MANIFEST.in deleted file mode 100644 index cdeb27468..000000000 --- a/thirdparty/ryml/MANIFEST.in +++ /dev/null @@ -1,3 +0,0 @@ -# MANIFEST.in must be in root directory. -# See https://github.com/pypa/setuptools/issues/2615 -graft ext diff --git a/thirdparty/ryml/README.md b/thirdparty/ryml/README.md deleted file mode 100644 index ddfa35454..000000000 --- a/thirdparty/ryml/README.md +++ /dev/null @@ -1,1136 +0,0 @@ -# Rapid YAML -[![MIT Licensed](https://img.shields.io/badge/License-MIT-green.svg)](https://github.com/biojppm/rapidyaml/blob/master/LICENSE.txt) -[![release](https://img.shields.io/github/v/release/biojppm/rapidyaml?color=g&include_prereleases&label=release%20&sort=semver)](https://github.com/biojppm/rapidyaml/releases) -[![PyPI](https://img.shields.io/pypi/v/rapidyaml?color=g)](https://pypi.org/project/rapidyaml/) -[![Docs](https://img.shields.io/badge/docs-docsforge-blue)](https://rapidyaml.docsforge.com/) -[![Gitter](https://badges.gitter.im/rapidyaml/community.svg)](https://gitter.im/rapidyaml/community) - -[![test](https://github.com/biojppm/rapidyaml/workflows/test/badge.svg?branch=master)](https://github.com/biojppm/rapidyaml/actions) - -[![Codecov](https://codecov.io/gh/biojppm/rapidyaml/branch/master/graph/badge.svg?branch=master)](https://codecov.io/gh/biojppm/rapidyaml) - - -Or ryml, for short. ryml is a C++ library to parse and emit YAML, -and do it fast, on everything from x64 to bare-metal chips without -operating system. (If you are looking to use your programs with a YAML tree -as a configuration tree with override facilities, take a look at -[c4conf](https://github.com/biojppm/c4conf)). - -ryml parses both read-only and in-situ source buffers; the resulting -data nodes hold only views to sub-ranges of the source buffer. No -string copies or duplications are done, and no virtual functions are -used. The data tree is a flat index-based structure stored in a single -array. Serialization happens only at your direct request, after -parsing / before emitting. Internally, the data tree representation -stores only string views and has no knowledge of types, but of course, -every node can have a YAML type tag. ryml makes it easy and fast to -read and modify the data tree. - -ryml is available as a single header file, or it can be used as a -simple library with cmake -- both separately (ie -build->install->`find_package()`) or together with your project (ie with -`add_subdirectory()`). (See below for examples). - -ryml can use custom global and per-tree memory allocators and error -handler callbacks, and is exception-agnostic. ryml provides a default -implementation for the allocator (using `std::malloc()`) and error -handlers (using using `std::abort()` is provided, but you can opt out -and provide your own memory allocation and eg, exception-throwing -callbacks. - -ryml does not depend on the STL, ie, it does not use any std container -as part of its data structures), but it can serialize and deserialize -these containers into the data tree, with the use of optional -headers. ryml ships with [c4core](https://github.com/biojppm/c4core), a -small C++ utilities multiplatform library. - -ryml is written in C++11, and compiles cleanly with: -* Visual Studio 2015 and later -* clang++ 3.9 and later -* g++ 4.8 and later -* Intel Compiler - -ryml is [extensively unit-tested in Linux, Windows and -MacOS](https://github.com/biojppm/rapidyaml/actions). The tests cover -x64, x86, wasm (emscripten), arm, aarch64, ppc64le and s390x -architectures, and include analysing ryml with: - * valgrind - * clang-tidy - * clang sanitizers: - * memory - * address - * undefined behavior - * thread - * [LGTM.com](https://lgtm.com/projects/g/biojppm/rapidyaml) - -ryml also [runs in -bare-metal](https://github.com/biojppm/rapidyaml/issues/193), and -[RISC-V -architectures](https://github.com/biojppm/c4core/pull/69). Both of -these are pending implementation of CI actions for continuous -validation, but ryml has been proven to work there. - -ryml is [available in Python](https://pypi.org/project/rapidyaml/), -and can very easily be compiled to JavaScript through emscripten (see -below). - -See also [the changelog](https://github.com/biojppm/rapidyaml/tree/master/changelog) -and [the roadmap](https://github.com/biojppm/rapidyaml/tree/master/ROADMAP.md). - - - - ------- - -## Table of contents -* [Is it rapid?](#is-it-rapid) - * [Comparison with yaml-cpp](#comparison-with-yaml-cpp) - * [Performance reading JSON](#performance-reading-json) - * [Performance emitting](#performance-emitting) -* [Quick start](#quick-start) -* [Using ryml in your project](#using-ryml-in-your-project) - * [Package managers](#package-managers) - * [Single header file](#single-header-file) - * [As a library](#as-a-library) - * [Quickstart samples](#quickstart-samples) - * [CMake build settings for ryml](#cmake-build-settings-for-ryml) - * [Forcing ryml to use a different c4core version](#forcing-ryml-to-use-a-different-c4core-version) -* [Other languages](#other-languages) - * [JavaScript](#javascript) - * [Python](#python) -* [YAML standard conformance](#yaml-standard-conformance) - * [Test suite status](#test-suite-status) -* [Known limitations](#known-limitations) -* [Alternative libraries](#alternative-libraries) -* [License](#license) - - ------- - -## Is it rapid? - -You bet! On a i7-6800K CPU @3.40GHz: - * ryml parses YAML at about ~150MB/s on Linux and ~100MB/s on Windows (vs2017). - * **ryml parses JSON at about ~450MB/s on Linux**, faster than sajson (didn't - try yet on Windows). - * compared against the other existing YAML libraries for C/C++: - * ryml is in general between 2 and 3 times faster than [libyaml](https://github.com/yaml/libyaml) - * ryml is in general between 10 and 70 times faster than - [yaml-cpp](https://github.com/jbeder/yaml-cpp), and in some cases as - much as 100x and [even - 200x](https://github.com/biojppm/c4core/pull/16#issuecomment-700972614) faster. - -[Here's the benchmark](./bm/bm_parse.cpp). Using different -approaches within ryml (in-situ/read-only vs. with/without reuse), a YAML / -JSON buffer is repeatedly parsed, and compared against other libraries. - -### Comparison with yaml-cpp - -The first result set is for Windows, and is using a [appveyor.yml config -file](./bm/cases/appveyor.yml). A comparison of these results is -summarized on the table below: - -| Read rates (MB/s) | ryml | yamlcpp | compared | -|------------------------------|--------|---------|--------------| -| appveyor / vs2017 / Release | 101.5 | 5.3 | 20x / 5.2% | -| appveyor / vs2017 / Debug | 6.4 | 0.0844 | 76x / 1.3% | - - -The next set of results is taken in Linux, comparing g++ 8.2 and clang++ 7.0.1 in -parsing a YAML buffer from a [travis.yml config -file](./bm/cases/travis.yml) or a JSON buffer from a [compile_commands.json -file](./bm/cases/compile_commands.json). You -can [see the full results here](./bm/results/parse.linux.i7_6800K.md). -Summarizing: - -| Read rates (MB/s) | ryml | yamlcpp | compared | -|-----------------------------|--------|---------|------------| -| json / clang++ / Release | 453.5 | 15.1 | 30x / 3% | -| json / g++ / Release | 430.5 | 16.3 | 26x / 4% | -| json / clang++ / Debug | 61.9 | 1.63 | 38x / 3% | -| json / g++ / Debug | 72.6 | 1.53 | 47x / 2% | -| travis / clang++ / Release | 131.6 | 8.08 | 16x / 6% | -| travis / g++ / Release | 176.4 | 8.23 | 21x / 5% | -| travis / clang++ / Debug | 10.2 | 1.08 | 9x / 1% | -| travis / g++ / Debug | 12.5 | 1.01 | 12x / 8% | - -The 450MB/s read rate for JSON puts ryml squarely in the same ballpark -as [RapidJSON](https://github.com/Tencent/rapidjson) and other fast json -readers -([data from here](https://lemire.me/blog/2018/05/03/how-fast-can-you-parse-json/)). -Even parsing full YAML is at ~150MB/s, which is still in that performance -ballpark, albeit at its lower end. This is something to be proud of, as the -YAML specification is much more complex than JSON: [23449 vs 1969 words](https://www.arp242.net/yaml-config.html#its-pretty-complex). - - -### Performance reading JSON - -So how does ryml compare against other JSON readers? Well, it's one of the -fastest! - -The benchmark is the [same as above](./bm/parse.cpp), and it is reading -the [compile_commands.json](./bm/cases/compile_commands.json), The `_arena` -suffix notes parsing a read-only buffer (so buffer copies are performed), -while the `_inplace` suffix means that the source buffer can be parsed in -place. The `_reuse` means the data tree and/or parser are reused on each -benchmark repeat. - -Here's what we get with g++ 8.2: - -| Benchmark | Release,MB/s | Debug,MB/s | -|:----------------------|-------------:|------------:| -| rapidjson_arena | 509.9 | 43.4 | -| rapidjson_inplace | 1329.4 | 68.2 | -| sajson_inplace | 434.2 | 176.5 | -| sajson_arena | 430.7 | 175.6 | -| jsoncpp_arena | 183.6 | ? 187.9 | -| nlohmann_json_arena | 115.8 | 21.5 | -| yamlcpp_arena | 16.6 | 1.6 | -| libyaml_arena | 113.9 | 35.7 | -| libyaml_arena_reuse | 114.6 | 35.9 | -| ryml_arena | 388.6 | 36.9 | -| ryml_inplace | 393.7 | 36.9 | -| ryml_arena_reuse | 446.2 | 74.6 | -| ryml_inplace_reuse | 457.1 | 74.9 | - -You can verify that (at least for this test) ryml beats most json -parsers at their own game, with the only exception of -[rapidjson](https://github.com/Tencent/rapidjson). And actually, in -Debug, [rapidjson](https://github.com/Tencent/rapidjson) is slower -than ryml, and [sajson](https://github.com/chadaustin/sajson) -manages to be faster (but not sure about jsoncpp; need to scrutinize there -the suspicious fact that the Debug result is faster than the Release result). - - -### Performance emitting - -[Emitting benchmarks](bm/bm_emit.cpp) also show similar speedups from -the existing libraries, also anecdotally reported by some users [(eg, -here's a user reporting 25x speedup from -yaml-cpp)](https://github.com/biojppm/rapidyaml/issues/28#issue-553855608). Also, in -some cases (eg, block folded multiline scalars), the speedup is as -high as 200x (eg, 7.3MB/s -> 1.416MG/s). - - -### CI results and request for files - -While a more effective way of showing the benchmark results is not -available yet, you can browse through the [runs of the benchmark -workflow in the -CI](https://github.com/biojppm/rapidyaml/actions/workflows/benchmarks.yml) -to scroll through the results for yourself. - -Also, if you have a case where ryml behaves very nicely or not as nicely as -claimed above, we would definitely like to see it! Please submit a pull request -adding the file to [bm/cases](bm/cases), or just send us the files. - - ------- - -## Quick start - -If you're wondering whether ryml's speed comes at a usage cost, you -need not: with ryml, you can have your cake and eat it too. Being -rapid is definitely NOT the same as being unpractical, so ryml was -written with easy AND efficient usage in mind, and comes with a two -level API for accessing and traversing the data tree. - -The following snippet is a quick overview taken from [the quickstart -sample](samples/quickstart.cpp). After cloning ryml (don't forget the -`--recursive` flag for git), you can very -easily build and run this executable using any of the build samples, -eg the [`add_subdirectory()` sample](samples/add_subdirectory/). - -```c++ -// Parse YAML code in place, potentially mutating the buffer. -// It is also possible to: -// - parse a read-only buffer using parse_in_arena() -// - reuse an existing tree (advised) -// - reuse an existing parser (advised) -char yml_buf[] = "{foo: 1, bar: [2, 3], john: doe}"; -ryml::Tree tree = ryml::parse_in_place(yml_buf); - -// Note: it will always be significantly faster to use mutable -// buffers and reuse tree+parser. -// -// Below you will find samples that show how to achieve reuse; but -// please note that for brevity and clarity, many of the examples -// here are parsing immutable buffers, and not reusing tree or -// parser. - - -//------------------------------------------------------------------ -// API overview - -// ryml has a two-level API: -// -// The lower level index API is based on the indices of nodes, -// where the node's id is the node's position in the tree's data -// array. This API is very efficient, but somewhat difficult to use: -size_t root_id = tree.root_id(); -size_t bar_id = tree.find_child(root_id, "bar"); // need to get the index right -CHECK(tree.is_map(root_id)); // all of the index methods are in the tree -CHECK(tree.is_seq(bar_id)); // ... and receive the subject index - -// The node API is a lightweight abstraction sitting on top of the -// index API, but offering a much more convenient interaction: -ryml::ConstNodeRef root = tree.rootref(); -ryml::ConstNodeRef bar = tree["bar"]; -CHECK(root.is_map()); -CHECK(bar.is_seq()); -// A node ref is a lightweight handle to the tree and associated id: -CHECK(root.tree() == &tree); // a node ref points at its tree, WITHOUT refcount -CHECK(root.id() == root_id); // a node ref's id is the index of the node -CHECK(bar.id() == bar_id); // a node ref's id is the index of the node - -// The node API translates very cleanly to the index API, so most -// of the code examples below are using the node API. - -// One significant point of the node API is that it holds a raw -// pointer to the tree. Care must be taken to ensure the lifetimes -// match, so that a node will never access the tree after the tree -// went out of scope. - - -//------------------------------------------------------------------ -// To read the parsed tree - -// ConstNodeRef::operator[] does a lookup, is O(num_children[node]). -CHECK(tree["foo"].is_keyval()); -CHECK(tree["foo"].key() == "foo"); -CHECK(tree["foo"].val() == "1"); -CHECK(tree["bar"].is_seq()); -CHECK(tree["bar"].has_key()); -CHECK(tree["bar"].key() == "bar"); -// maps use string keys, seqs use integral keys: -CHECK(tree["bar"][0].val() == "2"); -CHECK(tree["bar"][1].val() == "3"); -CHECK(tree["john"].val() == "doe"); -// An integral key is the position of the child within its parent, -// so even maps can also use int keys, if the key position is -// known. -CHECK(tree[0].id() == tree["foo"].id()); -CHECK(tree[1].id() == tree["bar"].id()); -CHECK(tree[2].id() == tree["john"].id()); -// Tree::operator[](int) searches a ***root*** child by its position. -CHECK(tree[0].id() == tree["foo"].id()); // 0: first child of root -CHECK(tree[1].id() == tree["bar"].id()); // 1: first child of root -CHECK(tree[2].id() == tree["john"].id()); // 2: first child of root -// NodeRef::operator[](int) searches a ***node*** child by its position: -CHECK(bar[0].val() == "2"); // 0 means first child of bar -CHECK(bar[1].val() == "3"); // 1 means second child of bar -// NodeRef::operator[](string): -// A string key is the key of the node: lookup is by name. So it -// is only available for maps, and it is NOT available for seqs, -// since seq members do not have keys. -CHECK(tree["foo"].key() == "foo"); -CHECK(tree["bar"].key() == "bar"); -CHECK(tree["john"].key() == "john"); -CHECK(bar.is_seq()); -// CHECK(bar["BOOM!"].is_seed()); // error, seqs do not have key lookup - -// Note that maps can also use index keys as well as string keys: -CHECK(root["foo"].id() == root[0].id()); -CHECK(root["bar"].id() == root[1].id()); -CHECK(root["john"].id() == root[2].id()); - -// IMPORTANT. The ryml tree uses indexed linked lists for storing -// children, so the complexity of `Tree::operator[csubstr]` and -// `Tree::operator[size_t]` is linear on the number of root -// children. If you use `Tree::operator[]` with a large tree where -// the root has many children, you will see a performance hit. -// -// To avoid this hit, you can create your own accelerator -// structure. For example, before doing a lookup, do a single -// traverse at the root level to fill an `map` -// mapping key names to node indices; with a node index, a lookup -// (via `Tree::get()`) is O(1), so this way you can get O(log n) -// lookup from a key. (But please do not use `std::map` if you -// care about performance; use something else like a flat map or -// sorted vector). -// -// As for node refs, the difference from `NodeRef::operator[]` and -// `ConstNodeRef::operator[]` to `Tree::operator[]` is that the -// latter refers to the root node, whereas the former are invoked -// on their target node. But the lookup process works the same for -// both and their algorithmic complexity is the same: they are -// both linear in the number of direct children. But of course, -// depending on the data, that number may be very different from -// one to another. - -//------------------------------------------------------------------ -// Hierarchy: - -{ - ryml::ConstNodeRef foo = root.first_child(); - ryml::ConstNodeRef john = root.last_child(); - CHECK(tree.size() == 6); // O(1) number of nodes in the tree - CHECK(root.num_children() == 3); // O(num_children[root]) - CHECK(foo.num_siblings() == 3); // O(num_children[parent(foo)]) - CHECK(foo.parent().id() == root.id()); // parent() is O(1) - CHECK(root.first_child().id() == root["foo"].id()); // first_child() is O(1) - CHECK(root.last_child().id() == root["john"].id()); // last_child() is O(1) - CHECK(john.first_sibling().id() == foo.id()); - CHECK(foo.last_sibling().id() == john.id()); - // prev_sibling(), next_sibling(): (both are O(1)) - CHECK(foo.num_siblings() == root.num_children()); - CHECK(foo.prev_sibling().id() == ryml::NONE); // foo is the first_child() - CHECK(foo.next_sibling().key() == "bar"); - CHECK(foo.next_sibling().next_sibling().key() == "john"); - CHECK(foo.next_sibling().next_sibling().next_sibling().id() == ryml::NONE); // john is the last_child() -} - - -//------------------------------------------------------------------ -// Iterating: -{ - ryml::csubstr expected_keys[] = {"foo", "bar", "john"}; - // iterate children using the high-level node API: - { - size_t count = 0; - for(ryml::ConstNodeRef const& child : root.children()) - CHECK(child.key() == expected_keys[count++]); - } - // iterate siblings using the high-level node API: - { - size_t count = 0; - for(ryml::ConstNodeRef const& child : root["foo"].siblings()) - CHECK(child.key() == expected_keys[count++]); - } - // iterate children using the lower-level tree index API: - { - size_t count = 0; - for(size_t child_id = tree.first_child(root_id); child_id != ryml::NONE; child_id = tree.next_sibling(child_id)) - CHECK(tree.key(child_id) == expected_keys[count++]); - } - // iterate siblings using the lower-level tree index API: - // (notice the only difference from above is in the loop - // preamble, which calls tree.first_sibling(bar_id) instead of - // tree.first_child(root_id)) - { - size_t count = 0; - for(size_t child_id = tree.first_sibling(bar_id); child_id != ryml::NONE; child_id = tree.next_sibling(child_id)) - CHECK(tree.key(child_id) == expected_keys[count++]); - } -} - - -//------------------------------------------------------------------ -// Gotchas: -CHECK(!tree["bar"].has_val()); // seq is a container, so no val -CHECK(!tree["bar"][0].has_key()); // belongs to a seq, so no key -CHECK(!tree["bar"][1].has_key()); // belongs to a seq, so no key -//CHECK(tree["bar"].val() == BOOM!); // ... so attempting to get a val is undefined behavior -//CHECK(tree["bar"][0].key() == BOOM!); // ... so attempting to get a key is undefined behavior -//CHECK(tree["bar"][1].key() == BOOM!); // ... so attempting to get a key is undefined behavior - - -//------------------------------------------------------------------ -// Deserializing: use operator>> -{ - int foo = 0, bar0 = 0, bar1 = 0; - std::string john; - root["foo"] >> foo; - root["bar"][0] >> bar0; - root["bar"][1] >> bar1; - root["john"] >> john; // requires from_chars(std::string). see serialization samples below. - CHECK(foo == 1); - CHECK(bar0 == 2); - CHECK(bar1 == 3); - CHECK(john == "doe"); -} - - -//------------------------------------------------------------------ -// Modifying existing nodes: operator<< vs operator= - -// As implied by its name, ConstNodeRef is a reference to a const -// node. It can be used to read from the node, but not write to it -// or modify the hierarchy of the node. If any modification is -// desired then a NodeRef must be used instead: -ryml::NodeRef wroot = tree.rootref(); - -// operator= assigns an existing string to the receiving node. -// This pointer will be in effect until the tree goes out of scope -// so beware to only assign from strings outliving the tree. -wroot["foo"] = "says you"; -wroot["bar"][0] = "-2"; -wroot["bar"][1] = "-3"; -wroot["john"] = "ron"; -// Now the tree is _pointing_ at the memory of the strings above. -// That is OK because those are static strings and will outlive -// the tree. -CHECK(root["foo"].val() == "says you"); -CHECK(root["bar"][0].val() == "-2"); -CHECK(root["bar"][1].val() == "-3"); -CHECK(root["john"].val() == "ron"); -// WATCHOUT: do not assign from temporary objects: -// { -// std::string crash("will dangle"); -// root["john"] = ryml::to_csubstr(crash); -// } -// CHECK(root["john"] == "dangling"); // CRASH! the string was deallocated - -// operator<< first serializes the input to the tree's arena, then -// assigns the serialized string to the receiving node. This avoids -// constraints with the lifetime, since the arena lives with the tree. -CHECK(tree.arena().empty()); -wroot["foo"] << "says who"; // requires to_chars(). see serialization samples below. -wroot["bar"][0] << 20; -wroot["bar"][1] << 30; -wroot["john"] << "deere"; -CHECK(root["foo"].val() == "says who"); -CHECK(root["bar"][0].val() == "20"); -CHECK(root["bar"][1].val() == "30"); -CHECK(root["john"].val() == "deere"); -CHECK(tree.arena() == "says who2030deere"); // the result of serializations to the tree arena -// using operator<< instead of operator=, the crash above is avoided: -{ - std::string ok("in_scope"); - // root["john"] = ryml::to_csubstr(ok); // don't, will dangle - wroot["john"] << ryml::to_csubstr(ok); // OK, copy to the tree's arena -} -CHECK(root["john"] == "in_scope"); // OK! -CHECK(tree.arena() == "says who2030deerein_scope"); // the result of serializations to the tree arena - - -//------------------------------------------------------------------ -// Adding new nodes: - -// adding a keyval node to a map: -CHECK(root.num_children() == 3); -wroot["newkeyval"] = "shiny and new"; // using these strings -wroot.append_child() << ryml::key("newkeyval (serialized)") << "shiny and new (serialized)"; // serializes and assigns the serialization -CHECK(root.num_children() == 5); -CHECK(root["newkeyval"].key() == "newkeyval"); -CHECK(root["newkeyval"].val() == "shiny and new"); -CHECK(root["newkeyval (serialized)"].key() == "newkeyval (serialized)"); -CHECK(root["newkeyval (serialized)"].val() == "shiny and new (serialized)"); -CHECK( ! tree.in_arena(root["newkeyval"].key())); // it's using directly the static string above -CHECK( ! tree.in_arena(root["newkeyval"].val())); // it's using directly the static string above -CHECK( tree.in_arena(root["newkeyval (serialized)"].key())); // it's using a serialization of the string above -CHECK( tree.in_arena(root["newkeyval (serialized)"].val())); // it's using a serialization of the string above -// adding a val node to a seq: -CHECK(root["bar"].num_children() == 2); -wroot["bar"][2] = "oh so nice"; -wroot["bar"][3] << "oh so nice (serialized)"; -CHECK(root["bar"].num_children() == 4); -CHECK(root["bar"][2].val() == "oh so nice"); -CHECK(root["bar"][3].val() == "oh so nice (serialized)"); -// adding a seq node: -CHECK(root.num_children() == 5); -wroot["newseq"] |= ryml::SEQ; -wroot.append_child() << ryml::key("newseq (serialized)") |= ryml::SEQ; -CHECK(root.num_children() == 7); -CHECK(root["newseq"].num_children() == 0); -CHECK(root["newseq (serialized)"].num_children() == 0); -// adding a map node: -CHECK(root.num_children() == 7); -wroot["newmap"] |= ryml::MAP; -wroot.append_child() << ryml::key("newmap (serialized)") |= ryml::SEQ; -CHECK(root.num_children() == 9); -CHECK(root["newmap"].num_children() == 0); -CHECK(root["newmap (serialized)"].num_children() == 0); -// -// When the tree is mutable, operator[] does not mutate the tree -// until the returned node is written to. -// -// Until such time, the NodeRef object keeps in itself the required -// information to write to the proper place in the tree. This is -// called being in a "seed" state. -// -// This means that passing a key/index which does not exist will -// not mutate the tree, but will instead store (in the node) the -// proper place of the tree to be able to do so, if and when it is -// required. -// -// This is a significant difference from eg, the behavior of -// std::map, which mutates the map immediately within the call to -// operator[]. -// -// All of the points above apply only if the tree is mutable. If -// the tree is const, then a NodeRef cannot be obtained from it; -// only a ConstNodeRef, which can never be used to mutate the -// tree. -CHECK(!root.has_child("I am not nothing")); -ryml::NodeRef nothing = wroot["I am nothing"]; -CHECK(nothing.valid()); // points at the tree, and a specific place in the tree -CHECK(nothing.is_seed()); // ... but nothing is there yet. -CHECK(!root.has_child("I am nothing")); // same as above -ryml::NodeRef something = wroot["I am something"]; -ryml::ConstNodeRef constsomething = wroot["I am something"]; -CHECK(!root.has_child("I am something")); // same as above -CHECK(something.valid()); -CHECK(something.is_seed()); // same as above -CHECK(!constsomething.valid()); // NOTE: because a ConstNodeRef - // cannot be used to mutate a - // tree, it is only valid() if it - // is pointing at an existing - // node. -something = "indeed"; // this will commit to the tree, mutating at the proper place -CHECK(root.has_child("I am something")); -CHECK(root["I am something"].val() == "indeed"); -CHECK(something.valid()); -CHECK(!something.is_seed()); // now the tree has this node, so the - // ref is no longer a seed -// now the constref is also valid (but it needs to be reassigned): -ryml::ConstNodeRef constsomethingnew = wroot["I am something"]; -CHECK(constsomethingnew.valid()); -// note that the old constref is now stale, because it only keeps -// the state at creation: -CHECK(!constsomething.valid()); - - -//------------------------------------------------------------------ -// Emitting: - -// emit to a FILE* -ryml::emit_yaml(tree, stdout); // there is also emit_json() -// emit to a stream -std::stringstream ss; -ss << tree; -std::string stream_result = ss.str(); -// emit to a buffer: -std::string str_result = ryml::emitrs_yaml(tree); // there is also emitrs_json() -// can emit to any given buffer: -char buf[1024]; -ryml::csubstr buf_result = ryml::emit_yaml(tree, buf); -// now check -ryml::csubstr expected_result = R"(foo: says who -bar: -- 20 -- 30 -- oh so nice -- oh so nice (serialized) -john: in_scope -newkeyval: shiny and new -newkeyval (serialized): shiny and new (serialized) -newseq: [] -newseq (serialized): [] -newmap: {} -newmap (serialized): [] -I am something: indeed -)"; -CHECK(buf_result == expected_result); -CHECK(str_result == expected_result); -CHECK(stream_result == expected_result); -// There are many possibilities to emit to buffer; -// please look at the emit sample functions below. - -//------------------------------------------------------------------ -// ConstNodeRef vs NodeRef - -ryml::NodeRef noderef = tree["bar"][0]; -ryml::ConstNodeRef constnoderef = tree["bar"][0]; - -// ConstNodeRef cannot be used to mutate the tree, but a NodeRef can: -//constnoderef = "21"; // compile error -//constnoderef << "22"; // compile error -noderef = "21"; // ok, can assign because it's not const -CHECK(tree["bar"][0].val() == "21"); -noderef << "22"; // ok, can serialize and assign because it's not const -CHECK(tree["bar"][0].val() == "22"); - -// it is not possible to obtain a NodeRef from a ConstNodeRef: -// noderef = constnoderef; // compile error - -// it is always possible to obtain a ConstNodeRef from a NodeRef: -constnoderef = noderef; // ok can assign const <- nonconst - -// If a tree is const, then only ConstNodeRef's can be -// obtained from that tree: -ryml::Tree const& consttree = tree; -//noderef = consttree["bar"][0]; // compile error -noderef = tree["bar"][0]; // ok -constnoderef = consttree["bar"][0]; // ok - -// ConstNodeRef and NodeRef can be compared for equality. -// Equality means they point at the same node. -CHECK(constnoderef == noderef); -CHECK(!(constnoderef != noderef)); - -//------------------------------------------------------------------ -// Dealing with UTF8 -ryml::Tree langs = ryml::parse_in_arena(R"( -en: Planet (Gas) -fr: Planète (Gazeuse) -ru: Планета (Газ) -ja: 惑星(ガス) -zh: 行星(气体) -# UTF8 decoding only happens in double-quoted strings,\ -# as per the YAML standard -decode this: "\u263A \xE2\x98\xBA" -and this as well: "\u2705 \U0001D11E" -)"); -// in-place UTF8 just works: -CHECK(langs["en"].val() == "Planet (Gas)"); -CHECK(langs["fr"].val() == "Planète (Gazeuse)"); -CHECK(langs["ru"].val() == "Планета (Газ)"); -CHECK(langs["ja"].val() == "惑星(ガス)"); -CHECK(langs["zh"].val() == "行星(气体)"); -// and \x \u \U codepoints are decoded (but only when they appear -// inside double-quoted strings, as dictated by the YAML -// standard): -CHECK(langs["decode this"].val() == "☺ ☺"); -CHECK(langs["and this as well"].val() == "✅ 𝄞"); - -//------------------------------------------------------------------ -// Getting the location of nodes in the source: -ryml::Parser parser; -ryml::Tree tree2 = parser.parse_in_arena("expected.yml", expected_result); -ryml::Location loc = parser.location(tree2["bar"][1]); -CHECK(parser.location_contents(loc).begins_with("30")); -CHECK(loc.line == 3u); -CHECK(loc.col == 4u); -``` - -The [quickstart.cpp sample](./samples/quickstart.cpp) (from which the -above overview was taken) has many more detailed examples, and should -be your first port of call to find out any particular point about -ryml's API. It is tested in the CI, and thus has the correct behavior. -There you can find the following subjects being addressed: - -```c++ -sample_substr(); ///< about ryml's string views (from c4core) -sample_parse_file(); ///< ready-to-go example of parsing a file from disk -sample_parse_in_place(); ///< parse a mutable YAML source buffer -sample_parse_in_arena(); ///< parse a read-only YAML source buffer -sample_parse_reuse_tree(); ///< parse into an existing tree, maybe into a node -sample_parse_reuse_parser(); ///< reuse an existing parser -sample_parse_reuse_tree_and_parser(); ///< how to reuse existing trees and parsers -sample_iterate_trees(); ///< visit individual nodes and iterate through trees -sample_create_trees(); ///< programatically create trees -sample_tree_arena(); ///< interact with the tree's serialization arena -sample_fundamental_types(); ///< serialize/deserialize fundamental types -sample_formatting(); ///< control formatting when serializing/deserializing -sample_base64(); ///< encode/decode base64 -sample_user_scalar_types(); ///< serialize/deserialize scalar (leaf/string) types -sample_user_container_types(); ///< serialize/deserialize container (map or seq) types -sample_std_types(); ///< serialize/deserialize STL containers -sample_emit_to_container(); ///< emit to memory, eg a string or vector-like container -sample_emit_to_stream(); ///< emit to a stream, eg std::ostream -sample_emit_to_file(); ///< emit to a FILE* -sample_emit_nested_node(); ///< pick a nested node as the root when emitting -sample_json(); ///< JSON parsing and emitting -sample_anchors_and_aliases(); ///< deal with YAML anchors and aliases -sample_tags(); ///< deal with YAML type tags -sample_docs(); ///< deal with YAML docs -sample_error_handler(); ///< set a custom error handler -sample_global_allocator(); ///< set a global allocator for ryml -sample_per_tree_allocator(); ///< set per-tree allocators -sample_static_trees(); ///< how to use static trees in ryml -sample_location_tracking(); ///< track node locations in the parsed source tree -``` - - ------- - -## Using ryml in your project - -### Package managers - -If you opt for package managers, here's where ryml is available so far -(thanks to all the contributors!): - * [vcpkg](https://vcpkg.io/en/packages.html): `vcpkg install ryml` - * Arch Linux/Manjaro: - * [rapidyaml-git (AUR)](https://aur.archlinux.org/packages/rapidyaml-git/) - * [python-rapidyaml-git (AUR)](https://aur.archlinux.org/packages/python-rapidyaml-git/) - * [PyPI](https://pypi.org/project/rapidyaml/) - -Although package managers are very useful for quickly getting up to -speed, the advised way is still to bring ryml as a submodule of your -project, building both together. This makes it easy to track any -upstream changes in ryml. Also, ryml is small and quick to build, so -there's not much of a cost for building it with your project. - -### Single header file -ryml is provided chiefly as a cmake library project, but it can also -be used as a single header file, and there is a [tool to -amalgamate](./tools/amalgamate.py) the code into a single header -file. The amalgamated header file is provided with each release, but -you can also generate a customized file suiting your particular needs -(or commit): - -```console -[user@host rapidyaml]$ python3 tools/amalgamate.py -h -usage: amalgamate.py [-h] [--c4core | --no-c4core] [--fastfloat | --no-fastfloat] [--stl | --no-stl] [output] - -positional arguments: - output output file. defaults to stdout - -optional arguments: - -h, --help show this help message and exit - --c4core amalgamate c4core together with ryml. this is the default. - --no-c4core amalgamate c4core together with ryml. the default is --c4core. - --fastfloat enable fastfloat library. this is the default. - --no-fastfloat enable fastfloat library. the default is --fastfloat. - --stl enable stl interop. this is the default. - --no-stl enable stl interop. the default is --stl. -``` - -The amalgamated header file contains all the function declarations and -definitions. To use it in the project, `#include` the header at will -in any header or source file in the project, but in one source file, -and only in that one source file, `#define` the macro -`RYML_SINGLE_HDR_DEFINE_NOW` **before including the header**. This -will enable the function definitions. For example: -```c++ -// foo.h -#include - -// foo.cpp -// ensure that foo.h is not included before this define! -#define RYML_SINGLE_HDR_DEFINE_NOW -#include -``` - -If you wish to package the single header into a shared library, then -you will need to define the preprocessor symbol `RYML_SHARED` during -compilation. - - -### As a library -The single header file is a good approach to quickly try the library, -but if you wish to make good use of CMake and its tooling ecosystem, -(and get better compile times), then ryml has you covered. - -As with any other cmake library, you have the option to integrate ryml into -your project's build setup, thereby building ryml together with your -project, or -- prior to configuring your project -- you can have ryml -installed either manually or through package managers. - -Currently [cmake](https://cmake.org/) is required to build ryml; we -recommend a recent cmake version, at least 3.13. - -Note that ryml uses submodules. Take care to use the `--recursive` flag -when cloning the repo, to ensure ryml's submodules are checked out as well: -```bash -git clone --recursive https://github.com/biojppm/rapidyaml -``` -If you omit `--recursive`, after cloning you -will have to do `git submodule update --init --recursive` -to ensure ryml's submodules are checked out. - -### Quickstart samples - -These samples show different ways of getting ryml into your application. All the -samples use [the same quickstart executable -source](./samples/quickstart.cpp), but are built in different ways, -showing several alternatives to integrate ryml into your project. We -also encourage you to refer to the [quickstart source](./samples/quickstart.cpp) itself, which -extensively covers most of the functionality that you may want out of -ryml. - -Each sample brings a `run.sh` script with the sequence of commands -required to successfully build and run the application (this is a bash -script and runs in Linux and MacOS, but it is also possible to run in -Windows via Git Bash or the WSL). Click on the links below to find out -more about each sample: - -| Sample name | ryml is part of build? | cmake file | commands | -|:-------------------|--------------------------|:-------------|:-------------| -| [`singleheader`](./samples/singleheader) | **yes**
ryml brought as a single header file,
not as a library | [`CMakeLists.txt`](./samples/singleheader/CMakeLists.txt) | [`run.sh`](./samples/singleheader/run.sh) | -| [`singleheaderlib`](./samples/singleheaderlib) | **yes**
ryml brought as a library
but from the single header file | [`CMakeLists.txt`](./samples/singleheaderlib/CMakeLists.txt) | [`run_shared.sh` (shared library)](./samples/singleheaderlib/run_shared.sh)
[`run_static.sh` (static library)](./samples/singleheaderlib/run_static.sh) | -| [`add_subdirectory`](./samples/add_subdirectory) | **yes** | [`CMakeLists.txt`](./samples/add_subdirectory/CMakeLists.txt) | [`run.sh`](./samples/add_subdirectory/run.sh) | -| [`fetch_content`](./samples/fetch_content) | **yes** | [`CMakeLists.txt`](./samples/fetch_content/CMakeLists.txt) | [`run.sh`](./samples/fetch_content/run.sh) | -| [`find_package`](./samples/find_package) | **no**
needs prior install or package | [`CMakeLists.txt`](./samples/find_package/CMakeLists.txt) | [`run.sh`](./samples/find_package/run.sh) | - -### CMake build settings for ryml -The following cmake variables can be used to control the build behavior of -ryml: - - * `RYML_WITH_TAB_TOKENS=ON/OFF`. Enable/disable support for tabs as - valid container tokens after `:` and `-`. Defaults to `OFF`, - because this may cost up to 10% in processing time. - * `RYML_DEFAULT_CALLBACKS=ON/OFF`. Enable/disable ryml's default - implementation of error and allocation callbacks. Defaults to `ON`. - * `RYML_STANDALONE=ON/OFF`. ryml uses - [c4core](https://github.com/biojppm/c4core), a C++ library with low-level - multi-platform utilities for C++. When `RYML_STANDALONE=ON`, c4core is - incorporated into ryml as if it is the same library. Defaults to `ON`. - -If you're developing ryml or just debugging problems with ryml itself, the -following cmake variables can be helpful: - * `RYML_DEV=ON/OFF`: a bool variable which enables development targets such as - unit tests, benchmarks, etc. Defaults to `OFF`. - * `RYML_DBG=ON/OFF`: a bool variable which enables verbose prints from - parsing code; can be useful to figure out parsing problems. Defaults to - `OFF`. - -#### Forcing ryml to use a different c4core version - -ryml is strongly coupled to c4core, and this is reinforced by the fact -that c4core is a submodule of the current repo. However, it is still -possible to use a c4core version different from the one in the repo -(of course, only if there are no incompatibilities between the -versions). You can find out how to achieve this by looking at the -[`custom_c4core` sample](./samples/custom_c4core/CMakeLists.txt). - - ------- - -## Other languages - -One of the aims of ryml is to provide an efficient YAML API for other -languages. JavaScript is fully available, and there is already a -cursory implementation for Python using only the low-level API. After -ironing out the general approach, other languages are likely to -follow (all of this is possible because we're using -[SWIG](http://www.swig.org/), which makes it easy to do so). - -### JavaScript - -A JavaScript+WebAssembly port is available, compiled through [emscripten](https://emscripten.org/). - - -### Python - -(Note that this is a work in progress. Additions will be made and things will -be changed.) With that said, here's an example of the Python API: - -```python -import ryml - -# ryml cannot accept strings because it does not take ownership of the -# source buffer; only bytes or bytearrays are accepted. -src = b"{HELLO: a, foo: b, bar: c, baz: d, seq: [0, 1, 2, 3]}" - -def check(tree): - # for now, only the index-based low-level API is implemented - assert tree.size() == 10 - assert tree.root_id() == 0 - assert tree.first_child(0) == 1 - assert tree.next_sibling(1) == 2 - assert tree.first_sibling(5) == 2 - assert tree.last_sibling(1) == 5 - # use bytes objects for queries - assert tree.find_child(0, b"foo") == 1 - assert tree.key(1) == b"foo") - assert tree.val(1) == b"b") - assert tree.find_child(0, b"seq") == 5 - assert tree.is_seq(5) - # to loop over children: - for i, ch in enumerate(ryml.children(tree, 5)): - assert tree.val(ch) == [b"0", b"1", b"2", b"3"][i] - # to loop over siblings: - for i, sib in enumerate(ryml.siblings(tree, 5)): - assert tree.key(sib) == [b"HELLO", b"foo", b"bar", b"baz", b"seq"][i] - # to walk over all elements - visited = [False] * tree.size() - for n, indentation_level in ryml.walk(tree): - # just a dumb emitter - left = " " * indentation_level - if tree.is_keyval(n): - print("{}{}: {}".format(left, tree.key(n), tree.val(n)) - elif tree.is_val(n): - print("- {}".format(left, tree.val(n)) - elif tree.is_keyseq(n): - print("{}{}:".format(left, tree.key(n)) - visited[inode] = True - assert False not in visited - # NOTE about encoding! - k = tree.get_key(5) - print(k) # '' - assert k == b"seq" # ok, as expected - assert k != "seq" # not ok - NOTE THIS! - assert str(k) != "seq" # not ok - assert str(k, "utf8") == "seq" # ok again - -# parse immutable buffer -tree = ryml.parse_in_arena(src) -check(tree) # OK - -# parse mutable buffer. -# requires bytearrays or objects offering writeable memory -mutable = bytearray(src) -tree = ryml.parse_in_place(mutable) -check(tree) # OK -``` -As expected, the performance results so far are encouraging. In -a [timeit benchmark](api/python/parse_bm.py) compared -against [PyYaml](https://pyyaml.org/) -and [ruamel.yaml](https://yaml.readthedocs.io/en/latest/), ryml parses -quicker by generally 100x and up to 400x: -``` -+----------------------------------------+-------+----------+----------+-----------+ -| style_seqs_blck_outer1000_inner100.yml | count | time(ms) | avg(ms) | avg(MB/s) | -+----------------------------------------+-------+----------+----------+-----------+ -| parse:RuamelYamlParse | 1 | 4564.812 | 4564.812 | 0.173 | -| parse:PyYamlParse | 1 | 2815.426 | 2815.426 | 0.280 | -| parse:RymlParseInArena | 38 | 588.024 | 15.474 | 50.988 | -| parse:RymlParseInArenaReuse | 38 | 466.997 | 12.289 | 64.202 | -| parse:RymlParseInPlace | 38 | 579.770 | 15.257 | 51.714 | -| parse:RymlParseInPlaceReuse | 38 | 462.932 | 12.182 | 64.765 | -+----------------------------------------+-------+----------+----------+-----------+ -``` -(Note that the parse timings above are somewhat biased towards ryml, because -it does not perform any type conversions in Python-land: return types -are merely `memoryviews` to the source buffer, possibly copied to the tree's -arena). - -As for emitting, the improvement can be as high as 3000x: -``` -+----------------------------------------+-------+-----------+-----------+-----------+ -| style_maps_blck_outer1000_inner100.yml | count | time(ms) | avg(ms) | avg(MB/s) | -+----------------------------------------+-------+-----------+-----------+-----------+ -| emit_yaml:RuamelYamlEmit | 1 | 18149.288 | 18149.288 | 0.054 | -| emit_yaml:PyYamlEmit | 1 | 2683.380 | 2683.380 | 0.365 | -| emit_yaml:RymlEmitToNewBuffer | 88 | 861.726 | 9.792 | 99.976 | -| emit_yaml:RymlEmitReuse | 88 | 437.931 | 4.976 | 196.725 | -+----------------------------------------+-------+-----------+-----------+-----------+ -``` - - ------- - -## YAML standard conformance - -ryml is close to feature complete. Most of the YAML features are well -covered in the unit tests, and expected to work, unless in the -exceptions noted below. - -Of course, there are many dark corners in YAML, and there certainly -can appear cases which ryml fails to parse. Your [bug reports or pull -requests](https://github.com/biojppm/rapidyaml/issues) are very -welcome. - -See also [the roadmap](./ROADMAP.md) for a list of future work. - - -### Known limitations - -ryml deliberately makes no effort to follow the standard in the -following situations: - -* Containers are not accepted as mapping keys: keys must be scalars. -* Tab characters after `:` and `-` are not accepted tokens, unless - ryml is compiled with the macro `RYML_WITH_TAB_TOKENS`. This - requirement exists because checking for tabs introduces branching - into the parser's hot code and in some cases costs as much as 10% - in parsing time. -* Anchor names must not end with a terminating colon: eg `&anchor: key: val`. -* Non-unique map keys are allowed. Enforcing key uniqueness in the - parser or in the tree would cause log-linear parsing complexity (for - root children on a mostly flat tree), and would increase code size - through added structural, logical and cyclomatic complexity. So - enforcing uniqueness in the parser would hurt users who may not care - about it (they may not care either because non-uniqueness is OK for - their use case, or because it is impossible to occur). On the other - hand, any user who requires uniqueness can easily enforce it by - doing a post-parse walk through the tree. So choosing to not enforce - key uniqueness adheres to the spirit of "don't pay for what you - don't use". -* `%YAML` directives have no effect and are ignored. -* `%TAG` directives are limited to a default maximum of 4 instances - per `Tree`. To increase this maximum, define the preprocessor symbol - `RYML_MAX_TAG_DIRECTIVES` to a suitable value. This arbitrary limit - reflects the usual practice of having at most 1 or 2 tag directives; - also, be aware that this feature is under consideration for removal - in YAML 1.3. - -Also, ryml tends to be on the permissive side where the YAML standard -dictates there should be an error; in many of these cases, ryml will -tolerate the input. This may be good or bad, but in any case is being -improved on (meaning ryml will grow progressively less tolerant of -YAML errors in the coming releases). So we strongly suggest to stay -away from those dark corners of YAML which are generally a source of -problems, which is a good practice anyway. - -If you do run into trouble and would like to investigate conformance -of your YAML code, beware of existing online YAML linters, many of -which are not fully conformant; instead, try using -[https://play.yaml.io](https://play.yaml.io), an amazing tool which -lets you dynamically input your YAML and continuously see the results -from all the existing parsers (kudos to @ingydotnet and the people -from the YAML test suite). And of course, if you detect anything wrong -with ryml, please [open an -issue](https://github.com/biojppm/rapidyaml/issues) so that we can -improve. - - -### Test suite status - -As part of its CI testing, ryml uses the [YAML test -suite](https://github.com/yaml/yaml-test-suite). This is an extensive -set of reference cases covering the full YAML spec. Each of these -cases have several subparts: - * `in-yaml`: mildly, plainly or extremely difficult-to-parse YAML - * `in-json`: equivalent JSON (where possible/meaningful) - * `out-yaml`: equivalent standard YAML - * `emit-yaml`: equivalent standard YAML - * `events`: reference results (ie, expected tree) - -When testing, ryml parses each of the 4 yaml/json parts, then emits -the parsed tree, then parses the emitted result and verifies that -emission is idempotent, ie that the emitted result is semantically the -same as its input without any loss of information. To ensure -consistency, this happens over four levels of parse/emission -pairs. And to ensure correctness, each of the stages is compared -against the `events` spec from the test, which constitutes the -reference. The tests also check for equality between the reference -events in the test case and the events emitted by ryml from the data -tree parsed from the test case input. All of this is then carried out -combining several variations: both unix `\n` vs windows `\r\n` line -endings, emitting to string, file or streams, which results in ~250 -tests per case part. With multiple parts per case and ~400 reference -cases in the test suite, this makes over several hundred thousand -individual tests to which ryml is subjected, which are added to the -unit tests in ryml, which also employ the same extensive -combinatorial approach. - -Also, note that in [their own words](http://matrix.yaml.io/), the -tests from the YAML test suite *contain a lot of edge cases that don't -play such an important role in real world examples*. And yet, despite -the extreme focus of the test suite, currently ryml only fails a minor -fraction of the test cases, mostly related with the deliberate -limitations noted above. Other than those limitations, by far the main -issue with ryml is that several standard-mandated parse errors fail to -materialize. For the up-to-date list of ryml failures in the -test-suite, refer to the [list of known -exceptions](test/test_suite/test_suite_parts.cpp) from ryml's test -suite runner, which is used as part of ryml's CI process. - - ------- - -## Alternative libraries - -Why this library? Because none of the existing libraries was quite -what I wanted. When I started this project in 2018, I was aware of these two -alternative C/C++ libraries: - - * [libyaml](https://github.com/yaml/libyaml). This is a bare C - library. It does not create a representation of the data tree, so - I don't see it as practical. My initial idea was to wrap parsing - and emitting around libyaml's convenient event handling, but to my - surprise I found out it makes heavy use of allocations and string - duplications when parsing. I briefly pondered on sending PRs to - reduce these allocation needs, but not having a permanent tree to - store the parsed data was too much of a downside. - * [yaml-cpp](https://github.com/jbeder/yaml-cpp). This library may - be full of functionality, but is heavy on the use of - node-pointer-based structures like `std::map`, allocations, string - copies, polymorphism and slow C++ stream serializations. This is - generally a sure way of making your code slower, and strong - evidence of this can be seen in the benchmark results above. - -Recently [libfyaml](https://github.com/pantoniou/libfyaml) -appeared. This is a newer C library, fully conformant to the YAML -standard with an amazing 100% success in the test suite; it also offers -the tree as a data structure. As a downside, it does not work in -Windows, and it is also multiple times slower parsing and emitting. - -When performance and low latency are important, using contiguous -structures for better cache behavior and to prevent the library from -trampling caches, parsing in place and using non-owning strings is of -central importance. Hence this Rapid YAML library which, with minimal -compromise, bridges the gap from efficiency to usability. This library -takes inspiration from -[RapidJSON](https://github.com/Tencent/rapidjson) and -[RapidXML](http://rapidxml.sourceforge.net/). - ------- -## License - -ryml is permissively licensed under the [MIT license](LICENSE.txt). - diff --git a/thirdparty/ryml/ROADMAP.md b/thirdparty/ryml/ROADMAP.md deleted file mode 100644 index ca43b7c77..000000000 --- a/thirdparty/ryml/ROADMAP.md +++ /dev/null @@ -1,18 +0,0 @@ -# Roadmap - -Roughly in order of priority: - - * Cleanup: - * Review & cleanup API surface. - * Turn calls to `C4_ASSERT()` into calls to `RYML_ASSERT()` - * Add emit formatting controls: - * add single-line flow formatter - * add multi-line flow formatters - * indenting - * non indenting - * keep current block formatter - * add customizable linebreak limits (number of columns) to every formatter - * add per node format flags - * (lesser priority) add auto formatter using reasonable heuristics to - switch between other existing formatters - * Investigate possibility of comment-preserving roundtrips diff --git a/thirdparty/ryml/api/python/.gitignore b/thirdparty/ryml/api/python/.gitignore deleted file mode 100644 index 830e7e4d6..000000000 --- a/thirdparty/ryml/api/python/.gitignore +++ /dev/null @@ -1,141 +0,0 @@ -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -pip-wheel-metadata/ -share/python-wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.nox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -*.py,cover -.hypothesis/ -.pytest_cache/ -cover/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -local_settings.py -db.sqlite3 -db.sqlite3-journal - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# IPython -profile_default/ -ipython_config.py - -# pyenv -# For a library or package, you might want to ignore these files since the code is -# intended to run in multiple environments; otherwise, check them in: -# .python-version - -# pipenv -# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. -# However, in case of collaboration, if having platform-specific dependencies or dependencies -# having no cross-platform support, pipenv may install dependencies that don't work, or not -# install all needed dependencies. -#Pipfile.lock - -# PEP 582; used by e.g. github.com/David-OConnor/pyflow -__pypackages__/ - -# Celery stuff -celerybeat-schedule -celerybeat.pid - -# SageMath parsed files -*.sage.py - -# Environments -.env -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json - -# Pyre type checker -.pyre/ - -# pytype static type analyzer -.pytype/ - -# Version file generated by setuptools_scm -version.py - -# SWIG produced file -ryml/ryml.py diff --git a/thirdparty/ryml/api/python/Makefile b/thirdparty/ryml/api/python/Makefile deleted file mode 100644 index bdb5a6ffd..000000000 --- a/thirdparty/ryml/api/python/Makefile +++ /dev/null @@ -1,94 +0,0 @@ -# -*- coding: utf-8 -*- -# SPDX-License-Identifier: MIT - -# Use bash even on Windows -SHELL := /bin/bash - -# On Windows the activate script is stored in a different location. -ACTIVATE_SCRIPT := venv/bin/activate -ifeq ($(OS),Windows_NT) -ACTIVATE_SCRIPT := venv/Scripts/activate -endif - -# How to invoke python -PYTHON := python -# How to invoke pytest -PYTEST := $(PYTHON) -m pytest -vvv - -ACTIVATE=[[ -e $(ACTIVATE_SCRIPT) ]] && source $(ACTIVATE_SCRIPT); - -.PHONY: clean -clean: - rm -rf dist *.egg-info - rm -rf ../../build ../../.egg* - rm -rf ryml/*.so ryml/ryml.py ryml/include ryml/lib - -.PHONY: venv-clean -venv-clean: - rm -rf venv - - -$(ACTIVATE_SCRIPT): requirements.txt Makefile - make venv - @touch $(ACTIVATE_SCRIPT) - -.PHONY: venv -venv: - virtualenv --python=python3 --always-copy venv - # Packaging tooling. - ${ACTIVATE} pip install -U pip - # Setup requirements. - ${ACTIVATE} pip install -v -r requirements.txt - ${ACTIVATE} pip install -v -e ../.. - @${ACTIVATE} $(PYTHON) -c "from ryml.version import version as v; print('Installed version:', v)" - -.PHONY: build-sdist -build-sdist: | $(ACTIVATE_SCRIPT) - ${ACTIVATE} (cd ../..; $(PYTHON) -m build --sdist --outdir $(PWD)/dist) - - -.PHONY: build-wheel -build-wheel: | $(ACTIVATE_SCRIPT) - rm -rf dist - $(MAKE) build-sdist - @ls -l dist/*.tar.gz - ${ACTIVATE} pip wheel -v dist/*.tar.gz --wheel-dir $(PWD)/dist - -.PHONY: build -build: - rm -rf build dist - $(MAKE) build-sdist - $(MAKE) build-wheel - -# PYPI_TEST = --repository-url https://test.pypi.org/legacy/ -PYPI_TEST = --repository testpypi - -.PHONY: upload-test -upload-test: | $(ACTIVATE_SCRIPT) - make clean - make build-sdist - ${ACTIVATE} twine upload ${PYPI_TEST} dist/* - -.PHONY: upload -upload: | $(ACTIVATE_SCRIPT) - make clean - make build-sdist - ${ACTIVATE} twine upload --verbose dist/* - -.PHONY: check -check: | $(ACTIVATE_SCRIPT) - make clean - make build-wheel - ${ACTIVATE} twine check dist/*.whl - -.PHONY: install -install: | $(ACTIVATE_SCRIPT) - ${ACTIVATE} $(PYTHON) setup.py install - -.PHONY: test -test: | $(ACTIVATE_SCRIPT) - ${ACTIVATE} $(PYTEST) tests - -.PHONY: version -version: | $(ACTIVATE_SCRIPT) - ${ACTIVATE} $(PYTHON) setup.py --version diff --git a/thirdparty/ryml/api/python/bm/bm_parse.py b/thirdparty/ryml/api/python/bm/bm_parse.py deleted file mode 100644 index 294be679b..000000000 --- a/thirdparty/ryml/api/python/bm/bm_parse.py +++ /dev/null @@ -1,237 +0,0 @@ -import ryml -import ruamel.yaml -import yaml -import timeit -import time -import copy -import prettytable -import os.path -from collections import OrderedDict as odict - - -def _nodbg(*args, **kwargs): - pass - - -def _dbg(*args, **kwargs): - print(*args, **kwargs, file=sys.stderr, flush=True) - - -dbg = _dbg - - -class RunResults: - - __slots__ = ('name', 'time_ms', 'count', 'avg', 'MBps') - - def __init__(self, name, time_ms, count, num_bytes): - self.name = name - self.time_ms = time_ms - self.count = count - self.avg = time_ms / count - num_megabytes = count * num_bytes / 1.0e6 - num_seconds = time_ms / 1000.0 - self.MBps = num_megabytes / num_seconds - - def __str__(self): - fmt = "{}: count={} time={:.3f}ms avg={:.3f}ms MB/s={:.3f}" - fmt = fmt.format(self.name, self.count, self.time_ms, self.avg, self.MBps) - return fmt - - -class BmCase: - - def __init__(self, filename): - with open(filename, "r") as f: - src = f.read() - self.filename = filename - self.src_as_str = src - self.src_as_bytes = bytes(src, "utf8") - self.src_as_bytearray = bytearray(src, "utf8") - self.src_as_bytearray_orig = copy.copy(self.src_as_bytearray) - self.emittree = ryml.parse_in_arena(self.src_as_bytearray) - self.emitbuf = bytearray(4 * len(self.src_as_str)) # should be enough - - def run(self, bm_method_name, cls): - def run_bm(obj, subject): - obj.count = 0 - t = timeit.Timer(subject) - delta = time.time() - result = t.autorange() #lambda number, time_taken: time_taken > 1.0) - delta = 1000. * (time.time() - delta) - return delta, obj.count - obj = cls(self) - if not hasattr(obj, bm_method_name): - return None - name = bm_method_name + ":" + cls.__name__ - dbg(name, "...") - method = getattr(obj, bm_method_name) - reset_name = 'reset_' + bm_method_name - reset_fn = getattr(obj, reset_name, None) - def bm_fn(): - method(self) - obj.count += 1 - if reset_fn is not None: - reset_fn(self) - delta, count = run_bm(obj, bm_fn) - # correct the benchmark to account for the time spent - # resetting - if reset_fn is not None: - # find out how much it takes to reset the bytearray - if not hasattr(obj, 'bm_reset_done'): - def bm_reset(): - reset_fn(self) - obj.count += 1 - rdelta, rcount = run_bm(obj, bm_reset) - obj.bm_reset_time_per_iteration = rdelta / rcount - dbg(name, "reset_time_per_iteration={:.3f}us".format(obj.bm_reset_time_per_iteration * 1000.0)) - obj.bm_reset_done = True - reset_correction = count * obj.bm_reset_time_per_iteration - dbg(name, "delta={:.3f}ms".format(delta), "reset_correction={:.3f}ms({:.2f}%)".format(reset_correction, 100.0 * reset_correction / delta)) - delta -= reset_correction - ret = RunResults(name, delta, count, len(self.src_as_str)) - dbg(name, "ok:", ret) - return ret - - -def run(case, benchmarks, approaches): - for bm in benchmarks: - results = odict() - for cls in approaches: - r = case.run(bm, cls) - if r is None: - continue - results[r.name] = r - table = prettytable.PrettyTable() - name = os.path.basename(case.filename) - table.field_names = [name, "count", "time(ms)", "avg(ms)", "avg(MB/s)"] - table.align[name] = "l" - def i(v): return "{:5d}".format(v) - def f(v): return "{:8.3f}".format(v) - for v in results.values(): - table.add_row([v.name, i(v.count), f(v.time_ms), f(v.avg), f(v.MBps)]) - print(table) - - -class BmCaseRun: - def __init__(self, case): - self.reset_bytearray = False - - -class RymlParseInArena(BmCaseRun): - - def parse(self, case): - _ = ryml.parse_in_arena(case.src_as_bytearray) - - -class RymlParseInArenaReuse(BmCaseRun): - - def __init__(self, case): - self.tree = ryml.Tree() - - def parse(self, case): - ryml.parse_in_arena(case.src_as_bytearray, tree=self.tree) - - def reset_parse(self, case): - self.tree.clear() - self.tree.clear_arena() - - -class RymlParseInPlace(BmCaseRun): - - def parse(self, case): - _ = ryml.parse_in_place(case.src_as_bytearray) - - def reset_parse(self, case): - case.src_as_bytearray = copy.copy(case.src_as_bytearray_orig) - - -class RymlParseInPlaceReuse(BmCaseRun): - - def __init__(self, case): - self.tree = ryml.Tree() - - def parse(self, case): - ryml.parse_in_place(case.src_as_bytearray, tree=self.tree) - - def reset_parse(self, case): - self.tree.clear() - self.tree.clear_arena() - case.src_as_bytearray = copy.copy(case.src_as_bytearray_orig) - - -class RuamelYamlParse(BmCaseRun): - - def parse(self, case): - _ = ruamel.yaml.load(case.src_as_str, Loader=ruamel.yaml.Loader) - - -class PyYamlParse(BmCaseRun): - - def parse(self, case): - _ = yaml.safe_load(case.src_as_str) - - -class RymlEmitToNewBuffer(BmCaseRun): - - def emit_yaml(self, case): - _ = ryml.emit_yaml(case.emittree) - - def emit_json(self, case): - _ = ryml.emit_json(case.emittree) - - -class RymlEmitReuse(BmCaseRun): - - def emit_yaml(self, case): - _ = ryml.emit_yaml_in_place(case.emittree, case.emitbuf) - - def emit_json(self, case): - _ = ryml.emit_json_in_place(case.emittree, case.emitbuf) - - -class RuamelYamlEmit: - - def __init__(self, case): - case.ruamel_emittree = ruamel.yaml.load(case.src_as_str, Loader=ruamel.yaml.Loader) - - def emit_yaml(self, case): - # https://stackoverflow.com/a/47617341/5875572 - class MyToStr: - def __init__(self, *args, **kwargs): - self.s = b"" - def write(self, s): - self.s += s - dumper = MyToStr() - ruamel.yaml.YAML().dump(case.ruamel_emittree, MyToStr()) - - -class PyYamlEmit: - - def __init__(self, case): - case.pyyaml_emittree = yaml.load(case.src_as_str, Loader=yaml.Loader) - - def emit_yaml(self, case): - _ = yaml.dump(case.pyyaml_emittree) - - -if __name__ == "__main__": - import sys - if len(sys.argv) < 2: - raise Exception("") - filename = sys.argv[1] - if filename.endswith("outer1000_inner1000.yml"): # this one is too heavy for the Python libs - exit(0) - case = BmCase(filename) - run(case, benchmarks=('parse', ), - approaches=(RuamelYamlParse, - PyYamlParse, - RymlParseInArena, - RymlParseInArenaReuse, - RymlParseInPlace, - RymlParseInPlaceReuse)) - run(case, benchmarks=('emit_yaml', 'emit_json', ), - approaches=(RuamelYamlEmit, - PyYamlEmit, - RymlEmitToNewBuffer, - RymlEmitReuse)) diff --git a/thirdparty/ryml/api/python/requirements.txt b/thirdparty/ryml/api/python/requirements.txt deleted file mode 100644 index 86c126420..000000000 --- a/thirdparty/ryml/api/python/requirements.txt +++ /dev/null @@ -1,5 +0,0 @@ -ruamel.yaml -ninja -pyyaml -prettytable -pytest diff --git a/thirdparty/ryml/api/python/ryml/__init__.py b/thirdparty/ryml/api/python/ryml/__init__.py deleted file mode 100644 index 8bbb62199..000000000 --- a/thirdparty/ryml/api/python/ryml/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from ryml.ryml import * -from .version import * diff --git a/thirdparty/ryml/api/python/tests/test_parse.py b/thirdparty/ryml/api/python/tests/test_parse.py deleted file mode 100644 index bb7973cb3..000000000 --- a/thirdparty/ryml/api/python/tests/test_parse.py +++ /dev/null @@ -1,488 +0,0 @@ -import ryml -from ryml.ryml import _same_ptr, _same_mem -import unittest - - -# ----------------------------------------------------------------------------- -# ----------------------------------------------------------------------------- -# ----------------------------------------------------------------------------- -class TestSubstrInterop(unittest.TestCase): - - # ------------------------------------------------ - # str - - # CAN create c4::csubstr from string object - def test11_str2csubstr(self): - s = "asdasd" - m = ryml.as_csubstr(s) - self.assertTrue(_same_ptr(s, m)) - self.assertTrue(_same_mem(s, m)) - self.assertEqual(s, ryml.u(m)) - # - m = ryml.as_csubstr(m) - self.assertTrue(_same_ptr(s, m)) - self.assertTrue(_same_mem(s, m)) - self.assertEqual(s, ryml.u(m)) - - # CANNOT create c4::substr from string object - def test12_str2substr(self): - s = "" - with self.assertRaises(TypeError) as context: - _ = ryml.as_substr(s) - self.assertTrue(type(context.exception), TypeError) - - # ------------------------------------------------ - # bytes - - # CAN create c4::csubstr from string object - def test21_bytes2csubstr(self): - s = b"foo21" - m = ryml.as_csubstr(s) - self.assertTrue(_same_ptr(s, m)) - self.assertTrue(_same_mem(s, m)) - self.assertEqual(s, m) - # - m = ryml.as_csubstr(m) - self.assertTrue(_same_ptr(s, m)) - self.assertTrue(_same_mem(s, m)) - self.assertEqual(s, m) - - # CANNOT create c4::csubstr from string object - def test22_bytes2substr(self): - s = b"foo22" - with self.assertRaises(TypeError) as context: - _ = ryml.as_substr(s) - self.assertTrue(type(context.exception), TypeError) - - # ------------------------------------------------ - # bytearray - - # CAN create c4::csubstr from string object - def test31_bytes2csubstr(self): - s = bytearray("foo31", "utf8") - m = ryml.as_csubstr(s) - self.assertTrue(_same_ptr(s, m)) - self.assertTrue(_same_mem(s, m)) - self.assertEqual(s, m) - # - m = ryml.as_csubstr(m) - self.assertTrue(_same_ptr(s, m)) - self.assertTrue(_same_mem(s, m)) - self.assertEqual(s, m) - - # CANNOT create c4::csubstr from string object - def test32_bytes2substr(self): - s = bytearray("foo31", "utf8") - m = ryml.as_csubstr(s) - self.assertTrue(_same_ptr(s, m)) - self.assertTrue(_same_mem(s, m)) - self.assertEqual(s, m) - # - m = ryml.as_csubstr(m) - self.assertTrue(_same_ptr(s, m)) - self.assertTrue(_same_mem(s, m)) - self.assertEqual(s, m) - - -# ----------------------------------------------------------------------------- -# ----------------------------------------------------------------------------- -# ----------------------------------------------------------------------------- - -def _addmap(t, node, k=None): - m = t.append_child(node) - if k is None: - t.to_map(m) - else: - t.to_map(m, k) - return m - - -def _addseq(t, node, k=None): - m = t.append_child(node) - if k is None: - t.to_seq(m) - else: - t.to_seq(m, k) - return m - - -def _addval(t, node, k, v=None): - ch = t.append_child(node) - if v is None: - t.to_val(ch, k) - else: - t.to_keyval(ch, k, v) - return ch - - -# ----------------------------------------------------------------------------- -# ----------------------------------------------------------------------------- -# ----------------------------------------------------------------------------- -def check_tree_mod(ut, t): - # some convenient shorthands - eq = ut.assertEqual - def _addval_and_check(node, k, v=None): - ch = _addval(t, node, k, v) - pos = t.child_pos(node, ch) - eq(t.child(node, pos), ch) - if v is not None: - eq(t.find_child(node, k), ch) - eq(t.child(node, pos), t.find_child(node, k)) - return ch - def _addseq_and_check(node, k): - ch = _addseq(t, node, k) - eq(t.find_child(node, k), ch) - return ch - def _addmap_and_check(node, k): - ch = _addmap(t, node, k) - eq(t.find_child(node, k), ch) - return ch - m = _addmap_and_check(t.root_id(), "check_tree_mod_map") - _addval_and_check(m, "k1", "v1") - _addval_and_check(m, "k2", "v2") - _addval_and_check(m, "k3", "v3") - eq(t.num_children(m), 3) - eq(t.num_siblings(t.first_child(m)), 3) - s = _addseq_and_check(t.root_id(), "check_tree_mod_seq") - _addval_and_check(s, "v1") - _addval_and_check(s, "v2") - _addval_and_check(s, "v3") - eq(t.num_children(s), 3) - eq(t.num_siblings(t.first_child(m)), 3) - - -# ----------------------------------------------------------------------------- -# ----------------------------------------------------------------------------- -# ----------------------------------------------------------------------------- -class SimpleTestCase: - - yaml = "{'HELLO': a, foo: \"b\", bar: c, baz: d, seq: [0, 1, 2, 3]}" - - def check(self, ut, t, is_json=False): - # some convenient shorthands - eq = ut.assertEqual - ne = ut.assertNotEqual - fs = ut.assertFalse - tr = ut.assertTrue - # - eq(t.size(), 10) - tr(t.is_root(0)) - eq(t.num_children(0), 5) - eq(t.find_child(0, b"HELLO"), 1) - eq(t.find_child(0, b"foo"), 2) - eq(t.find_child(0, b"bar"), 3) - eq(t.find_child(0, b"baz"), 4) - eq(t.find_child(0, b"seq"), 5) - eq(t.parent(0), ryml.NONE) - eq(t.parent(1), 0) - eq(t.parent(2), 0) - eq(t.parent(3), 0) - eq(t.parent(4), 0) - eq(t.parent(5), 0) - fs(t.is_root(1)) - fs(t.is_root(2)) - fs(t.is_root(3)) - fs(t.is_root(4)) - fs(t.is_root(5)) - fs(t.has_child(0, b"foozzie")) - fs(t.has_child(0, b"bark")) - fs(t.has_child(0, b"bart")) - fs(t.has_child(0, b"bazk")) - eq(t.next_sibling(0), ryml.NONE) - eq(t.prev_sibling(0), ryml.NONE) - eq(t.prev_sibling(1), ryml.NONE) - eq(t.next_sibling(5), ryml.NONE) - tr(t.has_child(0, b"HELLO")) - tr(t.has_child(0, b"foo")) - tr(t.has_child(0, b"bar")) - tr(t.has_child(0, b"baz")) - eq(t.key(1), b"HELLO") - eq(t.key(2), b"foo") - eq(t.key(3), b"bar") - eq(t.key(4), b"baz") - eq(t.key(5), b"seq") - eq(t.val(1), b"a") - eq(t.val(2), b"b") - eq(t.val(3), b"c") - eq(t.val(4), b"d") - eq(t.val(6), b"0") - eq(t.val(7), b"1") - eq(t.val(8), b"2") - eq(t.val(9), b"3") - if not is_json: - tr(t.is_key_quoted(1)) - fs(t.is_key_quoted(2)) - fs(t.is_key_quoted(3)) - fs(t.is_key_quoted(4)) - fs(t.is_key_quoted(5)) - else: - tr(t.is_key_quoted(1)) - tr(t.is_key_quoted(2)) - tr(t.is_key_quoted(3)) - tr(t.is_key_quoted(4)) - tr(t.is_key_quoted(5)) - if not is_json: - fs(t.is_val_quoted(1)) - tr(t.is_val_quoted(2)) - fs(t.is_val_quoted(3)) - fs(t.is_val_quoted(4)) - fs(t.is_val_quoted(5)) - fs(t.is_val_quoted(6)) - fs(t.is_val_quoted(7)) - fs(t.is_val_quoted(8)) - fs(t.is_val_quoted(9)) - else: - tr(t.is_val_quoted(1)) - tr(t.is_val_quoted(2)) - tr(t.is_val_quoted(3)) - tr(t.is_val_quoted(4)) - fs(t.is_val_quoted(5)) - fs(t.is_val_quoted(6)) - fs(t.is_val_quoted(7)) - fs(t.is_val_quoted(8)) - fs(t.is_val_quoted(9)) - if not is_json: - tr(t.is_quoted(1)) - tr(t.is_quoted(2)) - fs(t.is_quoted(3)) - fs(t.is_quoted(4)) - fs(t.is_quoted(5)) - fs(t.is_quoted(6)) - fs(t.is_quoted(7)) - fs(t.is_quoted(8)) - fs(t.is_quoted(9)) - else: - tr(t.is_quoted(1)) - tr(t.is_quoted(2)) - tr(t.is_quoted(3)) - tr(t.is_quoted(4)) - tr(t.is_quoted(5)) - fs(t.is_quoted(6)) - fs(t.is_quoted(7)) - fs(t.is_quoted(8)) - fs(t.is_quoted(9)) - tr(t.has_sibling(1, b"bar")) - tr(t.has_sibling(1, b"baz")) - tr(t.has_sibling(2, b"foo")) - tr(t.has_sibling(2, b"baz")) - tr(t.has_sibling(3, b"foo")) - tr(t.has_sibling(3, b"bar")) - for i in (1, 2, 3, 4, 5): - eq(t.find_sibling(i, b"HELLO"), 1) - eq(t.find_sibling(i, b"foo"), 2) - eq(t.find_sibling(i, b"bar"), 3) - eq(t.find_sibling(i, b"baz"), 4) - eq(t.find_sibling(i, b"seq"), 5) - # - num = 0 - for id in ryml.children(t): - num += 1 - eq(id, num) - eq(num, t.num_children(t.root_id())) - eq(num, t.num_siblings(t.first_child(t.root_id()))) - # - num = 0 - for id in ryml.children(t, 1): - num += 1 - eq(num, 0) - # - num = 0 - for id in ryml.siblings(t, 1): - num += 1 - eq(id, num) - eq(num, t.num_children(t.root_id())) - eq(num, t.num_siblings(t.first_child(t.root_id()))) - # - num = 0 - for id in ryml.siblings(t, 3): - num += 1 - eq(id, num) - eq(num, 5) - eq(num, t.num_siblings(t.first_child(t.root_id()))) - # - for i, ch in enumerate(ryml.children(t, 5)): - eq(t.val(ch), [b"0", b"1", b"2", b"3"][i]) - sibs = [b"HELLO", b"foo", b"bar", b"baz", b"seq"] - sibs_s = ["HELLO", "foo", "bar", "baz", "seq"] - for i, sib in enumerate(ryml.siblings(t, 5)): - k = t.key(sib) - k_s = str(k, "utf8") - eq(k, sibs[i]) - eq(k_s, sibs_s[i]) - ne(k, sibs_s[i]) - ne(k_s, sibs[i]) - k_s = str(k) - ne(k_s, sibs_s[i]) - ne(k_s, sibs[i]) - num = 0 - for id in ryml.siblings(t, 0): - num += 1 - eq(num, 1) - # - num = 0 - for id, level in ryml.walk(t): - num += 1 - if t.is_root(id): - eq(id, 0) - eq(level, 0) - if t.is_map(id): - eq(id, 0) - eq(level, 0) - if t.is_seq(id): - eq(id, 5) - eq(level, 1) - if t.is_keyval(id): - tr(id > 0 and id < 5) - if t.is_val(id): - tr(id > 5) - eq(level, 2) - eq(num, t.size()) - # - num = 0 - for id in ryml.walk(t, 5): - num += 1 - eq(num, 5) - # - num = 0 - for id in ryml.walk(t, 9): - num += 1 - eq(num, 1) - check_tree_mod(ut, t) - - -# ----------------------------------------------------------------------------- -# ----------------------------------------------------------------------------- -# ----------------------------------------------------------------------------- -class TestRunner(unittest.TestCase): - - def setUp(self): - self._setUp(SimpleTestCase()) - - # allow creating this class with different cases - # if they are added - def _setUp(self, case): - self.case = case - self.src_as_str = str(case.yaml) - self.src_as_bytes = bytes(case.yaml, "utf8") - self.src_as_bytearray = bytearray(case.yaml, "utf8") - - # ---------------------------------------------------------- - def test11_str__arena(self): # cannot read string buffers (or can we?) - tree = ryml.parse_in_arena(self.src_as_str) - self.case.check(self, tree) - - def test12_str__arena__reuse_tree(self): # cannot read string buffers (or can we?) - t = ryml.Tree() - ryml.parse_in_arena(self.src_as_str, tree=t) - self.case.check(self, t) - - def test13_str__inplace(self): # cannot mutate string buffers (or can we?) - with self.assertRaises(TypeError) as context: - ryml.parse_in_place(self.src_as_str) - self.assertTrue(type(context.exception), TypeError) - - # ---------------------------------------------------------- - def test21_bytes__arena(self): - tree = ryml.parse_in_arena(self.src_as_bytes) - self.case.check(self, tree) - - def test22_bytes__arena__reuse_tree(self): - t = ryml.Tree() - r = ryml.parse_in_arena(self.src_as_bytes, tree=t) - self.assertTrue(r is t) - self.case.check(self, t) - - def test23_bytes__inplace(self): # cannot mutate bytes buffers - with self.assertRaises(TypeError) as context: - ryml.parse_in_place(self.src_as_bytes) - self.assertTrue(type(context.exception), TypeError) - - # ---------------------------------------------------------- - def test31_bytearray__arena(self): - tree = ryml.parse_in_arena(self.src_as_bytearray) - self.case.check(self, tree) - - def test32_bytearray__arena__reuse_tree(self): - t = ryml.Tree() - r = ryml.parse_in_arena(self.src_as_bytearray, tree=t) - self.assertTrue(r is t) - self.case.check(self, t) - - def test33_bytearray__inplace(self): # bytearray buffers are mutable - tree = ryml.parse_in_place(self.src_as_bytearray) - self.case.check(self, tree) - - def test34_bytearray__inplace__reuse_tree(self): # bytearray buffers are mutable - t = ryml.Tree() - r = ryml.parse_in_place(self.src_as_bytearray, tree=t) - self.assertTrue(r is t) - self.case.check(self, t) - - # ---------------------------------------------------------- - def test41_emit_yaml(self): - tree = ryml.parse_in_arena(self.src_as_bytearray) - yaml = ryml.emit_yaml(tree) - output_tree = ryml.parse_in_arena(yaml) - self.case.check(self, output_tree) - - def test41_emit_json(self): - tree = ryml.parse_in_arena(self.src_as_bytearray) - json = ryml.emit_json(tree) - output_tree = ryml.parse_in_arena(json) - self.case.check(self, output_tree, is_json=True) - - def test42_compute_emit_yaml_length(self): - tree = ryml.parse_in_arena(self.src_as_bytearray) - yaml = ryml.emit_yaml(tree) - length = ryml.compute_emit_yaml_length(tree) - self.assertEqual(len(yaml), length) - - def test42_compute_emit_json_length(self): - tree = ryml.parse_in_arena(self.src_as_bytearray) - json = ryml.emit_json(tree) - length = ryml.compute_emit_json_length(tree) - self.assertEqual(len(json), length) - - def test43_emit_yaml_inplace(self): - tree = ryml.parse_in_arena(self.src_as_bytearray) - yaml = ryml.emit_yaml(tree) - length = ryml.compute_emit_yaml_length(tree) - self.assertEqual(len(yaml), length) - buf = bytearray(length) - s = ryml.emit_yaml_in_place(tree, buf) - self.assertEqual(len(s), length) - self.assertTrue(s.tobytes().decode('utf-8') == yaml) - self.assertTrue(buf.decode('utf-8') == yaml) - - def test43_emit_json_inplace(self): - tree = ryml.parse_in_arena(self.src_as_bytearray) - json = ryml.emit_json(tree) - length = ryml.compute_emit_json_length(tree) - self.assertEqual(len(json), length) - buf = bytearray(length) - s = ryml.emit_json_in_place(tree, buf) - self.assertEqual(len(s), length) - self.assertTrue(s.tobytes().decode('utf-8') == json) - self.assertTrue(buf.decode('utf-8') == json) - - def test44_emit_yaml_short_buf(self): - tree = ryml.parse_in_arena(self.src_as_bytearray) - length = ryml.compute_emit_yaml_length(tree) - buf = bytearray(length-1) - with self.assertRaises(IndexError): - ryml.emit_yaml_in_place(tree, buf) - - def test44_emit_json_short_buf(self): - tree = ryml.parse_in_arena(self.src_as_bytearray) - length = ryml.compute_emit_json_length(tree) - buf = bytearray(length-1) - with self.assertRaises(IndexError): - ryml.emit_json_in_place(tree, buf) - - - -# ----------------------------------------------------------------------------- -# ----------------------------------------------------------------------------- -# ----------------------------------------------------------------------------- -if __name__ == "__main__": - unittest.main() diff --git a/thirdparty/ryml/api/ryml.i b/thirdparty/ryml/api/ryml.i deleted file mode 100644 index ac226142a..000000000 --- a/thirdparty/ryml/api/ryml.i +++ /dev/null @@ -1,662 +0,0 @@ - -%module ryml - - -//----------------------------------------------------------------------------- -// this block will be pasted verbatim in the generated C++ source file - -%{ -// specifies that the resulting C file should be built as a python -// extension, inserting the module init code -#define SWIG_FILE_WITH_INIT - -#include - -namespace c4 { -namespace yml { - -using substr = c4::substr; -using csubstr = c4::csubstr; - -} /* namespace yml */ -} /* namespace c4 */ - -%} - -//----------------------------------------------------------------------------- - - -%apply (const char *STRING, size_t LENGTH) { (const char *str, size_t len) }; -%apply (char *STRING, size_t LENGTH) { (char *str, size_t len) }; -%newobject emit_malloc; - -%typemap(in) c4::substr { -#if defined(SWIGPYTHON) - Py_buffer view; - int ok = PyObject_CheckBuffer($input); - if(ok) - { - ok = (0 == PyObject_GetBuffer($input, &view, PyBUF_SIMPLE|PyBUF_WRITABLE)); - } - if(ok) - { - $1 = c4::substr((char*)view.buf, view.len); - PyBuffer_Release(&view); - } - else - { - PyErr_SetString(PyExc_TypeError, "could not get mutable memory for c4::csubstr - have you passed a str?"); - SWIG_fail; - } -#else -#error no "in" typemap defined for this export language -#endif -}; - -%typemap(in) c4::csubstr { -#if defined(SWIGPYTHON) - Py_buffer view; - view.buf = nullptr; - int ok = PyObject_CheckBuffer($input); - if(ok) - { - ok = (0 == PyObject_GetBuffer($input, &view, PyBUF_CONTIG_RO)); - } - if(ok) - { - $1 = c4::csubstr((const char*)view.buf, view.len); - PyBuffer_Release(&view); - } - else - { - // https://stackoverflow.com/questions/36098984/python-3-3-c-api-and-utf-8-strings - Py_ssize_t sz = 0; - const char *buf = PyUnicode_AsUTF8AndSize($input, &sz); - if(buf || sz == 0) - { - $1 = c4::csubstr(buf, sz); - } - else - { - PyErr_SetString(PyExc_TypeError, "c4::csubstr: could not get readonly memory from python object"); - SWIG_fail; - } - } -#else -#error no "in" typemap defined for this export language -#endif -}; -// Copy the typecheck code for "char *". -%typemap(typecheck) c4::substr = char *; -%typemap(typecheck) c4::csubstr = const char *; - - -%typemap(out) c4::csubstr { -#if defined(SWIGPYTHON) - if($1.str == nullptr) { - $result = Py_None; - Py_INCREF($result); - } else { - PyObject *obj = PyMemoryView_FromMemory((char*)$1.str, $1.len, PyBUF_READ); - if( ! obj) - { - PyErr_SetString(PyExc_TypeError, "could not get readonly memory from c4::csubstr - have you passed a str?"); - SWIG_fail; - } - $result = obj; - } -#else -#error no "out" typemap defined for this export language -#endif -}; - - -%inline %{ - -void parse_csubstr(c4::csubstr s, c4::yml::Tree *t) -{ - c4::yml::parse_in_arena(s, t); -} - -void parse_substr(c4::substr s, c4::yml::Tree *t) -{ - c4::yml::parse_in_place(s, t); -} - -char * emit_yaml_malloc(c4::yml::Tree const& t, size_t id) -{ - c4::substr buf; - c4::substr ret = c4::yml::emit_yaml(t, id, buf, /*error_on_excess*/false); - if(ret.str == nullptr && ret.len > 0) - { - // Use new[] to parse with delete[] in SWIG. - char * alloc = new char[ret.len + 1]; // we'll return a c-string and not a csubstr - c4::substr alloced_buf(alloc, ret.len); - ret = c4::yml::emit_yaml(t, id, alloced_buf, /*error_on_excess*/true); - ret.str[ret.len] = 0; - } - return ret.str; -} - -char * emit_json_malloc(c4::yml::Tree const& t, size_t id) -{ - c4::substr buf; - c4::substr ret = c4::yml::emit_json(t, id, buf, /*error_on_excess*/false); - if(ret.str == nullptr && ret.len > 0) - { - // Use new[] to parse with delete[] in SWIG. - char * alloc = new char[ret.len + 1]; // we'll return a c-string and not a csubstr - c4::substr alloced_buf(alloc, ret.len); - ret = c4::yml::emit_json(t, id, alloced_buf, /*error_on_excess*/true); - ret.str[ret.len] = 0; - } - return ret.str; -} - -size_t emit_yaml_length(const c4::yml::Tree &t, size_t id) -{ - c4::substr buf; - c4::substr ret = c4::yml::emit_yaml(t, id, buf, /*error_on_excess*/false); - return ret.len; -} - -size_t emit_json_length(const c4::yml::Tree &t, size_t id) -{ - c4::substr buf; - c4::substr ret = c4::yml::emit_json(t, id, buf, /*error_on_excess*/false); - return ret.len; -} - -bool emit_yaml_to_substr(const c4::yml::Tree &t, size_t id, c4::substr s, size_t *OUTPUT) -{ - c4::substr result = c4::yml::emit_yaml(t, id, s, /*error_on_excess*/false); - *OUTPUT = result.len; - return result.str == nullptr; -} - -bool emit_json_to_substr(const c4::yml::Tree &t, size_t id, c4::substr s, size_t *OUTPUT) -{ - c4::substr result = c4::yml::emit_json(t, id, s, /*error_on_excess*/false); - *OUTPUT = result.len; - return result.str == nullptr; -} - - -// force a roundtrip to C++, which triggers a conversion to csubstr and returns it as a memoryview -c4::csubstr _get_as_csubstr(c4::csubstr s) -{ - //printf("_get_as_csubstr: %p[%zu]'%.*s'\n", s.str, s.len, (int)s.len, s.str); - return s; -} - -c4::csubstr _get_as_substr(c4::substr s) -{ - //printf("_get_as_substr: %p[%zu]'%.*s'\n", s.str, s.len, (int)s.len, s.str); - return s; -} - - -// utilities for testing -bool _same_ptr(c4::csubstr l, c4::csubstr r) -{ - return l.str == r.str; -} - -bool _same_mem(c4::csubstr l, c4::csubstr r) -{ - return l.str == r.str && l.len == r.len; -} - - -%} - - -//----------------------------------------------------------------------------- - -%pythoncode %{ - -from deprecation import deprecated - - -def as_csubstr(s): - return _get_as_csubstr(s) - -def as_substr(s): - return _get_as_substr(s) - -def u(memview): - return str(memview, "utf8") - - -def children(tree, node=None): - assert tree is not None - if node is None: - node = tree.root_id() - ch = tree.first_child(node) - while ch != NONE: - yield ch - ch = tree.next_sibling(ch) - - -def siblings(tree, node): - assert tree is not None - if node is None: - return - ch = tree.first_sibling(node) - while ch != NONE: - yield ch - ch = tree.next_sibling(ch) - - -def walk(tree, node=None, indentation_level=0): - assert tree is not None - if node is None: node = tree.root_id() - yield node, indentation_level - ch = tree.first_child(node) - while ch != NONE: - for gc, il in walk(tree, ch, indentation_level + 1): - yield gc, il - ch = tree.next_sibling(ch) - - -@deprecated(deprecated_in="0.5.0", details="Use parse_in_arena() instead") -def parse(buf, **kwargs): - return parse_in_arena(tree, id) -def parse_in_arena(buf, **kwargs): - return _call_parse(parse_csubstr, buf, **kwargs) -def parse_in_place(buf, **kwargs): - _check_valid_for_in_situ(buf) - return _call_parse(parse_substr, buf, **kwargs) - - - -def _call_parse(parse_fn, buf, **kwargs): - tree = kwargs.get("tree", Tree()) - parse_fn(buf, tree) - return tree - - -def _check_valid_for_in_situ(obj): - if type(obj) in (str, bytes): - raise TypeError("cannot parse in situ: " + type(obj).__name__) - - - -@deprecated(deprecated_in="0.5.0", details="Use emit_yaml() instead") -def emit(tree, id=None): - return emit_yaml(tree, id) -def emit_yaml(tree, id=None): - if id is None: - id = tree.root_id() - return emit_yaml_malloc(tree, id) -def emit_json(tree, id=None): - if id is None: - id = tree.root_id() - return emit_json_malloc(tree, id) - - -@deprecated(deprecated_in="0.5.0", details="Use compute_emit_yaml_length() instead") -def compute_emit_length(tree, id=None): - return compute_emit_yaml_length(tree, id) -def compute_emit_yaml_length(tree, id=None): - if id is None: - id = tree.root_id() - return emit_yaml_length(tree, id) -def compute_emit_json_length(tree, id=None): - if id is None: - id = tree.root_id() - return emit_json_length(tree, id) - - -@deprecated(deprecated_in="0.5.0", details="Use emit_yaml_in_place() instead") -def emit_in_place(tree, buf, id=None): - return emit_yaml_in_place(tree, buf, id) -def emit_yaml_in_place(tree, buf, id=None): - return _emit_fn_in_place(tree, buf, id, emit_yaml_to_substr) -def emit_json_in_place(tree, buf, id=None): - return _emit_fn_in_place(tree, buf, id, emit_json_to_substr) -def _emit_fn_in_place(tree, buf, id, fn): - if id is None: - id = tree.root_id() - (failed, expected_size) = fn(tree, id, buf) - if failed: - raise IndexError("Output buffer has {} bytes, but emit requires {} bytes".format( - len(buf), expected_size)) - return memoryview(buf)[:expected_size] - -%} - -//----------------------------------------------------------------------------- - -namespace c4 { -namespace yml { - -constexpr const size_t NONE = (size_t)-1; - -typedef enum { - NOTYPE = 0, ///< no type is set - VAL = (1<<0), ///< a leaf node, has a (possibly empty) value - KEY = (1<<1), ///< is member of a map, must have non-empty key - MAP = (1<<2), ///< a map: a parent of keyvals - SEQ = (1<<3), ///< a seq: a parent of vals - DOC = (1<<4), ///< a document - STREAM = (1<<5)|SEQ, ///< a stream: a seq of docs - KEYREF = (1<<6), ///< a *reference: the key references an &anchor - VALREF = (1<<7), ///< a *reference: the val references an &anchor - KEYANCH = (1<<8), ///< the key has an &anchor - VALANCH = (1<<9), ///< the val has an &anchor - KEYTAG = (1<<10), ///< the key has an explicit tag/type - VALTAG = (1<<11), ///< the val has an explicit tag/type -} NodeType_e; - - -struct NodeType -{ - NodeType_e type; - - NodeType(); - NodeType(NodeType_e t); - ~NodeType(); - - const char *type_str(); - static const char* type_str(NodeType_e t); - - void set(NodeType_e t); - void add(NodeType_e t); - void rem(NodeType_e t); - - bool is_stream() const; - bool is_doc() const; - bool is_container() const; - bool is_map() const; - bool is_seq() const; - bool has_val() const; - bool has_key() const; - bool is_val() const; - bool is_keyval() const; - bool has_key_tag() const; - bool has_val_tag() const; - bool has_key_anchor() const; - bool has_val_anchor() const; - bool has_anchor() const; - bool is_key_ref() const; - bool is_val_ref() const; - bool is_ref() const; - bool is_anchor_or_ref() const; - bool is_key_quoted() const; - bool is_val_quoted() const; - bool is_quoted() const; -}; - - -struct Tree -{ - Tree(); - ~Tree(); - - void reserve(size_t node_capacity); - void reserve_arena(size_t node_capacity); - void clear(); - void clear_arena(); - - size_t size() const; - size_t capacity() const; - size_t slack() const; - - size_t arena_size() const; - size_t arena_capacity() const; - size_t arena_slack() const; - - void resolve(); - -public: - - // getters - - NodeType_e type(size_t node) const; - const char* type_str(size_t node) const; - - c4::csubstr key (size_t node) const; - c4::csubstr key_tag (size_t node) const; - c4::csubstr key_ref (size_t node) const; - c4::csubstr key_anchor(size_t node) const; - c4::yml::NodeScalar keysc(size_t node) const; - - c4::csubstr val (size_t node) const; - c4::csubstr val_tag (size_t node) const; - c4::csubstr val_ref (size_t node) const; - c4::csubstr val_anchor(size_t node) const; - c4::yml::NodeScalar valsc(size_t node) const; - -public: - - // node predicates - - bool is_root(size_t node) const; - bool is_stream(size_t node) const; - bool is_doc(size_t node) const; - bool is_container(size_t node) const; - bool is_map(size_t node) const; - bool is_seq(size_t node) const; - bool has_val(size_t node) const; - bool has_key(size_t node) const; - bool is_val(size_t node) const; - bool is_keyval(size_t node) const; - bool has_key_tag(size_t node) const; - bool has_val_tag(size_t node) const; - bool has_key_anchor(size_t node) const; - bool has_val_anchor(size_t node) const; - bool is_key_ref(size_t node) const; - bool is_val_ref(size_t node) const; - bool is_ref(size_t node) const; - bool is_anchor_or_ref(size_t node) const; - bool is_key_quoted(size_t node) const; - bool is_val_quoted(size_t node) const; - bool is_quoted(size_t node) const; - bool is_anchor(size_t node) const; - bool parent_is_seq(size_t node) const; - bool parent_is_map(size_t node) const; - bool empty(size_t node) const; - bool has_anchor(size_t node, c4::csubstr a) const; - -public: - - // hierarchy predicates - - bool has_parent(size_t node) const; - bool has_child(size_t node, c4::csubstr key) const; - //bool has_child(size_t node, size_t ch) const; - bool has_children(size_t node) const; - bool has_sibling(size_t node, c4::csubstr key) const; - //bool has_sibling(size_t node, size_t sib) const; - bool has_other_siblings(size_t node) const; - -public: - - // hierarchy getters - - size_t root_id() const; - - size_t parent(size_t node) const; - size_t prev_sibling(size_t node) const; - size_t next_sibling(size_t node) const; - size_t num_children(size_t node) const; - size_t child_pos(size_t node, size_t ch) const; - size_t first_child(size_t node) const; - size_t last_child(size_t node) const; - size_t child(size_t node, size_t pos) const; - size_t find_child(size_t node, c4::csubstr key) const; - size_t num_siblings(size_t node) const; - size_t num_other_siblings(size_t node) const; - size_t sibling_pos(size_t node, size_t sib) const; - size_t first_sibling(size_t node) const; - size_t last_sibling(size_t node) const; - size_t sibling(size_t node, size_t pos) const; - size_t find_sibling(size_t node, c4::csubstr key) const; - -public: - - void to_keyval(size_t node, c4::csubstr key, c4::csubstr val, int more_flags=0); - void to_map(size_t node, c4::csubstr key, int more_flags=0); - void to_seq(size_t node, c4::csubstr key, int more_flags=0); - void to_val(size_t node, c4::csubstr val, int more_flags=0); - void to_stream(size_t node, int more_flags=0); - void to_map(size_t node, int more_flags=0); - void to_seq(size_t node, int more_flags=0); - void to_doc(size_t node, int more_flags=0); - - void set_key_tag(size_t node, c4::csubstr tag); - void set_key_anchor(size_t node, c4::csubstr anchor); - void set_val_anchor(size_t node, c4::csubstr anchor); - void set_key_ref (size_t node, c4::csubstr ref ); - void set_val_ref (size_t node, c4::csubstr ref ); - - void _set_key(size_t node, c4::csubstr key, int more_flags=0); - void _set_val(size_t node, c4::csubstr val, int more_flags=0); - - void set_val_tag(size_t node, c4::csubstr tag); - void rem_key_anchor(size_t node); - void rem_val_anchor(size_t node); - void rem_key_ref (size_t node); - void rem_val_ref (size_t node); - void rem_anchor_ref(size_t node); - -public: - - /** create and insert a new child of "parent". insert after the (to-be) - * sibling "after", which must be a child of "parent". To insert as the - * first child, set after to NONE */ - size_t insert_child(size_t parent, size_t after); - size_t prepend_child(size_t parent); - size_t append_child(size_t parent); - -public: - - //! create and insert a new sibling of n. insert after "after" - size_t insert_sibling(size_t node, size_t after); - size_t prepend_sibling(size_t node); - size_t append_sibling(size_t node); - -public: - - //! remove an entire branch at once: ie remove the children and the node itself - void remove(size_t node); - - //! remove all the node's children, but keep the node itself - void remove_children(size_t node); - -public: - - void reorder(); - - /** change the node's position in the parent */ - void move(size_t node, size_t after); - - /** change the node's parent and position */ - void move(size_t node, size_t new_parent, size_t after); - /** change the node's parent and position */ - size_t move(Tree * src, size_t node, size_t new_parent, size_t after); - - /** recursively duplicate the node */ - size_t duplicate(size_t node, size_t new_parent, size_t after); - /** recursively duplicate a node from a different tree */ - size_t duplicate(Tree const* src, size_t node, size_t new_parent, size_t after); - - /** recursively duplicate the node's children (but not the node) */ - void duplicate_children(size_t node, size_t parent, size_t after); - /** recursively duplicate the node's children (but not the node), where the node is from a different tree */ - void duplicate_children(Tree const* src, size_t node, size_t parent, size_t after); - - void duplicate_contents(size_t node, size_t where); - - /** duplicate the node's children (but not the node) in a new parent, but - * omit repetitions where a duplicated node has the same key (in maps) or - * value (in seqs). If one of the duplicated children has the same key - * (in maps) or value (in seqs) as one of the parent's children, the one - * that is placed closest to the end will prevail. */ - void duplicate_children_no_rep(size_t node, size_t parent, size_t after); - -}; - -/* -%extend Tree { - - bool has_anchor(size_t node, const char *str, size_t len) const - { - return $self->has_anchor(node, c4::csubstr(str, len)); - } - - bool has_child(size_t node, const char *str, size_t len) const - { - return $self->has_child(node, c4::csubstr(str, len)); - } - - bool has_sibling(size_t node, const char *str, size_t len) const - { - return $self->has_sibling(node, c4::csubstr(str, len)); - } - - size_t find_child(size_t node, const char *str, size_t len) const - { - return $self->find_child(node, c4::csubstr(str, len)); - } - - size_t find_sibling(size_t node, const char *str, size_t len) const - { - return $self->find_sibling(node, c4::csubstr(str, len)); - } - - void to_keyval(size_t node, const char *keystr, size_t keylen, const char *valstr, size_t vallen, int more_flags=0) - { - return $self->to_keyval(node, c4::csubstr(keystr, keylen), c4::csubstr(valstr, vallen), more_flags); - } - - void to_map(size_t node, const char *keystr, size_t keylen, int more_flags=0) - { - return $self->to_map(node, c4::csubstr(keystr, keylen), more_flags); - } - - void to_seq(size_t node, const char *keystr, size_t keylen, int more_flags=0) - { - return $self->to_seq(node, c4::csubstr(keystr, keylen), more_flags); - } - - void to_val(size_t node, const char *valstr, size_t vallen, int more_flags=0) - { - return $self->to_val(node, c4::csubstr(valstr, vallen), more_flags); - } - - void set_key_tag(size_t node, const char *str, size_t len) - { - return $self->set_key_tag(node, c4::csubstr(str, len)); - } - void set_val_tag(size_t node, const char *str, size_t len) - { - return $self->set_val_tag(node, c4::csubstr(str, len)); - } - - void set_key_anchor(size_t node, const char *str, size_t len) - { - return $self->set_key_anchor(node, c4::csubstr(str, len)); - } - void set_val_anchor(size_t node, const char *str, size_t len) - { - return $self->set_val_anchor(node, c4::csubstr(str, len)); - } - - void set_key_ref(size_t node, const char *str, size_t len) - { - return $self->set_key_ref(node, c4::csubstr(str, len)); - } - void set_val_ref(size_t node, const char *str, size_t len) - { - return $self->set_val_ref(node, c4::csubstr(str, len)); - } - -}; -*/ - -} // namespace yml -} // namespace c4 - -//----------------------------------------------------------------------------- diff --git a/thirdparty/ryml/changelog/0.1.0.md b/thirdparty/ryml/changelog/0.1.0.md deleted file mode 100644 index b2ea04861..000000000 --- a/thirdparty/ryml/changelog/0.1.0.md +++ /dev/null @@ -1,44 +0,0 @@ -This is the first ryml release. Future releases will have a more organized changelog; for now, only recent major changes are listed. - -Please be aware that there are still some anticipated breaking changes in the API before releasing the 1.0 major version. These are highlighted in [the repo ROADMAP](https://github.com/biojppm/rapidyaml/blob/v0.1.0/ROADMAP.md). - -* 2020/October - * [MR#89](https://github.com/biojppm/rapidyaml/pull/89): - * fix python API generation in windows - * use github actions for testing and releasing - * [MR#88](https://github.com/biojppm/rapidyaml/pull/88): [fix MacOS compilation and installs](https://github.com/biojppm/rapidyaml/issues/75). This is a fix from [c4core](https://github.com/biojppm/cmake/issues/1). - * [MR#88](https://github.com/biojppm/rapidyaml/pull/88): [fix boolean handling](https://github.com/biojppm/rapidyaml/issues/74). This is a fix from [c4core](https://github.com/biojppm/c4core/pull/18/). `true` and `false` are now parsed correctly into `bool` variables: - ```c++ - auto tree = parse("{foo: true, bar: false}"); - ``` - Emitting `bool` variables still defaults to `0`/`1`, like the default behaviour in the STL. To explicitly request `true`/`false` use `c4::fmt::boolalpha()`: - ```c++ - node << var; // "1" or "0" - node << c4::fmt::boolalpha(var); // "true" or "false" - ``` -* 2020/September - * [***Breaking change***] [MR#85](https://github.com/biojppm/rapidyaml/pull/85) null values in YAML are now parsed to null strings instead of YAML null token "~": - ```c++ - auto tree = parse("{foo: , bar: ''}"); - // previous: - assert(tree["foo"].val() == "~"); - assert(tree["bar"].val() == ""); - // now: - assert(tree["foo"].val() == nullptr); // notice that this is now null - assert(tree["bar"].val() == ""); - ``` - * [MR#85](https://github.com/biojppm/rapidyaml/pull/85) Commas after tags are now allowed: - ```yaml - {foo: !!str, bar: ''} # now the comma does not cause an error - ``` - * [MR#81](https://github.com/biojppm/rapidyaml/pull/81): Always compile with extra pedantic warnings. -* 2020/May - * [***Breaking change***] the error callback now receives a source location object: - ```c++ - // previous - using pfn_error = void (*)(const char* msg, size_t msg_len, void *user_data); - // now: - using pfn_error = void (*)(const char* msg, size_t msg_len, Location location, void *user_data); - ``` - * Parser fixes to improve test suite success: [MR#73](https://github.com/biojppm/rapidyaml/pull/73), [MR#71](https://github.com/biojppm/rapidyaml/pull/71), [MR#68](https://github.com/biojppm/rapidyaml/pull/68), [MR#67](https://github.com/biojppm/rapidyaml/pull/67), [MR#66](https://github.com/biojppm/rapidyaml/pull/66) - * Fix compilation as DLL on windows [MR#69](https://github.com/biojppm/rapidyaml/pull/69) diff --git a/thirdparty/ryml/changelog/0.2.0.md b/thirdparty/ryml/changelog/0.2.0.md deleted file mode 100644 index 4bddffdd6..000000000 --- a/thirdparty/ryml/changelog/0.2.0.md +++ /dev/null @@ -1,29 +0,0 @@ -### New features & improvements -- Enable parsing into nested nodes ([87f4184](https://github.com/biojppm/rapidyaml/commit/87f4184)) -- `as_json()` can now be called with tree and node id ([4c23041](https://github.com/biojppm/rapidyaml/commit/4c23041)) -- Add `Parser::reserve_stack()` ([f31fb9f](https://github.com/biojppm/rapidyaml/commit/f31fb9f)) -- Add uninstall target ([PR #122](https://github.com/biojppm/rapidyaml/pull/122)) -- Update [c4core](https://github.com/biojppm/c4core) to v0.1.1 -- Add a [quickstart sample](samples/quickstart.cpp) with build examples. -- Update [README.md](README.md) to refer to the quickstart -- Add [gdb visualizers](src/ryml-gdbtypes.py) -- Add `SO_VERSION` to shared builds - -### Fixes -- Fix [#139](https://github.com/biojppm/rapidyaml/issues/139): substr and csubstr not found in ryml namespace -- Fix [#131](https://github.com/biojppm/rapidyaml/issues/131): resolve references to map keys -- Fix [#129](https://github.com/biojppm/rapidyaml/issues/129): quoted strings starting with * parsed as references -- Fix [#128](https://github.com/biojppm/rapidyaml/issues/128): segfault on nonexistent anchor -- Fix [#124](https://github.com/biojppm/rapidyaml/issues/124): parse failure in comments with trailing colon -- Fix [#121](https://github.com/biojppm/rapidyaml/issues/121): preserve quotes when emitting scalars -- Fix [#103](https://github.com/biojppm/rapidyaml/issues/103): ambiguous parsing of null/empty scalars -- Fix [#90](https://github.com/biojppm/rapidyaml/issues/90): CMAKE_CXX_STANDARD ignored -- Fix [#40](https://github.com/biojppm/rapidyaml/issues/40): quadratic complexity from use of `sscanf(%f)` -- Fix emitting json to streams ([dc6af83](https://github.com/biojppm/rapidyaml/commit/dc6af83)) -- Set the global memory resource when setting global callbacks ([511cba0](https://github.com/biojppm/rapidyaml/commit/511cba0)) -- Fix python packaging ([PR #102](https://github.com/biojppm/rapidyaml/pull/102)) - -### Special thanks -- @Gei0r -- @litghost -- @costashatz diff --git a/thirdparty/ryml/changelog/0.2.1.md b/thirdparty/ryml/changelog/0.2.1.md deleted file mode 100644 index 3dc9310d3..000000000 --- a/thirdparty/ryml/changelog/0.2.1.md +++ /dev/null @@ -1,235 +0,0 @@ -This release is focused on bug fixes and compliance with the [YAML test suite](https://github.com/yaml/yaml-test-suite). - -### Breaking changes - -- Fix parsing behavior of root-level scalars: now these are parsed into a DOCVAL, not SEQ->VAL ([5ba0d56](https://github.com/biojppm/rapidyaml/pull/144/commits/5ba0d56904daef1509f0073695145c4835ab1b30), from [PR #144](https://github.com/biojppm/rapidyaml/pull/144)). Eg, - ```yaml - --- - this is a scalar - --- # previously this was parsed as - - this is a scalar - ``` -- Cleanup type predicate API ([PR #155](https://github.com/biojppm/rapidyaml/pull/155))): - - ensure all type predicates from `Tree` and `NodeRef` forward to the corresponding predicate in `NodeType` - - remove all type predicates and methods from `NodeData`; use the equivalent call from `Tree` or `NodeRef`. For example, for `is_map()`: - ```c++ - Tree t = parse("{foo: bar}"); - size_t map_id = t.root_id(); - NodeRef map = t.rootref(); - t.get(map_id)->is_map(); // compile error: no longer exists - assert(t.is_map(map_id)); // OK - assert(map.is_map()); // OK - ``` - - Further cleanup to the type predicate API will be done in the future, especially around the `.has_*()` vs corresponding `.is_*()` naming scheme. - - -### New features & improvements - -- `Tree::lookup_path_or_modify()`: add overload to graft existing branches ([PR #141](https://github.com/biojppm/rapidyaml/pull/141)) -- Callbacks: improve test coverage ([PR #141](https://github.com/biojppm/rapidyaml/pull/141)) -- [YAML test suite](https://github.com/yaml/yaml-test-suite) ([PR #144](https://github.com/biojppm/rapidyaml/pull/144), [PR #145](https://github.com/biojppm/rapidyaml/pull/145)): big progress towards compliance with the suite. There are still a number of existing problems, which are the subject of ongoing work. See the [list of current known failures](../test/test_suite/test_suite_parts.cpp) in the test suite file. -- Python wheels and source package are now [uploaded to PyPI](https://pypi.org/project/rapidyaml/) as part of the release process. - - -### Fixes - -#### Anchors and references -- Fix resolving of nodes with keyref+valref ([PR #144](https://github.com/biojppm/rapidyaml/pull/144)): `{&a a: &b b, *b: *a}` -- Fix parsing of implicit scalars when tags are present ([PR #145](https://github.com/biojppm/rapidyaml/pull/145)): - ```yaml - - &a # test case PW8X - - a - - &a : a - b: &b - - &c : &a - - ? &d - - ? &e - : &a - ``` -- Fix [#151](https://github.com/biojppm/rapidyaml/issues/151): scalars beginning with `*` or `&` or `<<` are now correctly quoted when emitting ([PR #156](https://github.com/biojppm/rapidyaml/pull/156)). -- Also from [PR #156](https://github.com/biojppm/rapidyaml/pull/156), map inheritance nodes like `<<: *anchor` or `<<: [*anchor1, *anchor2]` now have a `KEYREF` flag in their type (until a call to `Tree::resolve()`): - ```c++ - Tree tree = parse("{map: &anchor {foo: bar}, copy: {<<: *anchor}}"); - assert(tree["copy"]["<<"].is_key_ref()); // previously this did not hold - assert(tree["copy"]["<<"].is_val_ref()); // ... but this did - ``` - -#### Tags -- Fix parsing of tag dense maps and seqs ([PR #144](https://github.com/biojppm/rapidyaml/pull/144)): - ```yaml - --- !!map { - k: !!seq [ a, !!str b], - j: !!seq - [ a, !!str b] - --- !!seq [ - !!map { !!str k: v}, - !!map { !!str ? k: v} - ] - --- !!map - !!str foo: !!map # there was a parse error with the multiple tags - !!int 1: !!float 20.0 - !!int 3: !!float 40.0 - --- !!seq - - !!map - !!str k1: v1 - !!str k2: v2 - !!str k3: v3 - ``` - -#### Whitespace -- Fix parsing of double-quoted scalars with tabs ([PR #145](https://github.com/biojppm/rapidyaml/pull/145)): - ```yaml - "This has a\ttab" - # is now correctly parsed as "This has atab" - ``` -- Fix filtering of leading and trailing whitespace within double-quoted scalars ([PR #145](https://github.com/biojppm/rapidyaml/pull/145)): - ```yaml - # test case 4ZYM, 7A4E, TL85 - " - foo - - bar - baz - " - # is now correctly parsed as " foo\nbar\nbaz " - ``` -- Fix parsing of tabs within YAML tokens ([PR #145](https://github.com/biojppm/rapidyaml/pull/145)): - ```yaml - ---scalar # test case K54U - ---{} # test case Q5MG - --- # test case DC7X - a: b - seq: - - a - c: d#X - ``` -- Fix parsing of flow-style maps with ommitted values without any space ([PR #145](https://github.com/biojppm/rapidyaml/pull/145)): - ```yaml - # test case 4ABK - - {foo: , bar: , baz: } # this was parsed correctly as {foo: ~, bar: ~, baz: ~} - - {foo:, bar:, baz:} # ... but this was parsed as {'foo:': , 'bar:': ~, 'baz:': ~} - ``` - -#### Scalars -- Unescape forward slashes in double quoted string ([PR #145](https://github.com/biojppm/rapidyaml/pull/145)): - ```yaml - --- escaped slash: "a\/b" # test case 3UYS - # is now parsed as: - --- escaped slash: "a/b" - ``` -- Fix filtering of indented regions in folded scalars ([PR #145](https://github.com/biojppm/rapidyaml/pull/145)): - ```yaml - # test case 7T8X - - > - - folded - line - - next - line - * bullet - - * list - * lines - - last - line - ``` - is now correctly parsed as `\nfolded line\nnext line\n * bullet\n\n * list\n * lines\n\nlast line\n`. -- Fix parsing of special characters within plain scalars ([PR #145](https://github.com/biojppm/rapidyaml/pull/145)): - ```yaml - # test case 3MYT - k:#foo - &a !t s - !t s - # now correctly parsed as "k:#foo &a !t s !t s" - ``` -- Fix parsing of comments after complex keys ([PR #145](https://github.com/biojppm/rapidyaml/pull/145)): - ```yaml - # test case X8DW - ? key - # comment - : value - # now correctly parsed as {key: value} - ``` -- Fix parsing of consecutive complex keys within maps ([PR #145](https://github.com/biojppm/rapidyaml/pull/145)) - ```yaml - # test case 7W2P, ZWK4 - ? a - ? b - c: - ? d - e: - # now correctly parsed as {a: ~, b: ~, c: ~, d: ~, e: ~} - ``` -- Fix [#152](https://github.com/biojppm/rapidyaml/issues/152): parse error with folded scalars that are the last in a container ([PR #157](https://github.com/biojppm/rapidyaml/pull/157)): - ```yaml - exec: - command: - # before the fix, this folded scalar failed to parse - - | - exec pg_isready -U "dog" -d "dbname=dog" -h 127.0.0.1 -p 5432 - parses: no - ``` -- Fix: documents consisting of a quoted scalar now retain the VALQUO flag ([PR #156](https://github.com/biojppm/rapidyaml/pull/156)) - ```c++ - Tree tree = parse("'this is a quoted scalar'"); - assert(tree.rootref().is_doc()); - assert(tree.rootref().is_val()); - assert(tree.rootref().is_val_quoted()); - ``` - - -#### Document structure -- Empty docs are now parsed as a docval with a null node: - ```yaml - --- # test cases 6XDY, 6ZKB, 9BXL, PUW8 - --- - --- - ``` - is now parsed as - ```yaml - --- ~ - --- ~ - --- ~ - ``` -- Prevent creation of DOC nodes from stream-level comments or tags ([PR #145](https://github.com/biojppm/rapidyaml/pull/145)): - ```yaml - !foo "bar" - ... - # Global - %TAG ! tag:example.com,2000:app/ - --- - !foo "bar" - ``` - was parsed as - ```yaml - --- - !foo "bar" - --- - # notice the empty doc in here - --- - !foo "bar" - ``` - and it is now correctly parsed as - ```yaml - --- - !foo "bar" - --- - !foo "bar" - ``` - (other than the known limitation that ryml does not do tag lookup). - - -#### General - -- Fix [#147](https://github.com/biojppm/rapidyaml/issues/147): serialize/deserialize special float values `.nan`, `.inf`, `-.inf` ([PR #149](https://github.com/biojppm/rapidyaml/pull/149)) -- Fix [#142](https://github.com/biojppm/rapidyaml/issues/142): `preprocess_json()`: ensure quoted ranges are skipped when slurping containers -- Ensure error macros expand to a single statement ([PR #141](https://github.com/biojppm/rapidyaml/pull/141)) -- Update c4core to [0.1.4](https://github.com/biojppm/c4core/releases/tag/v0.1.4) - - -### Special thanks - -- @Gei0r - diff --git a/thirdparty/ryml/changelog/0.2.2.md b/thirdparty/ryml/changelog/0.2.2.md deleted file mode 100644 index 508759d97..000000000 --- a/thirdparty/ryml/changelog/0.2.2.md +++ /dev/null @@ -1 +0,0 @@ -Yank python package 0.2.1, was accidentally created while iterating the PyPI submission from the Github action. This release does not add any change, and is functionally the same as [0.2.1](https://github.com/biojppm/rapidyaml/releases/tag/v0.2.1). diff --git a/thirdparty/ryml/changelog/0.2.3.md b/thirdparty/ryml/changelog/0.2.3.md deleted file mode 100644 index 268ebd3ec..000000000 --- a/thirdparty/ryml/changelog/0.2.3.md +++ /dev/null @@ -1,285 +0,0 @@ -This release is focused on bug fixes and compliance with the [YAML test suite](https://github.com/yaml/yaml-test-suite). - -### New features -- Add support for CPU architectures aarch64, ppc64le, s390x. -- Update c4core to [0.1.7](https://github.com/biojppm/c4core/releases/tag/v0.1.7) -- `Tree` and `NodeRef`: add document getter `doc()` and `docref()` - ```c++ - Tree tree = parse(R"(--- - doc0 - --- - doc1 - )"); - NodeRef stream = t.rootref(); - assert(stream.is_stream()); - // tree.doc(i): get the index of the i-th doc node. - // Equivalent to tree.child(tree.root_id(), i) - assert(tree.doc(0) == 1u); - assert(tree.doc(1) == 2u); - // tree.docref(i), same as above, return NodeRef - assert(tree.docref(0).val() == "doc0"); - assert(tree.docref(1).val() == "doc1"); - // stream.doc(i), same as above, given NodeRef - assert(stream.doc(0).val() == "doc0"); - assert(stream.doc(1).val() == "doc1"); - ``` - -### Fixes - -- Fix compilation with `C4CORE_NO_FAST_FLOAT` ([PR #163](https://github.com/biojppm/rapidyaml/pull/163)) - -#### Flow maps - -- Fix parse of multiline plain scalars inside flow maps ([PR #161](https://github.com/biojppm/rapidyaml/pull/161)): - ```yaml - # test case UT92 - # all parsed as "matches %": 20 - - { matches - % : 20 } - - { matches - %: 20 } - - { matches - %: - 20 } - ``` - - -#### Tags - -- Fix parsing of tags followed by comments in sequences ([PR #161](https://github.com/biojppm/rapidyaml/pull/161)): - ```yaml - # test case 735Y - - !!map # Block collection - foo : bar - ``` - -#### Quoted scalars -- Fix filtering of tab characters in quoted scalars ([PR #161](https://github.com/biojppm/rapidyaml/pull/161)): - ```yaml - --- - # test case 5GBF - "Empty line - - as a line feed" - # now correctly parsed as "Empty line\nas a line feed" - --- - # test case PRH3 - ' 1st non-empty - - 2nd non-empty - 3rd non-empty ' - # now correctly parsed as " 1st non-empty\n2nd non-empty 3rd non-empty " - ``` -- Fix filtering of backslash characters in double-quoted scalars ([PR #161](https://github.com/biojppm/rapidyaml/pull/161)): - ```yaml - # test cases NP9H, Q8AD - "folded - to a space, - - to a line feed, or \ - \ non-content" - # now correctly parsed as "folded to a space,\nto a line feed, or \t \tnon-content" - ``` -- Ensure filtering of multiline quoted scalars ([PR #161](https://github.com/biojppm/rapidyaml/pull/161)): - ```yaml - # all scalars now correctly parsed as "quoted string", - # both for double and single quotes - --- - "quoted - string" - --- "quoted - string" - --- - - "quoted - string" - --- - - "quoted - string" - --- - "quoted - string": "quoted - string" - --- - "quoted - string": "quoted - string" - ``` - - -#### Block scalars -- Ensure no newlines are added when emitting block scalars ([PR #161](https://github.com/biojppm/rapidyaml/pull/161)) -- Fix parsing of block spec with both chomping and indentation: chomping may come before or after the indentation ([PR #161](https://github.com/biojppm/rapidyaml/pull/161)): - ```yaml - # the block scalar specs below now have the same effect. - # test cases: D83L, P2AD - - |2- - explicit indent and chomp - - |-2 - chomp and explicit indent - ``` -- Fix [inference of block indentation](https://yaml.org/spec/1.2.2/#8111-block-indentation-indicator) with leading blank lines ([PR #161](https://github.com/biojppm/rapidyaml/pull/161)): - ```yaml - # test cases: 4QFQ, 7T8X - - > - - - # child1 - # parsed as "\n\n child1" - --- # test case DWX9 - | - - - literal - - - text - - # Comment - # parsed as "\n\nliteral\n \n\ntext\n" - ``` -- Fix parsing of same-indentation block scalars ([PR #161](https://github.com/biojppm/rapidyaml/pull/161)): - ```yaml - # test case W4TN - # all docs have the same value: "%!PS-Adobe-2.0" - --- | - %!PS-Adobe-2.0 - ... - --- > - %!PS-Adobe-2.0 - ... - --- | - %!PS-Adobe-2.0 - ... - --- > - %!PS-Adobe-2.0 - ... - --- | - %!PS-Adobe-2.0 - --- > - %!PS-Adobe-2.0 - --- | - %!PS-Adobe-2.0 - --- > - %!PS-Adobe-2.0 - ``` -- Folded block scalars: fix folding of newlines at the border of indented parts ([PR #161](https://github.com/biojppm/rapidyaml/pull/161)): - ```yaml - # test case 6VJK - # now correctly parsed as "Sammy Sosa completed another fine season with great stats.\n\n 63 Home Runs\n 0.288 Batting Average\n\nWhat a year!\n" - > - Sammy Sosa completed another - fine season with great stats. - - 63 Home Runs - 0.288 Batting Average - - What a year! - --- - # test case MJS9 - # now correctly parsed as "foo \n\n \t bar\n\nbaz\n" - > - foo - - bar - - baz - ``` -- Folded block scalars: fix folding of newlines when the indented part is at the begining of the scalar ([PR #161](https://github.com/biojppm/rapidyaml/pull/161)): - ```yaml - # test case F6MC - a: >2 - more indented - regular - # parsed as a: " more indented\nregular\n" - b: >2 - - - more indented - regular - # parsed as b: "\n\n more indented\nregular\n" - ``` - -#### Plain scalars -- Fix parsing of whitespace within plain scalars ([PR #161](https://github.com/biojppm/rapidyaml/pull/161)): - ```yaml - --- - # test case NB6Z - key: - value - with - - tabs - tabs - - foo - - bar - baz - - # is now correctly parsed as "value with\ntabs tabs\nfoo\nbar baz" - --- - # test case 9YRD, EX5H (trailing whitespace) - a - b - c - d - - e - # is now correctly parsed as "a b c d\ne" - ``` -- Fix parsing of unindented plain scalars at the root level scope ([PR #161](https://github.com/biojppm/rapidyaml/pull/161)) - ```yaml - --- # this parsed - Bare - scalar - is indented - # was correctly parsed as "Bare scalar is indented" - --- # but this failed to parse successfully: - Bare - scalar - is not indented - # is now correctly parsed as "Bare scalar is not indented" - --- # test case NB6Z - value - with - - tabs - tabs - - foo - - bar - baz - - # now correctly parsed as "value with\ntabs tabs\nfoo\nbar baz" - --- - --- # test cases EXG3, 82AN - ---word1 - word2 - # now correctly parsed as "---word1 word2" - ``` -- Fix parsing of comments within plain scalars - ```yaml - # test case 7TMG - --- # now correctly parsed as "word1" - word1 - # comment - --- # now correctly parsed as [word1, word2] - [ word1 - # comment - , word2] - ``` - -#### Python API -- Add missing node predicates in SWIG API definition ([PR #166](https://github.com/biojppm/rapidyaml/pull/166)): - - `is_anchor_or_ref()` - - `is_key_quoted()` - - `is_val_quoted()` - - `is_quoted()` - - -### Thanks - ---- @mbs-c ---- @simu ---- @QuellaZhang diff --git a/thirdparty/ryml/changelog/0.3.0.md b/thirdparty/ryml/changelog/0.3.0.md deleted file mode 100644 index 3bd5875d2..000000000 --- a/thirdparty/ryml/changelog/0.3.0.md +++ /dev/null @@ -1,104 +0,0 @@ -### Breaking changes - -Despite ryml being still in a non-stable 0.x.y version, considerable effort goes into trying to avoid breaking changes. However, this release has to collect on the [semantic versioning](https://semver.org/) prerogative for breaking changes. This is a needed improvement, so sorry for any nuisance! - -**The allocation and error callback logic was revamped** on the [amalgamation PR](https://github.com/biojppm/rapidyaml/pull/172). Now trees and parsers receive (and store) a full `ryml::Callbacks` object instead of the (now removed) `ryml::Allocator` which had a pointer to a (now removed) `ryml::MemoryResourceCallbacks`, which was a (now removed) `ryml::MemoryResource`. To be clear, the `Callbacks` class is unchanged, other than removing some unneeded helper methods. - -These changes were motivated by unfortunate name clashes between `c4::Allocator/ryml::Allocator` and `c4::MemoryResource/ryml::MemoryResource`, occurring if `` or `` were included before ``. They also significantly simplify this part of the API, making it really easier to understand. - -As a consequence of the above changes, the global memory resource getters and setters for ryml were also removed: `ryml::get_memory_resource()/ryml::set_memory_resource()`. - -Here's an example of the required changes in client code. First the old client code (from the quickstart): - -```c++ -struct PerTreeMemoryExample : public ryml::MemoryResource -{ - void *allocate(size_t len, void * hint) override; - void free(void *mem, size_t len) override; -}; - -PerTreeMemoryExample mrp; -PerTreeMemoryExample mr1; -PerTreeMemoryExample mr2; - -ryml::Parser parser = {ryml::Allocator(&mrp)}; -ryml::Tree tree1 = {ryml::Allocator(&mr1)}; -ryml::Tree tree2 = {ryml::Allocator(&mr2)}; -``` - -Should now be rewritten to: - -```c++ -struct PerTreeMemoryExample -{ - ryml::Callbacks callbacks() const; // helper to create the callbacks -}; - -PerTreeMemoryExample mrp; -PerTreeMemoryExample mr1; -PerTreeMemoryExample mr2; - -ryml::Parser parser = {mrp.callbacks()}; -ryml::Tree tree1 = {mr1.callbacks()}; -ryml::Tree tree2 = {mr2.callbacks()}; -``` - - -### New features -- Add amalgamation into a single header file ([PR #172](https://github.com/biojppm/rapidyaml/pull/172)): - - The amalgamated header will be available together with the deliverables from each release. - - To generate the amalgamated header: - ```console - $ python tools/amalgamate.py ryml_all.hpp - ``` - - To use the amalgamated header: - - Include at will in any header of your project. - - In one - and only one - of your project source files, `#define RYML_SINGLE_HDR_DEFINE_NOW` and then `#include `. This will enable the function and class definitions in the header file. For example, here's a sample program: - ```c++ - #include - #define RYML_SINGLE_HDR_DEFINE_NOW // do this before the include - #include - int main() - { - auto tree = ryml::parse("{foo: bar}"); - std::cout << tree["foo"].val() << "\n"; - } - ``` -- Add `Tree::change_type()` and `NodeRef::change_type()` ([PR #171](https://github.com/biojppm/rapidyaml/pull/171)): - ```c++ - // clears a node and sets its type to a different type (one of `VAL`, `SEQ`, `MAP`): - Tree t = parse("{keyval0: val0, keyval1: val1, keyval2: val2}"); - t[0].change_type(VAL); - t[1].change_type(MAP); - t[2].change_type(SEQ); - Tree expected = parse("{keyval0: val0, keyval1: {}, keyval2: []}"); - assert(emitrs(t) == emitrs(expected)); - ``` -- Add support for compilation with emscripten (WebAssembly+javascript) ([PR #176](https://github.com/biojppm/rapidyaml/pull/176)). - -### Fixes - -- Take block literal indentation as relative to current indentation level, rather than as an absolute indentation level ([PR #178](https://github.com/biojppm/rapidyaml/pull/178)): - ```yaml - foo: - - | - child0 - - |2 - child2 # indentation is 4, not 2 - ``` -- Fix parsing when seq member maps start without a key ([PR #178](https://github.com/biojppm/rapidyaml/pull/178)): - ```yaml - # previously this resulted in a parse error - - - : empty key - - - : another empty key - ``` -- Prefer passing `substr` and `csubstr` by value instead of const reference ([PR #171](https://github.com/biojppm/rapidyaml/pull/171)) -- Fix [#173](https://github.com/biojppm/rapidyaml/issues/173): add alias target `ryml::ryml` ([PR #174](https://github.com/biojppm/rapidyaml/pull/174)) -- Speedup compilation of tests by removing linking with yaml-cpp and libyaml. ([PR #177](https://github.com/biojppm/rapidyaml/pull/177)) -- Fix [c4core#53](https://github.com/biojppm/c4core/issues/53): cmake install targets were missing call to `export()` ([PR #179](https://github.com/biojppm/c4core/pull/179)). -- Add missing export to `Tree` ([PR #181](https://github.com/biojppm/c4core/pull/181)). - - -### Thanks - -- @aviktorov diff --git a/thirdparty/ryml/changelog/0.4.0.md b/thirdparty/ryml/changelog/0.4.0.md deleted file mode 100644 index 1c9c43914..000000000 --- a/thirdparty/ryml/changelog/0.4.0.md +++ /dev/null @@ -1,229 +0,0 @@ -This release improves compliance with the [YAML test suite](https://github.com/yaml/yaml-test-suite/) (thanks @ingydotnet and @perlpunk for extensive and helpful cooperation), and adds node location tracking using the parser. - - -### Breaking changes - -As part of the [new feature to track source locations](https://github.com/biojppm/rapidyaml/pull/168), opportunity was taken to address a number of pre-existing API issues. These changes consisted of: - -- Deprecate `c4::yml::parse()` and `c4::yml::Parser::parse()` overloads; all these functions will be removed in short order. Until removal, any call from client code will trigger a compiler warning. -- Add `parse()` alternatives, either `parse_in_place()` or `parse_in_arena()`: - - `parse_in_place()` receives only `substr` buffers, ie mutable YAML source buffers. Trying to pass a `csubstr` buffer to `parse_in_place()` will cause a compile error: - ```c++ - substr readwrite = /*...*/; - Tree tree = parse_in_place(readwrite); // OK - - csubstr readonly = /*...*/; - Tree tree = parse_in_place(readonly); // compile error - ``` - - `parse_in_arena()` receives only `csubstr` buffers, ie immutable YAML source buffers. Prior to parsing, the buffer is copied to the tree's arena, then the copy is parsed in place. Because `parse_in_arena()` is meant for immutable buffers, overloads receiving a `substr` YAML buffer are now declared but marked deprecated, and intentionally left undefined, such that calling `parse_in_arena()` with a `substr` will cause a linker error as well as a compiler warning. - ```c++ - substr readwrite = /*...*/; - Tree tree = parse_in_arena(readwrite); // compile warning+linker error - ``` - This is to prevent an accidental extra copy of the mutable source buffer to the tree's arena: `substr` is implicitly convertible to `csubstr`. If you really intend to parse an originally mutable buffer in the tree's arena, convert it first explicitly to immutable by assigning the `substr` to a `csubstr` prior to calling `parse_in_arena()`: - ```c++ - substr readwrite = /*...*/; - csubstr readonly = readwrite; // ok - Tree tree = parse_in_arena(readonly); // ok - ``` - This problem does not occur with `parse_in_place()` because `csubstr` is not implicitly convertible to `substr`. -- In the python API, `ryml.parse()` was removed and not just deprecated; the `parse_in_arena()` and `parse_in_place()` now replace this. -- `Callbacks`: changed behavior in `Parser` and `Tree`: - - When a tree is copy-constructed or move-constructed to another, the receiving tree will start with the callbacks of the original. - - When a tree is copy-assigned or move-assigned to another, the receiving tree will now change its callbacks to the original. - - When a parser creates a new tree, the tree will now use a copy of the parser's callbacks object. - - When an existing tree is given directly to the parser, both the tree and the parser now retain their own callback objects; any allocation or error during parsing will go through the respective callback object. - - -### New features - -- Add tracking of source code locations. This is useful for reporting semantic errors after the parsing phase (ie where the YAML is syntatically valid and parsing is successful, but the tree contents are semantically invalid). The locations can be obtained lazily from the parser when the first location is queried: - ```c++ - // To obtain locations, use of the parser is needed: - ryml::Parser parser; - ryml::Tree tree = parser.parse_in_arena("source.yml", R"({ - aa: contents, - foo: [one, [two, three]] - })"); - // After parsing, on the first call to obtain a location, - // the parser will cache a lookup structure to accelerate - // tracking the location of a node, with complexity - // O(numchars(srcbuffer)). Then it will do the lookup, with - // complexity O(log(numlines(srcbuffer))). - ryml::Location loc = parser.location(tree.rootref()); - assert(parser.location_contents(loc).begins_with("{")); - // note the location members are zero-based: - assert(loc.offset == 0u); - assert(loc.line == 0u); - assert(loc.col == 0u); - // On the next call to location(), the accelerator is reused - // and only the lookup is done. - loc = parser.location(tree["aa"]); - assert(parser.location_contents(loc).begins_with("aa")); - assert(loc.offset == 2u); - assert(loc.line == 1u); - assert(loc.col == 0u); - // KEYSEQ in flow style: points at the key - loc = parser.location(tree["foo"]); - assert(parser.location_contents(loc).begins_with("foo")); - assert(loc.offset == 16u); - assert(loc.line == 2u); - assert(loc.col == 0u); - loc = parser.location(tree["foo"][0]); - assert(parser.location_contents(loc).begins_with("one")); - assert(loc.line == 2u); - assert(loc.col == 6u); - // SEQ in flow style: location points at the opening '[' (there's no key) - loc = parser.location(tree["foo"][1]); - assert(parser.location_contents(loc).begins_with("[")); - assert(loc.line == 2u); - assert(loc.col == 11u); - loc = parser.location(tree["foo"][1][0]); - assert(parser.location_contents(loc).begins_with("two")); - assert(loc.line == 2u); - assert(loc.col == 12u); - loc = parser.location(tree["foo"][1][1]); - assert(parser.location_contents(loc).begins_with("three")); - assert(loc.line == 2u); - assert(loc.col == 17u); - // NOTE: reusing the parser with a new YAML source buffer - // will invalidate the accelerator. - ``` - See more details in the [quickstart sample](https://github.com/biojppm/rapidyaml/blob/bfb073265abf8c58bbeeeed7fb43270e9205c71c/samples/quickstart.cpp#L3759). Thanks to @cschreib for submitting a working example proving how simple it could be to achieve this. -- `Parser`: - - add `source()` and `filename()` to get the latest buffer and filename to be parsed - - add `callbacks()` to get the parser's callbacks -- Add `from_tag_long()` and `normalize_tag_long()`: - ```c++ - assert(from_tag_long(TAG_MAP) == ""); - assert(normalize_tag_long("!!map") == ""); - ``` -- Add an experimental API to resolve tags based on the tree's tag directives. This API is still imature and will likely be subject to changes, so we won't document it yet. -- Regarding emit styles (see issue [#37](https://github.com/biojppm/rapidyaml/issues/37)): add an experimental API to force flow/block style on container nodes, as well as block-literal/block-folded/double-quoted/single-quoted/plain styles on scalar nodes. This API is also immature and will likely be subject to changes, so we won't document it yet. But if you are desperate for this functionality, the new facilities will let you go further. -- Add preliminary support for bare-metal ARM architectures, with CI tests pending implementation of QEMU action. ([#193](https://github.com/biojppm/rapidyaml/issues/193), [c4core#63](https://github.com/biojppm/c4core/issues/63)). -- Add preliminary support for RISC-V architectures, with CI tests pending availability of RISC-V based github actions. ([c4core#69](https://github.com/biojppm/c4core/pulls/69)). - - -### Fixes - -- Fix edge cases of parsing of explicit keys (ie keys after `?`) ([PR#212](https://github.com/biojppm/rapidyaml/pulls/212)): - ```yaml - # all these were fixed: - ? : # empty - ? explicit key # this comment was not parsed correctly - ? # trailing empty key was not added to the map - ``` -- Fixed parsing of tabs used as whitespace tokens after `:` or `-`. This feature [is costly (see some benchmark results here)](https://github.com/biojppm/rapidyaml/pull/211#issuecomment-1030688035) and thus it is disabled by default, and requires defining a macro or cmake option `RYML_WITH_TAB_TOKENS` to enable ([PR#211](https://github.com/biojppm/rapidyaml/pulls/211)). -- Allow tab indentation in flow seqs ([PR#215](https://github.com/biojppm/rapidyaml/pulls/215)) (6CA3). -- ryml now parses successfully compact JSON code `{"like":"this"}` without any need for preprocessing. This code was not valid YAML 1.1, but was made valid in YAML 1.2. So the `preprocess_json()` functions, used to insert spaces after `:` are no longer necessary and have been removed. If you were using these functions, remove the calls and just pass the original source directly to ryml's parser ([PR#210](https://github.com/biojppm/rapidyaml/pulls/210)). -- Fix handling of indentation when parsing block scalars ([PR#210](https://github.com/biojppm/rapidyaml/pulls/210)): - ```yaml - --- - | - hello - there - --- - | - ciao - qua - --- - - | - hello - there - - | - ciao - qua - --- - foo: | - hello - there - bar: | - ciao - qua - ``` -- Fix parsing of maps when opening a scope with whitespace before the colon ([PR#210](https://github.com/biojppm/rapidyaml/pulls/210)): - ```yaml - foo0 : bar - --- - foo1 : bar # the " :" was causing an assert - --- - foo2 : bar - --- - foo3 : bar - --- - foo4 : bar - ``` -- Ensure container keys preserve quote flags when the key is quoted ([PR#210](https://github.com/biojppm/rapidyaml/pulls/210)). -- Ensure scalars beginning with `%` are emitted with quotes (([PR#216](https://github.com/biojppm/rapidyaml/pulls/216)). -- Fix [#203](https://github.com/biojppm/rapidyaml/issues/203): when parsing, do not convert `null` or `~` to null scalar strings. Now the scalar strings contain the verbatim contents of the original scalar; to query whether a scalar value is null, use `Tree::key_is_null()/val_is_null()` and `NodeRef::key_is_null()/val_is_null()` which return true if it is empty or any of the unquoted strings `~`, `null`, `Null`, or `NULL`. ([PR#207](https://github.com/biojppm/rapidyaml/pulls/207)): -- Fix [#205](https://github.com/biojppm/rapidyaml/issues/205): fix parsing of escaped characters in double-quoted strings: `"\\\"\n\r\t\\/\\0\b\f\a\v\e\_\N\L\P"` ([PR#207](https://github.com/biojppm/rapidyaml/pulls/207)). -- Fix [#204](https://github.com/biojppm/rapidyaml/issues/204): add decoding of unicode codepoints `\x` `\u` `\U` in double-quoted scalars: - ```c++ - Tree tree = parse_in_arena(R"(["\u263A \xE2\x98\xBA \u2705 \U0001D11E"])"); - assert(tree[0].val() == "☺ ☺ ✅ 𝄞"); - ``` - This is mandated by the YAML standard and was missing from ryml ([PR#207](https://github.com/biojppm/rapidyaml/pulls/207)). -- Fix emission of nested nodes which are sequences: when these are given as the emit root, the `- ` from the parent node was added ([PR#210](https://github.com/biojppm/rapidyaml/pulls/210)): - ```c++ - const ryml::Tree tree = ryml::parse_in_arena(R"( - - - Rochefort 10 - - Busch - - Leffe Rituel - - - and so - - many other - - wonderful beers - )"); - // before (error), YAML valid but not expected - //assert(ryml::emitrs(tree[0][3]) == R"(- - and so - // - many other - // - wonderful beers - //)"); - // now: YAML valid and expected - assert(ryml::emitrs(tree[0][3]) == R"(- and so - - many other - - wonderful beers - )"); - ``` -- Fix parsing of isolated `!`: should be an empty val tagged with `!` (UKK06-02) ([PR#215](https://github.com/biojppm/rapidyaml/pulls/215)). -- Fix [#193](https://github.com/biojppm/rapidyaml/issues/193): amalgamated header missing `#include ` which prevented compilation in bare-metal `arm-none-eabi` ([PR #195](https://github.com/biojppm/rapidyaml/pull/195), requiring also [c4core #64](https://github.com/biojppm/c4core/pull/64)). -- Accept `infinity`,`inf` and `nan` as special float values (but not mixed case: eg `InFiNiTy` or `Inf` or `NaN` are not accepted) ([PR #186](https://github.com/biojppm/rapidyaml/pull/186)). -- Accept special float values with upper or mixed case: `.Inf`, `.INF`, `.NaN`, `.NAN`. Previously, only low-case `.inf` and `.nan` were accepted ([PR #186](https://github.com/biojppm/rapidyaml/pull/186)). -- Accept `null` with upper or mixed case: `Null` or `NULL`. Previously, only low-case `null` was accepted ([PR #186](https://github.com/biojppm/rapidyaml/pull/186)). -- Fix [#182](https://github.com/biojppm/rapidyaml/issues/182): add missing export of DLL symbols, and document requirements for compiling shared library from the amalgamated header. [PR #183](https://github.com/biojppm/rapidyaml/pull/183), also [PR c4core#56](https://github.com/biojppm/c4core/pull/56) and [PR c4core#57](https://github.com/biojppm/c4core/pull/57). -- Fix [#185](https://github.com/biojppm/rapidyaml/issues/185): compilation failures in earlier Xcode versions ([PR #187](https://github.com/biojppm/rapidyaml/pull/187) and [PR c4core#61](https://github.com/biojppm/c4core/pull/61)): - - `c4/substr_fwd.hpp`: (failure in Xcode 12 and earlier) forward declaration for `std::allocator` is inside the `inline namespace __1`, unlike later versions. - - `c4/error.hpp`: (failure in debug mode in Xcode 11 and earlier) `__clang_major__` does not mean the same as in the common clang, and as a result the warning `-Wgnu-inline-cpp-without-extern` does not exist there. -- Ensure error messages do not wrap around the buffer when the YAML source line is too long ([PR#210](https://github.com/biojppm/rapidyaml/pulls/210)). -- Ensure error is emitted on unclosed flow sequence characters eg `[[[` ([PR#210](https://github.com/biojppm/rapidyaml/pulls/210)). Same thing for `[]]`. -- Refactor error message building and parser debug logging to use the new dump facilities in c4core ([PR#212](https://github.com/biojppm/rapidyaml/pulls/212)). -- Parse: fix read-after-free when duplicating a parser state node, when pushing to the stack requires a stack buffer resize ([PR#210](https://github.com/biojppm/rapidyaml/pulls/210)). -- Add support for legacy gcc 4.8 ([PR#217](https://github.com/biojppm/rapidyaml/pulls/217)). - - -### Improvements - -- Rewrite filtering of scalars to improve parsing performance ([PR #188](https://github.com/biojppm/rapidyaml/pull/188)). Previously the scalar strings were filtered in place, which resulted in quadratic complexity in terms of scalar length. This did not matter for small scalars fitting the cache (which is the more frequent case), but grew in cost as the scalars grew larger. To achieve linearity, the code was changed so that the strings are now filtered to a temporary scratch space in the parser, and copied back to the output buffer after filtering, if any change occurred. The improvements were large for the folded scalars; the table below shows the benchmark results of throughput (MB/s) for several files containing large scalars of a single type: - | scalar type | before | after | improvement | - |:------------|-------:|-------:|---------:| - | block folded | 276 | 561 | 103% | - | block literal | 331 | 611 | 85% | - | single quoted | 247 | 267 | 8% | - | double quoted | 212 | 230 | 8% | - | plain (unquoted) | 173 | 186 | 8% | - - The cost for small scalars is negligible, with benchmark improvement in the interval of -2% to 5%, so well within the margin of benchmark variability in a regular OS. In the future, this will be optimized again by copying each character in place, thus completely avoiding the staging arena. -- `Callbacks`: add `operator==()` and `operator!=()` ([PR #168](https://github.com/biojppm/rapidyaml/pull/168)). -- `Tree`: on error or assert prefer the error callback stored into the tree's current `Callbacks`, rather than the global `Callbacks` ([PR #168](https://github.com/biojppm/rapidyaml/pull/168)). -- `detail::stack<>`: improve behavior when assigning from objects `Callbacks`, test all rule-of-5 scenarios ([PR #168](https://github.com/biojppm/rapidyaml/pull/168)). -- Improve formatting of error messages. - - -### Thanks - -- @ingydotnet -- @perlpunk -- @cschreib -- @fargies -- @Xeonacid -- @aviktorov -- @xTVaser diff --git a/thirdparty/ryml/changelog/0.4.1.md b/thirdparty/ryml/changelog/0.4.1.md deleted file mode 100644 index c8735aa6e..000000000 --- a/thirdparty/ryml/changelog/0.4.1.md +++ /dev/null @@ -1,3 +0,0 @@ -### Fixes - -- Fix [#223](https://github.com/biojppm/rapidyaml/issues/223): assertion peeking into the last line when it was whitespaces only. diff --git a/thirdparty/ryml/changelog/0.5.0.md b/thirdparty/ryml/changelog/0.5.0.md deleted file mode 100644 index 467706e7c..000000000 --- a/thirdparty/ryml/changelog/0.5.0.md +++ /dev/null @@ -1,174 +0,0 @@ - -### Breaking changes - -- Make the node API const-correct ([PR#267](https://github.com/biojppm/rapidyaml/pull/267)): added `ConstNodeRef` to hold a constant reference to a node. As the name implies, a `ConstNodeRef` object cannot be used in any tree-mutating operation. It is also smaller than the existing `NodeRef` (and faster because it does not need to check its own validity on every access). As a result of this change, there are now some constraints when obtaining a ref from a tree, and existing code is likely to break in this type of situation: - ```c++ - const Tree const_tree = ...; - NodeRef nr = const_tree.rootref(); // ERROR (was ok): cannot obtain a mutating NodeRef from a const Tree - ConstNodeRef cnr = const_tree.rootref(); // ok - - Tree tree = ...; - NodeRef nr = tree.rootref(); // ok - ConstNodeRef cnr = tree.rootref(); // ok (implicit conversion from NodeRef to ConstNodeRef) - // to obtain a ConstNodeRef from a mutable Tree - // while avoiding implicit conversion, use the `c` - // prefix: - ConstNodeRef cnr = tree.crootref(); - // likewise for tree.ref() and tree.cref(). - - nr = cnr; // ERROR: cannot obtain NodeRef from ConstNodeRef - cnr = nr; // ok - ``` - The use of `ConstNodeRef` also needs to be propagated through client code. One such place is when deserializing types: - ```c++ - // needs to be changed from: - template bool read(ryml::NodeRef const& n, T *var); - // ... to: - template bool read(ryml::ConstNodeRef const& n, T *var); - ``` - - The initial version of `ConstNodeRef/NodeRef` had the problem that const methods in the CRTP base did not participate in overload resolution ([#294](https://github.com/biojppm/rapidyaml/issues/294)), preventing calls from `const NodeRef` objects. This was fixed by moving non-const methods to the CRTP base and disabling them with SFINAE ([PR#295](https://github.com/biojppm/rapidyaml/pull/295)). - - Also added disambiguation iteration methods: `.cbegin()`, `.cend()`, `.cchildren()`, `.csiblings()` ([PR#295](https://github.com/biojppm/rapidyaml/pull/295)). -- Deprecate `emit()` and `emitrs()` ([#120](https://github.com/biojppm/rapidyaml/issues/120), [PR#303](https://github.com/biojppm/rapidyaml/pull/303)): use `emit_yaml()` and `emitrs_yaml()` instead. This was done to improve compatibility with Qt, which leaks a macro named `emit`. For more information, see [#120](https://github.com/biojppm/rapidyaml/issues/120). - - In the Python API: - - Deprecate `emit()`, add `emit_yaml()` and `emit_json()`. - - Deprecate `compute_emit_length()`, add `compute_emit_yaml_length()` and `compute_emit_json_length()`. - - Deprecate `emit_in_place()`, add `emit_yaml_in_place()` and `emit_json_in_place()`. - - Calling the deprecated functions will now trigger a warning. -- Location querying is no longer done lazily ([#260](https://github.com/biojppm/rapidyaml/issues/260), [PR#307](https://github.com/biojppm/rapidyaml/pull/307)). It now requires explicit opt-in when instantiating the parser. With this change, the accelerator structure for location querying is now built when parsing: - ```c++ - Parser parser(ParserOptions().locations(true)); - // now parsing also builds location lookup: - Tree t = parser.parse_in_arena("myfile.yml", "foo: bar"); - assert(parser.location(t["foo"]).line == 0u); - ``` - - Locations are disabled by default: - ```c++ - Parser parser; - assert(parser.options().locations() == false); - ``` -- Deprecate `Tree::arena_pos()`: use `Tree::arena_size()` instead ([PR#290](https://github.com/biojppm/rapidyaml/pull/290)). -- Deprecate pointless `has_siblings()`: use `Tree::has_other_siblings()` instead ([PR#330](https://github.com/biojppm/rapidyaml/pull/330). - - -### Performance improvements - -- Improve performance of integer serialization and deserialization (in [c4core](https://github.com/biojppm/c4core)). Eg, on Linux/g++11.2, with integral types: - - `c4::to_chars()` can be expected to be roughly... - - ~40% to 2x faster than `std::to_chars()` - - ~10x-30x faster than `sprintf()` - - ~50x-100x faster than a naive `stringstream::operator<<()` followed by `stringstream::str()` - - `c4::from_chars()` can be expected to be roughly... - - ~10%-30% faster than `std::from_chars()` - - ~10x faster than `scanf()` - - ~30x-50x faster than a naive `stringstream::str()` followed by `stringstream::operator>>()` - For more details, see [the changelog for c4core 0.1.10](https://github.com/biojppm/c4core/releases/tag/v0.1.10). -- Fix [#289](https://github.com/biojppm/rapidyaml/issues/289) and [#331](https://github.com/biojppm/rapidyaml/issues/331) - parsing of single-line flow-style sequences had quadratic complexity, causing long parse times in ultra long lines [PR#293](https://github.com/biojppm/rapidyaml/pull/293)/[PR#332](https://github.com/biojppm/rapidyaml/pull/332). - - This was due to scanning for the token `: ` before scanning for `,` or `]`, which caused line-length scans on every scalar scan. Changing the order of the checks was enough to address the quadratic complexity, and the parse times for flow-style are now in line with block-style. - - As part of this changeset, a significant number of runtime branches was eliminated by separating `Parser::_scan_scalar()` into several different `{seq,map}x{block,flow}` functions specific for each context. Expect some improvement in parse times. - - Also, on Debug builds (or assertion-enabled builds) there was a paranoid assertion calling `Tree::has_child()` in `Tree::insert_child()` that caused quadratic behavior because the assertion had linear complexity. It was replaced with a somewhat equivalent O(1) assertion. - - Now the byte throughput is independent of line size for styles and containers. This can be seen in the table below, which shows parse troughputs in MB/s of 1000 containers of different styles and sizes (flow containers are in a single line): - - | Container | Style | 10elms | 100elms | 1000elms | - |-----------|-------|-------------|--------------|---------------| - | 1000 Maps | block | 50.8MB/s | 57.8MB/s | 63.9MB/s | - | 1000 Maps | flow | 58.2MB/s | 65.9MB/s | 74.5MB/s | - | 1000 Seqs | block | 55.7MB/s | 59.2MB/s | 60.0MB/s | - | 1000 Seqs | flow | 52.8MB/s | 55.6MB/s | 54.5MB/s | -- Fix [#329](https://github.com/biojppm/rapidyaml/issues/329): complexity of `has_sibling()` and `has_child()` is now O(1), previously was linear ([PR#330](https://github.com/biojppm/rapidyaml/pull/330)). - - -### Fixes - -- Fix [#233](https://github.com/biojppm/rapidyaml/issues/233) - accept leading colon in the first key of a flow map (`UNK` node) [PR#234](https://github.com/biojppm/rapidyaml/pull/234): - ```yaml - :foo: # parse error on the leading colon - :bar: a # parse error on the leading colon - :barbar: b # was ok - :barbarbar: c # was ok - foo: # was ok - bar: a # was ok - :barbar: b # was ok - :barbarbar: c # was ol - ``` -- Fix [#253](https://github.com/biojppm/rapidyaml/issues/253): double-quoted emitter should encode carriage-return `\r` to preserve roundtrip equivalence: - ```yaml - Tree tree; - NodeRef root = tree.rootref(); - root |= MAP; - root["s"] = "t\rt"; - root["s"] |= _WIP_VAL_DQUO; - std::string s = emitrs(tree); - EXPECT_EQ(s, "s: \"t\\rt\"\n"); - Tree tree2 = parse_in_arena(to_csubstr(s)); - EXPECT_EQ(tree2["s"].val(), tree["s"].val()); - ``` -- Fix parsing of empty block folded+literal scalars when they are the last child of a container (part of [PR#264](https://github.com/biojppm/rapidyaml/issues/264)): - ```yaml - seq: - - "" - - '' - - > - - | # error, the resulting val included all the YAML from the next node - seq2: - - "" - - '' - - | - - > # error, the resulting val included all the YAML from the next node - map: - a: "" - b: '' - c: > - d: | # error, the resulting val included all the YAML from the next node - map2: - a: "" - b: '' - c: | - d: > # error, the resulting val included all the YAML from the next node - lastly: the last - ``` -- Fix [#274](https://github.com/biojppm/rapidyaml/issues/274) ([PR#296](https://github.com/biojppm/rapidyaml/pull/296)): Lists with unindented items and trailing empty values parse incorrectly: - ```yaml - foo: - - bar - - - baz: qux - ``` - was wrongly parsed as - ```yaml - foo: - - bar - - baz: qux - ``` -- Fix [#277](https://github.com/biojppm/rapidyaml/issues/277) ([PR#340](https://github.com/biojppm/rapidyaml/pull/340)): merge fails with duplicate keys. -- Fix [#337](https://github.com/biojppm/rapidyaml/issues/337) ([PR#338](https://github.com/biojppm/rapidyaml/pull/338)): empty lines in block scalars shall not have tab characters `\t`. -- Fix [#268](https://github.com/biojppm/rapidyaml/issues/268) ([PR#339](https://github.com/biojppm/rapidyaml/pull/339)): don't override key type_bits when copying val. This was causing problematic resolution of anchors/references. -- Fix [#309](https://github.com/biojppm/rapidyaml/issues/309) ([PR#310](https://github.com/biojppm/rapidyaml/pull/310)): emitted scalars containing `@` or `` ` `` should be quoted. - - The quotes should be added only when they lead the scalar. See [#320](https://github.com/biojppm/rapidyaml/issues/320) and [PR#334](https://github.com/biojppm/rapidyaml/pull/334). -- Fix [#297](https://github.com/biojppm/rapidyaml/issues/297) ([PR#298](https://github.com/biojppm/rapidyaml/pull/298)): JSON emitter should escape control characters. -- Fix [#292](https://github.com/biojppm/rapidyaml/issues/292) ([PR#299](https://github.com/biojppm/rapidyaml/pull/299)): JSON emitter should quote version string scalars like `0.1.2`. -- Fix [#291](https://github.com/biojppm/rapidyaml/issues/291) ([PR#299](https://github.com/biojppm/rapidyaml/pull/299)): JSON emitter should quote scalars with leading zero, eg `048`. -- Fix [#280](https://github.com/biojppm/rapidyaml/issues/280) ([PR#281](https://github.com/biojppm/rapidyaml/pull/281)): deserialization of `std::vector` failed because its `operator[]` returns a `reference` instead of `value_type`. -- Fix [#288](https://github.com/biojppm/rapidyaml/issues/288) ([PR#290](https://github.com/biojppm/rapidyaml/pull/290)): segfault on successive calls to `Tree::_grow_arena()`, caused by using the arena position instead of its length as starting point for the new arena capacity. -- Fix [#324](https://github.com/biojppm/rapidyaml/issues/324) ([PR#328](https://github.com/biojppm/rapidyaml/pull/328)): eager assertion prevented moving nodes to the first position in a parent. -- Fix `Tree::_clear_val()`: was clearing key instead ([PR#335](https://github.com/biojppm/rapidyaml/pull/335)). -- YAML test suite events emitter: fix emission of inheriting nodes. The events for `{<<: *anchor, foo: bar}` are now correctly emitted as: - ```yaml - =VAL :<< # previously was =ALI << - =ALI *anchor - =VAL :foo - =VAL :bar - ``` -- Fix [#246](https://github.com/biojppm/rapidyaml/issues/246): add missing `#define` for the include guard of the amalgamated header. -- Fix [#326](https://github.com/biojppm/rapidyaml/issues/326): honor runtime settings for calling debugbreak, add option to disable any calls to debugbreak. -- Fix [cmake#8](https://github.com/biojppm/cmake/issues/8): `SOVERSION` missing from shared libraries. - - -## Python - -- The Python packages for Windows and MacOSX are causing problems in the CI, and were mostly disabled. The problematic packages are successfully made, but then fail to be imported. This was impossible to reproduce outside of the CI, and they were disabled since they were delaying the release. As a consequence, the Python release will have very limited compiled packages for Windows (only Python 3.6 and 3.7) or MacOSX. Help would be appreciated from those interested in these packages. - - -## Thanks - -- @NaN-git -- @dancingbug diff --git a/thirdparty/ryml/cmake/uninstall.cmake b/thirdparty/ryml/cmake/uninstall.cmake deleted file mode 100644 index 5ac7ceb6d..000000000 --- a/thirdparty/ryml/cmake/uninstall.cmake +++ /dev/null @@ -1,24 +0,0 @@ -set(MANIFEST "${CMAKE_CURRENT_BINARY_DIR}/install_manifest.txt") - -if(NOT EXISTS ${MANIFEST}) - message(FATAL_ERROR "Cannot find install manifest: '${MANIFEST}'") -endif() - -file(STRINGS ${MANIFEST} files) -foreach(file ${files}) - if(EXISTS ${file}) - message(STATUS "Removing file: '${file}'") - - exec_program( - ${CMAKE_COMMAND} ARGS "-E remove ${file}" - OUTPUT_VARIABLE stdout - RETURN_VALUE result - ) - - if(NOT "${result}" STREQUAL 0) - message(FATAL_ERROR "Failed to remove file: '${file}'.") - endif() - else() - MESSAGE(STATUS "File '${file}' does not exist.") - endif() -endforeach(file) diff --git a/thirdparty/ryml/compat.cmake b/thirdparty/ryml/compat.cmake deleted file mode 100644 index bbdd16c31..000000000 --- a/thirdparty/ryml/compat.cmake +++ /dev/null @@ -1,11 +0,0 @@ - -# old gcc-4.8 support -if((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") AND - (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 4.8) AND - (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0)) - - # c++17 compiler required - set(C4RYML_BUILD_BENCHMARKS OFF CACHE BOOL "" FORCE) - # LLVM required - set(C4RYML_SANITIZE OFF CACHE BOOL "" FORCE) -endif() diff --git a/thirdparty/ryml/ext/c4core/.github/release.sh b/thirdparty/ryml/ext/c4core/.github/release.sh deleted file mode 100644 index 68d24d3d0..000000000 --- a/thirdparty/ryml/ext/c4core/.github/release.sh +++ /dev/null @@ -1,129 +0,0 @@ -#!/bin/bash - - -# useful to iterate when fixing the release: -# ver=0.2.1 ; ( set -x ; git tag -d v$ver ; git push origin :v$ver ) ; (set -x ; set -e ; tbump --only-patch --non-interactive $ver ; git add -u ; git commit --amend --no-edit ; git tag --annotate --message "v$ver" "v$ver" ; git push -f --tags origin ) - - -function c4_release_create() -{ - ( \ - set -euxo pipefail ; \ - ver=$(_c4_validate_ver $1) ; \ - branch=$(_c4_validate_branch) ; \ - c4_release_bump $ver ; \ - c4_release_commit $ver $branch \ - ) -} - -function c4_release_redo() -{ - ( \ - set -euxo pipefail ; \ - ver=$(_c4_validate_ver $1) ; \ - branch=$(_c4_validate_branch) ; \ - c4_release_delete $ver ; \ - c4_release_bump $ver ; \ - c4_release_amend $ver $branch \ - ) -} - -function c4_release_bump() -{ - ( \ - set -euxo pipefail ; \ - ver=$(_c4_validate_ver $1) ; \ - tbump --non-interactive --only-patch $ver \ - ) -} - -function c4_release_commit() -{ - ( \ - set -euxo pipefail ; \ - ver=$(_c4_validate_ver $1) ; \ - branch=$(_c4_validate_branch) ; \ - tag=v$ver ; \ - git add -u ; \ - git commit -m $tag ; \ - git tag --annotate --message $tag $tag ; \ - ) -} - -function c4_release_amend() -{ - ( \ - set -euxo pipefail ; \ - ver=$(_c4_validate_ver $1) ; \ - branch=$(_c4_validate_branch) ; \ - tag=v$ver ; \ - git add -u ; \ - git commit --amend -m $tag ; \ - git tag --annotate --message $tag $tag ; \ - ) -} - -function c4_release_delete() -{ - ( \ - set -euxo pipefail ; \ - ver=$(_c4_validate_ver $1) ; \ - git tag -d v$ver ; \ - git push origin :v$ver \ - ) -} - -function c4_release_push() -{ - ( \ - set -euxo pipefail ; \ - ver=$(_c4_validate_ver $1) ; \ - branch=$(_c4_validate_branch) ; \ - tag=v$ver ; \ - git push origin $branch ; \ - git push --tags origin $tag \ - ) -} - -function c4_release_force_push() -{ - ( \ - set -euxo pipefail ; \ - ver=$(_c4_validate_ver $1) ; \ - branch=$(_c4_validate_branch) ; \ - tag=v$ver ; \ - git push -f origin $branch ; \ - git push -f --tags origin $tag \ - ) -} - -function _c4_validate_ver() -{ - ver=$1 - if [ -z "$ver" ] ; then \ - exit 1 - fi - ver=$(echo $ver | sed "s:v\(.*\):\1:") - #sver=$(echo $ver | sed "s:\([0-9]*\.[0-9]*\..[0-9]*\).*:\1:") - if [ ! -f changelog/$ver.md ] ; then \ - if [ -f changelog/current.md ] ; then - git mv changelog/current.md changelog/$ver.md - touch changelog/current.md - git add changelog/current.md - else - echo "ERROR: could not find changelog/$ver.md or changelog/current.md" - exit 1 - fi - fi - echo $ver -} - -function _c4_validate_branch() -{ - branch=$(git rev-parse --abbrev-ref HEAD) - if [ "$branch" != "master" ] ; then - echo "ERROR: release branch must be master" - exit 1 - fi - echo $branch -} diff --git a/thirdparty/ryml/ext/c4core/.github/reqs.sh b/thirdparty/ryml/ext/c4core/.github/reqs.sh deleted file mode 100644 index 9937616af..000000000 --- a/thirdparty/ryml/ext/c4core/.github/reqs.sh +++ /dev/null @@ -1,314 +0,0 @@ -#!/usr/bin/env bash - -set -x - -# input environment variables: -# OS: the operating system -# CXX_: the compiler version. eg, g++-9 or clang++-6.0 -# BT: the build type -# VG: whether to install valgrind -# ARM: whether to arm cross-compiler and emulator -# GITHUB_WORKFLOW: when run from github -# API: whether to install swig -# CMANY: whether to install cmany - - - -#------------------------------------------------------------------------------- - -function c4_install_test_requirements() -{ - os=$1 - case "$os" in - ubuntu*) - c4_install_test_requirements_ubuntu - return 0 - ;; - macos*) - c4_install_test_requirements_macos - return 0 - ;; - win*) - c4_install_test_requirements_windows - return 0 - ;; - *) - return 0 - ;; - esac -} - -function c4_install_test_requirements_windows() -{ - if [ "$CMANY" == "ON" ] ; then - pip install cmany - fi - if [ "$API" == "ON" ] ; then - choco install swig - which swig - fi - # ensure chocolatey does not override cmake's cpack - which cpack - choco_cpack="/c/ProgramData/Chocolatey/bin/cpack.exe" - if [ -f $choco_cpack ] ; then - newname=$(echo $choco_cpack | sed 's:cpack:choco-cpack:') - mv -vf $choco_cpack $newname - fi - which cpack -} - -function c4_install_test_requirements_macos() -{ - if [ "$CMANY" == "ON" ] ; then - sudo pip3 install cmany - fi -} - -function c4_install_test_requirements_ubuntu() -{ - UBUNTU_RELEASE=$(lsb_release -rs) - UBUNTU_RELEASE_NAME=$(lsb_release -cs) - APT_PKG="" # all - PIP_PKG="" - c4_gather_test_requirements_ubuntu - echo "apt packages: $APT_PKG" - echo "pip packages: $PIP_PKG" - c4_install_test_requirements_ubuntu_impl - echo 'INSTALL COMPLETE!' -} - - -function c4_install_all_possible_requirements_ubuntu() -{ - export CXX_=all - export BT=Coverage - APT_PKG="" # all - PIP_PKG="" - sudo dpkg --add-architecture i386 - c4_gather_test_requirements_ubuntu - _c4_add_arm_compilers - echo "apt packages: $APT_PKG" - echo "pip packages: $PIP_PKG" - c4_install_test_requirements_ubuntu_impl - echo 'INSTALL COMPLETE!' -} - - -function c4_gather_test_requirements_ubuntu() -{ - if [ "$GITHUB_WORKFLOW" != "" ] ; then - sudo dpkg --add-architecture i386 - else - _add_apt build-essential - _add_apt cmake - fi - - _add_apt linux-libc-dev:i386 - _add_apt libc6:i386 - _add_apt libc6-dev:i386 - _add_apt libc6-dbg:i386 - _c4_addlibcxx - - _c4_gather_compilers "$CXX_" - - _add_apt python3-setuptools - _add_apt python3-pip - - #_add_apt iwyu - #_add_apt cppcheck - #_add_pip cpplint - # oclint? - if [ "$VG" == "ON" ] ; then - _add_apt valgrind - fi - - if [ "$BT" == "Coverage" ]; then - _add_apt lcov - _add_apt libffi-dev - _add_apt libssl-dev - _add_pip requests[security] - _add_pip pyopenssl - _add_pip ndg-httpsclient - _add_pip pyasn1 - _add_pip cpp-coveralls - fi - - if [ "$CMANY" != "" ] ; then - _add_pip cmany - fi - - case "$CXX_" in - arm*) - _c4_add_arm_compilers - ;; - esac -} - - -function c4_install_test_requirements_ubuntu_impl() -{ - wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key 2>/dev/null | sudo apt-key add - - wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | sudo apt-key add - - sudo -E apt-add-repository --yes "deb https://apt.kitware.com/ubuntu/ $UBUNTU_RELEASE_NAME main" - sudo -E add-apt-repository --yes ppa:ubuntu-toolchain-r/test - - if [ "$APT_PKG" != "" ] ; then - #sudo -E apt-get clean - sudo -E apt-get update - sudo -E apt-get install -y --force-yes $APT_PKG - fi - - if [ "$PIP_PKG" != "" ]; then - sudo pip3 install $PIP_PKG - fi -} - - -#------------------------------------------------------------------------------- - -function _c4_add_arm_compilers() -{ - # this is going to be deprecated: - # https://askubuntu.com/questions/1243252/how-to-install-arm-none-eabi-gdb-on-ubuntu-20-04-lts-focal-fossa - sudo -E add-apt-repository --yes ppa:team-gcc-arm-embedded/ppa - - _add_apt gcc-arm-embedded - _add_apt g++-arm-linux-gnueabihf - _add_apt g++-multilib-arm-linux-gnueabihf - _add_apt qemu -} - - -function _c4_gather_compilers() -{ - cxx=$1 - case $cxx in - g++-12 ) _c4_addgcc 12 ;; - g++-11 ) _c4_addgcc 11 ;; - g++-10 ) _c4_addgcc 10 ;; - g++-9 ) _c4_addgcc 9 ;; - g++-8 ) _c4_addgcc 8 ;; - g++-7 ) _c4_addgcc 7 ;; - g++-6 ) _c4_addgcc 6 ;; - g++-5 ) _c4_addgcc 5 ;; - #g++-4.9 ) _c4_addgcc 4.9 ;; # https://askubuntu.com/questions/1036108/install-gcc-4-9-at-ubuntu-18-04 - g++-4.8 ) _c4_addgcc 4.8 ;; - clang++-13 ) _c4_addclang 13 ;; - clang++-12 ) _c4_addclang 12 ;; - clang++-11 ) _c4_addclang 11 ;; - clang++-10 ) _c4_addclang 10 ;; - clang++-9 ) _c4_addclang 9 ;; - clang++-8 ) _c4_addclang 8 ;; - clang++-7 ) _c4_addclang 7 ;; - clang++-6.0) _c4_addclang 6.0 ;; - clang++-5.0) _c4_addclang 5.0 ;; - clang++-4.0) _c4_addclang 4.0 ;; - clang++-3.9) _c4_addclang 3.9 ;; - all) - all="g++-11 g++-10 g++-9 g++-8 g++-7 g++-6 g++-5 clang++-12 clang++-11 clang++-10 clang++-9 clang++-8 clang++-7 clang++-6.0 clang++-5.0 clang++-4.0 clang++-3.9" - echo "installing all compilers: $all" - for cxx in $all ; do - _c4_gather_compilers $cxx - done - ;; - "") - # use default compiler - ;; - arm*) - ;; - *) - echo "unknown compiler: $cxx" - exit 1 - ;; - esac -} - -# add a gcc compiler -function _c4_addgcc() -{ - gccversion=$1 - case $gccversion in - 5 ) - _add_apt gcc-5 "deb http://dk.archive.ubuntu.com/ubuntu/ xenial main" - _add_apt gcc-5 "deb http://dk.archive.ubuntu.com/ubuntu/ xenial universe" - ;; - *) - ;; - esac - _add_apt g++-$gccversion - _add_apt g++-$gccversion-multilib - _add_apt libstdc++-$gccversion-dev - _add_apt lib32stdc++-$gccversion-dev -} - -# add a clang compiler -function _c4_addclang() -{ - clversion=$1 - case $clversion in - # in 18.04, clang9 and later require PPAs - 9 | 10 | 11 | 12 | 13) - _add_apt clang-$clversion "deb http://apt.llvm.org/$UBUNTU_RELEASE_NAME/ llvm-toolchain-$UBUNTU_RELEASE_NAME-$clversion main" - # libstdc++ is required - _c4_addgcc 11 - _c4_addgcc 10 - _c4_addgcc 9 - ;; - "") - _add_apt clang - ;; - *) - _add_apt clang-$clversion - ;; - esac - _add_apt g++-multilib # this is required for 32 bit https://askubuntu.com/questions/1057341/unable-to-find-stl-headers-in-ubuntu-18-04 - _add_apt clang-tidy-$clversion -} - -# add libc++ -function _c4_addlibcxx() -{ - _add_apt clang - _add_apt libc++1 - _add_apt libc++abi-dev - _add_apt libc++-dev - #_add_apt libc++1:i386 - #_add_apt libc++abi-dev:i386 - #_add_apt libc++-dev:i386 -} - - -#------------------------------------------------------------------------------- - -# add a pip package to the list -function _add_pip() -{ - pkgs=$* - PIP_PKG="$PIP_PKG $pkgs" - echo "adding to pip packages: $pkgs" -} - -# add a debian package to the list -function _add_apt() -{ - pkgs=$1 - sourceslist=$2 - APT_PKG="$APT_PKG $pkgs" - echo "adding to apt packages: $pkgs" - _add_src "$sourceslist" "# for packages: $pkgs" -} - -# add an apt source -function _add_src() -{ - sourceslist=$1 - comment=$2 - if [ ! -z "$sourceslist" ] ; then - echo "adding apt source: $sourceslist" - sudo bash -c "cat >> /etc/apt/sources.list < $coverage_service" - cmake --build $build_dir --config $BT --target ${PROJ_PFX_TARGET}coverage-submit-$coverage_service -} - -# WIP -function c4_run_static_analysis() -{ - if _c4skipbitlink "$1" ; then return 0 ; fi - id=$1 - linktype=$(_c4linktype $id) - build_dir=`pwd`/build/$id - # https://blog.kitware.com/static-checks-with-cmake-cdash-iwyu-clang-tidy-lwyu-cpplint-and-cppcheck/ - pushd $PROJ_DIR -} - -function c4_cfg_test() -{ - if _c4skipbitlink "$1" ; then return 0 ; fi - id=$1 - # - build_dir=`pwd`/build/$id - install_dir=`pwd`/install/$id - mkdir -p $build_dir - mkdir -p $install_dir - # - if [ "$TOOLCHAIN" != "" ] ; then - toolchain_file=`pwd`/$TOOLCHAIN - if [ ! -f "$toolchain_file" ] ; then - echo "ERROR: toolchain not found: $toolchain_file" - exit 1 - fi - _addcmkflags -DCMAKE_TOOLCHAIN_FILE=$toolchain_file - else - bits=$(_c4bits $id) - linktype=$(_c4linktype $id) - case "$linktype" in - static) _addcmkflags -DBUILD_SHARED_LIBS=OFF ;; - shared) _addcmkflags -DBUILD_SHARED_LIBS=ON ;; - *) - echo "ERROR: unknown linktype: $linktype" - exit 1 - ;; - esac - fi - if [ "$STD" != "" ] ; then - _addcmkflags -DC4_CXX_STANDARD=$STD - _addprojflags CXX_STANDARD=$STD - fi - if [ "$LIBCXX" != "" ] ; then - _addprojflags USE_LIBCXX=$LIBCXX - fi - # - if [ "$DEV" != "OFF" ] ; then - _addprojflags DEV=ON - fi - case "$LINT" in - all ) _addprojflags LINT=ON LINT_TESTS=ON LINT_CLANG_TIDY=ON LINT_PVS_STUDIO=ON ;; - clang-tidy) _addprojflags LINT=ON LINT_TESTS=ON LINT_CLANG_TIDY=ON LINT_PVS_STUDIO=OFF ;; - pvs-studio) _addprojflags LINT=ON LINT_TESTS=ON LINT_CLANG_TIDY=OFF LINT_PVS_STUDIO=ON ;; - * ) _addprojflags LINT=OFF ;; - esac - case "$SAN" in - ALL) _addprojflags SANITIZE=ON ;; - A ) _addprojflags SANITIZE=ON ASAN=ON TSAN=OFF MSAN=OFF UBSAN=OFF ;; - T ) _addprojflags SANITIZE=ON ASAN=OFF TSAN=ON MSAN=OFF UBSAN=OFF ;; - M ) _addprojflags SANITIZE=ON ASAN=OFF TSAN=OFF MSAN=ON UBSAN=OFF ;; - UB ) _addprojflags SANITIZE=ON ASAN=OFF TSAN=OFF MSAN=OFF UBSAN=ON ;; - * ) _addprojflags SANITIZE=OFF ;; - esac - case "$SAN_ONLY" in - ON) _addprojflags SANITIZE_ONLY=ON ;; - * ) _addprojflags SANITIZE_ONLY=OFF ;; - esac - case "$VG" in - ON) _addprojflags VALGRIND=ON VALGRIND_SGCHECK=OFF ;; # FIXME SGCHECK should be ON - * ) _addprojflags VALGRIND=OFF VALGRIND_SGCHECK=OFF ;; - esac - case "$BM" in - ON) _addprojflags BUILD_BENCHMARKS=ON ;; - * ) _addprojflags BUILD_BENCHMARKS=OFF ;; - esac - if [ "$BT" == "Coverage" ] ; then - # the coverage repo tokens can be set in the travis environment: - # export CODECOV_TOKEN=....... - # export COVERALLS_REPO_TOKEN=....... - _addprojflags COVERAGE_CODECOV=ON COVERAGE_CODECOV_SILENT=OFF - _addprojflags COVERAGE_COVERALLS=ON COVERAGE_COVERALLS_SILENT=OFF - fi - if [ ! -z "$VERBOSE_MAKEFILES" ] ; then - _addcmkflags -DCMAKE_VERBOSE_MAKEFILES=$VERBOSE_MAKEFILES - fi - _addcmkflags -DCMAKE_EXPORT_COMPILE_COMMANDS=ON - if [ ! -z "$CMAKE_FLAGS" ] ; then - _addcmkflags $CMAKE_FLAGS - fi - - echo "building with additional cmake flags: $CMFLAGS" - - export C4_EXTERN_DIR=`pwd`/build/extern - mkdir -p $C4_EXTERN_DIR - - cmake --version - pwd - - # - # bash quote handling is a fiasco, and I could not find a way of storing - # quoted strings in variables and then expand the variables with correct quotes - # so we have to do this precious jewell of chicanery: - case "$CXX_" in - vs2022) - cmake -S $PROJ_DIR -B $build_dir -DCMAKE_INSTALL_PREFIX="$install_dir" \ - -G 'Visual Studio 17 2022' -A $(_c4vsarchtype $id) \ - $(_c4_add_ehsc_to_vs_arm32 $id) \ - -DCMAKE_BUILD_TYPE=$BT $CMFLAGS - ;; - vs2019) - cmake -S $PROJ_DIR -B $build_dir -DCMAKE_INSTALL_PREFIX="$install_dir" \ - -G 'Visual Studio 16 2019' -A $(_c4vsarchtype $id) \ - $(_c4_add_ehsc_to_vs_arm32 $id) \ - -DCMAKE_BUILD_TYPE=$BT $CMFLAGS - ;; - vs2017) - case "$bits" in - 64) g="Visual Studio 15 2017 Win64" ;; - 32) g="Visual Studio 15 2017" ;; - *) exit 1 ;; - esac - cmake -S $PROJ_DIR -B $build_dir -DCMAKE_INSTALL_PREFIX="$install_dir" \ - $(_c4_add_ehsc_to_vs_arm32 $id) \ - -DCMAKE_BUILD_TYPE=$BT -G "$g" $CMFLAGS - ;; - xcode) - g=Xcode - case "$bits" in - 64) a="x86_64" ;; - 32) a="i386" - echo "xcode does not support i386" - exit 1 # i386 is deprecated in xcode - ;; - esac - cmake -S $PROJ_DIR -B $build_dir -DCMAKE_INSTALL_PREFIX="$install_dir" \ - -DCMAKE_BUILD_TYPE=$BT -G "$g" -DCMAKE_OSX_ARCHITECTURES=$a $CMFLAGS - ;; - arm*|"") # make sure arm* comes before *g++ or *gcc* - cmake -S $PROJ_DIR -B $build_dir -DCMAKE_INSTALL_PREFIX="$install_dir" \ - -DCMAKE_BUILD_TYPE=$BT $CMFLAGS - ;; - *g++*|*gcc*|*clang*) - export CC_=$(echo "$CXX_" | sed 's:clang++:clang:g' | sed 's:g++:gcc:g') - _c4_choose_clang_tidy $CXX_ - cmake -S $PROJ_DIR -B $build_dir -DCMAKE_INSTALL_PREFIX="$install_dir" \ - -DCMAKE_BUILD_TYPE=$BT $CMFLAGS \ - -DCMAKE_C_COMPILER=$CC_ -DCMAKE_CXX_COMPILER=$CXX_ \ - -DCMAKE_C_FLAGS="-std=c99 -m$bits" -DCMAKE_CXX_FLAGS="-m$bits" - cmake --build $build_dir --target help | sed 1d | sort - ;; - em++) - emcmake cmake -S $PROJ_DIR -B $build_dir -DCMAKE_INSTALL_PREFIX="$install_dir" \ - -DCMAKE_BUILD_TYPE=$BT $CMFLAGS -DCMAKE_CXX_FLAGS="-s DISABLE_EXCEPTION_CATCHING=0" - ;; - *) - echo "unknown compiler" - exit 1 - ;; - esac -} - -function _c4_choose_clang_tidy() -{ - cxx=$1 - # only for clang compilers. - case $cxx in - clang*) - # try with version first - clang_tidy_ver=$(echo $cxx | sed "s:++:-tidy:") - clang_tidy=$(echo $cxx | sed "s:++.*:-tidy:") - for n in $clang_tidy_ver $clang_tidy ; do - exe=$(which $n) - echo "searching for $n: $exe" - if [ -z "$exe" ] ; then - echo "could not find $clang_tidy" - else - _addcmkflags "-DCLANG_TIDY=$exe" - return 0 - fi - done - echo "error: could not find clang-tidy for $cxx" - exit 1 - ;; - esac -} - -# add cmake flags without project prefix -function _addcmkflags() -{ - for f in $* ; do - CMFLAGS="$CMFLAGS ${f}" - done -} - -# add cmake flags with project prefix -function _addprojflags() -{ - for f in $* ; do - CMFLAGS="$CMFLAGS -D${PROJ_PFX_CMAKE}${f}" - done -} - -function _c4_add_ehsc_to_vs_arm32() -{ - id=$1 - case "$CXX_" in - vs*) - case "$id" in - arm32|arm32shared|arm32static|shared32arm|static32arm|arm) - echo '-DCMAKE_CXX_FLAGS="/EHsc"' - ;; - *) - esac - ;; - esac -} - -function _c4_parallel_build_flags() -{ - case "$CXX_" in - vs2022|vs2019|vs2017|vs2015) - # https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild-command-line-reference?view=vs-2019 - # https://stackoverflow.com/questions/2619198/how-to-get-number-of-cores-in-win32 - if [ -z "$NUM_JOBS_BUILD" ] ; then - echo "/maxcpucount:$NUMBER_OF_PROCESSORS" - else - echo "/maxcpucount:$NUM_JOBS_BUILD" - fi - ;; - xcode) - # https://stackoverflow.com/questions/5417835/how-to-modify-the-number-of-parallel-compilation-with-xcode - # https://gist.github.com/nlutsenko/ee245fbd239087d22137 - if [ -z "$NUM_JOBS_BUILD" ] ; then - echo "-IDEBuildOperationMaxNumberOfConcurrentCompileTasks=$(sysctl -n hw.ncpu)" - else - echo "-IDEBuildOperationMaxNumberOfConcurrentCompileTasks=$NUM_JOBS_BUILD" - fi - ;; - *g++*|*gcc*|*clang*|em++) - if [ -z "$NUM_JOBS_BUILD" ] ; then - echo "-j $(nproc)" - else - echo "-j $NUM_JOBS_BUILD" - fi - ;; - "") # allow empty compiler - ;; - *) - echo "unknown compiler" - exit 1 - ;; - esac -} - -function _c4_generator_build_flags() -{ - case "$CXX_" in - vs2022|vs2019|vs2017|vs2015) - ;; - xcode) - # WTF??? - # https://github.com/biojppm/rapidyaml/pull/97/checks?check_run_id=1504677928#step:7:964 - # https://stackoverflow.com/questions/51153525/xcode-10-unable-to-attach-db-error - echo "-UseModernBuildSystem=NO" - ;; - *g++*|*gcc*|*clang*|em++) - ;; - "") # allow empty compiler - ;; - *) - echo "unknown compiler" - exit 1 - ;; - esac -} diff --git a/thirdparty/ryml/ext/c4core/.github/vagrant/Vagrantfile b/thirdparty/ryml/ext/c4core/.github/vagrant/Vagrantfile deleted file mode 100644 index 6f3d9d237..000000000 --- a/thirdparty/ryml/ext/c4core/.github/vagrant/Vagrantfile +++ /dev/null @@ -1,80 +0,0 @@ -# -*- mode: ruby -*- -# vi: set ft=ruby : - -# 1) download and install vagrant: https://www.vagrantup.com/downloads.html -# (do not install ubuntu's 14.04 16.04 version, see https://stackoverflow.com/questions/22717428/vagrant-error-failed-to-mount-folders-in-linux-guest ): -# 2) vagrant plugin install vagrant-vbguest -# 3) vagrant up --provider virtualbox -# 4) vagrant ssh - -# All Vagrant configuration is done below. The "2" in Vagrant.configure -# configures the configuration version (we support older styles for -# backwards compatibility). Please don't change it unless you know what -# you're doing. -Vagrant.configure(2) do |config| - # The most common configuration options are documented and commented below. - # For a complete reference, please see the online documentation at - # https://docs.vagrantup.com. - - # Every Vagrant development environment requires a box. You can search for - # boxes at https://atlas.hashicorp.com/search. - config.vm.box = "generic/ubuntu2004" - - # Disable automatic box update checking. If you disable this, then - # boxes will only be checked for updates when the user runs - # `vagrant box outdated`. This is not recommended. - # config.vm.box_check_update = false - - # Create a forwarded port mapping which allows access to a specific port - # within the machine from a port on the host machine. In the example below, - # accessing "localhost:8080" will access port 80 on the guest machine. - # config.vm.network "forwarded_port", guest: 80, host: 8080 - - #config.ssh.username = 'travis' - #config.ssh.password = 'travis' - - # Create a private network, which allows host-only access to the machine - # using a specific IP. - # config.vm.network "private_network", ip: "192.168.33.10" - - # Create a public network, which generally matched to bridged network. - # Bridged networks make the machine appear as another physical device on - # your network. - # config.vm.network "public_network" - - # Share an additional folder to the guest VM. The first argument is - # the path on the host to the actual folder. The second argument is - # the path on the guest to mount the folder. And the optional third - # argument is a set of non-required options. - config.vm.synced_folder "../../../..", "/vagrant" - - #config.vm.synced_folder '.', '/vagrant', disabled: true - - # Provider-specific configuration so you can fine-tune various - # backing providers for Vagrant. These expose provider-specific options. - # Example for VirtualBox: - # - # config.vm.provider "virtualbox" do |vb| - # # Display the VirtualBox GUI when booting the machine - # vb.gui = true - # - # # Customize the amount of memory on the VM: - # vb.memory = "1024" - # end - # - # View the documentation for the provider you are using for more - # information on available options. - - # Define a Vagrant Push strategy for pushing to Atlas. Other push strategies - # such as FTP and Heroku are also available. See the documentation at - # https://docs.vagrantup.com/v2/push/atlas.html for more information. - # config.push.define "atlas" do |push| - # push.app = "YOUR_ATLAS_USERNAME/YOUR_APPLICATION_NAME" - # end - - # Enable provisioning with a shell script. Additional provisioners such as - # Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the - # documentation for more information about their specific syntax and use. - #config.vm.provision "shell", path: "travis-install.sh" - -end diff --git a/thirdparty/ryml/ext/c4core/.github/vagrant/macos/Vagrantfile b/thirdparty/ryml/ext/c4core/.github/vagrant/macos/Vagrantfile deleted file mode 100644 index 62806c970..000000000 --- a/thirdparty/ryml/ext/c4core/.github/vagrant/macos/Vagrantfile +++ /dev/null @@ -1,71 +0,0 @@ -# -*- mode: ruby -*- -# vi: set ft=ruby : - -# All Vagrant configuration is done below. The "2" in Vagrant.configure -# configures the configuration version (we support older styles for -# backwards compatibility). Please don't change it unless you know what -# you're doing. -Vagrant.configure("2") do |config| - # The most common configuration options are documented and commented below. - # For a complete reference, please see the online documentation at - # https://docs.vagrantup.com. - - # Every Vagrant development environment requires a box. You can search for - # boxes at https://vagrantcloud.com/search. - config.vm.box = "ramsey/macos-catalina" - config.vm.box_version = "1.0.0" - - # Disable automatic box update checking. If you disable this, then - # boxes will only be checked for updates when the user runs - # `vagrant box outdated`. This is not recommended. - # config.vm.box_check_update = false - - # Create a forwarded port mapping which allows access to a specific port - # within the machine from a port on the host machine. In the example below, - # accessing "localhost:8080" will access port 80 on the guest machine. - # NOTE: This will enable public access to the opened port - # config.vm.network "forwarded_port", guest: 80, host: 8080 - - # Create a forwarded port mapping which allows access to a specific port - # within the machine from a port on the host machine and only allow access - # via 127.0.0.1 to disable public access - # config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1" - - # Create a private network, which allows host-only access to the machine - # using a specific IP. - # config.vm.network "private_network", ip: "192.168.33.10" - - # Create a public network, which generally matched to bridged network. - # Bridged networks make the machine appear as another physical device on - # your network. - # config.vm.network "public_network" - - # Share an additional folder to the guest VM. The first argument is - # the path on the host to the actual folder. The second argument is - # the path on the guest to mount the folder. And the optional third - # argument is a set of non-required options. - # config.vm.synced_folder "../data", "/vagrant_data" - - # Provider-specific configuration so you can fine-tune various - # backing providers for Vagrant. These expose provider-specific options. - # Example for VirtualBox: - # - # config.vm.provider "virtualbox" do |vb| - # # Display the VirtualBox GUI when booting the machine - # vb.gui = true - # - # # Customize the amount of memory on the VM: - # vb.memory = "1024" - # end - # - # View the documentation for the provider you are using for more - # information on available options. - - # Enable provisioning with a shell script. Additional provisioners such as - # Ansible, Chef, Docker, Puppet and Salt are also available. Please see the - # documentation for more information about their specific syntax and use. - # config.vm.provision "shell", inline: <<-SHELL - # apt-get update - # apt-get install -y apache2 - # SHELL -end diff --git a/thirdparty/ryml/ext/c4core/.github/vagrant/vagrant-provision.sh b/thirdparty/ryml/ext/c4core/.github/vagrant/vagrant-provision.sh deleted file mode 100755 index efa958738..000000000 --- a/thirdparty/ryml/ext/c4core/.github/vagrant/vagrant-provision.sh +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env bash - -set -x - -# https://askubuntu.com/questions/735201/installing-clang-3-8-on-ubuntu-14-04-3 -wget -O - http://llvm.org/apt/llvm-snapshot.gpg.key | sudo apt-key add - - -done=$(grep C4STL /etc/apt/sources.list) -if [ -z "$done" ] ; then - cat >> /etc/apt/sources.list </dev/null | gpg --dearmor - | tee /usr/share/keyrings/kitware-archive-keyring.gpg >/dev/null - echo 'deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ focal main' | tee /etc/apt/sources.list.d/kitware.list >/dev/null - apt-get update -y - rm /usr/share/keyrings/kitware-archive-keyring.gpg - apt-get install kitware-archive-keyring - apt-get update -y - fi - apt-get install -y cmake cmake-data - cmake --version - run: | - set -x - uname -a - pwd - ls -lFhp . - # - bdir=build_${{matrix.arch}}_${{matrix.bt}}_${{matrix.std}} - idir=install_${{matrix.arch}}_${{matrix.bt}}_${{matrix.std}} - mkdir -p $bdir - # - cmake -S . -B $bdir \ - -DCMAKE_INSTALL_PREFIX=$idir \ - -DCMAKE_BUILD_TYPE=${{matrix.bt}} \ - -DC4_CXX_STANDARD=${{matrix.std}} \ - -DCXX_STANDARD=${{matrix.std}} \ - -DC4CORE_DEV=ON \ - -DC4CORE_BUILD_BENCHMARKS=OFF \ - -DC4CORE_SANITIZE=OFF \ - -DC4CORE_LINT=OFF \ - -DC4CORE_VALGRIND=OFF - # - cmake --build $bdir -j --target c4core-test-build - # - cmake --build $bdir --target c4core-test-run diff --git a/thirdparty/ryml/ext/c4core/.github/workflows/benchmarks.yml b/thirdparty/ryml/ext/c4core/.github/workflows/benchmarks.yml deleted file mode 100644 index acc7dd630..000000000 --- a/thirdparty/ryml/ext/c4core/.github/workflows/benchmarks.yml +++ /dev/null @@ -1,250 +0,0 @@ -name: benchmarks - -defaults: - run: - # Use a bash shell so we can use the same syntax for environment variable - # access regardless of the host operating system - shell: bash -e -x {0} - -on: - # https://github.community/t/how-to-trigger-an-action-on-push-or-pull-request-but-not-both/16662 - workflow_dispatch: - push: - branches: - - master - pull_request: - branches: - - master - -env: - PROJ_PFX_TARGET: c4core- - PROJ_PFX_CMAKE: C4CORE_ - CMAKE_FLAGS: - NUM_JOBS_BUILD: # 4 - - -jobs: - - gettag: - runs-on: ubuntu-latest - steps: - # use fetch-depth to ensure all tags are fetched - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive, fetch-depth: 0}} - - name: Variables (from tag) - if: contains(github.ref, 'tags/v') - run: | - # https://github.community/t/how-to-get-just-the-tag-name/16241/11 - SRC_TAG=${GITHUB_REF#refs/tags/} - SRC_VERSION=${GITHUB_REF#refs/tags/v} - cat < vars.sh - export SRC_TAG=$SRC_TAG - export SRC_VERSION=$SRC_VERSION - EOF - - name: Variables (from commit, no tag) - if: ${{ !contains(github.ref, 'tags/v') }} - run: | - set -x - branch_name=${GITHUB_REF#refs/heads/} - # builds triggered from PRs have the branch_name like this: refs/pull/150/merge - # so filter to eg pr0150_merge - branch_name=`echo $branch_name | sed "s:refs/pull/\([0-9]*\)/\(.*\):pr0\1_\2:"` - # sanitize the branch name; eg merge/foo-bar -> merge_foo_bar - branch_name=`echo $branch_name | sed 's:[/.-]:_:g'` - git config --global --add safe.directory $(pwd) - SRC_TAG=$(git describe || git rev-parse --short HEAD) # eg v0.2.0-110-gda837e0 - SRC_VERSION="${branch_name}-${SRC_TAG}" - cat < vars.sh - export SRC_TAG=$SRC_TAG - export SRC_VERSION=$SRC_VERSION - EOF - - name: Verify vars.sh - run: cat vars.sh ; source vars.sh ; echo $SRC_TAG ; echo $SRC_VERSION - - name: Save vars.sh - uses: actions/upload-artifact@v3 - with: {name: vars.sh, path: ./vars.sh} - - bm_x86_64: - name: bm/x86_64/c++${{matrix.std}}/${{matrix.cxx}}/${{matrix.bt}} - needs: gettag - if: | - (!contains(github.event.head_commit.message, 'skip all')) || - (!contains(github.event.head_commit.message, 'skip benchmarks')) || - contains(github.event.head_commit.message, 'only benchmarks') - continue-on-error: true - runs-on: ${{matrix.os}} - strategy: - fail-fast: false - matrix: - include: - - {std: 17, cxx: g++-10, bt: Release, os: ubuntu-20.04, bitlinks: static64 static32} - - {std: 20, cxx: g++-10, bt: Release, os: ubuntu-20.04, bitlinks: static64 static32} - # - - {std: 17, cxx: vs2019, bt: Release, os: windows-2019, bitlinks: static64 static32} - - {std: 20, cxx: vs2019, bt: Release, os: windows-2019, bitlinks: static64 static32} - - {std: 17, cxx: vs2022, bt: Release, os: windows-2022, bitlinks: static64 static32} - - {std: 20, cxx: vs2022, bt: Release, os: windows-2022, bitlinks: static64 static32} - # - - {std: 17, cxx: xcode, xcver: 13, bt: Release, os: macos-11, bitlinks: static64} - env: {BM: ON, STD: "${{matrix.std}}", CXX_: "${{matrix.cxx}}", BT: "${{matrix.bt}}", BITLINKS: "${{matrix.bitlinks}}", VG: "${{matrix.vg}}", SAN: "${{matrix.san}}", LINT: "${{matrix.lint}}", OS: "${{matrix.os}}"} - steps: - # use fetch-depth to ensure all tags are fetched - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive, fetch-depth: 0}} - - {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS} - - name: Download vars.sh - uses: actions/download-artifact@v3 - with: {name: vars.sh, path: ./} - - {name: show info, run: source .github/setenv.sh && c4_show_info} - - name: Install python 3.10 for plotting - uses: actions/setup-python@v4 - with: { python-version: '3.10' } - - name: install benchmark plotting dependencies - run: | - which python - which pip - python --version - pip --version - pip install -v -r cmake/bm-xp/requirements.txt - python -c 'import munch ; print("ok!") ; exit(0)' - echo $? - - name: shared64-configure--------------------------------------------------- - run: export CMAKE_FLAGS="-DPython_EXECUTABLE=$(which python)" && source .github/setenv.sh && c4_cfg_test shared64 - - {name: shared64-build, run: source .github/setenv.sh && c4_build_target shared64 c4core-bm-build} - - {name: shared64-run, run: export NUM_JOBS_BUILD=1 && source .github/setenv.sh && c4_run_target shared64 c4core-bm-run} - - {name: shared64-plot, run: export NUM_JOBS_BUILD=1 && source .github/setenv.sh && c4_run_target shared64 c4core-bm-plot} - - name: static64-configure--------------------------------------------------- - run: export CMAKE_FLAGS="-DPython_EXECUTABLE=$(which python)" && source .github/setenv.sh && c4_cfg_test static64 - - {name: static64-build, run: source .github/setenv.sh && c4_build_target static64 c4core-bm-build} - - {name: static64-run, run: export NUM_JOBS_BUILD=1 && source .github/setenv.sh && c4_run_target static64 c4core-bm-run} - - {name: static64-plot, run: export NUM_JOBS_BUILD=1 && source .github/setenv.sh && c4_run_target static64 c4core-bm-plot} - - name: static32-configure--------------------------------------------------- - run: export CMAKE_FLAGS="-DPython_EXECUTABLE=$(which python)" && source .github/setenv.sh && c4_cfg_test static32 - - {name: static32-build, run: source .github/setenv.sh && c4_build_target static32 c4core-bm-build} - - {name: static32-run, run: export NUM_JOBS_BUILD=1 && source .github/setenv.sh && c4_run_target static32 c4core-bm-run} - - {name: static32-plot, run: export NUM_JOBS_BUILD=1 && source .github/setenv.sh && c4_run_target static32 c4core-bm-plot} - - name: shared32-configure--------------------------------------------------- - run: export CMAKE_FLAGS="-DPython_EXECUTABLE=$(which python)" && source .github/setenv.sh && c4_cfg_test shared32 - - {name: shared32-build, run: source .github/setenv.sh && c4_build_target shared32 c4core-bm-build} - - {name: shared32-run, run: export NUM_JOBS_BUILD=1 && source .github/setenv.sh && c4_run_target shared32 c4core-bm-run} - - {name: shared32-plot, run: export NUM_JOBS_BUILD=1 && source .github/setenv.sh && c4_run_target shared32 c4core-bm-plot} - - name: gather benchmark results - run: | - set -x - source vars.sh - echo SRC_TAG=$SRC_TAG - echo SRC_VERSION=$SRC_VERSION - desc=$SRC_TAG - for bl in ${{matrix.bitlinks}} ; do - dst=$(echo benchmark_results/$desc/x86_64/${{matrix.cxx}}-${{matrix.bt}}-c++${{matrix.std}}-$bl | sed 's:++-:xx:g' | sed 's:+:x:g') - mkdir -p $dst - find build -name bm-results - mv -vf build/$bl/bm/bm-results/* $dst/. - done - - name: upload benchmark result artifacts - uses: actions/upload-artifact@v3 - with: - name: benchmark_results - path: benchmark_results/ - - #-------------------------------------------------------------------------------------------------- - bm_rarearch: - name: bm/${{matrix.arch}}/c++${{matrix.std}}/${{matrix.bt}} - needs: gettag - if: | - (!contains(github.event.head_commit.message, 'skip all')) || - (!contains(github.event.head_commit.message, 'skip benchmarks')) || - contains(github.event.head_commit.message, 'only benchmarks') - continue-on-error: true - runs-on: ubuntu-20.04 - strategy: - fail-fast: false - matrix: - include: - - {std: 17, bt: Release, arch: aarch64, distro: ubuntu20.04} - # the python dependencies cannot be installed for this one: - #- {std: 17, bt: Release, arch: ppc64le, distro: ubuntu20.04} - # - # the github runners are failing for the following: - #- {std: 11, bt: Release, arch: s390x , distro: ubuntu20.04} - #- {std: 17, bt: Release, arch: s390x , distro: ubuntu20.04} - ## - #- {std: 11, bt: Release, arch: armv6 , distro: ubuntu18.04} - #- {std: 17, bt: Release, arch: armv6 , distro: ubuntu18.04} - ## - #- {std: 11, bt: Release, arch: armv7 , distro: ubuntu18.04} - #- {std: 17, bt: Release, arch: armv7 , distro: ubuntu18.04} - steps: - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive, fetch-depth: 0}} - - name: Download vars.sh - uses: actions/download-artifact@v3 - with: {name: vars.sh, path: ./} - - name: test - uses: uraimo/run-on-arch-action@v2.3.0 - with: - arch: ${{matrix.arch}} - distro: ${{matrix.distro}} - install: | - set -x - apt-get update -y - apt-get install -y \ - git \ - build-essential - # arm platforms need an up-to-date cmake: - # https://gitlab.kitware.com/cmake/cmake/-/issues/20568 - if [ "${{matrix.arch}}" == "armv6" ] || [ "${{matrix.arch}}" == "armv7" ] ; then - apt-get install -y \ - gpg \ - wget \ - apt-transport-https - wget --no-check-certificate -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | tee /usr/share/keyrings/kitware-archive-keyring.gpg >/dev/null - echo 'deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ focal main' | tee /etc/apt/sources.list.d/kitware.list >/dev/null - apt-get update -y - rm /usr/share/keyrings/kitware-archive-keyring.gpg - apt-get install kitware-archive-keyring - apt-get update -y - fi - apt-get install -y cmake cmake-data - cmake --version - apt-get install -y python3 python3-pip - run: | - set -x - uname -a - pwd - ls -lFhp . - # - pip3 install -v -r cmake/bm-xp/requirements.txt - # - bdir=build_${{matrix.arch}}_${{matrix.bt}}_${{matrix.std}} - idir=install_${{matrix.arch}}_${{matrix.bt}}_${{matrix.std}} - mkdir -p $bdir - # - cmake -S . -B $bdir \ - -DCMAKE_INSTALL_PREFIX=$idir \ - -DCMAKE_BUILD_TYPE=${{matrix.bt}} \ - -DC4_CXX_STANDARD=${{matrix.std}} \ - -DCXX_STANDARD=${{matrix.std}} \ - -DC4CORE_DEV=ON \ - -DC4CORE_BUILD_TESTS=OFF \ - -DC4CORE_BUILD_BENCHMARKS=ON \ - -DC4CORE_SANITIZE=OFF \ - -DC4CORE_LINT=OFF \ - -DC4CORE_VALGRIND=OFF - # - cmake --build $bdir -j --target c4core-bm-build - # - cmake --build $bdir -j 1 --target c4core-bm-run - # - cmake --build $bdir -j 1 --target c4core-bm-plot - # - source vars.sh - echo SRC_TAG=$SRC_TAG - echo SRC_VERSION=$SRC_VERSION - desc=$SRC_TAG - dst=$(echo benchmark_results/$desc/${{matrix.arch}}/${{matrix.bt}}-c++${{matrix.std}} | sed 's:++-:xx:g' | sed 's:+:x:g') - mkdir -p $dst - find $bdir -name bm-results - mv -vf $bdir/bm/bm-results/* $dst/. - - name: upload benchmark result artifacts - uses: actions/upload-artifact@v3 - with: - name: benchmark_results - path: benchmark_results/ diff --git a/thirdparty/ryml/ext/c4core/.github/workflows/clang.yml b/thirdparty/ryml/ext/c4core/.github/workflows/clang.yml deleted file mode 100644 index df2194885..000000000 --- a/thirdparty/ryml/ext/c4core/.github/workflows/clang.yml +++ /dev/null @@ -1,230 +0,0 @@ -name: clang - -defaults: - #if: "!contains(github.event.head_commit.message, 'skip ci')" # SKIP - run: - # Use a bash shell so we can use the same syntax for environment variable - # access regardless of the host operating system - shell: bash -e -x {0} - -on: - # https://github.community/t/how-to-trigger-an-action-on-push-or-pull-request-but-not-both/16662 - workflow_dispatch: - push: - branches: - - master - pull_request: - branches: - - master - -env: - PROJ_PFX_TARGET: c4core- - PROJ_PFX_CMAKE: C4CORE_ - CMAKE_FLAGS: - NUM_JOBS_BUILD: # 4 - - -# ubuntu-20.04: -# # https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu2004-README.md -# gcc: 7.5.0, 8.4.0, 9.3.0, 10.2.0 -# clang: 8.0.1, 9.0.1, 10.0.0 -# ubuntu-18.04: -# # https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu1804-README.md -# gcc: 7.5.0, 8.4.0, 9.3.0, 10.1.0 -# clang: 6.0.0, 8.0.0, 9.0.0 -# macos-11.0: macOS Big Sur 11.0 -# # https://github.com/actions/virtual-environments/blob/main/images/macos/macos-11.0-Readme.md -# Xcode 12.1 11.7 -# clang/LLVM 10.0.1 -# gcc-8 gcc-9 -# macos-10.15: macOS Catalina 10.15 -# # https://github.com/actions/virtual-environments/blob/main/images/macos/macos-10.15-Readme.md -# Xcode 12.1 11.7 -# clang/LLVM 11.0.0 -# gcc-8 gcc-9 -# windows-2019: -# # https://github.com/actions/virtual-environments/blob/main/images/win/Windows2019-Readme.md -# vs2019 -# windows-2016: -# # https://github.com/actions/virtual-environments/blob/main/images/win/Windows2016-Readme.md -# vs2017 - -jobs: - - #---------------------------------------------------------------------------- - clang_canary: - name: clang_canary/${{matrix.cxx}}/c++${{matrix.std}}/${{matrix.bt}} - continue-on-error: true - if: always() # https://stackoverflow.com/questions/62045967/github-actions-is-there-a-way-to-continue-on-error-while-still-getting-correct - runs-on: ${{matrix.os}} - strategy: - fail-fast: false - matrix: - include: - - {std: 20, cxx: clang++-10 , bt: Debug , os: ubuntu-20.04, bitlinks: shared64 static32} - - {std: 20, cxx: clang++-10 , bt: Release, os: ubuntu-20.04, bitlinks: shared64 static32} - - {std: 11, cxx: clang++-6.0, bt: Debug , os: ubuntu-20.04, bitlinks: shared64 static32} - - {std: 11, cxx: clang++-6.0, bt: Release, os: ubuntu-20.04, bitlinks: shared64 static32} - env: {STD: "${{matrix.std}}", CXX_: "${{matrix.cxx}}", BT: "${{matrix.bt}}", BITLINKS: "${{matrix.bitlinks}}", VG: "${{matrix.vg}}", SAN: "${{matrix.san}}", LINT: "${{matrix.lint}}", OS: "${{matrix.os}}"} - steps: - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} - - {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS} - - {name: show info, run: source .github/setenv.sh && c4_show_info} - - name: shared64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared64 - - {name: shared64-build, run: source .github/setenv.sh && c4_build_test shared64} - - {name: shared64-run, run: source .github/setenv.sh && c4_run_test shared64} - - {name: shared64-pack, run: source .github/setenv.sh && c4_package shared64} - - name: static64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static64 - - {name: static64-build, run: source .github/setenv.sh && c4_build_test static64} - - {name: static64-run, run: source .github/setenv.sh && c4_run_test static64} - - {name: static64-pack, run: source .github/setenv.sh && c4_package static64} - - name: static32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static32 - - {name: static32-build, run: source .github/setenv.sh && c4_build_test static32} - - {name: static32-run, run: source .github/setenv.sh && c4_run_test static32} - - {name: static32-pack, run: source .github/setenv.sh && c4_package static32} - - name: shared32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared32 - - {name: shared32-build, run: source .github/setenv.sh && c4_build_test shared32} - - {name: shared32-run, run: source .github/setenv.sh && c4_run_test shared32} - - {name: shared32-pack, run: source .github/setenv.sh && c4_package shared32} - - #---------------------------------------------------------------------------- - clang_extended: - name: clang_extended/${{matrix.cxx}}/c++${{matrix.std}}/${{matrix.bt}}/vg${{matrix.vg}} - continue-on-error: true - if: always() # https://stackoverflow.com/questions/62045967/github-actions-is-there-a-way-to-continue-on-error-while-still-getting-correct - runs-on: ${{matrix.os}} - strategy: - fail-fast: false - matrix: - include: - - {std: 20, cxx: clang++-10 , bt: Debug , vg: on, os: ubuntu-18.04} - - {std: 20, cxx: clang++-10 , bt: Release, vg: on, os: ubuntu-18.04} - - {std: 11, cxx: clang++-9 , bt: Debug , vg: on, os: ubuntu-18.04} - - {std: 11, cxx: clang++-9 , bt: Release, vg: on, os: ubuntu-18.04} - - {std: 11, cxx: clang++-8 , bt: Debug , vg: on, os: ubuntu-18.04} - - {std: 11, cxx: clang++-8 , bt: Release, vg: on, os: ubuntu-18.04} - - {std: 11, cxx: clang++-7 , bt: Debug , vg: on, os: ubuntu-18.04} - - {std: 11, cxx: clang++-7 , bt: Release, vg: on, os: ubuntu-18.04} - - {std: 11, cxx: clang++-6.0, bt: Debug , vg: on, os: ubuntu-18.04} - - {std: 11, cxx: clang++-6.0, bt: Release, vg: on, os: ubuntu-18.04} - - {std: 11, cxx: clang++-5.0, bt: Debug , vg: on, os: ubuntu-18.04} - - {std: 11, cxx: clang++-5.0, bt: Release, vg: on, os: ubuntu-18.04} - - {std: 11, cxx: clang++-4.0, bt: Debug , vg: on, os: ubuntu-18.04} - - {std: 11, cxx: clang++-4.0, bt: Release, vg: on, os: ubuntu-18.04} - - {std: 11, cxx: clang++-3.9, bt: Debug , vg: on, os: ubuntu-18.04} - - {std: 11, cxx: clang++-3.9, bt: Release, vg: on, os: ubuntu-18.04} - env: {STD: "${{matrix.std}}", CXX_: "${{matrix.cxx}}", BT: "${{matrix.bt}}", BITLINKS: "${{matrix.bitlinks}}", VG: "${{matrix.vg}}", SAN: "${{matrix.san}}", LINT: "${{matrix.lint}}", OS: "${{matrix.os}}"} - steps: - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} - - {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS} - - {name: show info, run: source .github/setenv.sh && c4_show_info} - - name: shared64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared64 - - {name: shared64-build, run: source .github/setenv.sh && c4_build_test shared64} - - {name: shared64-run, run: source .github/setenv.sh && c4_run_test shared64} - - {name: shared64-pack, run: source .github/setenv.sh && c4_package shared64} - - name: static64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static64 - - {name: static64-build, run: source .github/setenv.sh && c4_build_test static64} - - {name: static64-run, run: source .github/setenv.sh && c4_run_test static64} - - {name: static64-pack, run: source .github/setenv.sh && c4_package static64} - - name: static32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static32 - - {name: static32-build, run: source .github/setenv.sh && c4_build_test static32} - - {name: static32-run, run: source .github/setenv.sh && c4_run_test static32} - - {name: static32-pack, run: source .github/setenv.sh && c4_package static32} - - name: shared32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared32 - - {name: shared32-build, run: source .github/setenv.sh && c4_build_test shared32} - - {name: shared32-run, run: source .github/setenv.sh && c4_run_test shared32} - - {name: shared32-pack, run: source .github/setenv.sh && c4_package shared32} - - #---------------------------------------------------------------------------- - clang_sanitize: - name: clang_sanitize/c++${{matrix.std}}/${{matrix.bt}}/vg${{matrix.vg}} - continue-on-error: true - if: always() # https://stackoverflow.com/questions/62045967/github-actions-is-there-a-way-to-continue-on-error-while-still-getting-correct - runs-on: ${{matrix.os}} - strategy: - fail-fast: false - matrix: - include: - # these jobs take much longer, so run only one bitlink pair per job to profit from parallelism - - {std: 11, cxx: clang++-10 , bt: Debug , vg: ON, san: ALL, bitlinks: shared64 static64, os: ubuntu-18.04} - - {std: 11, cxx: clang++-10 , bt: Debug , vg: ON, san: ALL, bitlinks: shared32 static32, os: ubuntu-18.04} - - {std: 11, cxx: clang++-10 , bt: Release, vg: ON, san: ALL, bitlinks: shared64 static64, os: ubuntu-18.04} - - {std: 11, cxx: clang++-10 , bt: Release, vg: ON, san: ALL, bitlinks: shared32 static32, os: ubuntu-18.04} - - {std: 14, cxx: clang++-10 , bt: Debug , vg: ON, san: ALL, bitlinks: shared64 static64, os: ubuntu-18.04} - - {std: 14, cxx: clang++-10 , bt: Debug , vg: ON, san: ALL, bitlinks: shared32 static32, os: ubuntu-18.04} - - {std: 14, cxx: clang++-10 , bt: Release, vg: ON, san: ALL, bitlinks: shared64 static64, os: ubuntu-18.04} - - {std: 14, cxx: clang++-10 , bt: Release, vg: ON, san: ALL, bitlinks: shared32 static32, os: ubuntu-18.04} - - {std: 17, cxx: clang++-10 , bt: Debug , vg: ON, san: ALL, bitlinks: shared64 static64, os: ubuntu-18.04} - - {std: 17, cxx: clang++-10 , bt: Debug , vg: ON, san: ALL, bitlinks: shared32 static32, os: ubuntu-18.04} - - {std: 17, cxx: clang++-10 , bt: Release, vg: ON, san: ALL, bitlinks: shared64 static64, os: ubuntu-18.04} - - {std: 17, cxx: clang++-10 , bt: Release, vg: ON, san: ALL, bitlinks: shared32 static32, os: ubuntu-18.04} - - {std: 20, cxx: clang++-10 , bt: Debug , vg: ON, san: ALL, bitlinks: shared64 static64, os: ubuntu-18.04} - - {std: 20, cxx: clang++-10 , bt: Debug , vg: ON, san: ALL, bitlinks: shared32 static32, os: ubuntu-18.04} - - {std: 20, cxx: clang++-10 , bt: Release, vg: ON, san: ALL, bitlinks: shared64 static64, os: ubuntu-18.04} - - {std: 20, cxx: clang++-10 , bt: Release, vg: ON, san: ALL, bitlinks: shared32 static32, os: ubuntu-18.04} - env: {STD: "${{matrix.std}}", CXX_: "${{matrix.cxx}}", BT: "${{matrix.bt}}", BITLINKS: "${{matrix.bitlinks}}", VG: "${{matrix.vg}}", SAN: "${{matrix.san}}", LINT: "${{matrix.lint}}", OS: "${{matrix.os}}"} - steps: - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} - - {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS} - - {name: show info, run: source .github/setenv.sh && c4_show_info} - - name: shared64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared64 - - {name: shared64-build, run: source .github/setenv.sh && c4_build_test shared64} - - {name: shared64-run, run: source .github/setenv.sh && c4_run_test shared64} - - {name: shared64-pack, run: source .github/setenv.sh && c4_package shared64} - - name: static64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static64 - - {name: static64-build, run: source .github/setenv.sh && c4_build_test static64} - - {name: static64-run, run: source .github/setenv.sh && c4_run_test static64} - - {name: static64-pack, run: source .github/setenv.sh && c4_package static64} - - name: static32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static32 - - {name: static32-build, run: source .github/setenv.sh && c4_build_test static32} - - {name: static32-run, run: source .github/setenv.sh && c4_run_test static32} - - {name: static32-pack, run: source .github/setenv.sh && c4_package static32} - - name: shared32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared32 - - {name: shared32-build, run: source .github/setenv.sh && c4_build_test shared32} - - {name: shared32-run, run: source .github/setenv.sh && c4_run_test shared32} - - {name: shared32-pack, run: source .github/setenv.sh && c4_package shared32} - - #---------------------------------------------------------------------------- -# # https://blog.kitware.com/static-checks-with-cmake-cdash-iwyu-clang-tidy-lwyu-cpplint-and-cppcheck/ -# static_analysis: -# continue-on-error: true -# if: always() # https://stackoverflow.com/questions/62045967/github-actions-is-there-a-way-to-continue-on-error-while-still-getting-correct -# runs-on: ${{matrix.os}} -# strategy: -# fail-fast: false -# matrix: -# include: -# # these jobs take much longer, so run only one bitlink pair per job to profit from parallelism -# - {std: 11, cxx: clang++-10, bt: Debug , bitlinks: shared64, os: ubuntu-18.04} -# - {std: 11, cxx: clang++-10, bt: Release, bitlinks: shared64, os: ubuntu-18.04} -# - {std: 14, cxx: clang++-10, bt: Debug , bitlinks: shared64, os: ubuntu-18.04} -# - {std: 14, cxx: clang++-10, bt: Release, bitlinks: shared64, os: ubuntu-18.04} -# - {std: 17, cxx: clang++-10, bt: Debug , bitlinks: shared64, os: ubuntu-18.04} -# - {std: 17, cxx: clang++-10, bt: Release, bitlinks: shared64, os: ubuntu-18.04} -# - {std: 20, cxx: clang++-10, bt: Debug , bitlinks: shared64, os: ubuntu-18.04} -# - {std: 20, cxx: clang++-10, bt: Release, bitlinks: shared64, os: ubuntu-18.04} -# env: {STD: "${{matrix.std}}", CXX_: "${{matrix.cxx}}", BT: "${{matrix.bt}}", BITLINKS: "${{matrix.bitlinks}}", VG: "${{matrix.vg}}", SAN: "${{matrix.san}}", LINT: "${{matrix.lint}}", OS: "${{matrix.os}}"} -# steps: -# - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} -# - {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS} -# - {name: show info, run: source .github/setenv.sh && c4_show_info} -# - name: shared64-configure--------------------------------------------------- -# run: source .github/setenv.sh && c4_cfg_test shared64 -# - {name: shared64-build, run: source .github/setenv.sh && c4_build_test shared64} -# - {name: clang-tidy, run: cmake "-DCMAKE_CXX_CLANG_TIDY=/usr/bin/clang-tidy-3.9;-checks=*" ../path/to/source} -# - {name: cppcheck, run: cmake "-DCMAKE_CXX_CPPCHECK=/usr/bin/cppcheck;--std=c++11" ../path/to/source} -# - {name: cpplint, run: cmake "-DCMAKE_CXX_CPPLINT=/usr/local/bin/cpplint;--linelength=179" ..} -# - {name: include-what-you-use, run: cmake "-DCMAKE_CXX_INCLUDE_WHAT_YOU_USE=/usr/bin/iwyu;--transitive_includes_only" ..} -# - {name: link-what-you-use, run: cmake -DCMAKE_LINK_WHAT_YOU_USE=TRUE ..} diff --git a/thirdparty/ryml/ext/c4core/.github/workflows/clang_tidy.yml b/thirdparty/ryml/ext/c4core/.github/workflows/clang_tidy.yml deleted file mode 100644 index 9d452ec4c..000000000 --- a/thirdparty/ryml/ext/c4core/.github/workflows/clang_tidy.yml +++ /dev/null @@ -1,97 +0,0 @@ -name: clang_tidy - -defaults: - #if: "!contains(github.event.head_commit.message, 'skip ci')" # SKIP - run: - # Use a bash shell so we can use the same syntax for environment variable - # access regardless of the host operating system - shell: bash -e -x {0} - -on: - # https://github.community/t/how-to-trigger-an-action-on-push-or-pull-request-but-not-both/16662 - workflow_dispatch: - push: - branches: - - master - pull_request: - branches: - - master - -env: - PROJ_PFX_TARGET: c4core- - PROJ_PFX_CMAKE: C4CORE_ - CMAKE_FLAGS: - NUM_JOBS_BUILD: # 4 - - -# ubuntu-20.04: -# # https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu2004-README.md -# gcc: 7.5.0, 8.4.0, 9.3.0, 10.2.0 -# clang: 8.0.1, 9.0.1, 10.0.0 -# ubuntu-18.04: -# # https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu1804-README.md -# gcc: 7.5.0, 8.4.0, 9.3.0, 10.1.0 -# clang: 6.0.0, 8.0.0, 9.0.0 -# macos-11.0: macOS Big Sur 11.0 -# # https://github.com/actions/virtual-environments/blob/main/images/macos/macos-11.0-Readme.md -# Xcode 12.1 11.7 -# clang/LLVM 10.0.1 -# gcc-8 gcc-9 -# macos-10.15: macOS Catalina 10.15 -# # https://github.com/actions/virtual-environments/blob/main/images/macos/macos-10.15-Readme.md -# Xcode 12.1 11.7 -# clang/LLVM 11.0.0 -# gcc-8 gcc-9 -# windows-2019: -# # https://github.com/actions/virtual-environments/blob/main/images/win/Windows2019-Readme.md -# vs2019 -# windows-2016: -# # https://github.com/actions/virtual-environments/blob/main/images/win/Windows2016-Readme.md -# vs2017 - -jobs: - - #---------------------------------------------------------------------------- - clang_tidy: - name: clang_tidy/c++${{matrix.std}}/${{matrix.bt}} - continue-on-error: true - if: always() # https://stackoverflow.com/questions/62045967/github-actions-is-there-a-way-to-continue-on-error-while-still-getting-correct - runs-on: ${{matrix.os}} - strategy: - fail-fast: false - matrix: - include: - # clang tidy takes a long time, so don't do multiple bits/linktypes - - {std: 11, cxx: clang++-9, bt: Debug , lint: clang-tidy, bitlinks: shared64, os: ubuntu-20.04} - - {std: 11, cxx: clang++-9, bt: Debug , lint: clang-tidy, bitlinks: shared32, os: ubuntu-20.04} - - {std: 11, cxx: clang++-9, bt: Debug , lint: clang-tidy, bitlinks: static64, os: ubuntu-20.04} - - {std: 11, cxx: clang++-9, bt: Debug , lint: clang-tidy, bitlinks: static32, os: ubuntu-20.04} - - {std: 11, cxx: clang++-9, bt: ReleaseWithDebInfo, lint: clang-tidy, bitlinks: shared64, os: ubuntu-20.04} - - {std: 11, cxx: clang++-9, bt: ReleaseWithDebInfo, lint: clang-tidy, bitlinks: shared32, os: ubuntu-20.04} - - {std: 11, cxx: clang++-9, bt: ReleaseWithDebInfo, lint: clang-tidy, bitlinks: static64, os: ubuntu-20.04} - - {std: 11, cxx: clang++-9, bt: ReleaseWithDebInfo, lint: clang-tidy, bitlinks: static32, os: ubuntu-20.04} - env: {STD: "${{matrix.std}}", CXX_: "${{matrix.cxx}}", BT: "${{matrix.bt}}", BITLINKS: "${{matrix.bitlinks}}", VG: "${{matrix.vg}}", SAN: "${{matrix.san}}", LINT: "${{matrix.lint}}", OS: "${{matrix.os}}"} - steps: - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} - - {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS} - - {name: show info, run: source .github/setenv.sh && c4_show_info} - - name: shared64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared64 - - {name: shared64-build, run: source .github/setenv.sh && c4_build_test shared64} - - {name: shared64-run, run: source .github/setenv.sh && c4_run_test shared64} - - {name: shared64-pack, run: source .github/setenv.sh && c4_package shared64} - - name: static64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static64 - - {name: static64-build, run: source .github/setenv.sh && c4_build_test static64} - - {name: static64-run, run: source .github/setenv.sh && c4_run_test static64} - - {name: static64-pack, run: source .github/setenv.sh && c4_package static64} - - name: static32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static32 - - {name: static32-build, run: source .github/setenv.sh && c4_build_test static32} - - {name: static32-run, run: source .github/setenv.sh && c4_run_test static32} - - {name: static32-pack, run: source .github/setenv.sh && c4_package static32} - - name: shared32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared32 - - {name: shared32-build, run: source .github/setenv.sh && c4_build_test shared32} - - {name: shared32-run, run: source .github/setenv.sh && c4_run_test shared32} - - {name: shared32-pack, run: source .github/setenv.sh && c4_package shared32} diff --git a/thirdparty/ryml/ext/c4core/.github/workflows/codeql.yml b/thirdparty/ryml/ext/c4core/.github/workflows/codeql.yml deleted file mode 100644 index ca8d78bb7..000000000 --- a/thirdparty/ryml/ext/c4core/.github/workflows/codeql.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: "CodeQL" - -on: - push: - branches: [ "master" ] - pull_request: - branches: [ "master" ] - schedule: - - cron: "59 18 * * 1" - -jobs: - analyze: - name: Analyze - runs-on: ubuntu-latest - permissions: - actions: read - contents: read - security-events: write - - strategy: - fail-fast: false - matrix: - language: [ cpp ] - - steps: - - name: Checkout - uses: actions/checkout@v3 - with: - submodules: recursive - - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: ${{ matrix.language }} - queries: +security-and-quality - - - name: Autobuild - uses: github/codeql-action/autobuild@v2 - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 - with: - category: "/language:${{ matrix.language }}" diff --git a/thirdparty/ryml/ext/c4core/.github/workflows/coverage.yml b/thirdparty/ryml/ext/c4core/.github/workflows/coverage.yml deleted file mode 100644 index 6f593de14..000000000 --- a/thirdparty/ryml/ext/c4core/.github/workflows/coverage.yml +++ /dev/null @@ -1,150 +0,0 @@ -name: coverage - -defaults: - #if: "!contains(github.event.head_commit.message, 'skip ci')" # SKIP - run: - # Use a bash shell so we can use the same syntax for environment variable - # access regardless of the host operating system - shell: bash -e -x {0} - -on: - # https://github.community/t/how-to-trigger-an-action-on-push-or-pull-request-but-not-both/16662 - workflow_dispatch: - push: - branches: - - master - pull_request: - branches: - - master - -env: - PROJ_PFX_TARGET: c4core- - PROJ_PFX_CMAKE: C4CORE_ - CMAKE_FLAGS: - NUM_JOBS_BUILD: # 4 - - -jobs: - - #---------------------------------------------------------------------------- - coverage: - name: coverage/${{matrix.name}} - # if: github.ref == 'refs/heads/master' - continue-on-error: true - if: always() # https://stackoverflow.com/questions/62045967/github-actions-is-there-a-way-to-continue-on-error-while-still-getting-correct - runs-on: ${{matrix.os}} - strategy: - fail-fast: false - matrix: - include: - - {name: c++11, std: 11, cxx: g++-9, cc: gcc-9, bt: Coverage, os: ubuntu-20.04} - - {name: c++17, std: 17, cxx: g++-9, cc: gcc-9, bt: Coverage, os: ubuntu-20.04} - #- {name: c++20, std: 20, cxx: g++-9, cc: gcc-9, bt: Coverage, os: ubuntu-20.04} - env: { - STD: "${{matrix.std}}", CXX_: "${{matrix.cxx}}", BT: "${{matrix.bt}}", BITLINKS: "${{matrix.bitlinks}}", VG: "${{matrix.vg}}", SAN: "${{matrix.san}}", LINT: "${{matrix.lint}}", OS: "${{matrix.os}}", - CODECOV_TOKEN: "${{secrets.CODECOV_TOKEN}}", - COVERALLS_REPO_TOKEN: "${{secrets.COVERALLS_REPO_TOKEN}}", - COVERALLS_PARALLEL: true, - } - steps: - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} - - {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS} - - {name: show info, run: source .github/setenv.sh && c4_show_info} - - name: static64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static64 - - {name: static64-build, run: source .github/setenv.sh && c4_build_test static64} - - {name: static64-run, run: source .github/setenv.sh && c4_build_target static64 c4core-coverage} - - name: static64-coverage-artifacts - uses: actions/upload-artifact@v3 - with: - name: coverage-static64 - path: | - build/static64/lcov/ - build/static64/coverage3-final_filtered.lcov - - {name: static64-submit-codecov, run: source .github/setenv.sh && c4_submit_coverage static64 codecov} - - {name: static64-submit-coveralls, run: source .github/setenv.sh && c4_submit_coverage static64 coveralls, - env: {COVERALLS_FLAG_NAME: "${{matrix.name}}/static64"}} - - name: static32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static32 - - {name: static32-build, run: source .github/setenv.sh && c4_build_test static32} - - {name: static32-run, run: source .github/setenv.sh && c4_build_target static32 c4core-coverage} - - name: static32-coverage-artifacts - uses: actions/upload-artifact@v3 - with: - name: coverage-static32 - path: | - build/static32/lcov/ - build/static32/coverage3-final_filtered.lcov - - {name: static32-submit-codecov, run: source .github/setenv.sh && c4_submit_coverage static32 codecov} - - {name: static32-submit-coveralls, run: source .github/setenv.sh && c4_submit_coverage static32 coveralls, - env: {COVERALLS_FLAG_NAME: "${{matrix.name}}/static32"}} - - #---------------------------------------------------------------------------- - coverage_nofastfloat: - name: coverage/${{matrix.name}} - # if: github.ref == 'refs/heads/master' - continue-on-error: true - if: always() # https://stackoverflow.com/questions/62045967/github-actions-is-there-a-way-to-continue-on-error-while-still-getting-correct - runs-on: ${{matrix.os}} - strategy: - fail-fast: false - matrix: - include: - - {name: nofastfloat/c++11, std: 11, cxx: g++-9, cc: gcc-9, bt: Coverage, os: ubuntu-20.04} - - {name: nofastfloat/c++17, std: 17, cxx: g++-9, cc: gcc-9, bt: Coverage, os: ubuntu-20.04} - env: { - STD: "${{matrix.std}}", - CXX_: "${{matrix.cxx}}", - BT: "${{matrix.bt}}", - OS: "${{matrix.os}}", - CODECOV_TOKEN: "${{secrets.CODECOV_TOKEN}}", - COVERALLS_REPO_TOKEN: "${{secrets.COVERALLS_REPO_TOKEN}}", - COVERALLS_PARALLEL: true, # https://docs.coveralls.io/parallel-build-webhook - COVERALLS_FLAG_NAME: "${{matrix.name}}", - BDIR: "build/nofastfloat-${{matrix.cxx}}-cxx${{matrix.std}}", - IDIR: "install/nofastfloat-${{matrix.cxx}}-cxx${{matrix.std}}", - } - steps: - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} - - {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS} - - {name: show info, run: source .github/setenv.sh && c4_show_info} - - name: nofastfloat-configure------------------------------------------------ - run: | - set -x - mkdir -p $BDIR - mkdir -p $IDIR - cmake -S . -B $BDIR \ - -DC4CORE_WITH_FASTFLOAT=OFF \ - -DC4_CXX_STANDARD=${{matrix.std}} \ - -DC4CORE_CXX_STANDARD=${{matrix.std}} \ - -DC4CORE_BUILD_TESTS=ON \ - -DC4CORE_VALGRIND=OFF \ - -DC4CORE_COVERAGE_CODECOV=ON \ - -DC4CORE_COVERAGE_COVERALLS=ON \ - -DCMAKE_INSTALL_PREFIX=$IDIR \ - -DCMAKE_BUILD_TYPE=Coverage \ - -DCMAKE_CXX_COMPILER=${{matrix.cxx}} \ - -DCMAKE_C_COMPILER=${{matrix.cc}} - - {name: nofastfloat-build, run: cmake --build $BDIR --config Coverage --target c4core-test-build -j} - - {name: nofastfloat-run, run: cmake --build $BDIR --config Coverage --target c4core-coverage} - - name: nofastfloat-coverage-artifacts - uses: actions/upload-artifact@v3 - with: - name: coverage-shared32 - path: | - build/nofastfloat-${{matrix.cxx}}-cxx${{matrix.std}}/lcov/ - build/nofastfloat-${{matrix.cxx}}-cxx${{matrix.std}}/coverage3-final_filtered.lcov - - {name: nofastfloat-submit-codecov, run: cmake --build $BDIR --config Coverage --target c4core-coverage-submit-codecov} - - {name: nofastfloat-submit-coveralls, run: cmake --build $BDIR --config Coverage --target c4core-coverage-submit-coveralls} - - # https://github.com/marketplace/actions/coveralls-github-action - coveralls_finish: - needs: [coverage, coverage_nofastfloat] - runs-on: ubuntu-latest - steps: - - name: coveralls-notify - continue-on-error: true - uses: coverallsapp/github-action@master - with: - github-token: ${{ secrets.github_token }} - parallel-finished: true diff --git a/thirdparty/ryml/ext/c4core/.github/workflows/emscripten.yml b/thirdparty/ryml/ext/c4core/.github/workflows/emscripten.yml deleted file mode 100644 index cabe5d293..000000000 --- a/thirdparty/ryml/ext/c4core/.github/workflows/emscripten.yml +++ /dev/null @@ -1,99 +0,0 @@ -name: emscripten - -# running in a local machine: -# /usr/lib/emscripten/emcmake cmake -DCMAKE_BUILD_TYPE=Debug -S . -B build/emscripten -DC4CORE_DEV=ON -DC4CORE_SANITIZE=OFF -DC4CORE_BUILD_BENCHMARKS=OFF -DCMAKE_CXX_FLAGS="-s DISABLE_EXCEPTION_CATCHING=0" && cmake --build build/emscripten/ -j --target c4core-test-charconv && ( cd build/emscripten/test/ && ctest --output-on-failure -R charconv ) - -defaults: - #if: "!contains(github.event.head_commit.message, 'skip ci')" # SKIP - run: - # Use a bash shell so we can use the same syntax for environment variable - # access regardless of the host operating system - shell: bash -e -x {0} - -on: - # https://github.community/t/how-to-trigger-an-action-on-push-or-pull-request-but-not-both/16662 - workflow_dispatch: - push: - branches: - - master - pull_request: - branches: - - master - -env: - PROJ_PFX_TARGET: c4core- - PROJ_PFX_CMAKE: C4CORE_ - CMAKE_FLAGS: - NUM_JOBS_BUILD: # 4 - - -# ubuntu-20.04: -# # https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu2004-README.md -# gcc: 7.5.0, 8.4.0, 9.3.0, 10.2.0 -# clang: 8.0.1, 9.0.1, 10.0.0 -# ubuntu-18.04: -# # https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu1804-README.md -# gcc: 7.5.0, 8.4.0, 9.3.0, 10.1.0 -# clang: 6.0.0, 8.0.0, 9.0.0 -# macos-11.0: macOS Big Sur 11.0 -# # https://github.com/actions/virtual-environments/blob/main/images/macos/macos-11.0-Readme.md -# Xcode 12.1 11.7 -# clang/LLVM 10.0.1 -# gcc-8 gcc-9 -# macos-10.15: macOS Catalina 10.15 -# # https://github.com/actions/virtual-environments/blob/main/images/macos/macos-10.15-Readme.md -# Xcode 12.1 11.7 -# clang/LLVM 11.0.0 -# gcc-8 gcc-9 -# windows-2019: -# # https://github.com/actions/virtual-environments/blob/main/images/win/Windows2019-Readme.md -# vs2019 -# windows-2016: -# # https://github.com/actions/virtual-environments/blob/main/images/win/Windows2016-Readme.md -# vs2017 - -jobs: - - #---------------------------------------------------------------------------- - emscripten: - name: emscripten/${{matrix.emver}}/c++${{matrix.std}}/${{matrix.bt}} - continue-on-error: true - if: always() # https://stackoverflow.com/questions/62045967/github-actions-is-there-a-way-to-continue-on-error-while-still-getting-correct - runs-on: ${{matrix.os}} - strategy: - fail-fast: false - matrix: - include: - #- {std: 11, cxx: em++, emver: 2.0.34, bt: Debug , os: ubuntu-latest, bitlinks: static32} - - {std: 11, cxx: em++, emver: 2.0.34, bt: Release, os: ubuntu-latest, bitlinks: static32} - #- {std: 20, cxx: em++, emver: 2.0.34, bt: Debug , os: ubuntu-latest, bitlinks: static32} - - {std: 20, cxx: em++, emver: 2.0.34, bt: Release, os: ubuntu-latest, bitlinks: static32} - #- {std: 11, cxx: em++, emver: 3.0.0 , bt: Debug , os: ubuntu-latest, bitlinks: static32} - - {std: 11, cxx: em++, emver: 3.0.0 , bt: Release, os: ubuntu-latest, bitlinks: static32} - #- {std: 20, cxx: em++, emver: 3.0.0 , bt: Debug , os: ubuntu-latest, bitlinks: static32} - - {std: 20, cxx: em++, emver: 3.0.0 , bt: Release, os: ubuntu-latest, bitlinks: static32} - env: - STD: "${{matrix.std}}" - CXX_: "${{matrix.cxx}}" - BT: "${{matrix.bt}}" - BITLINKS: "${{matrix.bitlinks}}" - VG: "${{matrix.vg}}" - SAN: "${{matrix.san}}" - LINT: "${{matrix.lint}}" - OS: "${{matrix.os}}" - EM_VERSION: "${{matrix.emver}}" - EM_CACHE_FOLDER: 'emsdk-cache' - steps: - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} - - name: setup emscripten cache - id: cache-system-libraries - uses: actions/cache@v3 - with: {path: "${{env.EM_CACHE_FOLDER}}", key: "${{env.EM_VERSION}}-${{runner.os}}"} - - name: setup emscripten - uses: mymindstorm/setup-emsdk@v11 - with: {version: "${{matrix.emver}}", actions-cache-folder: "${{env.EM_CACHE_FOLDER}}"} - - {name: show info, run: source .github/setenv.sh && c4_show_info} - - name: static32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static32 - - {name: static32-build, run: source .github/setenv.sh && c4_build_test static32} - - {name: static32-run, run: source .github/setenv.sh && c4_run_test static32} diff --git a/thirdparty/ryml/ext/c4core/.github/workflows/gcc.yml b/thirdparty/ryml/ext/c4core/.github/workflows/gcc.yml deleted file mode 100644 index 5398d5f22..000000000 --- a/thirdparty/ryml/ext/c4core/.github/workflows/gcc.yml +++ /dev/null @@ -1,181 +0,0 @@ -name: gcc - -defaults: - #if: "!contains(github.event.head_commit.message, 'skip ci')" # SKIP - run: - # Use a bash shell so we can use the same syntax for environment variable - # access regardless of the host operating system - shell: bash -e -x {0} - -on: - # https://github.community/t/how-to-trigger-an-action-on-push-or-pull-request-but-not-both/16662 - workflow_dispatch: - push: - branches: - - master - pull_request: - branches: - - master - -env: - PROJ_PFX_TARGET: c4core- - PROJ_PFX_CMAKE: C4CORE_ - CMAKE_FLAGS: - NUM_JOBS_BUILD: # 4 - - -# ubuntu-20.04: -# # https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu2004-README.md -# gcc: 7.5.0, 8.4.0, 9.3.0, 10.2.0 -# clang: 8.0.1, 9.0.1, 10.0.0 -# ubuntu-18.04: -# # https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu1804-README.md -# gcc: 7.5.0, 8.4.0, 9.3.0, 10.1.0 -# clang: 6.0.0, 8.0.0, 9.0.0 -# macos-11.0: macOS Big Sur 11.0 -# # https://github.com/actions/virtual-environments/blob/main/images/macos/macos-11.0-Readme.md -# Xcode 12.1 11.7 -# clang/LLVM 10.0.1 -# gcc-8 gcc-9 -# macos-10.15: macOS Catalina 10.15 -# # https://github.com/actions/virtual-environments/blob/main/images/macos/macos-10.15-Readme.md -# Xcode 12.1 11.7 -# clang/LLVM 11.0.0 -# gcc-8 gcc-9 -# windows-2019: -# # https://github.com/actions/virtual-environments/blob/main/images/win/Windows2019-Readme.md -# vs2019 -# windows-2016: -# # https://github.com/actions/virtual-environments/blob/main/images/win/Windows2016-Readme.md -# vs2017 - -jobs: - - #---------------------------------------------------------------------------- - gcc_canary: - name: gcc_canary/${{matrix.cxx}}/c++${{matrix.std}}/${{matrix.bt}} - continue-on-error: true - if: always() # https://stackoverflow.com/questions/62045967/github-actions-is-there-a-way-to-continue-on-error-while-still-getting-correct - runs-on: ${{matrix.os}} - strategy: - fail-fast: false - matrix: - include: - - {std: 11, cxx: g++-7 , bt: Debug , os: ubuntu-20.04, bitlinks: shared64 static32} - - {std: 11, cxx: g++-7 , bt: Release, os: ubuntu-20.04, bitlinks: shared64 static32} - - {std: 20, cxx: g++-10 , bt: Debug , os: ubuntu-20.04, bitlinks: shared64 static32} - - {std: 20, cxx: g++-10 , bt: Release, os: ubuntu-20.04, bitlinks: shared64 static32} - - {std: 11, cxx: g++-5 , bt: Debug , os: ubuntu-20.04, bitlinks: shared64 static32} - - {std: 11, cxx: g++-5 , bt: Release, os: ubuntu-20.04, bitlinks: shared64 static32} - - {std: 11, cxx: g++-4.8 , bt: Debug, os: ubuntu-18.04, bitlinks: shared64 static32} - - {std: 11, cxx: g++-4.8 , bt: Release, os: ubuntu-18.04, bitlinks: shared64 static32} - env: {STD: "${{matrix.std}}", CXX_: "${{matrix.cxx}}", BT: "${{matrix.bt}}", BITLINKS: "${{matrix.bitlinks}}", VG: "${{matrix.vg}}", SAN: "${{matrix.san}}", LINT: "${{matrix.lint}}", OS: "${{matrix.os}}"} - steps: - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} - - {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS} - - {name: show info, run: source .github/setenv.sh && c4_show_info} - - name: shared64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared64 - - {name: shared64-build, run: source .github/setenv.sh && c4_build_test shared64} - - {name: shared64-run, run: source .github/setenv.sh && c4_run_test shared64} - - {name: shared64-pack, run: source .github/setenv.sh && c4_package shared64} - - name: static64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static64 - - {name: static64-build, run: source .github/setenv.sh && c4_build_test static64} - - {name: static64-run, run: source .github/setenv.sh && c4_run_test static64} - - {name: static64-pack, run: source .github/setenv.sh && c4_package static64} - - name: static32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static32 - - {name: static32-build, run: source .github/setenv.sh && c4_build_test static32} - - {name: static32-run, run: source .github/setenv.sh && c4_run_test static32} - - {name: static32-pack, run: source .github/setenv.sh && c4_package static32} - - name: shared32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared32 - - {name: shared32-build, run: source .github/setenv.sh && c4_build_test shared32} - - {name: shared32-run, run: source .github/setenv.sh && c4_run_test shared32} - - {name: shared32-pack, run: source .github/setenv.sh && c4_package shared32} - - #---------------------------------------------------------------------------- - gcc_extended: - name: gcc_extended/${{matrix.cxx}}/c++${{matrix.std}}/${{matrix.bt}}/vg${{matrix.vg}} - continue-on-error: true - if: always() # https://stackoverflow.com/questions/62045967/github-actions-is-there-a-way-to-continue-on-error-while-still-getting-correct - runs-on: ${{matrix.os}} - strategy: - fail-fast: false - matrix: - include: - # VALGRIND - - {std: 11, cxx: g++-10, bt: Debug , vg: ON, os: ubuntu-20.04} - - {std: 11, cxx: g++-10, bt: Release, vg: ON, os: ubuntu-20.04} - - {std: 14, cxx: g++-10, bt: Debug , vg: ON, os: ubuntu-20.04} - - {std: 14, cxx: g++-10, bt: Release, vg: ON, os: ubuntu-20.04} - - {std: 17, cxx: g++-10, bt: Debug , vg: ON, os: ubuntu-20.04} - - {std: 17, cxx: g++-10, bt: Release, vg: ON, os: ubuntu-20.04} - - {std: 20, cxx: g++-10, bt: Debug , vg: ON, os: ubuntu-20.04} - - {std: 20, cxx: g++-10, bt: Release, vg: ON, os: ubuntu-20.04} - # - - {std: 11, cxx: g++-9, bt: Debug , os: ubuntu-20.04} - - {std: 11, cxx: g++-9, bt: Release, os: ubuntu-20.04} - - {std: 11, cxx: g++-8, bt: Debug , os: ubuntu-20.04} - - {std: 11, cxx: g++-8, bt: Release, os: ubuntu-20.04} - - {std: 11, cxx: g++-7, bt: Debug , os: ubuntu-20.04} - - {std: 11, cxx: g++-7, bt: Release, os: ubuntu-20.04} - - {std: 11, cxx: g++-6, bt: Debug , os: ubuntu-18.04} - - {std: 11, cxx: g++-6, bt: Release, os: ubuntu-18.04} - - {std: 11, cxx: g++-5, bt: Debug , os: ubuntu-18.04} - - {std: 11, cxx: g++-5, bt: Release, os: ubuntu-18.04} - - {std: 11, cxx: g++-4.8, bt: Debug, os: ubuntu-18.04} - - {std: 11, cxx: g++-4.8, bt: Release, os: ubuntu-18.04} - env: {STD: "${{matrix.std}}", CXX_: "${{matrix.cxx}}", BT: "${{matrix.bt}}", BITLINKS: "${{matrix.bitlinks}}", VG: "${{matrix.vg}}", SAN: "${{matrix.san}}", LINT: "${{matrix.lint}}", OS: "${{matrix.os}}"} - steps: - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} - - {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS} - - {name: show info, run: source .github/setenv.sh && c4_show_info} - - name: shared64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared64 - - {name: shared64-build, run: source .github/setenv.sh && c4_build_test shared64} - - {name: shared64-run, run: source .github/setenv.sh && c4_run_test shared64} - - {name: shared64-pack, run: source .github/setenv.sh && c4_package shared64} - - name: static64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static64 - - {name: static64-build, run: source .github/setenv.sh && c4_build_test static64} - - {name: static64-run, run: source .github/setenv.sh && c4_run_test static64} - - {name: static64-pack, run: source .github/setenv.sh && c4_package static64} - - name: static32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static32 - - {name: static32-build, run: source .github/setenv.sh && c4_build_test static32} - - {name: static32-run, run: source .github/setenv.sh && c4_run_test static32} - - {name: static32-pack, run: source .github/setenv.sh && c4_package static32} - - name: shared32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared32 - - {name: shared32-build, run: source .github/setenv.sh && c4_build_test shared32} - - {name: shared32-run, run: source .github/setenv.sh && c4_run_test shared32} - - {name: shared32-pack, run: source .github/setenv.sh && c4_package shared32} - - #---------------------------------------------------------------------------- - arm: - continue-on-error: true - if: always() # https://stackoverflow.com/questions/62045967/github-actions-is-there-a-way-to-continue-on-error-while-still-getting-correct - runs-on: ${{matrix.os}} - strategy: - fail-fast: false - matrix: - include: - # these jobs take much longer, so run only one bitlink pair per job to profit from parallelism - - {std: 11, bt: Debug , toolchain: cmake/Toolchain-Arm-ubuntu.cmake, cxx: arm-linux-gnueabihf-gcc, os: ubuntu-18.04} - - {std: 11, bt: Release, toolchain: cmake/Toolchain-Arm-ubuntu.cmake, cxx: arm-linux-gnueabihf-gcc, os: ubuntu-18.04} - - {std: 14, bt: Debug , toolchain: cmake/Toolchain-Arm-ubuntu.cmake, cxx: arm-linux-gnueabihf-gcc, os: ubuntu-18.04} - - {std: 14, bt: Release, toolchain: cmake/Toolchain-Arm-ubuntu.cmake, cxx: arm-linux-gnueabihf-gcc, os: ubuntu-18.04} - - {std: 17, bt: Debug , toolchain: cmake/Toolchain-Arm-ubuntu.cmake, cxx: arm-linux-gnueabihf-gcc, os: ubuntu-18.04} - - {std: 17, bt: Release, toolchain: cmake/Toolchain-Arm-ubuntu.cmake, cxx: arm-linux-gnueabihf-gcc, os: ubuntu-18.04} - env: {TOOLCHAIN: "${{matrix.toolchain}}", STD: "${{matrix.std}}", CXX_: "${{matrix.cxx}}", BT: "${{matrix.bt}}", BITLINKS: "${{matrix.bitlinks}}", VG: "${{matrix.vg}}", SAN: "${{matrix.san}}", LINT: "${{matrix.lint}}", OS: "${{matrix.os}}"} - steps: - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} - - {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS} - - {name: show info, run: source .github/setenv.sh && c4_show_info} - - name: configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test arm - - {name: build, run: source .github/setenv.sh && c4_build_test arm} - - {name: run, run: source .github/setenv.sh && c4_run_test arm} - - {name: pack, run: source .github/setenv.sh && c4_package arm} diff --git a/thirdparty/ryml/ext/c4core/.github/workflows/libcxx.yml b/thirdparty/ryml/ext/c4core/.github/workflows/libcxx.yml deleted file mode 100644 index f55fe6adc..000000000 --- a/thirdparty/ryml/ext/c4core/.github/workflows/libcxx.yml +++ /dev/null @@ -1,111 +0,0 @@ -name: libcxx - -defaults: - #if: "!contains(github.event.head_commit.message, 'skip ci')" # SKIP - run: - # Use a bash shell so we can use the same syntax for environment variable - # access regardless of the host operating system - shell: bash -e -x {0} - -on: - # https://github.community/t/how-to-trigger-an-action-on-push-or-pull-request-but-not-both/16662 - workflow_dispatch: - push: - branches: - - master - pull_request: - branches: - - master - -env: - PROJ_PFX_TARGET: c4core- - PROJ_PFX_CMAKE: C4CORE_ - CMAKE_FLAGS: - NUM_JOBS_BUILD: # 4 - - -# ubuntu-20.04: -# # https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu2004-README.md -# gcc: 7.5.0, 8.4.0, 9.3.0, 10.2.0 -# clang: 8.0.1, 9.0.1, 10.0.0 -# ubuntu-18.04: -# # https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu1804-README.md -# gcc: 7.5.0, 8.4.0, 9.3.0, 10.1.0 -# clang: 6.0.0, 8.0.0, 9.0.0 -# macos-11.0: macOS Big Sur 11.0 -# # https://github.com/actions/virtual-environments/blob/main/images/macos/macos-11.0-Readme.md -# Xcode 12.1 11.7 -# clang/LLVM 10.0.1 -# gcc-8 gcc-9 -# macos-10.15: macOS Catalina 10.15 -# # https://github.com/actions/virtual-environments/blob/main/images/macos/macos-10.15-Readme.md -# Xcode 12.1 11.7 -# clang/LLVM 11.0.0 -# gcc-8 gcc-9 -# windows-2019: -# # https://github.com/actions/virtual-environments/blob/main/images/win/Windows2019-Readme.md -# vs2019 -# windows-2016: -# # https://github.com/actions/virtual-environments/blob/main/images/win/Windows2016-Readme.md -# vs2017 - -jobs: - - #---------------------------------------------------------------------------- - libcxx: - name: libc++/${{matrix.cxx}}/c++${{matrix.std}}/${{matrix.bt}} - continue-on-error: true - if: always() # https://stackoverflow.com/questions/62045967/github-actions-is-there-a-way-to-continue-on-error-while-still-getting-correct - runs-on: ${{matrix.os}} - strategy: - fail-fast: false - matrix: - include: - - {std: 20, cxx: clang++-10 , bt: Debug , os: ubuntu-20.04, bitlinks: shared64 static64} - - {std: 20, cxx: clang++-10 , bt: Release, os: ubuntu-20.04, bitlinks: shared64 static64} - - {std: 17, cxx: clang++-10 , bt: Debug , os: ubuntu-20.04, bitlinks: shared64 static64} - - {std: 17, cxx: clang++-10 , bt: Release, os: ubuntu-20.04, bitlinks: shared64 static64} - - {std: 14, cxx: clang++-10 , bt: Debug , os: ubuntu-20.04, bitlinks: shared64 static64} - - {std: 14, cxx: clang++-10 , bt: Release, os: ubuntu-20.04, bitlinks: shared64 static64} - - {std: 11, cxx: clang++-10 , bt: Debug , os: ubuntu-20.04, bitlinks: shared64 static64} - - {std: 11, cxx: clang++-10 , bt: Release, os: ubuntu-20.04, bitlinks: shared64 static64} - - {std: 17, cxx: clang++-6.0, bt: Debug , os: ubuntu-20.04, bitlinks: shared64 static64} - - {std: 17, cxx: clang++-6.0, bt: Release, os: ubuntu-20.04, bitlinks: shared64 static64} - - {std: 14, cxx: clang++-6.0, bt: Debug , os: ubuntu-20.04, bitlinks: shared64 static64} - - {std: 14, cxx: clang++-6.0, bt: Release, os: ubuntu-20.04, bitlinks: shared64 static64} - - {std: 11, cxx: clang++-6.0, bt: Debug , os: ubuntu-20.04, bitlinks: shared64 static64} - - {std: 11, cxx: clang++-6.0, bt: Release, os: ubuntu-20.04, bitlinks: shared64 static64} - env: - LIBCXX: ON # <---- enable libc++ - STD: "${{matrix.std}}" - CXX_: "${{matrix.cxx}}" - BT: "${{matrix.bt}}" - BITLINKS: "${{matrix.bitlinks}}" - VG: "${{matrix.vg}}" - SAN: "${{matrix.san}}" - LINT: "${{matrix.lint}}" - OS: "${{matrix.os}}" - steps: - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} - - {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS} - - {name: show info, run: source .github/setenv.sh && c4_show_info} - - name: shared64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared64 - - {name: shared64-build, run: source .github/setenv.sh && c4_build_test shared64} - - {name: shared64-run, run: source .github/setenv.sh && c4_run_test shared64} - - {name: shared64-pack, run: source .github/setenv.sh && c4_package shared64} - - name: static64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static64 - - {name: static64-build, run: source .github/setenv.sh && c4_build_test static64} - - {name: static64-run, run: source .github/setenv.sh && c4_run_test static64} - - {name: static64-pack, run: source .github/setenv.sh && c4_package static64} - - name: static32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static32 - - {name: static32-build, run: source .github/setenv.sh && c4_build_test static32} - - {name: static32-run, run: source .github/setenv.sh && c4_run_test static32} - - {name: static32-pack, run: source .github/setenv.sh && c4_package static32} - - name: shared32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared32 - - {name: shared32-build, run: source .github/setenv.sh && c4_build_test shared32} - - {name: shared32-run, run: source .github/setenv.sh && c4_run_test shared32} - - {name: shared32-pack, run: source .github/setenv.sh && c4_package shared32} diff --git a/thirdparty/ryml/ext/c4core/.github/workflows/macosx.yml b/thirdparty/ryml/ext/c4core/.github/workflows/macosx.yml deleted file mode 100644 index 33145e5c7..000000000 --- a/thirdparty/ryml/ext/c4core/.github/workflows/macosx.yml +++ /dev/null @@ -1,103 +0,0 @@ -name: macosx - -defaults: - #if: "!contains(github.event.head_commit.message, 'skip ci')" # SKIP - run: - # Use a bash shell so we can use the same syntax for environment variable - # access regardless of the host operating system - shell: bash -e -x {0} - -on: - # https://github.community/t/how-to-trigger-an-action-on-push-or-pull-request-but-not-both/16662 - workflow_dispatch: - push: - branches: - - master - pull_request: - branches: - - master - -env: - PROJ_PFX_TARGET: c4core- - PROJ_PFX_CMAKE: C4CORE_ - CMAKE_FLAGS: - NUM_JOBS_BUILD: # 4 - - -# ubuntu-20.04: -# # https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu2004-README.md -# gcc: 7.5.0, 8.4.0, 9.3.0, 10.2.0 -# clang: 8.0.1, 9.0.1, 10.0.0 -# ubuntu-18.04: -# # https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu1804-README.md -# gcc: 7.5.0, 8.4.0, 9.3.0, 10.1.0 -# clang: 6.0.0, 8.0.0, 9.0.0 -# macos-11.0: macOS Big Sur 11.0 -# # https://github.com/actions/virtual-environments/blob/main/images/macos/macos-11.0-Readme.md -# Xcode 12.1 11.7 -# clang/LLVM 10.0.1 -# gcc-8 gcc-9 -# macos-10.15: macOS Catalina 10.15 -# # https://github.com/actions/virtual-environments/blob/main/images/macos/macos-10.15-Readme.md -# Xcode 12.1 11.7 -# clang/LLVM 11.0.0 -# gcc-8 gcc-9 -# windows-2019: -# # https://github.com/actions/virtual-environments/blob/main/images/win/Windows2019-Readme.md -# vs2019 -# windows-2016: -# # https://github.com/actions/virtual-environments/blob/main/images/win/Windows2016-Readme.md -# vs2017 - -jobs: - - #---------------------------------------------------------------------------- - xcode: - name: xcode${{matrix.xcver}}/c++${{matrix.std}}/${{matrix.bt}} - continue-on-error: true - if: always() # https://stackoverflow.com/questions/62045967/github-actions-is-there-a-way-to-continue-on-error-while-still-getting-correct - runs-on: ${{matrix.os}} - strategy: - fail-fast: false - matrix: - include: - - {std: 11, cxx: xcode, xcver: 13, bt: Debug , os: macos-11, bitlinks: shared64 static64} - - {std: 11, cxx: xcode, xcver: 13, bt: Release, os: macos-11, bitlinks: shared64 static64} - - {std: 17, cxx: xcode, xcver: 13, bt: Debug , os: macos-11, bitlinks: shared64 static64} - - {std: 17, cxx: xcode, xcver: 13, bt: Release, os: macos-11, bitlinks: shared64 static64} - # - - {std: 11, cxx: xcode, xcver: 12, bt: Debug , os: macos-11, bitlinks: shared64 static64} - - {std: 11, cxx: xcode, xcver: 12, bt: Release, os: macos-11, bitlinks: shared64 static64} - - {std: 17, cxx: xcode, xcver: 12, bt: Debug , os: macos-11, bitlinks: shared64 static64} - - {std: 17, cxx: xcode, xcver: 12, bt: Release, os: macos-11, bitlinks: shared64 static64} - # - - {std: 11, cxx: xcode, xcver: 11, bt: Debug , os: macos-11, bitlinks: shared64 static64} - - {std: 11, cxx: xcode, xcver: 11, bt: Release, os: macos-11, bitlinks: shared64 static64} - - {std: 17, cxx: xcode, xcver: 11, bt: Debug , os: macos-11, bitlinks: shared64 static64} - - {std: 17, cxx: xcode, xcver: 11, bt: Release, os: macos-11, bitlinks: shared64 static64} - env: {STD: "${{matrix.std}}", CXX_: "${{matrix.cxx}}", BT: "${{matrix.bt}}", BITLINKS: "${{matrix.bitlinks}}", VG: "${{matrix.vg}}", SAN: "${{matrix.san}}", LINT: "${{matrix.lint}}", OS: "${{matrix.os}}"} - steps: - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} - - {name: xcode, uses: maxim-lobanov/setup-xcode@v1, with: {xcode-version: "${{matrix.xcver}}" }} - - {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS} - - {name: show info, run: source .github/setenv.sh && c4_show_info} - - name: shared64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared64 - - {name: shared64-build, run: source .github/setenv.sh && c4_build_test shared64} - - {name: shared64-run, run: source .github/setenv.sh && c4_run_test shared64} - - {name: shared64-pack, run: source .github/setenv.sh && c4_package shared64} - - name: static64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static64 - - {name: static64-build, run: source .github/setenv.sh && c4_build_test static64} - - {name: static64-run, run: source .github/setenv.sh && c4_run_test static64} - - {name: static64-pack, run: source .github/setenv.sh && c4_package static64} - - name: shared32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared32 - - {name: shared32-build, run: source .github/setenv.sh && c4_build_test shared32} - - {name: shared32-run, run: source .github/setenv.sh && c4_run_test shared32} - - {name: shared32-pack, run: source .github/setenv.sh && c4_package shared32} - - name: static32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static32 - - {name: static32-build, run: source .github/setenv.sh && c4_build_test static32} - - {name: static32-run, run: source .github/setenv.sh && c4_run_test static32} - - {name: static32-pack, run: source .github/setenv.sh && c4_package static32} diff --git a/thirdparty/ryml/ext/c4core/.github/workflows/release.yml b/thirdparty/ryml/ext/c4core/.github/workflows/release.yml deleted file mode 100644 index 0f5a13873..000000000 --- a/thirdparty/ryml/ext/c4core/.github/workflows/release.yml +++ /dev/null @@ -1,197 +0,0 @@ -name: release - -defaults: - #if: "!contains(github.event.head_commit.message, 'skip ci')" # SKIP - run: - # Use a bash shell so we can use the same syntax for environment variable - # access regardless of the host operating system - shell: bash -e -x {0} - -on: - # https://github.community/t/how-to-trigger-an-action-on-push-or-pull-request-but-not-both/16662 - workflow_dispatch: - push: - tags: - - v0.* - - v1.* - - v2.* - branches: - - master - pull_request: - branches: - - master - -env: - PROJ_PKG_NAME: c4core- - PROJ_PFX_TARGET: c4core- - PROJ_PFX_CMAKE: C4CORE_ - CMAKE_FLAGS: - NUM_JOBS_BUILD: # 4 - - -# useful to iterate when fixing the release: -# ver=0.2.1 ; ( set -x ; git tag -d v$ver ; git push origin :v$ver ) ; (set -x ; set -e ; tbump --only-patch --non-interactive $ver ; git add -u ; git commit --amend --no-edit ; git tag --annotate --message "v$ver" "v$ver" ; git push -f --tags origin ) - -jobs: - - gettag: - runs-on: ubuntu-latest - steps: - # use fetch-depth to ensure all tags are fetched - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive, fetch-depth: 0}} - - name: Variables (from tag) - if: contains(github.ref, 'tags/v') - run: | - # https://github.community/t/how-to-get-just-the-tag-name/16241/11 - SRC_TAG=${GITHUB_REF#refs/tags/} - SRC_VERSION=${GITHUB_REF#refs/tags/v} - cat < vars.sh - export SRC_TAG=$SRC_TAG - export SRC_VERSION=$SRC_VERSION - EOF - - name: Variables (from commit, no tag) - if: ${{ !contains(github.ref, 'tags/v') }} - run: | - set -x - branch_name=${GITHUB_REF#refs/heads/} - # builds triggered from PRs have the branch_name like this: refs/pull/150/merge - # so filter to eg pr0150_merge - branch_name=`echo $branch_name | sed "s:refs/pull/\([0-9]*\)/\(.*\):pr0\1_\2:"` - # sanitize the branch name; eg merge/foo-bar -> merge_foo_bar - branch_name=`echo $branch_name | sed 's:[/.-]:_:g'` - SRC_TAG=$(git describe || git rev-parse --short HEAD) # eg v0.2.0-110-gda837e0 - SRC_VERSION="${branch_name}-${SRC_TAG}" - cat < vars.sh - export SRC_TAG=$SRC_TAG - export SRC_VERSION=$SRC_VERSION - EOF - - name: Verify vars.sh - run: cat vars.sh ; source vars.sh ; echo $SRC_TAG ; echo $SRC_VERSION - - name: Save vars.sh - uses: actions/upload-artifact@v3 - with: {name: vars.sh, path: ./vars.sh} - - #---------------------------------------------------------------------------- - # create source packages - src: - needs: gettag - runs-on: ubuntu-latest - steps: - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} - - name: Download vars.sh - uses: actions/download-artifact@v3 - with: {name: vars.sh, path: ./} - - name: Install python 3.9 - uses: actions/setup-python@v4 - with: { python-version: 3.9 } - - name: Install requirements - run: | - sudo -E pip install git-archive-all - - name: Create source packages - run: | - pwd - ls -lFhp - source vars.sh - echo SRC_TAG=$SRC_TAG - echo SRC_VERSION=$SRC_VERSION - id=${PROJ_PKG_NAME}${SRC_VERSION} - name=${id}-src - mkdir -p assets - git-archive-all --prefix $name assets/$name.tgz - git-archive-all --prefix $name assets/$name.zip - python --version - python tools/amalgamate.py assets/$id.hpp - - name: Save source artifacts - uses: actions/upload-artifact@v3 - with: {name: assets, path: assets} - - #---------------------------------------------------------------------------- - # create c++ packages - cpp: - name: cpp/${{matrix.config.os}}/${{matrix.config.gen}} - needs: gettag - runs-on: ${{matrix.config.os}} - env: {DEV: OFF, BT: Release, OS: "${{matrix.config.os}}", CXX_: "${{matrix.config.cxx}}", GEN: "${{matrix.config.gen}}"} - strategy: - fail-fast: false - matrix: - config: - # name of the artifact | suffix (gen) | suffix (package) | cpack gen | mime type | os | cxx - - {name: Ubuntu 20.04 deb , sfxg: unix64-shared-Release.deb, sfxp: ubuntu-20.04.deb , gen: DEB , mime: vnd.debian.binary-package, os: ubuntu-20.04 } - - {name: Windows VS2019 zip, sfxg: win64-shared-Release.zip , sfxp: windows-vs2019.zip , gen: ZIP , mime: zip , os: windows-2019, cxx: vs2019} - - {name: MacOSX sh , sfxg: apple64-shared-Release.sh, sfxp: macosx-xcode.sh , gen: STGZ , mime: x-sh , os: macos-11.0 , cxx: xcode } - steps: - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} - - name: Download vars.sh - uses: actions/download-artifact@v3 - with: {name: vars.sh, path: ./} - - {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS} - - {name: show info, run: source .github/setenv.sh && c4_show_info } - - name: shared64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared64 - - {name: shared64-build, run: source .github/setenv.sh && c4_build_target shared64} - - name: shared64-pack - run: source .github/setenv.sh && c4_package shared64 $GEN - - name: shared64-normalize - run: | - set -x - source vars.sh - mkdir -p assets - asset_src=`ls -1 ./build/shared64/${PROJ_PFX_TARGET}*-${{matrix.config.sfxg}}` - asset_dst=./assets/${PROJ_PKG_NAME}${SRC_VERSION}-${{matrix.config.sfxp}} - [ ! -f $asset_src ] && exit 1 - cp -fav $asset_src $asset_dst - - name: Save artifacts - uses: actions/upload-artifact@v3 - with: {name: assets, path: assets} - - #---------------------------------------------------------------------------- - release: - runs-on: ubuntu-latest - needs: - - src - - cpp - steps: - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} - - name: Gather artifacts - ./assets - uses: actions/download-artifact@v3 - with: {name: assets, path: assets} - - name: Verify existing artifacts - run: | - ls -lFhp assets/ - # - # Github - - name: Restore vars.sh - if: contains(github.ref, 'tags/v') - uses: actions/download-artifact@v3 - with: {name: vars.sh, path: ./} - - name: Save vars for following steps - if: contains(github.ref, 'tags/v') - id: vars - run: | - source vars.sh - version_body=${{github.workspace}}/changelog/$SRC_VERSION.md - if [ ! -f $version_body ] ; then - echo "version body file was not found: $version_body" - exit 1 - fi - echo "VERSION=$SRC_VERSION >> $GITHUB_OUTPUT" - echo "VERSION_BODY=$version_body >> $GITHUB_OUTPUT" - - name: Create Github Release - if: contains(github.ref, 'tags/v') - id: create_release - uses: actions/create-release@v1 - env: { GITHUB_TOKEN: "${{secrets.GITHUB_TOKEN}}" } - with: - tag_name: ${{github.ref}} - release_name: Release ${{steps.vars.outputs.VERSION}} - body_path: ${{steps.vars.outputs.VERSION_BODY}} - draft: true - prerelease: ${{contains(github.ref, 'rc')}} - - name: Upload assets to Github Release - if: contains(github.ref, 'tags/v') - uses: dwenegar/upload-release-assets@v1 - env: { GITHUB_TOKEN: "${{secrets.GITHUB_TOKEN}}" } - with: - release_id: ${{steps.create_release.outputs.id}} - assets_path: ./assets/ diff --git a/thirdparty/ryml/ext/c4core/.github/workflows/test_install.yml b/thirdparty/ryml/ext/c4core/.github/workflows/test_install.yml deleted file mode 100644 index 7f28e7578..000000000 --- a/thirdparty/ryml/ext/c4core/.github/workflows/test_install.yml +++ /dev/null @@ -1,104 +0,0 @@ -name: test_install - -defaults: - #if: "!contains(github.event.head_commit.message, 'skip ci')" # SKIP - run: - # Use a bash shell so we can use the same syntax for environment variable - # access regardless of the host operating system - shell: bash -e -x {0} - -on: - # https://github.community/t/how-to-trigger-an-action-on-push-or-pull-request-but-not-both/16662 - workflow_dispatch: - push: - branches: - - master - pull_request: - branches: - - master - -env: - PROJ_PFX_TARGET: c4core- - PROJ_PFX_CMAKE: C4CORE_ - CMAKE_FLAGS: - NUM_JOBS_BUILD: # 4 - -jobs: - - #---------------------------------------------------------------------------- - install_tests: - name: ${{matrix.name}}/${{matrix.bt}} - # if: github.ref == 'refs/heads/master' - continue-on-error: true - if: always() # https://stackoverflow.com/questions/62045967/github-actions-is-there-a-way-to-continue-on-error-while-still-getting-correct - runs-on: ${{matrix.os}} - strategy: - fail-fast: false - matrix: - include: - - {name: find_package/linux , sdir: test/test_install , os: ubuntu-20.04, cxx: g++-10 , gen: "-DCMAKE_CXX_COMPILER=g++-10" , tgt: all , bt: Release, vars: "-Dc4core_DIR=$GITHUB_WORKSPACE/$PDIR/lib/cmake/c4core -DC4CORE_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: } - - {name: find_package/linux , sdir: test/test_install , os: ubuntu-20.04, cxx: g++-10 , gen: "-DCMAKE_CXX_COMPILER=g++-10" , tgt: all , bt: Debug , vars: "-Dc4core_DIR=$GITHUB_WORKSPACE/$PDIR/lib/cmake/c4core -DC4CORE_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: } - - {name: find_package/linux/libcxx, sdir: test/test_install , os: ubuntu-20.04, cxx: clang++-9, gen: "-DCMAKE_CXX_COMPILER=clang++-9" , tgt: all , bt: Release, vars: "-Dc4core_DIR=$GITHUB_WORKSPACE/$PDIR/lib/cmake/c4core -DC4CORE_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: "-DC4CORE_USE_LIBCXX=ON"} - - {name: find_package/linux/libcxx, sdir: test/test_install , os: ubuntu-20.04, cxx: clang++-9, gen: "-DCMAKE_CXX_COMPILER=clang++-9" , tgt: all , bt: Debug , vars: "-Dc4core_DIR=$GITHUB_WORKSPACE/$PDIR/lib/cmake/c4core -DC4CORE_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: "-DC4CORE_USE_LIBCXX=ON"} - - {name: find_package/macos , sdir: test/test_install , os: macos-11.0 , cxx: xcode , gen: "-G Xcode -DCMAKE_OSX_ARCHITECTURES=x86_64", tgt: ALL_BUILD, bt: Release, vars: "-Dc4core_DIR=$GITHUB_WORKSPACE/$PDIR/lib/cmake/c4core -DC4CORE_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: } - - {name: find_package/macos , sdir: test/test_install , os: macos-11.0 , cxx: xcode , gen: "-G Xcode -DCMAKE_OSX_ARCHITECTURES=x86_64", tgt: ALL_BUILD, bt: Debug , vars: "-Dc4core_DIR=$GITHUB_WORKSPACE/$PDIR/lib/cmake/c4core -DC4CORE_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: } - - {name: find_package/win , sdir: test/test_install , os: windows-2019, cxx: vs2019 , gen: "-G 'Visual Studio 16 2019' -A x64" , tgt: ALL_BUILD, bt: Release, vars: "-Dc4core_DIR=$GITHUB_WORKSPACE/$PDIR/cmake -DC4CORE_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: } - - {name: find_package/win , sdir: test/test_install , os: windows-2019, cxx: vs2019 , gen: "-G 'Visual Studio 16 2019' -A x64" , tgt: ALL_BUILD, bt: Debug , vars: "-Dc4core_DIR=$GITHUB_WORKSPACE/$PDIR/cmake -DC4CORE_TEST_INSTALL_PACKAGE_MODE=ON", commonvars: } - # - - {name: find_library/linux , sdir: test/test_install , os: ubuntu-20.04, cxx: g++-10 , gen: "-DCMAKE_CXX_COMPILER=g++-10" , tgt: all , bt: Release, vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DC4CORE_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: } - - {name: find_library/linux , sdir: test/test_install , os: ubuntu-20.04, cxx: g++-10 , gen: "-DCMAKE_CXX_COMPILER=g++-10" , tgt: all , bt: Debug , vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DC4CORE_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: } - - {name: find_library/linux/libcxx, sdir: test/test_install , os: ubuntu-20.04, cxx: clang++-9, gen: "-DCMAKE_CXX_COMPILER=clang++-9" , tgt: all , bt: Release, vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DC4CORE_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: "-DC4CORE_USE_LIBCXX=ON"} - - {name: find_library/linux/libcxx, sdir: test/test_install , os: ubuntu-20.04, cxx: clang++-9, gen: "-DCMAKE_CXX_COMPILER=clang++-9" , tgt: all , bt: Debug , vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DC4CORE_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: "-DC4CORE_USE_LIBCXX=ON"} - - {name: find_library/macos , sdir: test/test_install , os: macos-11.0 , cxx: xcode , gen: "-G Xcode -DCMAKE_OSX_ARCHITECTURES=x86_64", tgt: ALL_BUILD, bt: Release, vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DC4CORE_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: } - - {name: find_library/macos , sdir: test/test_install , os: macos-11.0 , cxx: xcode , gen: "-G Xcode -DCMAKE_OSX_ARCHITECTURES=x86_64", tgt: ALL_BUILD, bt: Debug , vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DC4CORE_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: } - - {name: find_library/win , sdir: test/test_install , os: windows-2019, cxx: vs2019 , gen: "-G 'Visual Studio 16 2019' -A x64" , tgt: ALL_BUILD, bt: Release, vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DC4CORE_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: } - - {name: find_library/win , sdir: test/test_install , os: windows-2019, cxx: vs2019 , gen: "-G 'Visual Studio 16 2019' -A x64" , tgt: ALL_BUILD, bt: Debug , vars: "-DCMAKE_PREFIX_PATH=$GITHUB_WORKSPACE/$PDIR -DC4CORE_TEST_INSTALL_PACKAGE_MODE=OFF", commonvars: } - # - - {name: singleheader/linux , sdir: test/test_singleheader, os: ubuntu-20.04, cxx: g++-10 , gen: "-DCMAKE_CXX_COMPILER=g++-10" , tgt: all , bt: Release, vars: , commonvars: } - - {name: singleheader/linux , sdir: test/test_singleheader, os: ubuntu-20.04, cxx: g++-10 , gen: "-DCMAKE_CXX_COMPILER=g++-10" , tgt: all , bt: Debug , vars: , commonvars: } - - {name: singleheader/linux/libcxx, sdir: test/test_singleheader, os: ubuntu-20.04, cxx: clang++-9, gen: "-DCMAKE_CXX_COMPILER=clang++-9" , tgt: all , bt: Release, vars: , commonvars: "-DC4CORE_USE_LIBCXX=ON"} - - {name: singleheader/linux/libcxx, sdir: test/test_singleheader, os: ubuntu-20.04, cxx: clang++-9, gen: "-DCMAKE_CXX_COMPILER=clang++-9" , tgt: all , bt: Debug , vars: , commonvars: "-DC4CORE_USE_LIBCXX=ON"} - - {name: singleheader/macos , sdir: test/test_singleheader, os: macos-11.0 , cxx: xcode , gen: "-G Xcode -DCMAKE_OSX_ARCHITECTURES=x86_64", tgt: ALL_BUILD, bt: Release, vars: , commonvars: } - - {name: singleheader/macos , sdir: test/test_singleheader, os: macos-11.0 , cxx: xcode , gen: "-G Xcode -DCMAKE_OSX_ARCHITECTURES=x86_64", tgt: ALL_BUILD, bt: Debug , vars: , commonvars: } - - {name: singleheader/win , sdir: test/test_singleheader, os: windows-2019, cxx: vs2019 , gen: "-G 'Visual Studio 16 2019' -A x64" , tgt: ALL_BUILD, bt: Release, vars: , commonvars: } - - {name: singleheader/win , sdir: test/test_singleheader, os: windows-2019, cxx: vs2019 , gen: "-G 'Visual Studio 16 2019' -A x64" , tgt: ALL_BUILD, bt: Debug , vars: , commonvars: } - env: - CXX_: "${{matrix.cxx}}" - BT: "${{matrix.bt}}" - OS: "${{matrix.os}}" - BDIR: "build/${{matrix.name}}-${{matrix.bt}}" - IDIR: "install/${{matrix.name}}-${{matrix.bt}}" - PDIR: "prefix/${{matrix.name}}-${{matrix.bt}}" - steps: - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} - - {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS} - - {name: show info, run: source .github/setenv.sh && c4_show_info} - - name: Install python 3.9 - uses: actions/setup-python@v4 - with: { python-version: 3.9 } - - name: preinstall - run: | - if [ "${{matrix.sdir}}" == "test/test_install" ] ; then - mkdir -p $BDIR-staging - cmake -S . -B $BDIR-staging -DCMAKE_INSTALL_PREFIX=$PDIR -DCMAKE_BUILD_TYPE=${{matrix.bt}} ${{matrix.gen}} ${{matrix.commonvars}} - cmake --build $BDIR-staging --config ${{matrix.bt}} --target ${{matrix.tgt}} -j - cmake --build $BDIR-staging --config ${{matrix.bt}} --target install - fi - - name: configure - run: | - mkdir -p $BDIR - mkdir -p $IDIR - cmake -S ${{matrix.sdir}} -B $BDIR \ - -DC4CORE_BUILD_TESTS=ON \ - -DC4CORE_VALGRIND=OFF \ - -DCMAKE_BUILD_TYPE=${{matrix.bt}} \ - -DCMAKE_INSTALL_PREFIX=$IDIR \ - ${{matrix.gen}} \ - ${{matrix.vars}} \ - ${{matrix.commonvars}} - - name: build - run: | - cmake --build $BDIR --config ${{matrix.bt}} --target c4core-test-build -j - - name: run - run: | - cmake --build $BDIR --config ${{matrix.bt}} --target c4core-test-run diff --git a/thirdparty/ryml/ext/c4core/.github/workflows/windows.yml b/thirdparty/ryml/ext/c4core/.github/workflows/windows.yml deleted file mode 100644 index 11a54f185..000000000 --- a/thirdparty/ryml/ext/c4core/.github/workflows/windows.yml +++ /dev/null @@ -1,157 +0,0 @@ -name: windows - -defaults: - #if: "!contains(github.event.head_commit.message, 'skip ci')" # SKIP - run: - # Use a bash shell so we can use the same syntax for environment variable - # access regardless of the host operating system - shell: bash -e -x {0} - -on: - # https://github.community/t/how-to-trigger-an-action-on-push-or-pull-request-but-not-both/16662 - workflow_dispatch: - push: - branches: - - master - pull_request: - branches: - - master - -env: - PROJ_PFX_TARGET: c4core- - PROJ_PFX_CMAKE: C4CORE_ - CMAKE_FLAGS: - NUM_JOBS_BUILD: # 4 - - -# ubuntu-20.04: -# # https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu2004-README.md -# gcc: 7.5.0, 8.4.0, 9.3.0, 10.2.0 -# clang: 8.0.1, 9.0.1, 10.0.0 -# ubuntu-18.04: -# # https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu1804-README.md -# gcc: 7.5.0, 8.4.0, 9.3.0, 10.1.0 -# clang: 6.0.0, 8.0.0, 9.0.0 -# macos-11.0: macOS Big Sur 11.0 -# # https://github.com/actions/virtual-environments/blob/main/images/macos/macos-11.0-Readme.md -# Xcode 12.1 11.7 -# clang/LLVM 10.0.1 -# gcc-8 gcc-9 -# macos-10.15: macOS Catalina 10.15 -# # https://github.com/actions/virtual-environments/blob/main/images/macos/macos-10.15-Readme.md -# Xcode 12.1 11.7 -# clang/LLVM 11.0.0 -# gcc-8 gcc-9 -# windows-2019: -# # https://github.com/actions/virtual-environments/blob/main/images/win/Windows2019-Readme.md -# vs2019 -# windows-2016: -# # https://github.com/actions/virtual-environments/blob/main/images/win/Windows2016-Readme.md -# vs2017 - -jobs: - - #---------------------------------------------------------------------------- - windows: - name: win/${{matrix.cxx}}/c++${{matrix.std}}/${{matrix.bt}} - continue-on-error: true - if: always() # https://stackoverflow.com/questions/62045967/github-actions-is-there-a-way-to-continue-on-error-while-still-getting-correct - runs-on: ${{matrix.os}} - strategy: - fail-fast: false - matrix: - include: - # github retired windows-2016 - #- {std: 11, cxx: vs2017, bt: Debug , os: windows-2016, bitlinks: shared64 static32} - #- {std: 11, cxx: vs2017, bt: Release, os: windows-2016, bitlinks: shared64 static32} - #- {std: 14, cxx: vs2017, bt: Debug , os: windows-2016, bitlinks: shared64 static32} - #- {std: 14, cxx: vs2017, bt: Release, os: windows-2016, bitlinks: shared64 static32} - # - - {std: 11, cxx: vs2019, bt: Debug , os: windows-2019, bitlinks: shared64 static32} - - {std: 11, cxx: vs2019, bt: Release, os: windows-2019, bitlinks: shared64 static32} - - {std: 14, cxx: vs2019, bt: Debug , os: windows-2019, bitlinks: shared64 static32} - - {std: 14, cxx: vs2019, bt: Release, os: windows-2019, bitlinks: shared64 static32} - - {std: 17, cxx: vs2019, bt: Debug , os: windows-2019, bitlinks: shared64 static32} - - {std: 17, cxx: vs2019, bt: Release, os: windows-2019, bitlinks: shared64 static32} - # - - {std: 11, cxx: vs2022, bt: Debug , os: windows-2022, bitlinks: shared64 static32} - - {std: 11, cxx: vs2022, bt: Release, os: windows-2022, bitlinks: shared64 static32} - - {std: 14, cxx: vs2022, bt: Debug , os: windows-2022, bitlinks: shared64 static32} - - {std: 14, cxx: vs2022, bt: Release, os: windows-2022, bitlinks: shared64 static32} - - {std: 17, cxx: vs2022, bt: Debug , os: windows-2022, bitlinks: shared64 static32} - - {std: 17, cxx: vs2022, bt: Release, os: windows-2022, bitlinks: shared64 static32} - - {std: 20, cxx: vs2022, bt: Debug , os: windows-2022, bitlinks: shared64 static32} - - {std: 20, cxx: vs2022, bt: Release, os: windows-2022, bitlinks: shared64 static32} - env: {STD: "${{matrix.std}}", CXX_: "${{matrix.cxx}}", BT: "${{matrix.bt}}", BITLINKS: "${{matrix.bitlinks}}", VG: "${{matrix.vg}}", SAN: "${{matrix.san}}", LINT: "${{matrix.lint}}", OS: "${{matrix.os}}"} - steps: - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} - - {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS} - - {name: show info, run: source .github/setenv.sh && c4_show_info} - - name: shared64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared64 - - {name: shared64-build, run: source .github/setenv.sh && c4_build_test shared64} - - {name: shared64-run, run: source .github/setenv.sh && c4_run_test shared64} - - {name: shared64-pack, run: source .github/setenv.sh && c4_package shared64} - - name: static64-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static64 - - {name: static64-build, run: source .github/setenv.sh && c4_build_test static64} - - {name: static64-run, run: source .github/setenv.sh && c4_run_test static64} - - {name: static64-pack, run: source .github/setenv.sh && c4_package static64} - - name: shared32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared32 - - {name: shared32-build, run: source .github/setenv.sh && c4_build_test shared32} - - {name: shared32-run, run: source .github/setenv.sh && c4_run_test shared32} - - {name: shared32-pack, run: source .github/setenv.sh && c4_package shared32} - - name: static32-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static32 - - {name: static32-build, run: source .github/setenv.sh && c4_build_test static32} - - {name: static32-run, run: source .github/setenv.sh && c4_run_test static32} - - {name: static32-pack, run: source .github/setenv.sh && c4_package static32} - - #---------------------------------------------------------------------------- - # TODO how to run? - windows_arm: - name: win_arm/${{matrix.cxx}}/c++${{matrix.std}}/${{matrix.bt}} - continue-on-error: true - if: always() # https://stackoverflow.com/questions/62045967/github-actions-is-there-a-way-to-continue-on-error-while-still-getting-correct - runs-on: ${{matrix.os}} - strategy: - fail-fast: false - matrix: - include: - - {std: 11, cxx: vs2019, bt: Debug , os: windows-2019, bitlinks: shared64arm static32arm} - - {std: 11, cxx: vs2019, bt: Release, os: windows-2019, bitlinks: shared64arm static32arm} - - {std: 17, cxx: vs2019, bt: Debug , os: windows-2019, bitlinks: shared64arm static32arm} - - {std: 17, cxx: vs2019, bt: Release, os: windows-2019, bitlinks: shared64arm static32arm} - # - # vs2022 has an internal compiler error on iarm32 Release builds: - # https://github.com/biojppm/c4core/runs/5593534734?check_suite_focus=true#step:15:126 - - {std: 11, cxx: vs2022, bt: Debug , os: windows-2022, bitlinks: shared64arm static32arm} - - {std: 11, cxx: vs2022, bt: Release, os: windows-2022, bitlinks: shared64arm } - - {std: 20, cxx: vs2022, bt: Debug , os: windows-2022, bitlinks: shared64arm static32arm} - - {std: 20, cxx: vs2022, bt: Release, os: windows-2022, bitlinks: shared64arm } - env: {STD: "${{matrix.std}}", CXX_: "${{matrix.cxx}}", BT: "${{matrix.bt}}", BITLINKS: "${{matrix.bitlinks}}", VG: "${{matrix.vg}}", SAN: "${{matrix.san}}", LINT: "${{matrix.lint}}", OS: "${{matrix.os}}"} - steps: - - {name: checkout, uses: actions/checkout@v3, with: {submodules: recursive}} - - {name: install requirements, run: source .github/reqs.sh && c4_install_test_requirements $OS} - - {name: show info, run: source .github/setenv.sh && c4_show_info} - - name: shared64arm-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared64arm - - {name: shared64arm-build, run: source .github/setenv.sh && c4_build_test shared64arm} - #- {name: shared64arm-run, run: source .github/setenv.sh && c4_run_test shared64arm} - - {name: shared64arm-pack, run: source .github/setenv.sh && c4_package shared64arm} - - name: static64arm-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static64arm - - {name: static64arm-build, run: source .github/setenv.sh && c4_build_test static64arm} - #- {name: static64arm-run, run: source .github/setenv.sh && c4_run_test static64arm} - - {name: static64arm-pack, run: source .github/setenv.sh && c4_package static64arm} - - name: shared32arm-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test shared32arm - - {name: shared32arm-build, run: source .github/setenv.sh && c4_build_test shared32arm} - #- {name: shared32arm-run, run: source .github/setenv.sh && c4_run_test shared32arm} - - {name: shared32arm-pack, run: source .github/setenv.sh && c4_package shared32arm} - - name: static32arm-configure--------------------------------------------------- - run: source .github/setenv.sh && c4_cfg_test static32arm - - {name: static32arm-build, run: source .github/setenv.sh && c4_build_test static32arm} - #- {name: static32arm-run, run: source .github/setenv.sh && c4_run_test static32arm} - - {name: static32arm-pack, run: source .github/setenv.sh && c4_package static32arm} diff --git a/thirdparty/ryml/ext/c4core/.gitignore b/thirdparty/ryml/ext/c4core/.gitignore deleted file mode 100644 index 9c258ea3b..000000000 --- a/thirdparty/ryml/ext/c4core/.gitignore +++ /dev/null @@ -1,34 +0,0 @@ -# text editor files -*.bck -\#* -*~ -.ccls-cache/ -.clangd/ -.cache/ -.cquery_cached_index/ -__pycache__/ - -# Visual Studio files -.vs/ -.vscode/ -# QtCreator files -CMakeLists.txt.user -# Eclipse -.project -.cproject -/.settings/ - -# build files -build/ -install/ -.python-version -compile_commands.json - -# test files -/Testing/ - -# continuous integration files -.github/vagrant/*.log -.github/vagrant/.vagrant -.github/vagrant/macos/.vagrant -src_singleheader/ \ No newline at end of file diff --git a/thirdparty/ryml/ext/c4core/.gitmodules b/thirdparty/ryml/ext/c4core/.gitmodules deleted file mode 100644 index 77f89eae3..000000000 --- a/thirdparty/ryml/ext/c4core/.gitmodules +++ /dev/null @@ -1,9 +0,0 @@ -[submodule "cmake"] - path = cmake - url = https://github.com/biojppm/cmake -[submodule "extern/debugbreak"] - path = src/c4/ext/debugbreak - url = https://github.com/biojppm/debugbreak -[submodule "src/c4/ext/fast_float"] - path = src/c4/ext/fast_float - url = https://github.com/fastfloat/fast_float diff --git a/thirdparty/ryml/ext/c4core/LICENSE-BOOST.txt b/thirdparty/ryml/ext/c4core/LICENSE-BOOST.txt deleted file mode 100644 index 689a5fa00..000000000 --- a/thirdparty/ryml/ext/c4core/LICENSE-BOOST.txt +++ /dev/null @@ -1,26 +0,0 @@ -src/c4/ext/sg14/inplace_function.h is distributed under the following terms: ----------------------------------------------------------------------------- - -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/thirdparty/ryml/ext/c4core/LICENSE.txt b/thirdparty/ryml/ext/c4core/LICENSE.txt deleted file mode 100644 index 47b6b4394..000000000 --- a/thirdparty/ryml/ext/c4core/LICENSE.txt +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2018, Joao Paulo Magalhaes - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. - diff --git a/thirdparty/ryml/ext/c4core/README.md b/thirdparty/ryml/ext/c4core/README.md deleted file mode 100644 index cd420954d..000000000 --- a/thirdparty/ryml/ext/c4core/README.md +++ /dev/null @@ -1,381 +0,0 @@ -# c4core - C++ core utilities - -[![MIT Licensed](https://img.shields.io/badge/License-MIT-green.svg)](https://github.com/biojppm/c4core/blob/master/LICENSE.txt) -[![Docs](https://img.shields.io/badge/docs-docsforge-blue)](https://c4core.docsforge.com/) -[![ci](https://github.com/biojppm/c4core/workflows/ci/badge.svg)](https://github.com/biojppm/c4core/actions?query=ci) - -[![Codecov](https://codecov.io/gh/biojppm/c4core/branch/master/graph/badge.svg)](https://codecov.io/gh/biojppm/c4core) -[![LGTM alerts](https://img.shields.io/lgtm/alerts/g/biojppm/c4core.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/biojppm/c4core/alerts/) -[![LGTM grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/biojppm/c4core.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/biojppm/c4core/context:cpp) - - -c4core is a library of low-level C++ utilities, written with low-latency -projects in mind. - -Some of the utilities provided by c4core have already equivalent -functionality in the C++ standard, but they are provided as the existing C++ -equivalent may be insufficient (eg, std::string_view), inefficient (eg, -std::string), heavy (eg streams), or plainly unusable on some -platforms/projects, (eg exceptions); some other utilities have equivalent -under consideration for C++ standardisation; and yet some other utilities -have (to my knowledge) no equivalent under consideration. Be that as it may, -I've been using these utilities in this or similar forms for some years now, -and I've found them incredibly useful in my projects. I'm packing these as a -separate library, as all of my projects use it. - -c4core is [extensively unit-tested in Linux, Windows and -MacOS](https://github.com/biojppm/c4core/actions). The tests cover -x64, x86, arm, wasm (emscripten), aarch64, ppc64le and s390x -architectures, and include analysing c4core with: - * valgrind - * clang-tidy - * clang sanitizers: - * memory - * address - * undefined behavior - * thread - * [LGTM.com](https://lgtm.com/projects/g/biojppm/c4core) - -c4core also works [in -bare-metal](https://github.com/biojppm/c4core/issues/63) as well as -[in RISC-V](https://github.com/biojppm/c4core/pull/69) but at the -moment it's not easy to add automated tests to the CI, so for now -these are not in the list of official architectures. - - -- [c4core - C++ core utilities](#c4core---c-core-utilities) - - [Obtaining c4core](#obtaining-c4core) - - [Using c4core in your project](#using-c4core-in-your-project) - - [CMake](#cmake) - - [Bazel](#bazel) - - [Header-only](#header-only) - - [Package managers](#package-managers) - - [Quick tour](#quick-tour) - - [Writeable string views: c4::substr and c4::csubstr](#writeable-string-views-c4substr-and-c4csubstr) - - [Value <-> character interoperation](#value---character-interoperation) - - [String formatting and parsing](#string-formatting-and-parsing) - - [`c4::span` and `c4::blob`](#c4span-and-c4blob) - - [Enums and enum symbols](#enums-and-enum-symbols) - - [Bitmasks and bitmask symbols](#bitmasks-and-bitmask-symbols) - - [Base64 encoding / decoding](#base64-encoding--decoding) - - [Fuzzy float comparison](#fuzzy-float-comparison) - - [Multi-platform / multi-compiler utilities](#multi-platform--multi-compiler-utilities) - - [Runtime assertions and error handling](#runtime-assertions-and-error-handling) - - [Memory allocation](#memory-allocation) - - [Mass initialization/construction/destruction](#mass-initializationconstructiondestruction) - - - - -## Obtaining c4core - -c4core uses git submodules. It is best to clone c4core with the `--recursive` -option: - -```bash -# using --recursive makes sure git submodules are also cloned at the same time -git clone --recursive https://github.com/biojppm/c4core -``` - -If you ommit the `--recursive` option, then after cloning you will have to -make git checkout the current version of the submodules, using `git submodule -init` followed by `git submodule update`. - - -## Using c4core in your project - -c4core can be built with [cmake](#cmake), or can be used header only. It can also be obtained through some package managers. - -### CMake - -The recommended way to use c4core is by making it part of your project -by using `add_subdirectory(${path_to_c4core_root})` in your -CMakeLists.txt. Doing this is not intrusive to your cmake project -because c4core is fast to build, also prefixes every cmake -variable with `C4CORE_`. But more importantly, this will enable you to -compile c4core with the exact same compile settings used by your -project. - -Here's a very quick complete example of setting up your project to use -c4core as a cmake subproject: -```cmake -project(foo) - -add_subdirectory(c4core) - -add_library(foo foo.cpp) -target_link_libraries(foo PUBLIC c4core) # that's it! -``` -Note above that the call to `target_link_libraries()` is using PUBLIC -linking. This is required to make sure the include directories from `c4core` -are transitively used by clients of `foo`. - - -### Header-only - -If you prefer to pick a single header to get you quickly going, [there is an amalgamation tool](tools/amalgamate.py) which generates this header: -```console -[user@host c4core]$ python tools/amalgamate.py -h -usage: amalgamate.py [-h] [--fastfloat | --no-fastfloat] [--stl | --no-stl] [output] - -positional arguments: - output output file. defaults to stdout - -options: - -h, --help show this help message and exit - --fastfloat enable fastfloat library. this is the default. - --no-fastfloat enable fastfloat library. the default is --fastfloat. - --stl enable stl interop. this is the default. - --no-stl enable stl interop. the default is --stl. -``` - - -### Package managers - -c4core is available through the following package managers: - - * [vcpkg](https://vcpkg.io/en/packages.html): `vcpkg install c4core` - * Arch Linux/Manjaro: - * [rapidyaml](https://aur.archlinux.org/packages/rapidyaml/) - - - - - -## Quick tour - -All of the utilities in this library are under the namespace `c4`; any -exposed macros use the prefix `C4_`: eg `C4_ASSERT()`. - - -### Writeable string views: c4::substr and c4::csubstr - -Here: [`#include `](src/c4/substr.hpp) - - -### Value <-> character interoperation - -Here: [`#include `](src/c4/charconv.hpp) - -```c++ -// TODO: elaborate on the topics: - -c4::digits_dec(), c4::read_dec(), c4::write_dec() -c4::digits_hex(), c4::read_hex(), c4::write_hex() -c4::digits_oct(), c4::read_oct(), c4::write_oct() -c4::digits_bin(), c4::read_bin(), c4::write_bin() - -c4::utoa(), c4::atou() -c4::itoa(), c4::atoi() -c4::ftoa(), c4::atof() -c4::dtoa(), c4::atod() -c4::xtoa(), c4::atox() - -c4::to_chars(), c4::from_chars() -c4::to_chars_sub() -c4::to_chars_first() -``` - -The charconv funcions above are very fast; even faster than C++'s fastest facility `std::from_chars()`, `std::to_chars()`. For continuous benchmark results, browse through c4core's [github CI benchmark runs](https://github.com/biojppm/c4core/actions/workflows/benchmarks.yml). For example, a benchmark run on Linux/g++11.2 shows that: -- `c4::to_chars()` can be expected to be roughly... - - ~40% to 2x faster than `std::to_chars()` - - ~10x-30x faster than `sprintf()` - - ~50x-100x faster than a naive `stringstream::operator<<()` followed by `stringstream::str()` -- `c4::from_chars()` can be expected to be roughly... - - ~10%-30% faster than `std::from_chars()` - - ~10x faster than `scanf()` - - ~30x-50x faster than a naive `stringstream::str()` followed by `stringstream::operator>>()` - -Here are the results: - -| Write throughput | | Read throughput | | -|:-------------------------|--------:|:-------------------------|---------:| -| **write `uint8_t`** | **MB/s**| **read `uint8_t`** | **MB/s**| -| `c4::to_chars` | 526.86 | `c4::from_chars` | 163.06 | -| `std::to_chars` | 379.03 | `std::from_chars` | 154.85 | -| `std::sprintf` | 20.49 | `std::scanf` | 15.75 | -| `std::stringstream` | 3.82 | `std::stringstream` | 3.83 | -| **write `int8_t`** | **MB/s**| **read `int8_t`** | **MB/s**| -| `c4::to_chars` | 599.98 | `c4::from_chars` | 184.20 | -| `std::to_chars` | 246.32 | `std::from_chars` | 156.40 | -| `std::sprintf` | 19.15 | `std::scanf` | 16.44 | -| `std::stringstream` | 3.83 | `std::stringstream` | 3.89 | -| **write `uint16_t`** | **MB/s**| **read `uint16_t`** | **MB/s**| -| `c4::to_chars` | 486.40 | `c4::from_chars` | 349.48 | -| `std::to_chars` | 454.24 | `std::from_chars` | 319.13 | -| `std::sprintf` | 38.74 | `std::scanf` | 28.12 | -| `std::stringstream` | 7.08 | `std::stringstream`| 6.73 | -| **write `int16_t`** | **MB/s**| **read `int16_t`** | **MB/s**| -| `c4::to_chars` | 507.44 | `c4::from_chars` | 282.95 | -| `std::to_chars` | 297.49 | `std::from_chars` | 186.18 | -| `std::sprintf` | 39.03 | `std::scanf` | 28.45 | -| `std::stringstream` | 6.98 | `std::stringstream`| 6.49 | -| **write `uint32_t`** | **MB/s**| **read `uint32_t`** | **MB/s**| -| `c4::to_chars` | 730.12 | `c4::from_chars` | 463.95 | -| `std::to_chars` | 514.76 | `std::from_chars` | 329.42 | -| `std::sprintf` | 71.19 | `std::scanf` | 44.97 | -| `std::stringstream` | 14.05 | `std::stringstream`| 12.57 | -| **write `int32_t`** | **MB/s**| **read `int32_t`** | **MB/s**| -| `c4::to_chars` | 618.76 | `c4::from_chars` | 345.53 | -| `std::to_chars` | 394.72 | `std::from_chars` | 224.46 | -| `std::sprintf` | 71.14 | `std::scanf` | 43.49 | -| `std::stringstream` | 13.91 | `std::stringstream`| 12.03 | -| **write `uint64_t`** | **MB/s**| **read `uint64_t`** | **MB/s**| -| `c4::to_chars` | 1118.87 | `c4::from_chars` | 928.49 | -| `std::to_chars` | 886.58 | `std::from_chars` | 759.03 | -| `std::sprintf` | 140.96 | `std::scanf` | 91.60 | -| `std::stringstream` | 28.01 | `std::stringstream`| 25.00 | -| **write `int64_t`** | **MB/s**| **read `int64_t`** | **MB/s**| -| `c4::to_chars` | 1198.78 | `c4::from_chars` | 713.76 | -| `std::to_chars` | 882.17 | `std::from_chars` | 646.18 | -| `std::sprintf` | 138.79 | `std::scanf` | 90.07 | -| `std::stringstream` | 27.62 | `std::stringstream`| 25.12 | - - -Or here are plots for g++12.1 and VS2019 (from the same computer): - -| Linux gxx12.1 | Windows VS2019 | -|---------------|----------------| -| ![atox-u32-linux](doc/img/linux-x86_64-gxx12.1-Release/c4core-bm-charconv-atox-mega_bytes_per_second-u32.png "atox-u32-linux") | ![atox-u32-windows](doc/img/windows-x86_64-vs2019-Release/c4core-bm-charconv-atox-mega_bytes_per_second-u32.png "atox-u32-windows") | -| ![atox-i32-linux](doc/img/linux-x86_64-gxx12.1-Release/c4core-bm-charconv-atox-mega_bytes_per_second-i32.png "atox-i32-linux") | ![atox-i32-windows](doc/img/windows-x86_64-vs2019-Release/c4core-bm-charconv-atox-mega_bytes_per_second-i32.png "atox-i32-windows") | -| ![atox-u64-linux](doc/img/linux-x86_64-gxx12.1-Release/c4core-bm-charconv-atox-mega_bytes_per_second-u64.png "atox-u64-linux") | ![atox-u64-windows](doc/img/windows-x86_64-vs2019-Release/c4core-bm-charconv-atox-mega_bytes_per_second-u64.png "atox-u64-windows") | -| ![atox-i64-linux](doc/img/linux-x86_64-gxx12.1-Release/c4core-bm-charconv-atox-mega_bytes_per_second-i64.png "atox-i64-linux") | ![atox-i64-windows](doc/img/windows-x86_64-vs2019-Release/c4core-bm-charconv-atox-mega_bytes_per_second-i64.png "atox-i64-windows") | -| ![atof-double-linux](doc/img/linux-x86_64-gxx12.1-Release/c4core-bm-charconv-atof-mega_bytes_per_second-double.png "atof-double-linux") | ![atof-double-windows](doc/img/windows-x86_64-vs2019-Release/c4core-bm-charconv-atof-mega_bytes_per_second-double.png "atof-double-windows") | -| ![atof-float-linux](doc/img/linux-x86_64-gxx12.1-Release/c4core-bm-charconv-atof-mega_bytes_per_second-float.png "atof-float-linux") | ![atof-float-windows](doc/img/windows-x86_64-vs2019-Release/c4core-bm-charconv-atof-mega_bytes_per_second-float.png "atof-float-windows") | -| | | -| ![xtoa-u32-linux](doc/img/linux-x86_64-gxx12.1-Release/c4core-bm-charconv-xtoa-mega_bytes_per_second-u32.png "xtoa-u32-linux") | ![xtoa-u32-windows](doc/img/windows-x86_64-vs2019-Release/c4core-bm-charconv-xtoa-mega_bytes_per_second-u32.png "xtoa-u32-windows") | -| ![xtoa-i32-linux](doc/img/linux-x86_64-gxx12.1-Release/c4core-bm-charconv-xtoa-mega_bytes_per_second-i32.png "xtoa-i32-linux") | ![xtoa-i32-windows](doc/img/windows-x86_64-vs2019-Release/c4core-bm-charconv-xtoa-mega_bytes_per_second-i32.png "xtoa-i32-windows") | -| ![xtoa-u64-linux](doc/img/linux-x86_64-gxx12.1-Release/c4core-bm-charconv-xtoa-mega_bytes_per_second-u64.png "xtoa-u64-linux") | ![xtoa-u64-windows](doc/img/windows-x86_64-vs2019-Release/c4core-bm-charconv-xtoa-mega_bytes_per_second-u64.png "xtoa-u64-windows") | -| ![xtoa-i64-linux](doc/img/linux-x86_64-gxx12.1-Release/c4core-bm-charconv-xtoa-mega_bytes_per_second-i64.png "xtoa-i64-linux") | ![xtoa-i64-windows](doc/img/windows-x86_64-vs2019-Release/c4core-bm-charconv-xtoa-mega_bytes_per_second-i64.png "xtoa-i64-windows") | - - - -### String formatting and parsing - -* [`#include `](src/c4/format.hpp) - -```c++ -// TODO: elaborate on the topics: - -c4::cat(), c4::uncat() -c4::catsep(), c4::uncatsep() -c4::format(), c4::unformat() - -c4::catrs() -c4::catseprs() -c4::formatrs() - -// formatting: -c4::fmt::overflow_checked -c4::fmt::real -c4::fmt::boolalpha -c4::fmt::dec -c4::fmt::hex -c4::fmt::oct -c4::fmt::bin -c4::fmt::zpad -c4::fmt::right -c4::fmt::left -c4::fmt::raw, c4::fmt::craw -c4::fmt::base64, c4::fmt::cbase64 -``` - -### `c4::span` and `c4::blob` - -* [`#include `](src/c4/span.hpp) -* [`#include `](src/c4/blob.hpp) - - -### Enums and enum symbols - -[`#include `](src/c4/enum.hpp) - -```c++ -// TODO: elaborate on the topics: - -c4::e2str(), c4::str2e() -``` - -### Bitmasks and bitmask symbols - -[`#include `](src/c4/bitmask.hpp) - -```c++ -// TODO: elaborate on the topics: - -c4::bm2str(), c4::str2bm() -``` - -### Base64 encoding / decoding - -[`#include `](src/c4/base64.hpp) - -### Fuzzy float comparison - - -### Multi-platform / multi-compiler utilities - -```c++ -// TODO: elaborate on the topics: -#include - -C4_RESTRICT, $, c$, $$, c$$ -#include -#include - -#include -#include - -C4_UNREACHABLE() - -c4::type_name() - -// portable attributes -C4_LIKELY()/C4_UNLIKELY() -C4_ALWAYS_INLINE -C4_CONST -C4_PURE -C4_HOT -C4_COLD -``` - -### Runtime assertions and error handling - -```c++ -// TODO: elaborate on the topics: - -error callback - -C4_ASSERT() -C4_XASSERT() -C4_CHECK() - -C4_ERROR() -C4_NOT_IMPLEMENTED() -``` - -### Memory allocation - -```c++ -// TODO: elaborate on the topics: - -c4::aalloc(), c4::afree() // aligned allocation - -c4::MemoryResource // global and scope - -c4::Allocator -``` - -### Mass initialization/construction/destruction - -```c++ -// TODO: elaborate on the topics: - -c4::make_room()/c4::destroy_room() -c4::construct()/c4::construct_n() -c4::destroy()/c4::destroy_n() -c4::copy_construct()/c4::copy_construct_n() -c4::copy_assign()/c4::copy_assign_n() -c4::move_construct()/c4::move_construct_n() -c4::move_assign()/c4::move_assign_n() -``` diff --git a/thirdparty/ryml/ext/c4core/ROADMAP.md b/thirdparty/ryml/ext/c4core/ROADMAP.md deleted file mode 100644 index 9857514e4..000000000 --- a/thirdparty/ryml/ext/c4core/ROADMAP.md +++ /dev/null @@ -1,23 +0,0 @@ -# ROADMAP - -## New features - -These changes will provide new features, and client code can be kept -unchanged. - - -## API changes - -These changes will require client code to be updated. - -* [breaking] drop use of C-style sprintf() formats in error messages and - assertions. Change the implementation to use c4::format() - ```c++ - C4_ASSERT_MSG(sz > s.size(), "sz=%zu s.size()=%zu", sz, s.size()); - // ... the above changes to: - C4_ASSERT_MSG(sz > s.size(), "sz={} s.size()={}", sz, s.size()); - ``` - -## Implementation changes - -* drop calls to sprintf() in charconv.hpp. diff --git a/thirdparty/ryml/ext/c4core/bm/bm.yml b/thirdparty/ryml/ext/c4core/bm/bm.yml deleted file mode 100644 index 885dcf7db..000000000 --- a/thirdparty/ryml/ext/c4core/bm/bm.yml +++ /dev/null @@ -1,32 +0,0 @@ - -prefix: c4core-bm - -# TODO https://stackoverflow.com/questions/12360547/tool-for-retrieving-the-list-of-functions-and-methods-in-a-c-code-base - -bm: - charconv-atox: - desc: read string to arithmetic value - src: bm_charconv.cpp - template_types: [uint8, int8, uint16, int16, uint32, int32, uint64, int64, float, double] - charconv-xtoa: - desc: write arithmetic value to string - src: bm_charconv.cpp - template_types: [uint8, int8, uint16, int16, uint32, int32, uint64, int64, float, double] - format-cat: - desc: compares stringification of a sequence of heterogeneous general types - src: bm_format.cpp - format-catfile: - desc: compares stringification to a file of a sequence of heterogeneous general types - src: bm_format.cpp - format-catsep: - desc: compares stringification of a sequence of heterogeneous general types - src: bm_format.cpp - format-catsepfile: - desc: compares stringification to a file of a sequence of heterogeneous general types - src: bm_format.cpp - format-format: - desc: compares formatting of a sequence of heterogeneous general types - src: bm_format.cpp - format-formatfile: - desc: compares stringification to a file of a sequence of heterogeneous general types - src: bm_format.cpp diff --git a/thirdparty/ryml/ext/c4core/bm/bm_atox.cpp b/thirdparty/ryml/ext/c4core/bm/bm_atox.cpp deleted file mode 100644 index b4ca2b609..000000000 --- a/thirdparty/ryml/ext/c4core/bm/bm_atox.cpp +++ /dev/null @@ -1,478 +0,0 @@ -#include "./bm_charconv.hpp" - - -// this is an exploratory benchmark to compare the possible -// combinations for all the components of the read_dec() algorithm - - -template -bool range_based_restrictvar0(c4::csubstr s, T * v) -{ - *v = 0; - for(char c : s) - { - if(C4_UNLIKELY(c < '0' || c > '9')) - return false; - *v = (*v) * T(10) + (T(c) - T('0')); - } - return true; -} - -template -bool range_based_restrictvar1(c4::csubstr s, T *C4_RESTRICT v) -{ - *v = 0; - for(char c : s) - { - if(C4_UNLIKELY(c < '0' || c > '9')) - return false; - *v = (*v) * T(10) + (T(c) - T('0')); - } - return true; -} - -template -bool indexloop_restrictvar0(c4::csubstr s, T * v) -{ - *v = 0; - for(size_t i = 0; i < s.len; ++i) - { - const char c = s.str[i]; - if(C4_UNLIKELY(c < '0' || c > '9')) - return false; - *v = (*v) * T(10) + (T(c) - T('0')); - } - return true; -} - -template -bool indexloop_restrictvar1(c4::csubstr s, T *C4_RESTRICT v) -{ - *v = 0; - for(size_t i = 0; i < s.len; ++i) - { - const char c = s.str[i]; - if(C4_UNLIKELY(c < '0' || c > '9')) - return false; - *v = (*v) * T(10) + (T(c) - T('0')); - } - return true; -} - -template -bool prefer_likely(c4::csubstr s, T * v) -{ - *v = 0; - for(char c : s) - { - if(C4_LIKELY(c >= '0' && c <= '9')) - *v = (*v) * T(10) + (T(c) - T('0')); - else - return false; - } - return true; -} - -template -bool no_early_return(c4::csubstr s, T *C4_RESTRICT v) -{ - *v = 0; - bool stat = true; - for(char c : s) - { - if(C4_LIKELY(c >= '0' && c <= '9')) - *v = (*v) * T(10) + (T(c) - T('0')); - else - { - stat = false; - break; - } - } - return stat; -} - -template -bool no_early_return_auto_type(c4::csubstr s, T *C4_RESTRICT v) -{ - *v = 0; - bool stat = true; - for(char c : s) - { - if(C4_LIKELY(c >= '0' && c <= '9')) - *v = (*v) * T(10) + (T)(c - '0'); - else - { - stat = false; - break; - } - } - return stat; -} - -template -bool no_early_return_auto_type2(c4::csubstr s, T *C4_RESTRICT v) -{ - *v = 0; - bool stat = true; - for(char c : s) - { - if(C4_LIKELY(c >= '0' && c <= '9')) - { - *v *= 10; - *v += (T)(c - '0'); - } - else - { - stat = false; - break; - } - } - return stat; -} - -#define _(i) (T)(s.str[i] - '0') -C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH("-Wimplicit-fallthrough") - -template -C4_ALWAYS_INLINE auto unroll_switch_nocheck(c4::csubstr s, T *C4_RESTRICT v) - -> typename std::enable_if::type -{ - *v = 0; - switch(s.len) - { - case 1: - *v = _(0); - return true; - case 2: - *v = T(10) * _(0) + _(1); - return true; - case 3: - *v = T(100) * _(0) + T(10) * _(1) + _(2); - return true; - } - return false; -} - -template -C4_ALWAYS_INLINE auto unroll_switch_nocheck(c4::csubstr s, T *C4_RESTRICT v) - -> typename std::enable_if::type -{ - *v = 0; - switch(s.len) - { - case 1: - *v = _(0); - return true; - case 2: - *v = T(10) * _(0) + _(1); - return true; - case 3: - *v = T(100) * _(0) + T(10) * _(1) + _(2); - return true; - case 4: - *v = T(1000) * _(0) + T(100) * _(1) + T(10) * _(2) + _(3); - return true; - case 5: - *v = T(10000) * _(0) + T(1000) * _(1) + T(100) * _(2) + T(10) * _(3) + _(4); - return true; - } - return false; -} - -template -C4_ALWAYS_INLINE auto unroll_switch_nocheck(c4::csubstr s, T *C4_RESTRICT v) - -> typename std::enable_if::type -{ - switch(s.len) - { - case 1: - *v = _(0); - return true; - case 2: - *v = T(10) * _(0) + _(1); - return true; - case 3: - *v = T(100) * _(0) + T(10) * _(1) + _(2); - return true; - case 4: - *v = T(1000) * _(0) + T(100) * _(1) + T(10) * _(2) + _(3); - return true; - case 5: - *v = T(10000) * _(0) + T(1000) * _(1) + T(100) * _(2) + T(10) * _(3) + _(4); - return true; - case 6: - *v = T(100000) * _(0) + T(10000) * _(1) + T(1000) * _(2) + T(100) * _(3) + T(10) * _(4) + _(5); - return true; - case 7: - *v = T(1000000) * _(0) + T(100000) * _(1) + T(10000) * _(2) + T(1000) * _(3) + T(100) * _(4) + T(10) * _(5) + _(6); - return true; - case 8: - *v = T(10000000) * _(0) + T(1000000) * _(1) + T(100000) * _(2) + T(10000) * _(3) + T(1000) * _(4) + T(100) * _(5) + T(10) * _(6) + _(7); - return true; - case 9: - *v = T(100000000) * _(0) + T(10000000) * _(1) + T(1000000) * _(2) + T(100000) * _(3) + T(10000) * _(4) + T(1000) * _(5) + T(100) * _(6) + T(10) * _(7) + _(8); - return true; - case 10: - *v = T(1000000000) * _(0) + T(100000000) * _(1) + T(10000000) * _(2) + T(1000000) * _(3) + T(100000) * _(4) + T(10000) * _(5) + T(1000) * _(6) + T(100) * _(7) + T(10) * _(8) + _(9); - return true; - } - return false; -} - -template -C4_ALWAYS_INLINE auto unroll_switch_nocheck(c4::csubstr s, T *C4_RESTRICT v) - -> typename std::enable_if::type -{ - switch(s.len) - { - case 1: - *v = _(0); - return true; - case 2: - *v = T(10) * _(0) + _(1); - return true; - case 3: - *v = T(100) * _(0) + T(10) * _(1) + _(2); - return true; - case 4: - *v = T(1000) * _(0) + T(100) * _(1) + T(10) * _(2) + _(3); - return true; - case 5: - *v = T(10000) * _(0) + T(1000) * _(1) + T(100) * _(2) + T(10) * _(3) + _(4); - return true; - case 6: - *v = T(100000) * _(0) + T(10000) * _(1) + T(1000) * _(2) + T(100) * _(3) + T(10) * _(4) + _(5); - return true; - case 7: - *v = T(1000000) * _(0) + T(100000) * _(1) + T(10000) * _(2) + T(1000) * _(3) + T(100) * _(4) + T(10) * _(5) + _(6); - return true; - case 8: - *v = T(10000000) * _(0) + T(1000000) * _(1) + T(100000) * _(2) + T(10000) * _(3) + T(1000) * _(4) + T(100) * _(5) + T(10) * _(6) + _(7); - return true; - case 9: - *v = T(100000000) * _(0) + T(10000000) * _(1) + T(1000000) * _(2) + T(100000) * _(3) + T(10000) * _(4) + T(1000) * _(5) + T(100) * _(6) + T(10) * _(7) + _(8); - return true; - case 10: - *v = T(1000000000) * _(0) + T(100000000) * _(1) + T(10000000) * _(2) + T(1000000) * _(3) + T(100000) * _(4) + T(10000) * _(5) + T(1000) * _(6) + T(100) * _(7) + T(10) * _(8) + _(9); - return true; - default: - { - size_t i = 0; - *v = 0; - for( ; i + 10 < s.len; ++i) - *v = *v * T(10) + _(i); - *v = T(1000000000) * _(i) + T(100000000) * _(i+1) + T(10000000) * _(i+2) + T(1000000) * _(i+3) + T(100000) * _(i+4) + T(10000) * _(i+5) + T(1000) * _(i+6) + T(100) * _(i+7) + T(10) * _(i+8) + _(i+9); - return true; - } - } - return false; -} - -#define ok(i) (s.str[i] >= '0' && s.str[i] <= '9') - -template -C4_ALWAYS_INLINE auto unroll_switch(c4::csubstr s, T *C4_RESTRICT v) - -> typename std::enable_if::type -{ - *v = 0; - switch(s.len) - { - case 1: - *v = _(0); - return ok(0); - case 2: - *v = T(10) * _(0) + _(1); - return ok(0) && ok(1); - case 3: - *v = T(100) * _(0) + T(10) * _(1) + _(2); - return ok(0) && ok(1) && ok(2); - } - return false; -} - -template -C4_ALWAYS_INLINE auto unroll_switch(c4::csubstr s, T *C4_RESTRICT v) - -> typename std::enable_if::type -{ - *v = 0; - switch(s.len) - { - case 1: - *v = _(0); - return true; - case 2: - *v = T(10) * _(0) + _(1); - return true; - case 3: - *v = T(100) * _(0) + T(10) * _(1) + _(2); - return ok(0) && ok(1) && ok(2); - case 4: - *v = T(1000) * _(0) + T(100) * _(1) + T(10) * _(2) + _(3); - return ok(0) && ok(1) && ok(2) && ok(3); - case 5: - *v = T(10000) * _(0) + T(1000) * _(1) + T(100) * _(2) + T(10) * _(3) + _(4); - return ok(0) && ok(1) && ok(2) && ok(3) && ok(4); - } - return false; -} - -template -C4_ALWAYS_INLINE auto unroll_switch(c4::csubstr s, T *C4_RESTRICT v) - -> typename std::enable_if::type -{ - switch(s.len) - { - case 1: - *v = _(0); - return ok(0); - case 2: - *v = T(10) * _(0) + _(1); - return ok(0) && ok(1); - case 3: - *v = T(100) * _(0) + T(10) * _(1) + _(2); - return ok(0) && ok(1) && ok(2); - case 4: - *v = T(1000) * _(0) + T(100) * _(1) + T(10) * _(2) + _(3); - return ok(0) && ok(1) && ok(2) && ok(3); - case 5: - *v = T(10000) * _(0) + T(1000) * _(1) + T(100) * _(2) + T(10) * _(3) + _(4); - return ok(0) && ok(1) && ok(2) && ok(3) && ok(4); - case 6: - *v = T(100000) * _(0) + T(10000) * _(1) + T(1000) * _(2) + T(100) * _(3) + T(10) * _(4) + _(5); - return ok(0) && ok(1) && ok(2) && ok(3) && ok(4) && ok(5); - case 7: - *v = T(1000000) * _(0) + T(100000) * _(1) + T(10000) * _(2) + T(1000) * _(3) + T(100) * _(4) + T(10) * _(5) + _(6); - return ok(0) && ok(1) && ok(2) && ok(3) && ok(4) && ok(5) && ok(6); - case 8: - *v = T(10000000) * _(0) + T(1000000) * _(1) + T(100000) * _(2) + T(10000) * _(3) + T(1000) * _(4) + T(100) * _(5) + T(10) * _(6) + _(7); - return ok(0) && ok(1) && ok(2) && ok(3) && ok(4) && ok(5) && ok(6) && ok(7); - case 9: - *v = T(100000000) * _(0) + T(10000000) * _(1) + T(1000000) * _(2) + T(100000) * _(3) + T(10000) * _(4) + T(1000) * _(5) + T(100) * _(6) + T(10) * _(7) + _(8); - return ok(0) && ok(1) && ok(2) && ok(3) && ok(4) && ok(5) && ok(6) && ok(7) && ok(8); - case 10: - *v = T(1000000000) * _(0) + T(100000000) * _(1) + T(10000000) * _(2) + T(1000000) * _(3) + T(100000) * _(4) + T(10000) * _(5) + T(1000) * _(6) + T(100) * _(7) + T(10) * _(8) + _(9); - return ok(0) && ok(1) && ok(2) && ok(3) && ok(4) && ok(5) && ok(6) && ok(7) && ok(8) && ok(9); - } - return false; -} - -template -C4_ALWAYS_INLINE auto unroll_switch(c4::csubstr s, T *C4_RESTRICT v) - -> typename std::enable_if::type -{ - switch(s.len) - { - case 1: - *v = _(0); - return ok(0); - case 2: - *v = T(10) * _(0) + _(1); - return ok(0) && ok(1); - case 3: - *v = T(100) * _(0) + T(10) * _(1) + _(2); - return ok(0) && ok(1) && ok(2); - case 4: - *v = T(1000) * _(0) + T(100) * _(1) + T(10) * _(2) + _(3); - return ok(0) && ok(1) && ok(2) && ok(3); - case 5: - *v = T(10000) * _(0) + T(1000) * _(1) + T(100) * _(2) + T(10) * _(3) + _(4); - return ok(0) && ok(1) && ok(2) && ok(3) && ok(4); - case 6: - *v = T(100000) * _(0) + T(10000) * _(1) + T(1000) * _(2) + T(100) * _(3) + T(10) * _(4) + _(5); - return ok(0) && ok(1) && ok(2) && ok(3) && ok(4) && ok(5); - case 7: - *v = T(1000000) * _(0) + T(100000) * _(1) + T(10000) * _(2) + T(1000) * _(3) + T(100) * _(4) + T(10) * _(5) + _(6); - return ok(0) && ok(1) && ok(2) && ok(3) && ok(4) && ok(5) && ok(6); - case 8: - *v = T(10000000) * _(0) + T(1000000) * _(1) + T(100000) * _(2) + T(10000) * _(3) + T(1000) * _(4) + T(100) * _(5) + T(10) * _(6) + _(7); - return ok(0) && ok(1) && ok(2) && ok(3) && ok(4) && ok(5) && ok(6) && ok(7); - case 9: - *v = T(100000000) * _(0) + T(10000000) * _(1) + T(1000000) * _(2) + T(100000) * _(3) + T(10000) * _(4) + T(1000) * _(5) + T(100) * _(6) + T(10) * _(7) + _(8); - return ok(0) && ok(1) && ok(2) && ok(3) && ok(4) && ok(5) && ok(6) && ok(7) && ok(8); - case 10: - *v = T(1000000000) * _(0) + T(100000000) * _(1) + T(10000000) * _(2) + T(1000000) * _(3) + T(100000) * _(4) + T(10000) * _(5) + T(1000) * _(6) + T(100) * _(7) + T(10) * _(8) + _(9); - return ok(0) && ok(1) && ok(2) && ok(3) && ok(4) && ok(5) && ok(6) && ok(7) && ok(8) && ok(9); - default: - { - size_t i = 0; - *v = 0; - for( ; i + 10 < s.len; ++i) - { - *v = *v * T(10) + _(i); - if(C4_UNLIKELY(!ok(i))) - return false; - } - *v = T(1000000000) * _(i) + T(100000000) * _(i+1) + T(10000000) * _(i+2) + T(1000000) * _(i+3) + T(100000) * _(i+4) + T(10000) * _(i+5) + T(1000) * _(i+6) + T(100) * _(i+7) + T(10) * _(i+8) + _(i+9); - return ok(i) && ok(i+1) && ok(i+2) && ok(i+3) && ok(i+4) && ok(i+5) && ok(i+6) && ok(i+7) && ok(i+8) && ok(i+9); - } - } - return false; -} - -C4_SUPPRESS_WARNING_GCC_CLANG_POP -#undef _ - - - - -#define DECLARE_BM(func) \ -template \ -void func(bm::State &st) \ -{ \ - random_strings_cref values = mkstrings_positive(); \ - T val = {}; \ - T sum = {}; \ - for(auto _ : st) \ - { \ - C4DOALL(kNumValues) \ - { \ - const bool ok = func(values.next(), &val); \ - sum += (T)(T(ok) + val); \ - } \ - } \ - bm::DoNotOptimize(sum); \ - report(st, kNumValues); \ -} - -#define DEFINE_BM(ty) \ - C4BM_TEMPLATE(unroll_switch_nocheck, ty); \ - C4BM_TEMPLATE(unroll_switch, ty); \ - C4BM_TEMPLATE(indexloop_restrictvar0, ty); \ - C4BM_TEMPLATE(indexloop_restrictvar1, ty); \ - C4BM_TEMPLATE(range_based_restrictvar0, ty); \ - C4BM_TEMPLATE(range_based_restrictvar1, ty); \ - C4BM_TEMPLATE(prefer_likely, ty); \ - C4BM_TEMPLATE(no_early_return, ty); \ - C4BM_TEMPLATE(no_early_return_auto_type, ty); \ - C4BM_TEMPLATE(no_early_return_auto_type2, ty); \ - - -DECLARE_BM(unroll_switch_nocheck) -DECLARE_BM(unroll_switch) -DECLARE_BM(indexloop_restrictvar0) -DECLARE_BM(indexloop_restrictvar1) -DECLARE_BM(range_based_restrictvar0) -DECLARE_BM(range_based_restrictvar1) -DECLARE_BM(prefer_likely) -DECLARE_BM(no_early_return) -DECLARE_BM(no_early_return_auto_type) -DECLARE_BM(no_early_return_auto_type2) - - -DEFINE_BM(uint8_t) -DEFINE_BM(int8_t) -DEFINE_BM(uint16_t) -DEFINE_BM(int16_t) -DEFINE_BM(uint32_t) -DEFINE_BM(int32_t) -DEFINE_BM(uint64_t) -DEFINE_BM(int64_t) - - -int main(int argc, char *argv[]) -{ - //do_test(); - bm::Initialize(&argc, argv); - bm::RunSpecifiedBenchmarks(); - return 0; -} diff --git a/thirdparty/ryml/ext/c4core/bm/bm_charconv.cpp b/thirdparty/ryml/ext/c4core/bm/bm_charconv.cpp deleted file mode 100644 index 888fb91b6..000000000 --- a/thirdparty/ryml/ext/c4core/bm/bm_charconv.cpp +++ /dev/null @@ -1,1617 +0,0 @@ -#include "./bm_charconv.hpp" - -#include -#if C4_CPP >= 17 -#include -#if defined(__cpp_lib_to_chars) -#define C4CORE_BM_HAVE_TOCHARS 1 -#endif -#include -#endif - -#ifdef C4CORE_BM_USE_RYU -#include -#include -#endif - -#ifdef C4CORE_BM_USE_FP -#include -#endif - - -// some of the benchmarks do not need to be templates, -// but it helps in the naming scheme. - -// xtoa means to string -// atox means string to - - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -C4FOR(T, isint) -c4_digits_dec(bm::State &st) -{ - random_values_cref values = mkvals_positive(); - unsigned sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - sum += c4::digits_dec(values.next()); - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -C4FOR(T, isint) -c4_digits_hex(bm::State &st) -{ - random_values_cref values = mkvals_positive(); - unsigned sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - sum += c4::digits_hex(values.next()); - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -C4FOR(T, isint) -c4_digits_oct(bm::State &st) -{ - random_values_cref values = mkvals_positive(); - unsigned sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - sum += c4::digits_oct(values.next()); - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -C4FOR(T, isint) -c4_digits_bin(bm::State &st) -{ - random_values_cref values = mkvals_positive(); - unsigned sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - sum += c4::digits_bin(values.next()); - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -C4FOR(T, isint) -atox_c4_read_dec(bm::State& st) -{ - random_strings_cref strings = mkstrings_positive(); - T val = {}, sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - c4::read_dec(strings.next(), &val); - sum += val; - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -C4FOR(T, isint) -atoxhex_c4_read_hex(bm::State& st) -{ - random_strings_cref strings = mkstrings_hex_positive(/*with_prefix*/false); - T val = {}, sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - c4::read_hex(strings.next(), &val); - sum += val; - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -C4FOR(T, isint) -atoxoct_c4_read_oct(bm::State& st) -{ - random_strings_cref strings = mkstrings_oct_positive(/*with_prefix*/false); - T val = {}, sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - c4::read_oct(strings.next(), &val); - sum += val; - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -C4FOR(T, isint) -atoxbin_c4_read_bin(bm::State& st) -{ - random_strings_cref strings = mkstrings_bin_positive(/*with_prefix*/false); - T val = {}, sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - c4::read_bin(strings.next(), &val); - sum += val; - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - - -C4FOR(T, isint) -xtoa_c4_write_dec(bm::State& st) -{ - string_buffer buf; - random_values_cref values = mkvals_positive(); - for(auto _ : st) - { - C4DOALL(kNumValues) - c4::write_dec(buf, values.next()); - } - bm::DoNotOptimize(buf); - report(st, kNumValues); -} - -C4FOR(T, isint) -xtoahex_c4_write_hex(bm::State& st) -{ - string_buffer buf; - random_values_cref values = mkvals_positive(); - for(auto _ : st) - { - C4DOALL(kNumValues) - c4::write_hex(buf, values.next()); - } - bm::DoNotOptimize(buf); - report(st, kNumValues); -} - -C4FOR(T, isint) -xtoaoct_c4_write_oct(bm::State& st) -{ - string_buffer buf; - random_values_cref values = mkvals_positive(); - for(auto _ : st) - { - C4DOALL(kNumValues) - c4::write_oct(buf, values.next()); - } - bm::DoNotOptimize(buf); - report(st, kNumValues); -} - -C4FOR(T, isint) -xtoabin_c4_write_bin(bm::State& st) -{ - string_buffer buf; - random_values_cref values = mkvals_positive(); - for(auto _ : st) - { - C4DOALL(kNumValues) - c4::write_bin(buf, values.next()); - } - bm::DoNotOptimize(buf); - report(st, kNumValues); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -C4FOR(T, isiint) -xtoa_c4_itoa(bm::State& st) -{ - string_buffer buf; - random_values_cref values = mkvals_positive(); - for(auto _ : st) - { - C4DOALL(kNumValues) - c4::itoa(buf, values.next()); - } - bm::DoNotOptimize(buf); - report(st, kNumValues); -} - -C4FOR(T, isuint) -xtoa_c4_utoa(bm::State& st) -{ - string_buffer buf; - random_values_cref values = mkvals_positive(); - for(auto _ : st) - { - C4DOALL(kNumValues) - c4::utoa(buf, values.next()); - } - bm::DoNotOptimize(buf); - report(st, kNumValues); -} - -C4FOR(T, isfloat) -xtoa_c4_ftoa(bm::State& st) -{ - string_buffer buf; - random_values_cref values = mkvals(); - for(auto _ : st) - { - C4DOALL(kNumValues) - c4::ftoa(buf, values.next()); - } - bm::DoNotOptimize(buf); - report(st, kNumValues); -} - -C4FOR(T, isdouble) -xtoa_c4_dtoa(bm::State& st) -{ - string_buffer buf; - random_values_cref values = mkvals(); - for(auto _ : st) - { - C4DOALL(kNumValues) - c4::dtoa(buf, values.next()); - } - bm::DoNotOptimize(buf); - report(st, kNumValues); -} - -C4FOR(T, isint) -xtoa_c4_xtoa(bm::State& st) -{ - string_buffer buf; - random_values values = mkvals_positive(); - for(auto _ : st) - { - C4DOALL(kNumValues) - c4::xtoa(buf, values.next()); - } - bm::DoNotOptimize(buf); - report(st, kNumValues); -} - -C4FOR(T, isreal) -xtoa_c4_xtoa(bm::State& st) -{ - string_buffer buf; - random_values_cref values = mkvals(); - for(auto _ : st) - { - C4DOALL(kNumValues) - c4::xtoa(buf, values.next()); - } - bm::DoNotOptimize(buf); - report(st, kNumValues); -} - - -//----------------------------------------------------------------------------- - -C4FOR(T, isiint) -atox_c4_atoi(bm::State& st) -{ - random_strings_cref strings = mkstrings_positive(); - T val = {}, sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - c4::atoi(strings.next(), &val); - sum += val; - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -C4FOR(T, isuint) -atox_c4_atou(bm::State& st) -{ - random_strings_cref strings = mkstrings_positive(); - T val = {}, sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - c4::atou(strings.next(), &val); - sum += val; - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -C4FOR(T, isfloat) -atox_c4_atof(bm::State& st) -{ - random_strings_cref strings = mkstrings(); - T val = {}, sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - c4::atof(strings.next(), &val); - sum += val; - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -C4FOR(T, isdouble) -atox_c4_atod(bm::State& st) -{ - random_strings_cref strings = mkstrings(); - T val = {}, sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - c4::atod(strings.next(), &val); - sum += val; - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -C4FOR(T, isint) -atox_c4_atox(bm::State& st) -{ - random_strings_cref strings = mkstrings_positive(); - T val = {}, sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - c4::atox(strings.next(), &val); - sum += val; - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -C4FOR(T, isreal) -atox_c4_atox(bm::State& st) -{ - random_strings_cref strings = mkstrings(); - T val = {}, sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - c4::atox(strings.next(), &val); - sum += val; - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - - -//----------------------------------------------------------------------------- - -C4FOR(T, isint) -atox_std_atoi(bm::State& st) -{ - random_strings_cref strings = mkstrings_positive(); - T val = {}, sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - val = (T) std::atoi(strings.next_s().c_str()); - sum += val; - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -C4FOR(T, isint) -atox_std_atol(bm::State& st) -{ - random_strings_cref strings = mkstrings_positive(); - T val = {}, sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - val = (T) std::atol(strings.next_s().c_str()); - sum += val; - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -C4FOR(T, isreal) -atox_std_atof(bm::State& st) -{ - random_strings_cref strings = mkstrings(); - T val = {}, sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - val = (T) std::atof(strings.next_s().c_str()); - sum += val; - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - - -//----------------------------------------------------------------------------- - -C4FOR(T, isint) -atox_std_strtol(bm::State& st) -{ - random_strings_cref strings = mkstrings_positive(); - T val = {}, sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - std::string const& s = strings.next_s(); - val = (T) std::strtol(s.data(), nullptr, 10); - sum += val; - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -C4FOR(T, isint) -atox_std_strtoll(bm::State& st) -{ - random_strings_cref strings = mkstrings_positive(); - T val = {}, sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - std::string const& s = strings.next_s(); - val = (T) std::strtoll(s.data(), nullptr, 10); - sum += val; - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -C4FOR(T, isint) -atox_std_strtoul(bm::State& st) -{ - random_strings_cref strings = mkstrings_positive(); - T val = {}, sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - std::string const& s = strings.next_s(); - val = (T) std::strtoul(s.data(), nullptr, 10); - sum += val; - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -C4FOR(T, isint) -atox_std_strtoull(bm::State& st) -{ - random_strings_cref strings = mkstrings_positive(); - T val = {}, sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - std::string const& s = strings.next_s(); - val = (T) std::strtoull(s.data(), nullptr, 10); - sum += val; - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -C4FOR(T, isreal) -atox_std_strtof(bm::State& st) -{ - random_strings_cref strings = mkstrings(); - T val = {}, sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - std::string const& s = strings.next_s(); - val = (T) std::strtof(s.data(), nullptr); - sum += val; - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -C4FOR(T, isreal) -atox_std_strtod(bm::State& st) -{ - random_strings_cref strings = mkstrings(); - T val = {}, sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - std::string const& s = strings.next_s(); - val = (T) std::strtod(s.data(), nullptr); - sum += val; - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -C4FOR(T, isreal) -atox_std_stof(bm::State &st) -{ - random_strings_cref strings = mkstrings(); - T val = {}, sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - val = std::stof(strings.next_s()); - sum += val; - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -C4FOR(T, isreal) -atox_std_stod(bm::State &st) -{ - random_strings_cref strings = mkstrings(); - T val = {}, sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - val = std::stod(strings.next_s()); - sum += val; - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - - -//----------------------------------------------------------------------------- - -#ifdef C4CORE_BM_USE_RYU -C4FOR(T, isfloat) -atox_ryu_s2f(bm::State &st) -{ - random_strings_cref strings = mkstrings(); - T val = {}, sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - c4::csubstr s = strings.next(); - s2f_n(s.data(), (int) s.size(), &val); - sum += val; - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -C4FOR(T, isdouble) -atox_ryu_s2d(bm::State &st) -{ - random_strings_cref strings = mkstrings(); - T val = {}, sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - c4::csubstr s = strings.next(); - s2d_n(s.data(), (int) s.size(), &val); - sum += val; - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -C4FOR(T, isfloat) -xtoa_ryu_f2s(bm::State &st) -{ - string_buffer buf; - random_values_cref values = mkvals(); - for(auto _ : st) - { - C4DOALL(kNumValues) - f2s_buffered_n(values.next(), buf.buf.str); - } - bm::DoNotOptimize(buf.buf); - report(st, kNumValues); -} - -C4FOR(T, isdouble) -xtoa_ryu_d2s(bm::State &st) -{ - string_buffer buf; - random_values_cref values = mkvals(); - for(auto _ : st) - { - C4DOALL(kNumValues) - d2s_buffered_n(values.next(), buf.buf.str); - } - bm::DoNotOptimize(buf.buf); - report(st, kNumValues); -} -#endif // C4CORE_BM_USE_RYU - - -//----------------------------------------------------------------------------- - -// fp is still experimental and undocumented; -// some assertions are firing in debug builds -// so we make these benchmarks available only with NDEBUG -#if (defined(C4CORE_BM_USE_FP)) && (!defined(NDEBUG)) -#undef C4CORE_BM_USE_FP -#endif - -#ifdef C4CORE_BM_USE_FP -C4FOR(T, isreal) -atox_fp_from_chars_limited(bm::State &st) -{ - random_strings_cref strings = mkstrings(); - T val = {}, sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - c4::csubstr s = strings.next(); - val = jkj::fp::from_chars_limited(s.begin(), s.end()).to_float(); - sum += val; - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} -#endif // C4CORE_BM_USE_FP - -#ifdef C4CORE_BM_USE_FP -C4FOR(T, isreal) -atox_fp_from_chars_unlimited(bm::State &st) -{ - random_strings_cref strings = mkstrings(); - T val = {}, sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - c4::csubstr s = strings.next(); - val = jkj::fp::from_chars_unlimited(s.begin(), s.end()).to_float(); - sum += val; - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} -#endif // C4CORE_BM_USE_FP - - -//----------------------------------------------------------------------------- - -C4FOR(T, isreal) -atox_fast_float(bm::State &st) -{ - random_strings_cref strings = mkstrings(); - T val = {}, sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - c4::csubstr s = strings.next(); - fast_float::from_chars(s.begin(), s.end(), val); - sum += val; - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - - -//----------------------------------------------------------------------------- - -template struct fmtspec; -template<> struct fmtspec< uint8_t> { static const char w[], r[]; }; -template<> struct fmtspec< int8_t> { static const char w[], r[]; }; -template<> struct fmtspec { static const char w[], r[]; }; -template<> struct fmtspec< int16_t> { static const char w[], r[]; }; -template<> struct fmtspec { static const char w[], r[]; }; -template<> struct fmtspec< int32_t> { static const char w[], r[]; }; -template<> struct fmtspec { static const char w[], r[]; }; -template<> struct fmtspec< int64_t> { static const char w[], r[]; }; -template<> struct fmtspec< float > { static const char w[], r[]; }; -template<> struct fmtspec< double > { static const char w[], r[]; }; - -constexpr const char fmtspec< uint8_t>::w[] = "%" PRIu8 ; -constexpr const char fmtspec< int8_t>::w[] = "%" PRIi8 ; -constexpr const char fmtspec::w[] = "%" PRIu16; -constexpr const char fmtspec< int16_t>::w[] = "%" PRIi16; -constexpr const char fmtspec::w[] = "%" PRIu32; -constexpr const char fmtspec< int32_t>::w[] = "%" PRIi32; -constexpr const char fmtspec::w[] = "%" PRIu64; -constexpr const char fmtspec< int64_t>::w[] = "%" PRIi64; -constexpr const char fmtspec< float >::w[] = "%g" ; -constexpr const char fmtspec< double >::w[] = "%lg" ; - -constexpr const char fmtspec< uint8_t>::r[] = "%" SCNu8 ; -constexpr const char fmtspec< int8_t>::r[] = "%" SCNi8 ; -constexpr const char fmtspec::r[] = "%" SCNu16; -constexpr const char fmtspec< int16_t>::r[] = "%" SCNi16; -constexpr const char fmtspec::r[] = "%" SCNu32; -constexpr const char fmtspec< int32_t>::r[] = "%" SCNi32; -constexpr const char fmtspec::r[] = "%" SCNu64; -constexpr const char fmtspec< int64_t>::r[] = "%" SCNi64; -constexpr const char fmtspec< float >::r[] = "%g" ; -constexpr const char fmtspec< double >::r[] = "%lg" ; - -C4FOR(T, isint) -xtoa_sprintf(bm::State& st) -{ - string_buffer buf; - random_values_cref values = mkvals_positive(); - for(auto _ : st) - { - C4DOALL(kNumValues) - ::snprintf(buf.buf.str, buf.buf.len, fmtspec::w, values.next()); - } - bm::DoNotOptimize(buf.buf); - report(st, kNumValues); -} - -C4FOR(T, isreal) -xtoa_sprintf(bm::State& st) -{ - string_buffer buf; - random_values_cref values = mkvals(); - C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH("-Wdouble-promotion") - for(auto _ : st) - { - C4DOALL(kNumValues) - ::snprintf(buf.buf.str, buf.buf.len, fmtspec::w, values.next()); - } - C4_SUPPRESS_WARNING_GCC_CLANG_POP - bm::DoNotOptimize(buf.buf); - report(st, kNumValues); -} - -C4FOR(T, isint) -atox_scanf(bm::State& st) -{ - random_strings_cref strings = mkstrings_positive(); - T val = {}, sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - ::sscanf(strings.next_s().c_str(), fmtspec::r, &val); - sum += val; - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -C4FOR(T, isreal) -atox_scanf(bm::State& st) -{ - random_strings_cref strings = mkstrings(); - T val = {}, sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - ::sscanf(strings.next_s().c_str(), fmtspec::r, &val); - sum += val; - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - - -//----------------------------------------------------------------------------- - -C4FOR(T, isint) -xtoa_sstream(bm::State& st) -{ - random_values_cref values = mkvals_positive(); - std::string out; C4_UNUSED(out); - for(auto _ : st) - { - C4DOALL(kNumValues) - { - std::stringstream ss; - ss << values.next(); - out = ss.str(); - } - } - bm::DoNotOptimize(out); - report(st, kNumValues); -} - -C4FOR(T, isreal) -xtoa_sstream(bm::State& st) -{ - random_values_cref values = mkvals(); - std::string out; C4_UNUSED(out); - for(auto _ : st) - { - C4DOALL(kNumValues) - { - std::stringstream ss; - ss << values.next(); - out = ss.str(); - } - } - bm::DoNotOptimize(out); - report(st, kNumValues); -} - -C4FOR(T, isint) -xtoa_sstream_reuse(bm::State& st) -{ - random_values_cref values = mkvals_positive(); - std::stringstream ss; - std::string out; C4_UNUSED(out); - for(auto _ : st) - { - C4DOALL(kNumValues) - { - ss.clear(); - ss.str(""); - ss << values.next(); - out = ss.str(); - } - } - bm::DoNotOptimize(out); - report(st, kNumValues); -} - -C4FOR(T, isreal) -xtoa_sstream_reuse(bm::State& st) -{ - random_values_cref values = mkvals(); - std::stringstream ss; - std::string out; C4_UNUSED(out); - for(auto _ : st) - { - C4DOALL(kNumValues) - { - ss.clear(); - ss.str(""); - ss << values.next(); - out = ss.str(); - } - } - bm::DoNotOptimize(out); - report(st, kNumValues); -} - -C4FOR(T, isint) -atox_sstream(bm::State& st) -{ - random_strings_cref strings = mkstrings_positive(); - T val = {}, sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - std::stringstream ss(strings.next_s()); - ss >> val; - sum += val; - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -C4FOR(T, isreal) -atox_sstream(bm::State& st) -{ - random_strings_cref strings = mkstrings(); - T val = {}, sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - std::stringstream ss(strings.next_s()); - ss >> val; - sum += val; - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -C4FOR(T, isint) -atox_sstream_reuse(bm::State& st) -{ - random_strings_cref strings = mkstrings_positive(); - std::stringstream ss; - T val = {}, sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - ss.clear(); - ss.str(strings.next_s()); - ss >> val; - sum += val; - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -C4FOR(T, isreal) -atox_sstream_reuse(bm::State& st) -{ - random_strings_cref strings = mkstrings(); - std::stringstream ss; - T val = {}, sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - ss.clear(); - ss.str(strings.next_s()); - ss >> val; - sum += val; - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - - -//----------------------------------------------------------------------------- - -C4FOR(T, isint) -xtoa_std_to_string(bm::State& st) -{ - random_values_cref values = mkvals_positive(); - std::string out; - for(auto _ : st) - { - C4DOALL(kNumValues) - out = std::to_string(values.next()); - } - bm::DoNotOptimize(out); - report(st, kNumValues); -} - -C4FOR(T, isreal) -xtoa_std_to_string(bm::State& st) -{ - random_values_cref values = mkvals(); - std::string out; - for(auto _ : st) - { - C4DOALL(kNumValues) - out = std::to_string(values.next()); - } - bm::DoNotOptimize(out); - report(st, kNumValues); -} - - -//----------------------------------------------------------------------------- - -C4FOR(T, isint) -xtoa_c4_to_chars(bm::State& st) -{ - random_values_cref values = mkvals_positive(); - string_buffer buf; - for(auto _ : st) - { - C4DOALL(kNumValues) - c4::to_chars(buf, values.next()); - } - bm::DoNotOptimize(buf); - report(st, kNumValues); -} - -C4FOR(T, isreal) -xtoa_c4_to_chars(bm::State& st) -{ - random_values_cref values = mkvals(); - string_buffer buf; - for(auto _ : st) - { - C4DOALL(kNumValues) - c4::to_chars(buf, values.next()); - } - bm::DoNotOptimize(buf); - report(st, kNumValues); -} - -C4FOR(T, isint) -atox_c4_from_chars(bm::State& st) -{ - random_strings_cref strings = mkstrings_positive(); - T val = {}, sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - c4::from_chars(strings.next(), &val); - sum += val; - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -C4FOR(T, isint) -atox_c4_from_chars_checked(bm::State& st) -{ - random_strings_cref strings = mkstrings_positive(); - T val = {}, sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - c4::from_chars(strings.next(), c4::fmt::overflow_checked(val)); - sum += val; - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -C4FOR(T, isreal) -atox_c4_from_chars(bm::State& st) -{ - random_strings_cref strings = mkstrings(); - T val = {}, sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - c4::from_chars(strings.next(), &val); - sum += val; - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -#if (C4_CPP >= 17) -C4FOR(T, isint) -xtoa_std_to_chars(bm::State& st) -{ - random_values_cref values = mkvals_positive(); - string_buffer buf; - for(auto _ : st) - { - C4DOALL(kNumValues) - std::to_chars(buf.begin(), buf.end(), values.next()); - } - bm::DoNotOptimize(buf); - report(st, kNumValues); -} -#endif - -#if C4CORE_BM_HAVE_TOCHARS -C4FOR(T, isreal) -xtoa_std_to_chars(bm::State& st) -{ - random_values_cref values = mkvals(); - string_buffer buf; - for(auto _ : st) - { - C4DOALL(kNumValues) - std::to_chars(buf.begin(), buf.end(), values.next()); - } - bm::DoNotOptimize(buf); - report(st, kNumValues); -} -#endif - -#if (C4_CPP >= 17) -C4FOR(T, isint) -atox_std_from_chars(bm::State& st) -{ - random_strings_cref strings = mkstrings_positive(); - T val = {}, sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - c4::csubstr s = strings.next(); - std::from_chars(s.begin(), s.end(), val); - sum += val; - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} -#endif - -#if C4CORE_BM_HAVE_TOCHARS -C4FOR(T, isreal) -atox_std_from_chars(bm::State& st) -{ - random_strings_cref strings = mkstrings(); - T val = {}, sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - c4::csubstr s = strings.next(); - std::from_chars(s.begin(), s.end(), val); - sum += val; - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} -#endif - - -//----------------------------------------------------------------------------- - -C4BM_TEMPLATE(c4_digits_dec, uint8_t); -C4BM_TEMPLATE(c4_digits_hex, uint8_t); -C4BM_TEMPLATE(c4_digits_oct, uint8_t); -C4BM_TEMPLATE(c4_digits_bin, uint8_t); - -C4BM_TEMPLATE(c4_digits_dec, int8_t); -C4BM_TEMPLATE(c4_digits_hex, int8_t); -C4BM_TEMPLATE(c4_digits_oct, int8_t); -C4BM_TEMPLATE(c4_digits_bin, int8_t); - -C4BM_TEMPLATE(c4_digits_dec, uint16_t); -C4BM_TEMPLATE(c4_digits_hex, uint16_t); -C4BM_TEMPLATE(c4_digits_oct, uint16_t); -C4BM_TEMPLATE(c4_digits_bin, uint16_t); - -C4BM_TEMPLATE(c4_digits_dec, int16_t); -C4BM_TEMPLATE(c4_digits_hex, int16_t); -C4BM_TEMPLATE(c4_digits_oct, int16_t); -C4BM_TEMPLATE(c4_digits_bin, int16_t); - -C4BM_TEMPLATE(c4_digits_dec, uint32_t); -C4BM_TEMPLATE(c4_digits_hex, uint32_t); -C4BM_TEMPLATE(c4_digits_oct, uint32_t); -C4BM_TEMPLATE(c4_digits_bin, uint32_t); - -C4BM_TEMPLATE(c4_digits_dec, int32_t); -C4BM_TEMPLATE(c4_digits_hex, int32_t); -C4BM_TEMPLATE(c4_digits_oct, int32_t); -C4BM_TEMPLATE(c4_digits_bin, int32_t); - -C4BM_TEMPLATE(c4_digits_dec, uint64_t); -C4BM_TEMPLATE(c4_digits_hex, uint64_t); -C4BM_TEMPLATE(c4_digits_oct, uint64_t); -C4BM_TEMPLATE(c4_digits_bin, uint64_t); - -C4BM_TEMPLATE(c4_digits_dec, int64_t); -C4BM_TEMPLATE(c4_digits_hex, int64_t); -C4BM_TEMPLATE(c4_digits_oct, int64_t); -C4BM_TEMPLATE(c4_digits_bin, int64_t); - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -C4BM_TEMPLATE(xtoahex_c4_write_hex, uint8_t); -C4BM_TEMPLATE(xtoaoct_c4_write_oct, uint8_t); -C4BM_TEMPLATE(xtoabin_c4_write_bin, uint8_t); - -C4BM_TEMPLATE(xtoahex_c4_write_hex, int8_t); -C4BM_TEMPLATE(xtoaoct_c4_write_oct, int8_t); -C4BM_TEMPLATE(xtoabin_c4_write_bin, int8_t); - -C4BM_TEMPLATE(xtoahex_c4_write_hex, uint16_t); -C4BM_TEMPLATE(xtoaoct_c4_write_oct, uint16_t); -C4BM_TEMPLATE(xtoabin_c4_write_bin, uint16_t); - -C4BM_TEMPLATE(xtoahex_c4_write_hex, int16_t); -C4BM_TEMPLATE(xtoaoct_c4_write_oct, int16_t); -C4BM_TEMPLATE(xtoabin_c4_write_bin, int16_t); - -C4BM_TEMPLATE(xtoahex_c4_write_hex, uint32_t); -C4BM_TEMPLATE(xtoaoct_c4_write_oct, uint32_t); -C4BM_TEMPLATE(xtoabin_c4_write_bin, uint32_t); - -C4BM_TEMPLATE(xtoahex_c4_write_hex, int32_t); -C4BM_TEMPLATE(xtoaoct_c4_write_oct, int32_t); -C4BM_TEMPLATE(xtoabin_c4_write_bin, int32_t); - -C4BM_TEMPLATE(xtoahex_c4_write_hex, uint64_t); -C4BM_TEMPLATE(xtoaoct_c4_write_oct, uint64_t); -C4BM_TEMPLATE(xtoabin_c4_write_bin, uint64_t); - -C4BM_TEMPLATE(xtoahex_c4_write_hex, int64_t); -C4BM_TEMPLATE(xtoaoct_c4_write_oct, int64_t); -C4BM_TEMPLATE(xtoabin_c4_write_bin, int64_t); - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -C4BM_TEMPLATE(xtoa_c4_write_dec, uint8_t); -C4BM_TEMPLATE(xtoa_c4_utoa, uint8_t); -C4BM_TEMPLATE(xtoa_c4_xtoa, uint8_t); -C4BM_TEMPLATE(xtoa_c4_to_chars, uint8_t); -#if (C4_CPP >= 17) -C4BM_TEMPLATE_TO_CHARS_INT(xtoa_std_to_chars, uint8_t); -#endif -C4BM_TEMPLATE(xtoa_std_to_string, uint8_t); -C4BM_TEMPLATE(xtoa_sprintf, uint8_t); -C4BM_TEMPLATE(xtoa_sstream_reuse, uint8_t); -C4BM_TEMPLATE(xtoa_sstream, uint8_t); - -C4BM_TEMPLATE(xtoa_c4_write_dec, int8_t); -C4BM_TEMPLATE(xtoa_c4_itoa, int8_t); -C4BM_TEMPLATE(xtoa_c4_xtoa, int8_t); -C4BM_TEMPLATE(xtoa_c4_to_chars, int8_t); -#if (C4_CPP >= 17) -C4BM_TEMPLATE_TO_CHARS_INT(xtoa_std_to_chars, int8_t); -#endif -C4BM_TEMPLATE(xtoa_std_to_string, int8_t); -C4BM_TEMPLATE(xtoa_sprintf, int8_t); -C4BM_TEMPLATE(xtoa_sstream_reuse, int8_t); -C4BM_TEMPLATE(xtoa_sstream, int8_t); - -C4BM_TEMPLATE(xtoa_c4_write_dec, uint16_t); -C4BM_TEMPLATE(xtoa_c4_utoa, uint16_t); -C4BM_TEMPLATE(xtoa_c4_xtoa, uint16_t); -C4BM_TEMPLATE(xtoa_c4_to_chars, uint16_t); -#if (C4_CPP >= 17) -C4BM_TEMPLATE_TO_CHARS_INT(xtoa_std_to_chars, uint16_t); -#endif -C4BM_TEMPLATE(xtoa_std_to_string, uint16_t); -C4BM_TEMPLATE(xtoa_sprintf, uint16_t); -C4BM_TEMPLATE(xtoa_sstream_reuse, uint16_t); -C4BM_TEMPLATE(xtoa_sstream, uint16_t); - -C4BM_TEMPLATE(xtoa_c4_write_dec, int16_t); -C4BM_TEMPLATE(xtoa_c4_itoa, int16_t); -C4BM_TEMPLATE(xtoa_c4_xtoa, int16_t); -C4BM_TEMPLATE(xtoa_c4_to_chars, int16_t); -#if (C4_CPP >= 17) -C4BM_TEMPLATE_TO_CHARS_INT(xtoa_std_to_chars, int16_t); -#endif -C4BM_TEMPLATE(xtoa_std_to_string, int16_t); -C4BM_TEMPLATE(xtoa_sprintf, int16_t); -C4BM_TEMPLATE(xtoa_sstream_reuse, int16_t); -C4BM_TEMPLATE(xtoa_sstream, int16_t); - -C4BM_TEMPLATE(xtoa_c4_write_dec, uint32_t); -C4BM_TEMPLATE(xtoa_c4_utoa, uint32_t); -C4BM_TEMPLATE(xtoa_c4_xtoa, uint32_t); -C4BM_TEMPLATE(xtoa_c4_to_chars, uint32_t); -#if (C4_CPP >= 17) -C4BM_TEMPLATE_TO_CHARS_INT(xtoa_std_to_chars, uint32_t); -#endif -C4BM_TEMPLATE(xtoa_std_to_string, uint32_t); -C4BM_TEMPLATE(xtoa_sprintf, uint32_t); -C4BM_TEMPLATE(xtoa_sstream_reuse, uint32_t); -C4BM_TEMPLATE(xtoa_sstream, uint32_t); - -C4BM_TEMPLATE(xtoa_c4_write_dec, int32_t); -C4BM_TEMPLATE(xtoa_c4_itoa, int32_t); -C4BM_TEMPLATE(xtoa_c4_xtoa, int32_t); -C4BM_TEMPLATE(xtoa_c4_to_chars, int32_t); -#if (C4_CPP >= 17) -C4BM_TEMPLATE_TO_CHARS_INT(xtoa_std_to_chars, int32_t); -#endif -C4BM_TEMPLATE(xtoa_std_to_string, int32_t); -C4BM_TEMPLATE(xtoa_sprintf, int32_t); -C4BM_TEMPLATE(xtoa_sstream_reuse, int32_t); -C4BM_TEMPLATE(xtoa_sstream, int32_t); - -C4BM_TEMPLATE(xtoa_c4_write_dec, uint64_t); -C4BM_TEMPLATE(xtoa_c4_utoa, uint64_t); -C4BM_TEMPLATE(xtoa_c4_xtoa, uint64_t); -C4BM_TEMPLATE(xtoa_c4_to_chars, uint64_t); -#if (C4_CPP >= 17) -C4BM_TEMPLATE_TO_CHARS_INT(xtoa_std_to_chars, uint64_t); -#endif -C4BM_TEMPLATE(xtoa_std_to_string, uint64_t); -C4BM_TEMPLATE(xtoa_sprintf, uint64_t); -C4BM_TEMPLATE(xtoa_sstream_reuse, uint64_t); -C4BM_TEMPLATE(xtoa_sstream, uint64_t); - -C4BM_TEMPLATE(xtoa_c4_write_dec, int64_t); -C4BM_TEMPLATE(xtoa_c4_itoa, int64_t); -C4BM_TEMPLATE(xtoa_c4_xtoa, int64_t); -C4BM_TEMPLATE(xtoa_c4_to_chars, int64_t); -#if (C4_CPP >= 17) -C4BM_TEMPLATE_TO_CHARS_INT(xtoa_std_to_chars, int64_t); -#endif -C4BM_TEMPLATE(xtoa_std_to_string, int64_t); -C4BM_TEMPLATE(xtoa_sprintf, int64_t); -C4BM_TEMPLATE(xtoa_sstream_reuse, int64_t); -C4BM_TEMPLATE(xtoa_sstream, int64_t); - -C4BM_TEMPLATE(xtoa_c4_ftoa, float); -C4BM_TEMPLATE(xtoa_c4_xtoa, float); -C4BM_TEMPLATE(xtoa_c4_to_chars, float); -#ifdef C4CORE_BM_USE_RYU -C4BM_TEMPLATE(xtoa_ryu_f2s, float); -#endif -#ifdef C4CORE_BM_HAVE_TOCHARS -C4BM_TEMPLATE_TO_CHARS_FLOAT(xtoa_std_to_chars, float); -#endif -C4BM_TEMPLATE(xtoa_std_to_string, float); -C4BM_TEMPLATE(xtoa_sprintf, float); -C4BM_TEMPLATE(xtoa_sstream_reuse, float); -C4BM_TEMPLATE(xtoa_sstream, float); - -C4BM_TEMPLATE(xtoa_c4_dtoa, double); -C4BM_TEMPLATE(xtoa_c4_xtoa, double); -C4BM_TEMPLATE(xtoa_c4_to_chars, double); -#ifdef C4CORE_BM_USE_RYU -C4BM_TEMPLATE(xtoa_ryu_d2s, double); -#endif -#ifdef C4CORE_BM_HAVE_TOCHARS -C4BM_TEMPLATE_TO_CHARS_FLOAT(xtoa_std_to_chars, double); -#endif -C4BM_TEMPLATE(xtoa_std_to_string, double); -C4BM_TEMPLATE(xtoa_sprintf, double); -C4BM_TEMPLATE(xtoa_sstream_reuse, double); -C4BM_TEMPLATE(xtoa_sstream, double); - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -C4BM_TEMPLATE(atoxhex_c4_read_hex, uint8_t); -C4BM_TEMPLATE(atoxoct_c4_read_oct, uint8_t); -C4BM_TEMPLATE(atoxbin_c4_read_bin, uint8_t); - -C4BM_TEMPLATE(atoxhex_c4_read_hex, int8_t); -C4BM_TEMPLATE(atoxoct_c4_read_oct, int8_t); -C4BM_TEMPLATE(atoxbin_c4_read_bin, int8_t); - -C4BM_TEMPLATE(atoxhex_c4_read_hex, uint16_t); -C4BM_TEMPLATE(atoxoct_c4_read_oct, uint16_t); -C4BM_TEMPLATE(atoxbin_c4_read_bin, uint16_t); - -C4BM_TEMPLATE(atoxhex_c4_read_hex, int16_t); -C4BM_TEMPLATE(atoxoct_c4_read_oct, int16_t); -C4BM_TEMPLATE(atoxbin_c4_read_bin, int16_t); - -C4BM_TEMPLATE(atoxhex_c4_read_hex, uint32_t); -C4BM_TEMPLATE(atoxoct_c4_read_oct, uint32_t); -C4BM_TEMPLATE(atoxbin_c4_read_bin, uint32_t); - -C4BM_TEMPLATE(atoxhex_c4_read_hex, int32_t); -C4BM_TEMPLATE(atoxoct_c4_read_oct, int32_t); -C4BM_TEMPLATE(atoxbin_c4_read_bin, int32_t); - -C4BM_TEMPLATE(atoxhex_c4_read_hex, uint64_t); -C4BM_TEMPLATE(atoxoct_c4_read_oct, uint64_t); -C4BM_TEMPLATE(atoxbin_c4_read_bin, uint64_t); - -C4BM_TEMPLATE(atoxhex_c4_read_hex, int64_t); -C4BM_TEMPLATE(atoxoct_c4_read_oct, int64_t); -C4BM_TEMPLATE(atoxbin_c4_read_bin, int64_t); - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - - -C4BM_TEMPLATE(atox_c4_read_dec, uint8_t); -C4BM_TEMPLATE(atox_c4_atou, uint8_t); -C4BM_TEMPLATE(atox_c4_atox, uint8_t); -C4BM_TEMPLATE(atox_c4_from_chars, uint8_t); -C4BM_TEMPLATE(atox_c4_from_chars_checked, uint8_t); -#if (C4_CPP >= 17) -C4BM_TEMPLATE_TO_CHARS_INT(atox_std_from_chars, uint8_t); -#endif -C4BM_TEMPLATE(atox_std_atoi, uint8_t); -C4BM_TEMPLATE(atox_std_strtoul, uint8_t); -C4BM_TEMPLATE(atox_scanf, uint8_t); -C4BM_TEMPLATE(atox_sstream_reuse, uint8_t); -C4BM_TEMPLATE(atox_sstream, uint8_t); - -C4BM_TEMPLATE(atox_c4_read_dec, int8_t); -C4BM_TEMPLATE(atox_c4_atoi, int8_t); -C4BM_TEMPLATE(atox_c4_atox, int8_t); -C4BM_TEMPLATE(atox_c4_from_chars, int8_t); -C4BM_TEMPLATE(atox_c4_from_chars_checked, int8_t); -#if (C4_CPP >= 17) -C4BM_TEMPLATE_TO_CHARS_INT(atox_std_from_chars, int8_t); -#endif -C4BM_TEMPLATE(atox_std_atoi, int8_t); -C4BM_TEMPLATE(atox_std_strtol, int8_t); -C4BM_TEMPLATE(atox_scanf, int8_t); -C4BM_TEMPLATE(atox_sstream_reuse, int8_t); -C4BM_TEMPLATE(atox_sstream, int8_t); - -C4BM_TEMPLATE(atox_c4_read_dec, uint16_t); -C4BM_TEMPLATE(atox_c4_atou, uint16_t); -C4BM_TEMPLATE(atox_c4_atox, uint16_t); -C4BM_TEMPLATE(atox_c4_from_chars, uint16_t); -C4BM_TEMPLATE(atox_c4_from_chars_checked, uint16_t); -#if (C4_CPP >= 17) -C4BM_TEMPLATE_TO_CHARS_INT(atox_std_from_chars, uint16_t); -#endif -C4BM_TEMPLATE(atox_std_atoi, uint16_t); -C4BM_TEMPLATE(atox_std_strtoul, uint16_t); -C4BM_TEMPLATE(atox_scanf, uint16_t); -C4BM_TEMPLATE(atox_sstream_reuse, uint16_t); -C4BM_TEMPLATE(atox_sstream, uint16_t); - -C4BM_TEMPLATE(atox_c4_read_dec, int16_t); -C4BM_TEMPLATE(atox_c4_atoi, int16_t); -C4BM_TEMPLATE(atox_c4_atox, int16_t); -C4BM_TEMPLATE(atox_c4_from_chars, int16_t); -C4BM_TEMPLATE(atox_c4_from_chars_checked, int16_t); -#if (C4_CPP >= 17) -C4BM_TEMPLATE_TO_CHARS_INT(atox_std_from_chars, int16_t); -#endif -C4BM_TEMPLATE(atox_std_atoi, int16_t); -C4BM_TEMPLATE(atox_std_strtol, int16_t); -C4BM_TEMPLATE(atox_scanf, int16_t); -C4BM_TEMPLATE(atox_sstream_reuse, int16_t); -C4BM_TEMPLATE(atox_sstream, int16_t); - -C4BM_TEMPLATE(atox_c4_read_dec, uint32_t); -C4BM_TEMPLATE(atox_c4_atou, uint32_t); -C4BM_TEMPLATE(atox_c4_atox, uint32_t); -C4BM_TEMPLATE(atox_c4_from_chars, uint32_t); -C4BM_TEMPLATE(atox_c4_from_chars_checked, uint32_t); -#if (C4_CPP >= 17) -C4BM_TEMPLATE_TO_CHARS_INT(atox_std_from_chars, uint32_t); -#endif -C4BM_TEMPLATE(atox_std_atoi, uint32_t); -C4BM_TEMPLATE(atox_std_strtoul, uint32_t); -C4BM_TEMPLATE(atox_scanf, uint32_t); -C4BM_TEMPLATE(atox_sstream_reuse, uint32_t); -C4BM_TEMPLATE(atox_sstream, uint32_t); - -C4BM_TEMPLATE(atox_c4_read_dec, int32_t); -C4BM_TEMPLATE(atox_c4_atoi, int32_t); -C4BM_TEMPLATE(atox_c4_atox, int32_t); -C4BM_TEMPLATE(atox_c4_from_chars, int32_t); -C4BM_TEMPLATE(atox_c4_from_chars_checked, int32_t); -#if (C4_CPP >= 17) -C4BM_TEMPLATE_TO_CHARS_INT(atox_std_from_chars, int32_t); -#endif -C4BM_TEMPLATE(atox_std_atoi, int32_t); -C4BM_TEMPLATE(atox_std_strtol, int32_t); -C4BM_TEMPLATE(atox_scanf, int32_t); -C4BM_TEMPLATE(atox_sstream_reuse, int32_t); -C4BM_TEMPLATE(atox_sstream, int32_t); - -C4BM_TEMPLATE(atox_c4_read_dec, uint64_t); -C4BM_TEMPLATE(atox_c4_atou, uint64_t); -C4BM_TEMPLATE(atox_c4_atox, uint64_t); -C4BM_TEMPLATE(atox_c4_from_chars, uint64_t); -C4BM_TEMPLATE(atox_c4_from_chars_checked, uint64_t); -#if (C4_CPP >= 17) -C4BM_TEMPLATE_TO_CHARS_INT(atox_std_from_chars, uint64_t); -#endif -C4BM_TEMPLATE(atox_std_atol, uint64_t); -C4BM_TEMPLATE(atox_std_strtoull, uint64_t); -C4BM_TEMPLATE(atox_scanf, uint64_t); -C4BM_TEMPLATE(atox_sstream_reuse, uint64_t); -C4BM_TEMPLATE(atox_sstream, uint64_t); - -C4BM_TEMPLATE(atox_c4_read_dec, int64_t); -C4BM_TEMPLATE(atox_c4_atoi, int64_t); -C4BM_TEMPLATE(atox_c4_atox, int64_t); -C4BM_TEMPLATE(atox_c4_from_chars, int64_t); -C4BM_TEMPLATE(atox_c4_from_chars_checked, int64_t); -#if (C4_CPP >= 17) -C4BM_TEMPLATE_TO_CHARS_INT(atox_std_from_chars, int64_t); -#endif -C4BM_TEMPLATE(atox_std_atol, int64_t); -C4BM_TEMPLATE(atox_std_strtoll, int64_t); -C4BM_TEMPLATE(atox_scanf, int64_t); -C4BM_TEMPLATE(atox_sstream_reuse, int64_t); -C4BM_TEMPLATE(atox_sstream, int64_t); - -C4BM_TEMPLATE(atox_c4_atof, float); -C4BM_TEMPLATE(atox_c4_atox, float); -C4BM_TEMPLATE(atox_c4_from_chars, float); -C4BM_TEMPLATE(atox_fast_float, float); -#ifdef C4CORE_BM_HAVE_TOCHARS -C4BM_TEMPLATE_TO_CHARS_FLOAT(atox_std_from_chars, float); -#endif -#ifdef C4CORE_BM_USE_RYU -C4BM_TEMPLATE(atox_ryu_s2f, float); -#endif -#ifdef C4CORE_BM_USE_FP -C4BM_FP_BENCHMARK(atox_fp_from_chars_limited, float); -C4BM_FP_BENCHMARK(atox_fp_from_chars_unlimited, float); -#endif -C4BM_TEMPLATE(atox_std_atof, float); -C4BM_TEMPLATE(atox_std_strtof, float); -C4BM_TEMPLATE(atox_std_stof, float); -C4BM_TEMPLATE(atox_scanf, float); -C4BM_TEMPLATE(atox_sstream_reuse, float); -C4BM_TEMPLATE(atox_sstream, float); - -C4BM_TEMPLATE(atox_c4_atod, double); -C4BM_TEMPLATE(atox_c4_atox, double); -C4BM_TEMPLATE(atox_c4_from_chars, double); -C4BM_TEMPLATE(atox_fast_float, double); -#ifdef C4CORE_BM_HAVE_TOCHARS -C4BM_TEMPLATE_TO_CHARS_FLOAT(atox_std_from_chars, double); -#endif -#ifdef C4CORE_BM_USE_RYU -C4BM_TEMPLATE(atox_ryu_s2d, double); -#endif -#ifdef C4CORE_BM_USE_FP -C4BM_FP_BENCHMARK(atox_fp_from_chars_limited, double); -C4BM_FP_BENCHMARK(atox_fp_from_chars_unlimited, double); -#endif -C4BM_TEMPLATE(atox_std_atof, double); -C4BM_TEMPLATE(atox_std_strtod, double); -C4BM_TEMPLATE(atox_std_stod, double); -C4BM_TEMPLATE(atox_scanf, double); -C4BM_TEMPLATE(atox_sstream_reuse, double); -C4BM_TEMPLATE(atox_sstream, double); - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -int main(int argc, char *argv[]) -{ - bm::Initialize(&argc, argv); - bm::RunSpecifiedBenchmarks(); - return 0; -} - -#include diff --git a/thirdparty/ryml/ext/c4core/bm/bm_charconv.hpp b/thirdparty/ryml/ext/c4core/bm/bm_charconv.hpp deleted file mode 100644 index 3a2b7dc13..000000000 --- a/thirdparty/ryml/ext/c4core/bm/bm_charconv.hpp +++ /dev/null @@ -1,454 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -inline double getmax(std::vector const& v) -{ - return *(std::max_element(std::begin(v), std::end(v))); -} -inline double getmin(std::vector const& v) -{ - return *(std::min_element(std::begin(v), std::end(v))); -} -inline double getrange(std::vector const& v) -{ - auto min_max = std::minmax_element(std::begin(v), std::end(v)); - return *min_max.second - *min_max.first; -} - -#define _c4bm_stats \ - /*->Repetitions(20)*/ \ - ->DisplayAggregatesOnly(true) \ - ->ComputeStatistics("range", &getrange) \ - ->ComputeStatistics("max", &getmax) \ - ->ComputeStatistics("min", &getmin) - -#define C4BM_TEMPLATE(fn, ...) BENCHMARK_TEMPLATE(fn, __VA_ARGS__) _c4bm_stats - - -// benchmarks depending on c++17 features are disabled using the -// preprocessor. google benchmark has state.SkipWithError() but it -// makes the program return a nonzero exit code when it finishes. So -// we must resort to the preprocessor to conditionally disable these -// benchmarks -#if defined(__cpp_lib_to_chars) || (C4_CPP >= 17) -#define C4BM_TEMPLATE_TO_CHARS_INT(fn, ...) BENCHMARK_TEMPLATE(fn, __VA_ARGS__) _c4bm_stats -#define C4BM_TEMPLATE_TO_CHARS_FLOAT(fn, ...) BENCHMARK_TEMPLATE(fn, __VA_ARGS__) _c4bm_stats -#else -#define C4BM_TEMPLATE_TO_CHARS_INT(fn, ...) void shutup_extra_semicolon() -#define C4BM_TEMPLATE_TO_CHARS_FLOAT(fn, ...) void shutup_extra_semicolon() -#endif - -C4_SUPPRESS_WARNING_GCC_CLANG_PUSH -C4_SUPPRESS_WARNING_GCC_CLANG("-Wdouble-promotion") -C4_SUPPRESS_WARNING_GCC_CLANG("-Wdeprecated") -C4_SUPPRESS_WARNING_GCC_CLANG("-Wsign-conversion") -C4_SUPPRESS_WARNING_GCC_CLANG("-Wconversion") - -#include - - -namespace bm = benchmark; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// utilities for use in the benchmarks below - - -// facilities to deuglify SFINAE -#define C4FOR(ty, condition) \ - template \ - typename std::enable_if::type -#define C4FOR2(ty1, ty2, condition) \ - template \ - typename std::enable_if::type - -#define isint(ty) std::is_integral::value -#define isiint(ty) std::is_integral::value && !std::is_unsigned::value -#define isuint(ty) std::is_integral::value && std::is_unsigned::value -#define isreal(ty) std::is_floating_point::value -#define isfloat(ty) std::is_same::value -#define isdouble(ty) std::is_same::value - - -/** convenience wrapper to avoid boilerplate code */ -template -void report(bm::State &st, size_t numvals=1) -{ - int64_t iters = (int64_t)(st.iterations() * numvals); - int64_t bytes = (int64_t)(st.iterations() * numvals * sizeof(T)); - st.SetBytesProcessed(bytes); - st.SetItemsProcessed(iters); -} -template -void report_threadavg(bm::State &st, size_t numvals=1) -{ - int64_t iters = (int64_t)(st.iterations() * numvals); - int64_t bytes = (int64_t)(st.iterations() * numvals * sizeof(T)); - st.SetBytesProcessed(bytes / (int64_t)st.threads()); - st.SetItemsProcessed(iters / (int64_t)st.threads()); -} - -template -constexpr bool is_pot(T val) -{ - return val > 0 && (val & (val-T(1))) == 0; -} - -constexpr const uint64_t kSeed = 37; -constexpr const size_t kNumValues = 1u<<20; // 1.049M -C4_STATIC_ASSERT(is_pot(kNumValues)); - - -template -T gen(Dist &dist, Eng &eng) -{ - return static_cast(dist(eng)); -} - -template -T gen_pos(Dist &dist, Eng &eng) -{ - T val = static_cast(dist(eng)); - while(val <= T(0)) - val = static_cast(dist(eng)); - return val; -} - -/** generate in place a random sequence of values: integral version*/ -C4FOR(T, isint) -generate_n(T *begin, T *end) -{ - // do not use T in the distribution: - // N4659 29.6.1.1 [rand.req.genl]/1e requires one of short, int, long, long long, unsigned short, unsigned int, unsigned long, or unsigned long long - std::uniform_int_distribution idist; - c4::rng::pcg rng(kSeed); - for(; begin != end; ++begin) - *begin = gen(idist, rng); -} - -C4FOR(T, isint) -generate_n_positive(T *begin, T *end) -{ - // do not use T in the distribution: - // N4659 29.6.1.1 [rand.req.genl]/1e requires one of short, int, long, long long, unsigned short, unsigned int, unsigned long, or unsigned long long - std::uniform_int_distribution idist; - c4::rng::pcg rng(kSeed); - for(; begin != end; ++begin) - *begin = gen_pos(idist, rng); -} - -/** generate in place a random sequence of values: real-number version*/ -C4FOR(T, isreal) -generate_n(T *begin, T *end) -{ - c4::rng::pcg rng(kSeed); - // make sure we also have some integral numbers in the real sequence - T *rstart = begin + (std::distance(begin, end) / 20); // 5% integral numbers - std::uniform_int_distribution idist; - std::uniform_real_distribution rdist; - for(; begin != rstart; ++begin) - *begin = gen(idist, rng); - for(; begin != end; ++begin) - *begin = gen(rdist, rng); -} - -/** generate in place a random sequence of values: real-number version*/ -C4FOR(T, isreal) -generate_n_positive(T *begin, T *end) -{ - c4::rng::pcg rng(kSeed); - // make sure we also have some integral numbers in the real sequence - T *rstart = begin + (std::distance(begin, end) / 20); // 5% integral numbers - std::uniform_int_distribution idist; - std::uniform_real_distribution rdist; - for(; begin != rstart; ++begin) - *begin = gen_pos(idist, rng); - for(; begin != end; ++begin) - *begin = gen_pos(rdist, rng); -} - - -/** a ring buffer with input values for xtoa benchmarks */ -template -struct random_values -{ - std::vector v; - mutable size_t curr; - size_t szm1; - T next() const { T f = v[curr]; curr = (curr + 1) & szm1; return f; } - random_values(bool positive_only, size_t sz) : v(sz), curr(0), szm1(sz) - { - C4_CHECK(is_pot(sz)); - if(positive_only) - generate_n_positive(&v.front(), &v.back()); - else - generate_n(&v.front(), &v.back()); - } -}; -template -using random_values_cref = random_values const&; - -template -random_values_cref mkvals() -{ - static random_values vals(/*positive_only*/false, kNumValues); - return vals; -} -template -random_values_cref mkvals_positive() -{ - static random_values vals(/*positive_only*/true, kNumValues); - return vals; -} - - -/** a ring buffer with input strings for atox benchmarks */ -struct random_strings -{ - std::vector v_s; - std::vector v; - std::vector arena; - mutable size_t curr; - size_t szm1; - - C4_HOT C4_ALWAYS_INLINE c4::csubstr next() const noexcept { c4::csubstr f = v[curr]; curr = (curr + 1) & szm1; return f; } - C4_HOT C4_ALWAYS_INLINE std::string const& next_s() const noexcept { std::string const& f = v_s[curr]; curr = (curr + 1) & szm1; return f; } - - random_strings() = default; - - template - void _init(random_values const& tmp) - { - C4_CHECK(is_pot(tmp.v.size())); - v.resize(tmp.v.size()); - v_s.resize(tmp.v.size()); - curr = 0; - szm1 = tmp.v.size() - 1; - } - void _build_arena() - { - size_t sum = 0; - for(std::string const& s : v_s) - sum += s.size(); - sum += v_s.size(); - v.resize(v_s.size()); - arena.resize(sum); - size_t pos = 0; - size_t i = 0; - for(std::string const& s : v_s) - { - memcpy(&arena[pos], s.data(), s.size()); - v[i++] = c4::csubstr(&arena[pos], s.size()); - pos += s.size(); - arena[pos++] = '\0'; - } - } - - template - void init_as(random_values const& tmp) - { - _init(tmp); - for(size_t i = 0; i < v.size(); ++i) - c4::catrs(&v_s[i], tmp.v[i]); - _build_arena(); - } - template - void init_as_hex(random_values const& tmp, bool with_prefix) - { - _init(tmp); - for(size_t i = 0; i < v.size(); ++i) - { - c4::catrs(&v_s[i], c4::fmt::hex(tmp.v[i])); - if(!with_prefix) - _erase_radix_prefix(&v_s[i]); - } - _build_arena(); - } - template - void init_as_oct(random_values const& tmp, bool with_prefix) - { - _init(tmp); - for(size_t i = 0; i < v.size(); ++i) - { - c4::catrs(&v_s[i], c4::fmt::oct(tmp.v[i])); - if(!with_prefix) - _erase_radix_prefix(&v_s[i]); - } - _build_arena(); - } - template - void init_as_bin(random_values const& tmp, bool with_prefix) - { - _init(tmp); - for(size_t i = 0; i < v.size(); ++i) - { - c4::catrs(&v_s[i], c4::fmt::bin(tmp.v[i])); - if(!with_prefix) - _erase_radix_prefix(&v_s[i]); - } - _build_arena(); - } - - static void _erase_radix_prefix(std::string *s) - { - C4_ASSERT(s->front() != '-'); - s->erase(0, 2); - } -}; -using random_strings_cref = random_strings const&; - -template -random_strings_cref mkstrings() -{ - static random_strings rs; - if(rs.v.empty()) - rs.init_as(mkvals()); - return rs; -} -template -random_strings_cref mkstrings_positive() -{ - static random_strings rs; - if(rs.v.empty()) - rs.init_as(mkvals_positive()); - return rs; -} -template -random_strings_cref mkstrings_hex(bool with_prefix=true) -{ - static random_strings rs; - static random_strings rs_wo_prefix; - if(with_prefix) - { - if(rs.v.empty()) - rs.init_as_hex(mkvals()); - return rs; - } - else - { - if(rs_wo_prefix.v.empty()) - rs_wo_prefix.init_as_hex(mkvals(), false); - return rs_wo_prefix; - } -} -template -random_strings_cref mkstrings_hex_positive(bool with_prefix=true) -{ - static random_strings rs; - static random_strings rs_wo_prefix; - if(with_prefix) - { - if(rs.v.empty()) - rs.init_as_hex(mkvals_positive(), true); - return rs; - } - else - { - if(rs_wo_prefix.v.empty()) - rs_wo_prefix.init_as_hex(mkvals_positive(), false); - return rs_wo_prefix; - } -} -template -random_strings_cref mkstrings_oct(bool with_prefix=true) -{ - static random_strings rs; - static random_strings rs_wo_prefix; - if(with_prefix) - { - if(rs.v.empty()) - rs.init_as_oct(mkvals(), true); - return rs; - } - else - { - if(rs_wo_prefix.v.empty()) - rs_wo_prefix.init_as_oct(mkvals(), false); - return rs_wo_prefix; - } -} -template -random_strings_cref mkstrings_oct_positive(bool with_prefix=true) -{ - static random_strings rs; - static random_strings rs_wo_prefix; - if(with_prefix) - { - if(rs.v.empty()) - rs.init_as_oct(mkvals_positive(), true); - return rs; - } - else - { - if(rs_wo_prefix.v.empty()) - rs_wo_prefix.init_as_oct(mkvals_positive(), false); - return rs_wo_prefix; - } -} -template -random_strings_cref mkstrings_bin(bool with_prefix=true) -{ - static random_strings rs; - static random_strings rs_wo_prefix; - if(with_prefix) - { - if(rs.v.empty()) - rs.init_as_bin(mkvals(), true); - return rs; - } - else - { - if(rs_wo_prefix.v.empty()) - rs_wo_prefix.init_as_bin(mkvals(), false); - return rs_wo_prefix; - } -} -template -random_strings_cref mkstrings_bin_positive(bool with_prefix=true) -{ - static random_strings rs; - static random_strings rs_wo_prefix; - if(with_prefix) - { - if(rs.v.empty()) - rs.init_as_bin(mkvals_positive(), true); - return rs; - } - else - { - if(rs_wo_prefix.v.empty()) - rs_wo_prefix.init_as_bin(mkvals_positive(), false); - return rs_wo_prefix; - } -} - - -/** a character buffer, easily convertible to c4::substr */ -template -struct sbuf -{ - char buf_[Dim]; - c4::substr buf; - sbuf() : buf_(), buf(buf_) {} - C4_HOT C4_ALWAYS_INLINE operator c4::substr& () { return buf; } - char* begin() { return buf.begin(); } - char* end() { return buf.end(); } -}; - -using string_buffer = sbuf<>; - -#define C4DOALL(n) for(size_t elm##__LINE__ = 0; elm##__LINE__ < n; ++elm##__LINE__) diff --git a/thirdparty/ryml/ext/c4core/bm/bm_format.cpp b/thirdparty/ryml/ext/c4core/bm/bm_format.cpp deleted file mode 100644 index 64d23cbf3..000000000 --- a/thirdparty/ryml/ext/c4core/bm/bm_format.cpp +++ /dev/null @@ -1,900 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace bm = benchmark; - -double getmax(std::vector const& v) -{ - return *(std::max_element(std::begin(v), std::end(v))); -} -double getmin(std::vector const& v) -{ - return *(std::min_element(std::begin(v), std::end(v))); -} -double getrange(std::vector const& v) -{ - auto min_max = std::minmax_element(std::begin(v), std::end(v)); - return *min_max.second - *min_max.first; -} - -#define _c4bm_stats \ - /*->Repetitions(20)*/ \ - ->DisplayAggregatesOnly(true) \ - ->ComputeStatistics("range", &getrange) \ - ->ComputeStatistics("max", &getmax) \ - ->ComputeStatistics("min", &getmin) - -#define C4BM(fn) BENCHMARK(fn) _c4bm_stats - -/** convenience wrapper to avoid boilerplate code */ -void report(bm::State &st, size_t sz) -{ - st.SetBytesProcessed(st.iterations() * static_cast(sz)); - st.SetItemsProcessed(st.iterations()); -} - - -const c4::csubstr sep = " --- "; - - -#define _c4argbundle_fmt "hello here you have some numbers: "\ - "1={}, 2={}, 3={}, 4={}, 5={}, 6={}, 7={}, 8={}, 9={}, size_t(283482349)={}, "\ - "\" \"=\"{}\", \"haha\"=\"{}\", std::string(\"hehe\")=\"{}\", "\ - "str=\"{}\"" - -#define _c4argbundle_fmt_printf "hello here you have some numbers: "\ - "1=%d, 2=%d, 3=%d, 4=%d, 5=%d, 6=%d, 7=%d, 8=%d, 9=%d, size_t(283482349)=%zu, "\ - "\" \"=\"%s\", \"haha\"=\"%s\", std::string(\"hehe\")=\"%s\", "\ - "str=\"%s\"" - -#define _c4argbundle_fmt_printf_sep "hello here you have some numbers: "\ - "1=%d%s2=%d%s3=%d%s4=%d%s5=%d%s6=%d%s7=%d%s8=%d%s9=%d%ssize_t(283482349)=%zu%s"\ - "\" \"=\"%s\"%s\"haha\"=\"%s\"%sstd::string(\"hehe\")=\"%s\"%s"\ - "str=\"%s\"" - -#define _c4argbundle \ - 1, 2, 3, 4, 5, 6, 7, 8, 9, size_t(283482349),\ - " ", "haha", std::string("hehe"),\ - std::string("asdlklkasdlkjasd asdlkjasdlkjasdlkjasdoiasdlkjasldkj") - -#define _c4argbundle_printf \ - 1, 2, 3, 4, 5, 6, 7, 8, 9, size_t(283482349),\ - " ", "haha", std::string("hehe").c_str(),\ - std::string("asdlklkasdlkjasd asdlkjasdlkjasdlkjasdoiasdlkjasldkj").c_str() - -#define _c4argbundle_printf_sep \ - 1, sep.str, 2, sep.str, 3, sep.str, 4, sep.str, 5, sep.str, 6, sep.str, 7, sep.str, 8, sep.str, 9, sep.str, size_t(283482349), sep.str,\ - " ", sep.str, "haha", sep.str, std::string("hehe").c_str(), sep.str,\ - std::string("asdlklkasdlkjasd asdlkjasdlkjasdlkjasdoiasdlkjasldkj").c_str() - -#define _c4argbundle_lshift \ - 1 << 2 << 3 << 4 << 5 << 6 << 7 << 8 << 9 << size_t(283482349)\ - << " " << "haha" << std::string("hehe")\ - << std::string("asdlklkasdlkjasd asdlkjasdlkjasdlkjasdoiasdlkjasldkj") - -#define _c4argbundle_lshift_sep \ - 1 << sep << 2 << sep << 3 << sep << 4 << sep << 5 << sep << 6 << sep << 7 << sep << 8 << sep << 9 << sep << size_t(283482349)\ - << sep << " " << sep << "haha" << sep << std::string("hehe")\ - << sep << std::string("asdlklkasdlkjasd asdlkjasdlkjasdlkjasdoiasdlkjasldkj") - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -namespace dump2str { -std::string c_style_subject; -void c_style(c4::csubstr s) { c_style_subject.append(s.str, s.len); } -struct cpp_style -{ - std::string subject = {}; - void operator() (c4::csubstr s) { subject.append(s.str, s.len); } -}; -struct lambda_style -{ - std::string subject = {}; -}; -} // namespace dump2str - -namespace dump2file { -FILE * c_style_subject; -void c_style(c4::csubstr s) { fwrite(s.str, 1, s.len, c_style_subject); } -struct cpp_style -{ - FILE * subject; - cpp_style() : subject(fopen("asdkjhasdkjhsdfoiefkjn", "wb")) {} - ~cpp_style() { fclose(subject); } - void operator() (c4::csubstr s) { fwrite(s.str, 1, s.len, subject); } -}; -struct lambda_style -{ - lambda_style() : subject(fopen("asdkjhasdkjhsdfoiefkjn", "wb")) {} - ~lambda_style() { fclose(subject); } - FILE * subject; -}; -} // namespace dump2fil - -template -C4_ALWAYS_INLINE typename std::enable_if::value, std::string>::type -std_to_string(T const& a) -{ - return std::to_string(a); -} - -template -C4_ALWAYS_INLINE typename std::enable_if::value, std::string const&>::type -std_to_string(std::string const& a) -{ - return a; -} - -C4_ALWAYS_INLINE std::string std_to_string(c4::csubstr a) -{ - return std::string(a.str, a.len); -} - -template -C4_ALWAYS_INLINE typename std::enable_if< ! std::is_arithmetic::value, std::string>::type -std_to_string(T const& a) -{ - return std::string(a); -} - -C4_ALWAYS_INLINE void cat_std_string_impl(std::string *) -{ -} - -C4_ALWAYS_INLINE void catsep_std_string_impl(std::string *) -{ -} - -template -void cat_std_string_impl(std::string *s, Arg const& a, Args const& ...args) -{ - *s += std_to_string(a); - cat_std_string_impl(s, args...); -} - -template -void catsep_std_string_impl(std::string *s, Arg const& a, Args const& ...args) -{ - *s += std_to_string(a); - if(sizeof...(args) > 0) - { - s->append(sep.str, sep.len); - catsep_std_string_impl(s, args...); - } -} - -void cat_std_stringstream_impl(std::stringstream &) -{ -} -void catsep_std_stringstream_impl(std::stringstream &) -{ -} - -template -void cat_std_stringstream_impl(std::stringstream &ss, Arg const& a, Args const& ...args) -{ - ss << a; - cat_std_stringstream_impl(ss, args...); -} - -template -void catsep_std_stringstream_impl(std::stringstream &ss, Arg const& a, Args const& ...args) -{ - ss << sep << a; - cat_std_stringstream_impl(ss, args...); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -void cat_c4cat_substr(bm::State &st) -{ - char buf_[256]; - c4::substr buf(buf_); - size_t sz = 0; - for(auto _ : st) - { - sz = cat(buf, _c4argbundle); - } - report(st, sz); -} - -void cat_c4catrs_reuse(bm::State &st) -{ - std::string buf; - size_t sz = 0; - for(auto _ : st) - { - c4::catrs(&buf, _c4argbundle); - sz = buf.size(); - } - report(st, sz); -} - -void cat_c4catrs_no_reuse(bm::State &st) -{ - size_t sz = 0; - for(auto _ : st) - { - auto buf = c4::catrs(_c4argbundle); - sz = buf.size(); - } - report(st, sz); -} - -void cat_c4catdump_c_style_static_dispatch(bm::State &st) -{ - char buf_[256]; - c4::substr buf(buf_); - size_t sz = c4::cat(buf, _c4argbundle); - for(auto _ : st) - { - c4::cat_dump<&dump2str::c_style>(buf, _c4argbundle); - } - report(st, sz); -} - -void cat_c4catdump_c_style_dynamic_dispatch(bm::State &st) -{ - char buf_[256]; - c4::substr buf(buf_); - size_t sz = c4::cat(buf, _c4argbundle); - for(auto _ : st) - { - sz = c4::cat_dump(&dump2str::c_style, buf, _c4argbundle); - } - report(st, sz); -} - -void cat_c4catdump_cpp_style(bm::State &st) -{ - char buf_[256]; - c4::substr buf(buf_); - size_t sz = c4::cat(buf, _c4argbundle); - dump2str::cpp_style dumper; - for(auto _ : st) - { - sz = c4::cat_dump(dumper, buf, _c4argbundle); - } - report(st, sz); -} - -void cat_c4catdump_lambda_style(bm::State &st) -{ - char buf_[256]; - c4::substr buf(buf_); - size_t sz = c4::cat(buf, _c4argbundle); - dump2str::lambda_style dumper; - auto lambda = [&dumper](c4::csubstr s) { dumper.subject.append(s.str, s.len); }; - for(auto _ : st) - { - sz = c4::cat_dump(lambda, buf, _c4argbundle); - } - report(st, sz); -} - -void cat_stdsstream_reuse(bm::State &st) -{ - size_t sz = 0; - std::stringstream ss; - for(auto _ : st) - { - ss.clear(); - ss.str(""); - cat_std_stringstream_impl(ss, _c4argbundle); - sz = ss.str().size(); - } - report(st, sz); -} - -void cat_stdsstream_no_reuse(bm::State &st) -{ - size_t sz = 0; - for(auto _ : st) - { - std::stringstream ss; - cat_std_stringstream_impl(ss, _c4argbundle); - sz = ss.str().size(); - } - report(st, sz); -} - -void cat_std_to_string_reuse(bm::State &st) -{ - size_t sz = 0; - std::string s; - for(auto _ : st) - { - s.clear(); - cat_std_string_impl(&s, _c4argbundle); - sz = s.size(); - } - report(st, sz); -} - -void cat_std_to_string_no_reuse(bm::State &st) -{ - size_t sz = 0; - for(auto _ : st) - { - std::string s; - cat_std_string_impl(&s, _c4argbundle); - sz = s.size(); - } - report(st, sz); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -void catfile_c4catdump_c_style_static_dispatch(bm::State &st) -{ - char buf_[256]; - c4::substr buf(buf_); - dump2file::cpp_style fileowner; - dump2file::c_style_subject = fileowner.subject; - size_t sz = c4::cat(buf, _c4argbundle); - for(auto _ : st) - { - c4::cat_dump<&dump2file::c_style>(buf, _c4argbundle); - } - report(st, sz); -} - -void catfile_c4catdump_c_style_dynamic_dispatch(bm::State &st) -{ - char buf_[256]; - c4::substr buf(buf_); - dump2file::cpp_style fileowner; - dump2file::c_style_subject = fileowner.subject; - size_t sz = c4::cat(buf, _c4argbundle); - for(auto _ : st) - { - c4::cat_dump(&dump2file::c_style, buf, _c4argbundle); - } - report(st, sz); -} - -void catfile_c4catdump_cpp_style(bm::State &st) -{ - char buf_[256]; - c4::substr buf(buf_); - size_t sz = c4::cat(buf, _c4argbundle); - dump2file::cpp_style dumper; - for(auto _ : st) - { - sz = c4::cat_dump(dumper, buf, _c4argbundle); - } - report(st, sz); -} - -void catfile_c4catdump_lambda_style(bm::State &st) -{ - char buf_[256]; - c4::substr buf(buf_); - size_t sz = c4::cat(buf, _c4argbundle); - dump2file::lambda_style dumper; - auto lambda = [&dumper](c4::csubstr s) { fwrite(s.str, 1, s.len, dumper.subject); }; - for(auto _ : st) - { - sz = c4::cat_dump(lambda, buf, _c4argbundle); - } - report(st, sz); -} - -void catfile_fprintf(bm::State &st) -{ - char buf[256]; - size_t sz = c4::cat(buf, _c4argbundle); - dump2file::cpp_style dumper; - for(auto _ : st) - { - fprintf(dumper.subject, _c4argbundle_fmt_printf, _c4argbundle_printf); - } - report(st, sz); -} - -void catfile_ofstream(bm::State &st) -{ - char buf[256]; - size_t sz = c4::cat(buf, _c4argbundle); - std::ofstream ofs("ddofgufgbmn4g0rtglf", std::ios::out|std::ios::binary); - for(auto _ : st) - { - ofs << _c4argbundle_lshift; - } - report(st, sz); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -void catsep_c4cat_substr(bm::State &st) -{ - char buf_[256]; - c4::substr buf(buf_); - size_t sz = 0; - for(auto _ : st) - { - sz = catsep(buf, _c4argbundle); - } - report(st, sz); -} - -void catsep_c4catrs_reuse(bm::State &st) -{ - std::string buf; - size_t sz = 0; - for(auto _ : st) - { - c4::catseprs(&buf, _c4argbundle); - sz = buf.size(); - } - report(st, sz); -} - -void catsep_c4catrs_no_reuse(bm::State &st) -{ - size_t sz = 0; - for(auto _ : st) - { - auto buf = c4::catseprs(sep, _c4argbundle); - sz = buf.size(); - } - report(st, sz); -} - -void catsep_c4catdump_c_style_static_dispatch(bm::State &st) -{ - char buf_[256]; - c4::substr buf(buf_); - size_t sz = c4::catsep(buf, _c4argbundle); - for(auto _ : st) - { - c4::catsep_dump<&dump2str::c_style>(buf, sep, _c4argbundle); - } - report(st, sz); -} - -void catsep_c4catdump_c_style_dynamic_dispatch(bm::State &st) -{ - char buf_[256]; - c4::substr buf(buf_); - size_t sz = c4::catsep(buf, _c4argbundle); - for(auto _ : st) - { - sz = c4::catsep_dump(&dump2str::c_style, buf, sep, _c4argbundle); - } - report(st, sz); -} - -void catsep_c4catdump_cpp_style(bm::State &st) -{ - char buf_[256]; - c4::substr buf(buf_); - size_t sz = c4::catsep(buf, _c4argbundle); - dump2str::cpp_style dumper; - for(auto _ : st) - { - sz = c4::catsep_dump(dumper, buf, sep, _c4argbundle); - } - report(st, sz); -} - -void catsep_c4catdump_lambda_style(bm::State &st) -{ - char buf_[256]; - c4::substr buf(buf_); - size_t sz = c4::catsep(buf, sep, _c4argbundle); - dump2str::lambda_style dumper; - auto lambda = [&dumper](c4::csubstr s) { dumper.subject.append(s.str, s.len); }; - for(auto _ : st) - { - sz = c4::catsep_dump(lambda, buf, _c4argbundle); - } - report(st, sz); -} - -void catsep_stdsstream_reuse(bm::State &st) -{ - size_t sz = 0; - std::stringstream ss; - for(auto _ : st) - { - ss.clear(); - ss.str(""); - catsep_std_stringstream_impl(ss, sep, _c4argbundle); - sz = ss.str().size(); - } - report(st, sz); -} - -void catsep_stdsstream_no_reuse(bm::State &st) -{ - size_t sz = 0; - for(auto _ : st) - { - std::stringstream ss; - catsep_std_stringstream_impl(ss, sep, _c4argbundle); - sz = ss.str().size(); - } - report(st, sz); -} - -void catsep_std_to_string_reuse(bm::State &st) -{ - size_t sz = 0; - std::string s; - for(auto _ : st) - { - s.clear(); - catsep_std_string_impl(&s, sep, _c4argbundle); - sz = s.size(); - } - report(st, sz); -} - -void catsep_std_to_string_no_reuse(bm::State &st) -{ - size_t sz = 0; - for(auto _ : st) - { - std::string s; - catsep_std_string_impl(&s, sep, _c4argbundle); - sz = s.size(); - } - report(st, sz); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -void catsepfile_c4catsepdump_c_style_static_dispatch(bm::State &st) -{ - char buf_[256]; - c4::substr buf(buf_); - dump2file::cpp_style fileowner; - dump2file::c_style_subject = fileowner.subject; - size_t sz = c4::catsep(buf, sep, _c4argbundle); - for(auto _ : st) - { - c4::catsep_dump<&dump2file::c_style>(buf, sep, _c4argbundle); - } - report(st, sz); -} - -void catsepfile_c4catsepdump_c_style_dynamic_dispatch(bm::State &st) -{ - char buf_[256]; - c4::substr buf(buf_); - dump2file::cpp_style fileowner; - dump2file::c_style_subject = fileowner.subject; - size_t sz = c4::catsep(buf, sep, _c4argbundle); - for(auto _ : st) - { - c4::catsep_dump(&dump2file::c_style, buf, sep, _c4argbundle); - } - report(st, sz); -} - -void catsepfile_c4catsepdump_cpp_style(bm::State &st) -{ - char buf_[256]; - c4::substr buf(buf_); - size_t sz = c4::catsep(buf, sep, _c4argbundle); - dump2file::cpp_style dumper; - for(auto _ : st) - { - c4::catsep_dump(dumper, buf, sep, _c4argbundle); - } - report(st, sz); -} - -void catsepfile_c4catsepdump_lambda_style(bm::State &st) -{ - char buf_[256]; - c4::substr buf(buf_); - size_t sz = c4::catsep(buf, sep, _c4argbundle); - dump2file::lambda_style dumper; - auto lambda = [&dumper](c4::csubstr s) { fwrite(s.str, 1, s.len, dumper.subject); }; - for(auto _ : st) - { - c4::catsep_dump(lambda, buf, sep, _c4argbundle); - } - report(st, sz); -} - -void catsepfile_fprintf(bm::State &st) -{ - char buf[256]; - size_t sz = c4::catsep(buf, sep, _c4argbundle); - dump2file::cpp_style dumper; - for(auto _ : st) - { - fprintf(dumper.subject, _c4argbundle_fmt_printf_sep, _c4argbundle_printf_sep); - } - report(st, sz); -} - -void catsepfile_ofstream(bm::State &st) -{ - char buf[256]; - size_t sz = c4::catsep(buf, sep, _c4argbundle); - std::ofstream ofs("ddofgufgbmn4g0rtglf", std::ios::out|std::ios::binary); - for(auto _ : st) - { - ofs << _c4argbundle_lshift_sep; - } - report(st, sz); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -void format_c4format(bm::State &st) -{ - char buf_[512]; - c4::substr buf(buf_); - size_t sz = 0; - for(auto _ : st) - { - sz = format(buf, _c4argbundle_fmt, _c4argbundle); - } - report(st, sz); -} - -void format_c4formatrs_reuse(bm::State &st) -{ - std::string buf; - size_t sz = 0; - for(auto _ : st) - { - c4::formatrs(&buf, _c4argbundle_fmt, _c4argbundle); - sz = buf.size(); - } - report(st, sz); -} - -void format_c4formatrs_no_reuse(bm::State &st) -{ - size_t sz = 0; - for(auto _ : st) - { - auto buf = c4::formatrs(_c4argbundle_fmt, _c4argbundle); - sz = buf.size(); - } - report(st, sz); -} - -void format_c4formatdump_c_style_static_dispatch(bm::State &st) -{ - char buf_[256]; - c4::substr buf(buf_); - size_t sz = c4::format(buf, _c4argbundle_fmt, _c4argbundle); - for(auto _ : st) - { - c4::format_dump<&dump2str::c_style>(buf, _c4argbundle_fmt, _c4argbundle); - } - report(st, sz); -} - -void format_c4formatdump_c_style_dynamic_dispatch(bm::State &st) -{ - char buf_[256]; - c4::substr buf(buf_); - size_t sz = c4::format(buf, _c4argbundle_fmt, _c4argbundle); - for(auto _ : st) - { - c4::format_dump(&dump2str::c_style, buf, _c4argbundle_fmt, _c4argbundle); - } - report(st, sz); -} - -void format_c4formatdump_cpp_style(bm::State &st) -{ - char buf_[256]; - c4::substr buf(buf_); - size_t sz = c4::format(buf, _c4argbundle_fmt, _c4argbundle); - dump2str::cpp_style dumper; - for(auto _ : st) - { - c4::format_dump(dumper, buf, _c4argbundle_fmt, _c4argbundle); - } - report(st, sz); -} - -void format_c4formatdump_lambda_style(bm::State &st) -{ - char buf_[256]; - c4::substr buf(buf_); - size_t sz = c4::format(buf, _c4argbundle_fmt, _c4argbundle); - dump2str::lambda_style dumper; - auto lambda = [&dumper](c4::csubstr s) { dumper.subject.append(s.str, s.len); }; - for(auto _ : st) - { - c4::format_dump(lambda, buf, _c4argbundle_fmt, _c4argbundle); - } - report(st, sz); -} - -void format_snprintf(bm::State &st) -{ - char buf_[512]; - c4::substr buf(buf_); - size_t sz = 0; - for(auto _ : st) - { - sz = (size_t) snprintf(buf.str, buf.len, _c4argbundle_fmt_printf, _c4argbundle_printf); - } - report(st, sz); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -void formatfile_c4formatdump_c_style_static_dispatch(bm::State &st) -{ - char buf_[256]; - c4::substr buf(buf_); - dump2file::cpp_style fileowner; - dump2file::c_style_subject = fileowner.subject; - size_t sz = c4::format(buf, _c4argbundle_fmt, _c4argbundle); - for(auto _ : st) - { - c4::format_dump<&dump2file::c_style>(buf, _c4argbundle_fmt, _c4argbundle); - } - report(st, sz); -} - -void formatfile_c4formatdump_c_style_dynamic_dispatch(bm::State &st) -{ - char buf_[256]; - c4::substr buf(buf_); - dump2file::cpp_style fileowner; - dump2file::c_style_subject = fileowner.subject; - size_t sz = c4::format(buf, _c4argbundle_fmt, _c4argbundle); - for(auto _ : st) - { - c4::format_dump(&dump2file::c_style, buf, _c4argbundle_fmt, _c4argbundle); - } - report(st, sz); -} - -void formatfile_c4formatdump_cpp_style(bm::State &st) -{ - char buf_[256]; - c4::substr buf(buf_); - size_t sz = c4::format(buf, _c4argbundle_fmt, _c4argbundle); - dump2file::cpp_style dumper; - for(auto _ : st) - { - c4::format_dump(dumper, buf, _c4argbundle_fmt, _c4argbundle); - } - report(st, sz); -} - -void formatfile_c4formatdump_lambda_style(bm::State &st) -{ - char buf_[256]; - c4::substr buf(buf_); - size_t sz = c4::format(buf, _c4argbundle_fmt, _c4argbundle); - dump2file::lambda_style dumper; - auto lambda = [&dumper](c4::csubstr s) { fwrite(s.str, 1, s.len, dumper.subject); }; - for(auto _ : st) - { - c4::format_dump(lambda, buf, _c4argbundle_fmt, _c4argbundle); - } - report(st, sz); -} - -void formatfile_fprintf(bm::State &st) -{ - char buf[256]; - size_t sz = c4::format(buf, _c4argbundle_fmt, _c4argbundle); - dump2file::cpp_style dumper; - for(auto _ : st) - { - fprintf(dumper.subject, _c4argbundle_fmt_printf, _c4argbundle_printf); - } - report(st, sz); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -C4BM(cat_c4cat_substr); -C4BM(cat_c4catrs_reuse); -C4BM(cat_c4catrs_no_reuse); -C4BM(cat_c4catdump_c_style_static_dispatch); -C4BM(cat_c4catdump_c_style_dynamic_dispatch); -C4BM(cat_c4catdump_cpp_style); -C4BM(cat_c4catdump_lambda_style); -C4BM(cat_std_to_string_reuse); -C4BM(cat_std_to_string_no_reuse); -C4BM(cat_stdsstream_reuse); -C4BM(cat_stdsstream_no_reuse); - -C4BM(catfile_c4catdump_c_style_static_dispatch); -C4BM(catfile_c4catdump_c_style_dynamic_dispatch); -C4BM(catfile_c4catdump_cpp_style); -C4BM(catfile_c4catdump_lambda_style); -C4BM(catfile_fprintf); -C4BM(catfile_ofstream); - - -C4BM(catsep_c4cat_substr); -C4BM(catsep_c4catrs_reuse); -C4BM(catsep_c4catrs_no_reuse); -C4BM(catsep_c4catdump_c_style_static_dispatch); -C4BM(catsep_c4catdump_c_style_dynamic_dispatch); -C4BM(catsep_c4catdump_cpp_style); -C4BM(catsep_c4catdump_lambda_style); -C4BM(catsep_std_to_string_reuse); -C4BM(catsep_std_to_string_no_reuse); -C4BM(catsep_stdsstream_reuse); -C4BM(catsep_stdsstream_no_reuse); - -C4BM(catsepfile_c4catsepdump_c_style_static_dispatch); -C4BM(catsepfile_c4catsepdump_c_style_dynamic_dispatch); -C4BM(catsepfile_c4catsepdump_cpp_style); -C4BM(catsepfile_c4catsepdump_lambda_style); -C4BM(catsepfile_fprintf); -C4BM(catsepfile_ofstream); - - -C4BM(format_c4format); -C4BM(format_c4formatrs_reuse); -C4BM(format_c4formatrs_no_reuse); -C4BM(format_c4formatdump_c_style_static_dispatch); -C4BM(format_c4formatdump_c_style_dynamic_dispatch); -C4BM(format_c4formatdump_cpp_style); -C4BM(format_c4formatdump_lambda_style); -C4BM(format_snprintf); - -C4BM(formatfile_c4formatdump_c_style_static_dispatch); -C4BM(formatfile_c4formatdump_c_style_dynamic_dispatch); -C4BM(formatfile_c4formatdump_cpp_style); -C4BM(formatfile_c4formatdump_lambda_style); -C4BM(formatfile_fprintf); - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -int main(int argc, char *argv[]) -{ - bm::Initialize(&argc, argv); - bm::RunSpecifiedBenchmarks(); - return 0; -} - - -#include - - diff --git a/thirdparty/ryml/ext/c4core/bm/bm_itoa_threads.cpp b/thirdparty/ryml/ext/c4core/bm/bm_itoa_threads.cpp deleted file mode 100644 index 0e102065a..000000000 --- a/thirdparty/ryml/ext/c4core/bm/bm_itoa_threads.cpp +++ /dev/null @@ -1,356 +0,0 @@ -#include "./bm_charconv.hpp" - -#include -#include -#include -#include -#include -#include -#include -#if defined(__cpp_lib_to_chars) || (C4_CPP >= 17) -#define C4_HAS_STDTOCHARS 1 -#else -#define C4_HAS_STDTOCHARS 0 -#endif -#if C4_HAS_STDTOCHARS -#include -#endif - -C4_SUPPRESS_WARNING_GCC_CLANG_PUSH -C4_SUPPRESS_WARNING_GCC_CLANG("-Wcast-align") -C4_SUPPRESS_WARNING_GCC("-Wuseless-cast") -#define FMT_HEADER_ONLY -#include - -#define STB_SPRINTF_IMPLEMENTATION -#include -C4_SUPPRESS_WARNING_GCC_POP - -#if C4_CXX >= 20 -#include -#define C4_HAS_STD_FORMAT (__has_cpp_attribute(__cpp_lib_format)) -#else -#define C4_HAS_STD_FORMAT (0) -#endif -#if C4_HAS_STD_FORMAT -#include -#endif - - -#define BMTHREADS(func) \ - BENCHMARK(func) \ - ->Threads(1) \ - ->Threads(2) \ - ->Threads(3) \ - ->Threads(4) \ - ->Threads(5) \ - ->Threads(6) \ - ->Threads(7) \ - ->Threads(8) \ - ->Threads(9) \ - ->Threads(10) \ - ->UseRealTime() \ - - -void snprintf(bm::State &st) -{ - size_t sum = {}; - char buf[100]; - int i = 0; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - int ret = snprintf(buf, sizeof(buf), "%i", i++); - sum += (size_t)ret + buf[0]; - } - } - bm::DoNotOptimize(sum); - report_threadavg(st, kNumValues); -} -BMTHREADS(snprintf); - - -#ifndef __linux__ -void snprintf_l(bm::State &st) -{ - size_t sum = {}; - char buf[100]; - int i = 0; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - #if defined(_MSC_VER) - int ret = _snprintf_l(buf, 100, "%i", NULL, i++); - #else - int ret = snprintf_l(buf, 100, NULL, "%i", i++); - #endif - sum += (size_t)ret + buf[0]; - } - } - bm::DoNotOptimize(sum); - report_threadavg(st, kNumValues); -} -BMTHREADS(snprintf_l); -#endif - - -void stb_snprintf(bm::State &st) -{ - size_t sum = {}; - char buf[100]; - int i = 0; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - stbsp_snprintf(buf, 100, "%i", i++); - sum += strlen(buf) + buf[0]; - } - } - bm::DoNotOptimize(sum); - report_threadavg(st, kNumValues); -} -BMTHREADS(stb_snprintf); - - - -void sstream(bm::State &st) -{ - size_t sum = {}; - std::stringstream buf; - int i = 0; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - buf.seekp(0); - buf << i++; - size_t len = (size_t)buf.tellp(); - buf.seekg(0); - int firstchar = buf.get(); - sum += len + firstchar; - } - } - bm::DoNotOptimize(sum); - report_threadavg(st, kNumValues); -} -BMTHREADS(sstream); - - -void sstream_naive(bm::State &st) -{ - size_t sum = {}; - int i = 0; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - std::stringstream buf; - buf << i++; - std::string ret = buf.str(); - sum += ret.size() + ret[0]; - } - } - bm::DoNotOptimize(sum); - report_threadavg(st, kNumValues); -} -BMTHREADS(sstream_naive); - - -void sstream_naive_reuse(bm::State &st) -{ - size_t sum = {}; - int i = 0; - std::stringstream buf; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - buf.clear(); - buf.str(""); - buf << i++; - std::string ret = buf.str(); - sum += ret.size() + ret[0]; - } - } - bm::DoNotOptimize(sum); - report_threadavg(st, kNumValues); -} -BMTHREADS(sstream_naive_reuse); - - -#ifdef _MSC_VER -void itoa(bm::State &st) -{ - char buf[100]; - size_t sum = {}; - int i = 0; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - ::_itoa(i++, buf, 10); - sum += strlen(buf) + buf[0]; - } - } - bm::DoNotOptimize(sum); - report_threadavg(st, kNumValues); -} -BMTHREADS(itoa); -#endif - - -#if C4_HAS_STD_FORMAT -static void std_format_to(bm::State &st) -{ - size_t sum = {}; - char buf[100]; - int i = 0; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - const auto res = std::format_to_n(buf, sizeof(buf), /*loc,*/ "{}", i++); - sum += (res.out - buf) + buf[0]; - } - } - bm::DoNotOptimize(sum); - report_threadavg(st, kNumValues); -} -BMTHREADS(std_format_to); -#endif - - -void fmtlib_format_to(bm::State &st) -{ - size_t sum = {}; - fmt::memory_buffer buf; - int i = 0; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - buf.clear(); - fmt::format_to(fmt::appender(buf), "{}", i++); - sum += buf.size() + buf[0]; - } - } - bm::DoNotOptimize(sum); - report_threadavg(st, kNumValues); -} -BMTHREADS(fmtlib_format_to); - - -#if C4_HAS_STDTOCHARS -void std_to_chars(bm::State &st) -{ - size_t sum = {}; - char buf[100]; - int i = 0; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - std::to_chars_result res = std::to_chars(buf, buf+sizeof(buf), i++); - sum += (res.ptr - buf) + buf[0]; - } - } - bm::DoNotOptimize(sum); - report_threadavg(st, kNumValues); -} -BMTHREADS(std_to_chars); -#endif - - -void c4_write_dec(bm::State &st) -{ - size_t sum = {}; - char buf_[100]; - c4::substr buf = buf_; - int i = 0; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - size_t len = c4::write_dec(buf, i++); - sum += len + buf[0]; - } - } - bm::DoNotOptimize(sum); - report_threadavg(st, kNumValues); -} -BMTHREADS(c4_write_dec); - - -void c4_itoa(bm::State &st) -{ - size_t sum = {}; - char buf_[100]; - c4::substr buf = buf_; - int i = 0; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - size_t len = c4::itoa(buf, i++); - sum += len + buf[0]; - } - } - bm::DoNotOptimize(sum); - report_threadavg(st, kNumValues); -} -BMTHREADS(c4_itoa); - - -void c4_xtoa(bm::State &st) -{ - size_t sum = {}; - char buf_[100]; - c4::substr buf = buf_; - int i = 0; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - size_t len = c4::xtoa(buf, i++); - sum += len + buf[0]; - } - } - bm::DoNotOptimize(sum); - report_threadavg(st, kNumValues); -} -BMTHREADS(c4_xtoa); - - -void c4_to_chars(bm::State &st) -{ - size_t sum = {}; - char buf_[100]; - c4::substr buf = buf_; - int i = 0; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - size_t len = c4::to_chars(buf, i++); - sum += len + buf[0]; - } - } - bm::DoNotOptimize(sum); - report_threadavg(st, kNumValues); -} -BMTHREADS(c4_to_chars); - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -int main(int argc, char *argv[]) -{ - bm::Initialize(&argc, argv); - bm::RunSpecifiedBenchmarks(); - return 0; -} diff --git a/thirdparty/ryml/ext/c4core/bm/bm_plot_c4core.py b/thirdparty/ryml/ext/c4core/bm/bm_plot_c4core.py deleted file mode 100644 index 23fa55ba3..000000000 --- a/thirdparty/ryml/ext/c4core/bm/bm_plot_c4core.py +++ /dev/null @@ -1,266 +0,0 @@ -import sys -import os -import re - -thisdir = os.path.dirname(os.path.abspath(__file__)) -moddir = os.path.abspath(f"{thisdir}/../cmake/bm-xp") -sys.path.insert(0, moddir) -import bm_plot as bm -from bm_util import first - -from dataclasses import dataclass -import prettytable - - -def get_function_benchmark(function_name, run: bm.BenchmarkRun): - for rbm in run.entries: - if rbm.meta.function == function_name: - return rbm - raise Exception(f"function not found: {function_name}. Existing: {[rbm.meta.function for rbm in run.entries]}") - - -@dataclass -class CharconvMeta: # also for atox - title: str - subject: str - function: str - data_type: bm.FundamentalTypes - - @classmethod - def make(cls, bm_title: str): - # eg: - # xtoa_c4_write_dec - # xtoa_c4_utoa - # xtoa_c4_xtoa - # xtoa_c4_to_chars - # xtoa_std_to_chars - # xtoa_std_to_string - # xtoa_sprintf - # xtoa_sstream_reuse - # xtoa_sstream - rx = re.compile(r'(atox|xtoa|xtoahex|xtoaoct|xtoabin)_(.*?)<(u?int\d+_t|float|double)>') - if not rx.fullmatch(bm_title): - raise Exception(f"cannot understand bm title: {bm_title}") - subject = rx.sub(r'\1', bm_title) - function = rx.sub(r'\2', bm_title) - data_type = rx.sub(r'\3', bm_title) - return cls( - title=bm_title, - subject=subject, - function=function.replace("c4_", "c4::").replace("std_", "std::"), - data_type=bm.FundamentalTypes.make(data_type) - ) - - @property - def shortname(self): - return self.function - - @property - def shortparams(self): - return str(self.data_type.short) - - @property - def shorttitle(self): - return f"{self.shortname}<{self.shortparams}>" - - -@dataclass -class CharconvThreadsMeta: - function: str - num_threads: int - - @classmethod - def make(cls, bm_title: str): - # eg: - # c4_itoa/real_time/threads:4 - rx = re.compile(r'(.*?)/real_time/threads:(\d+)') - if not rx.fullmatch(bm_title): - raise Exception(f"cannot understand bm title: {bm_title}") - function = rx.sub(r'\1', bm_title) - num_threads = int(rx.sub(r'\2', bm_title)) - return cls( - function=function.replace("c4_", "c4::").replace("std_", "std::"), - num_threads=num_threads - ) - - def checkbox_groups(self): - return {} - - @property - def shortname(self): - return self.function - - @property - def shorttitle(self): - return self.shortname - - -def plot_charconv_bars(bm_panel: bm.BenchmarkPanel, getref, - panel_title_human: str, - outputfile_prefix: str): - assert os.path.isabs(outputfile_prefix), outputfile_prefix - # make a comparison table - anchor = lambda run: f"{os.path.basename(outputfile_prefix)}-{first(run.meta).data_type}" - anchorlink = lambda run: f"
{first(run.meta).data_type}
" - with open(f"{outputfile_prefix}.txt", "w") as tablefile: - with open(f"{outputfile_prefix}.md", "w") as mdfile: - print(f"## {panel_title_human}\n\n

Data type benchmark results:

\n
    \n", - "\n".join([f"
  • {anchorlink(run)}
  • " for run in bm_panel.runs]), - "
\n\n", file=mdfile) - for run in bm_panel.runs: - data_type = first(run.meta).data_type - tabletitle = f"{outputfile_prefix}-{data_type.short}" - table = prettytable.PrettyTable(title=f"{panel_title_human}: {data_type}") - table.add_column("function", [m.shorttitle for m in run.meta], align="l") - for prop in ("mega_bytes_per_second", "cpu_time_ms"): - ref = getref(run) - bar_values = list(run.extract_plot_series(prop)) - bar_values_rel = list(run.extract_plot_series(prop, relative_to_entry=ref)) - bar_values_pc = list(run.extract_plot_series(prop, percent_of_entry=ref)) - pd = bm_panel.first_run.property_plot_data(prop) - hns = pd.human_name_short - table.add_column(hns, [f"{v_:7.2f}" for v_ in bar_values], align="r") - hns = hns.replace(" (ms)", "") - table.add_column(f"{hns}(x)", [f"{v_:5.2f}x" for v_ in bar_values_rel], align="r") - table.add_column(f"{hns}(%)", [f"{v_:7.2f}%" for v_ in bar_values_pc], align="r") - print(table, "\n\n") - print(table, "\n\n", file=tablefile) - pfx_bps = f"{os.path.basename(outputfile_prefix)}-mega_bytes_per_second-{data_type.short}" - pfx_cpu = f"{os.path.basename(outputfile_prefix)}-cpu_time_ms-{data_type.short}" - print(f""" -
-
- ---- - - - -### {panel_title_human}: `{data_type}` - -* Interactive html graphs for `{data_type}`: - * [MB/s](./{pfx_bps}.html) - * [CPU time](./{pfx_cpu}.html) - -[![{data_type}: MB/s](./{pfx_bps}.png)](./{pfx_bps}.png) -[![{data_type}: CPU time](./{pfx_cpu}.png)](./{pfx_cpu}.png) - -``` -{table} -``` -""", file=mdfile) - # make plots - for prop in ("mega_bytes_per_second", "cpu_time_ms"): - ps, ps_ = [], [] - pd = bm_panel.first_run.property_plot_data(prop) - bar_label = f"{pd.human_name_short}{pd.qty_type.comment}" - outfilename = f"{outputfile_prefix}-{prop}" - for run in bm_panel.runs: - data_type = first(run.meta).data_type - bar_names = [m.shorttitle for m in run.meta] - bar_values = list(run.extract_plot_series(prop)) - runtitle = f"{outfilename}-{data_type.short}" - # to save each bokeh plot separately and also - # a grid plot with all of them, we have to plot - # twice because bokeh does not allow saving twice - # the same plot from multiple pictures. - plotit = lambda: bm.plot_benchmark_run_as_bars(run, title=f"{panel_title_human}: {data_type}\n{bar_label}", - bar_names=bar_names, bar_values=bar_values, bar_label=bar_label) - # make one plot to save: - p, p_ = plotit() - bm._bokeh_save_html(f"{runtitle}.html", p) - bm._plt_save_png(f"{runtitle}.png") - bm._plt_clear() - # and another to gather: - p, p_ = plotit() - ps.append(p) - ps_.append(p_) - bm._plt_clear() - bm.bokeh_plot_many(ps, f"{outfilename}.html") - - -def plot_itoa_threads_(bm_panel: bm.BenchmarkPanel, getref, - panel_title_human: str, - outputfile_prefix: str): - assert os.path.isabs(outputfile_prefix), outputfile_prefix - orig = lambda yprop, **kw: lambda run: list(run.extract_plot_series(yprop, **kw)) - divnt = lambda yprop, **kw: lambda run: [v / n for v, n in run.extract_plot_series_with_threads(yprop, **kw)] - mulnt = lambda yprop, **kw: lambda run: [v * n for v, n in run.extract_plot_series_with_threads(yprop, **kw)] - xprop = "threads" - xpd = bm_panel.first_run.property_plot_data(xprop) - xlabel = f"{xpd.human_name_short}" - for yprop, ylog, yget in ( - #("mega_items_per_second", False, orig), - ("mega_bytes_per_second", False, orig), - #("iterations", False, divnt), - #("real_time_ms", True, mulnt), - ("cpu_time_ms", True, orig),): - ypd = bm_panel.first_run.property_plot_data(yprop) - ylabel = f"{ypd.human_name_short}{ypd.qty_type.comment}" - p = bm.plot_benchmark_panel_as_lines( - bm_panel, f"{panel_title_human}\n{ylabel}", - xget=orig("threads"), - yget=yget(yprop), - nameget=lambda run: first(run.meta).function, - ylog=ylog, - xlabel=xlabel, - ylabel=ylabel - ) - name = f"{outputfile_prefix}-lines-{yprop}" - # save png using matplotlib - bm._plt_save_png(f"{name}.png") - bm._plt_clear() - # save html using bokeh - bm._bokeh_save_html(f"{name}.html", p) - #bkp.show(p) - return p - - -def plot_itoa_threads(dir_: str, json_files): - panel = bm.BenchmarkPanel(json_files, CharconvThreadsMeta) - ref = lambda bmrun: get_function_benchmark("std::to_chars", run=bmrun) - plot_itoa_threads_(panel, ref, - f"itoa benchmark: convert 2M 32b integers to string", - f"{dir_}/c4core-bm-charconv_threads") - - -def plot_charconv_xtoa(dir_: str, json_files, is_ftoa: bool): - fcase = "ftoa" if is_ftoa else "xtoa" - panel = bm.BenchmarkPanel(json_files, CharconvMeta) - ref = lambda bmrun: get_function_benchmark("sprintf", run=bmrun) - plot_charconv_bars(panel, ref, - f"xtoa benchmark: convert 1M numbers to strings", - f"{dir_}/c4core-bm-charconv-{fcase}") - - -def plot_charconv_atox(dir_: str, json_files, is_atof: bool): - fcase = "atof" if is_atof else "atox" - panel = bm.BenchmarkPanel(json_files, CharconvMeta) - ref = lambda bmrun: get_function_benchmark("scanf", run=bmrun) - plot_charconv_bars(panel, ref, - f"atox benchmark: convert 1M strings to numbers", - f"{dir_}/c4core-bm-charconv-{fcase}") - - -if __name__ == '__main__': - args = sys.argv[1:] - if len(args) < 2: - raise Exception(f"usage: {sys.executable} {sys.argv[0]} benchmarkfile.json[,benchmarkfile2.json,...]") - cmd = args[0] - json_files = args[1:] - dir_ = os.path.dirname(json_files[0]) - for jf in json_files: - print("jf:", jf, flush=True) - assert os.path.dirname(jf) == dir_, (os.path.dirname(jf), dir_) - assert os.path.exists(jf), jf - if cmd == "itoa_threads": - plot_itoa_threads(dir_, json_files) - elif cmd == "xtoa" or cmd == "ftoa": - plot_charconv_xtoa(dir_, json_files, (cmd == "ftoa")) - elif cmd == "atox" or cmd == "atof": - plot_charconv_atox(dir_, json_files, (cmd == "atof")) - elif cmd == "format": - raise Exception(f"not implemented: {cmd}") - elif cmd == "digits": - pass # nothing to do - else: - raise Exception(f"not implemented: {cmd}") diff --git a/thirdparty/ryml/ext/c4core/bm/bm_xtoa.cpp b/thirdparty/ryml/ext/c4core/bm/bm_xtoa.cpp deleted file mode 100644 index 681e443c6..000000000 --- a/thirdparty/ryml/ext/c4core/bm/bm_xtoa.cpp +++ /dev/null @@ -1,1538 +0,0 @@ -#include "./bm_charconv.hpp" -#include -#include - - -// this is an exploratory benchmark to compare the possible -// combinations for all the components of the write_dec() algorithm - - -template using msb_func = unsigned (*)(T val); - -#if defined(__GNUC__) -# pragma GCC diagnostic push -# if __GNUC__ >= 8 -# pragma GCC diagnostic ignored "-Wstringop-truncation" -# pragma GCC diagnostic ignored "-Wstringop-overflow" -# endif -#endif - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -// WIP. -// TODO: _BitscanReverse() in MSVC -C4_SUPPRESS_WARNING_GCC_WITH_PUSH("-Wuseless-cast") -C4_CONSTEXPR14 C4_ALWAYS_INLINE -auto msb_intrinsic(unsigned v) noexcept - -> typename std::enable_if<__has_builtin(__builtin_clz), unsigned>::type -{ - using I = unsigned; - enum : I { total = (I)(I(8) * sizeof(I) - 1) }; - return (total - (I) __builtin_clz(v)); -} - -C4_CONSTEXPR14 C4_ALWAYS_INLINE -auto msb_intrinsic_64bit(unsigned long v) noexcept --> typename std::enable_if<__has_builtin(__builtin_clzl), unsigned>::type -{ - using I = unsigned long; - enum : I { total = (I)(I(8) * sizeof(I) - 1) }; - return (unsigned)(total - (I) __builtin_clzl(v)); -} - -C4_CONSTEXPR14 C4_ALWAYS_INLINE -auto msb_intrinsic_64bit(unsigned long long v) noexcept - -> typename std::enable_if<__has_builtin(__builtin_clzll), unsigned>::type -{ - using I = unsigned long long; - enum : I { total = (I)(I(8) * sizeof(I) - 1) }; - return (unsigned)(total - (I) __builtin_clzll(v)); -} -C4_SUPPRESS_WARNING_GCC_POP - -template -C4_CONSTEXPR14 C4_ALWAYS_INLINE unsigned msb_loop(I v) noexcept -{ - // https://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10Obvious - unsigned r = 0; - while (v >>= 1) // unroll for more speed... - r++; - return r; -} - -// https://graphics.stanford.edu/~seander/bithacks.html#IntegerLogLookup -constexpr static const int8_t LogTable256[256] = { -#define LT(n) n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n - -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, - LT(4), LT(5), LT(5), LT(6), LT(6), LT(6), LT(6), - LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7) -#undef LT -}; -template -C4_CONSTEXPR14 C4_ALWAYS_INLINE -unsigned msb_de_bruijn_32bit(I v) noexcept -{ - I t, tt; // temporaries - tt = v >> 16; - if (tt) - return (unsigned)((t = tt >> 8) ? 24 + LogTable256[t] : 16 + LogTable256[tt]); - return (unsigned)((t = v >> 8) ? 8 + LogTable256[t] : LogTable256[v]); -} - -template -C4_CONSTEXPR14 C4_ALWAYS_INLINE -unsigned msb_intrinsic_8bit(I v) noexcept -{ - return msb_intrinsic((unsigned)v); -} - -template -C4_CONSTEXPR14 C4_ALWAYS_INLINE -unsigned msb_divconq_8bit(I v) noexcept -{ - C4_STATIC_ASSERT(sizeof(I) == 1); - unsigned n = 0; - if(v & I(0xf0)) v >>= 4, n |= I(4); - if(v & I(0x0c)) v >>= 2, n |= I(2); - if(v & I(0x02)) v >>= 1, n |= I(1); - return n; -} - -template -C4_CONSTEXPR14 C4_ALWAYS_INLINE unsigned msb_intrinsic_16bit(I v) noexcept -{ - return msb_intrinsic((unsigned)v); -} - -template -C4_CONSTEXPR14 C4_ALWAYS_INLINE unsigned msb_divconq_16bit(I v) noexcept -{ - C4_STATIC_ASSERT(sizeof(I) == 2); - unsigned n = 0; - if(v & I(0xff00)) v >>= 8, n |= I(8); - if(v & I(0x00f0)) v >>= 4, n |= I(4); - if(v & I(0x000c)) v >>= 2, n |= I(2); - if(v & I(0x0002)) v >>= 1, n |= I(1); - return n; -} - -template -C4_CONSTEXPR14 C4_ALWAYS_INLINE unsigned msb_intrinsic_32bit(I v) noexcept -{ - return msb_intrinsic((unsigned)v); -} - -template -C4_CONSTEXPR14 C4_ALWAYS_INLINE unsigned msb_divconq_32bit(I v) noexcept -{ - C4_STATIC_ASSERT(sizeof(I) == 4); - unsigned n = 0; - if(v & I(0xffff0000)) v >>= 16, n |= I(16); - if(v & I(0x0000ff00)) v >>= 8, n |= I(8); - if(v & I(0x000000f0)) v >>= 4, n |= I(4); - if(v & I(0x0000000c)) v >>= 2, n |= I(2); - if(v & I(0x00000002)) v >>= 1, n |= I(1); - return n; -} - -template -C4_CONSTEXPR14 C4_ALWAYS_INLINE unsigned msb_divconq_branchless_32bit(I v) noexcept -{ - C4_STATIC_ASSERT(sizeof(I) == 4); - unsigned r = (unsigned)(v > 0xFFFF) << 4; v >>= r; - unsigned shift = (unsigned)(v > 0xFF ) << 3; v >>= shift; r |= shift; - shift = (unsigned)(v > 0xF ) << 2; v >>= shift; r |= shift; - shift = (unsigned)(v > 0x3 ) << 1; v >>= shift; r |= shift; - r |= (unsigned)(v >> 1); - return r; -} - -template -C4_CONSTEXPR14 C4_ALWAYS_INLINE unsigned msb_intrinsic_64bit(I v) noexcept -{ - return msb_intrinsic_64bit((uint64_t)v); -} - -template -C4_CONSTEXPR14 C4_ALWAYS_INLINE unsigned msb_divconq_64bit(I v) noexcept -{ - C4_STATIC_ASSERT(sizeof(I) == 8); - unsigned n = 0; - if(v & I(0xffffffff00000000)) v >>= 32, n |= I(32); - if(v & I(0x00000000ffff0000)) v >>= 16, n |= I(16); - if(v & I(0x000000000000ff00)) v >>= 8, n |= I(8); - if(v & I(0x00000000000000f0)) v >>= 4, n |= I(4); - if(v & I(0x000000000000000c)) v >>= 2, n |= I(2); - if(v & I(0x0000000000000002)) v >>= 1, n |= I(1); - return n; -} - - -template msbfunc> -void msb(bm::State &st) -{ - random_values_cref values = mkvals_positive(); - unsigned sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - sum += msbfunc(values.next()); - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - - -C4BM_TEMPLATE(msb, uint8_t, msb_intrinsic_8bit); -C4BM_TEMPLATE(msb, uint8_t, msb_divconq_8bit); -C4BM_TEMPLATE(msb, uint8_t, msb_loop); - -C4BM_TEMPLATE(msb, int8_t, msb_intrinsic_8bit); -C4BM_TEMPLATE(msb, int8_t, msb_divconq_8bit); -C4BM_TEMPLATE(msb, int8_t, msb_loop); - -C4BM_TEMPLATE(msb, uint16_t, msb_intrinsic_16bit); -C4BM_TEMPLATE(msb, uint16_t, msb_divconq_16bit); -C4BM_TEMPLATE(msb, uint16_t, msb_loop); - -C4BM_TEMPLATE(msb, int16_t, msb_intrinsic_16bit); -C4BM_TEMPLATE(msb, int16_t, msb_divconq_16bit); -C4BM_TEMPLATE(msb, int16_t, msb_loop); - -C4BM_TEMPLATE(msb, uint32_t, msb_intrinsic_32bit); -C4BM_TEMPLATE(msb, uint32_t, msb_de_bruijn_32bit); -C4BM_TEMPLATE(msb, uint32_t, msb_divconq_32bit); -C4BM_TEMPLATE(msb, uint32_t, msb_divconq_branchless_32bit); -C4BM_TEMPLATE(msb, uint32_t, msb_loop); - -C4BM_TEMPLATE(msb, int32_t, msb_intrinsic_32bit); -C4BM_TEMPLATE(msb, int32_t, msb_de_bruijn_32bit); -C4BM_TEMPLATE(msb, int32_t, msb_divconq_32bit); -C4BM_TEMPLATE(msb, int32_t, msb_divconq_branchless_32bit); -C4BM_TEMPLATE(msb, int32_t, msb_loop); - -C4BM_TEMPLATE(msb, uint64_t, msb_intrinsic_64bit); -C4BM_TEMPLATE(msb, uint64_t, msb_divconq_64bit); -C4BM_TEMPLATE(msb, uint64_t, msb_loop); - -C4BM_TEMPLATE(msb, int64_t, msb_intrinsic_64bit); -C4BM_TEMPLATE(msb, int64_t, msb_divconq_64bit); -C4BM_TEMPLATE(msb, int64_t, msb_loop); - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -namespace impl { - -template -C4_CONSTEXPR14 C4_ALWAYS_INLINE -auto digits_glibc(_Tp __value) noexcept - -> typename std::enable_if::value, unsigned>::type -{ - static_assert(std::is_integral<_Tp>::value, "implementation bug"); - static_assert(std::is_unsigned<_Tp>::value, "implementation bug"); - unsigned __n = 1; - const unsigned __b2 = __base * __base; - const unsigned __b3 = __b2 * __base; - const unsigned long __b4 = __b3 * __base; - for (;;) - { - if (__value < (unsigned)__base) return __n; - if (__value < __b2) return __n + 1; - if (__value < __b3) return __n + 2; - if (__value < __b4) return __n + 3; - __value /= (_Tp) __b4; - __n += 4; - } -} - -template -C4_CONSTEXPR14 C4_ALWAYS_INLINE -auto digits_glibc(_Tp __value, unsigned __base) noexcept - -> typename std::enable_if::value, unsigned>::type -{ - static_assert(std::is_integral<_Tp>::value, "implementation bug"); - static_assert(std::is_unsigned<_Tp>::value, "implementation bug"); - unsigned __n = 1; - const unsigned __b2 = __base * __base; - const unsigned __b3 = __b2 * __base; - const unsigned long __b4 = __b3 * __base; - for (;;) - { - if (__value < (unsigned)__base) return __n; - if (__value < __b2) return __n + 1; - if (__value < __b3) return __n + 2; - if (__value < __b4) return __n + 3; - __value /= (_Tp)__b4; - __n += 4; - } -} - -template -constexpr C4_ALWAYS_INLINE -auto digits_glibc(_Tp __value) noexcept - -> typename std::enable_if::value, unsigned>::type -{ - using U = typename std::make_unsigned<_Tp>::type; - return digits_glibc((U)__value); -} - -template -constexpr C4_ALWAYS_INLINE -auto digits_glibc(_Tp __value, unsigned __base) noexcept - -> typename std::enable_if::value, unsigned>::type -{ - using U = typename std::make_unsigned<_Tp>::type; - return digits_glibc((U)__value, __base); -} - - -//------------------------------------------- -// https://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10Obvious - -// these functions assume the numbers are positive even when the type -// is signed - -template -constexpr C4_ALWAYS_INLINE -auto digits_dec_naive_hifirst(T v) noexcept - -> typename std::enable_if::type -{ - // best when the numbers are uniformly distributed over the whole range - return ((v >= 100) ? 3u : ((v >= 10) ? 2u : 1u)); -} - -template -constexpr C4_ALWAYS_INLINE -auto digits_dec_naive_lofirst(T v) noexcept - -> typename std::enable_if::type -{ - // best when lower numbers are more likely - return ((v < 10) ? 1u : ((v < 100) ? 2u : 3u)); -} - - -// 16 bit - -template -constexpr C4_ALWAYS_INLINE -auto digits_dec_naive_hifirst(T v) noexcept - -> typename std::enable_if::type -{ - // best when the numbers are uniformly distributed over the whole range - return ((v >= 10000) ? 5u : (v >= 1000) ? 4u : (v >= 100) ? 3u : (v >= 10) ? 2u : 1u); -} - -template -constexpr C4_ALWAYS_INLINE -auto digits_dec_naive_lofirst(T v) noexcept - -> typename std::enable_if::type -{ - // best when lower numbers are more likely - return ((v < 100) ? ((v >= 10) ? 2u : 1u) : ((v < 1000) ? 3u : ((v < 10000) ? 4u : 5u))); -} - - -// 32 bit - -template -constexpr C4_ALWAYS_INLINE -auto digits_dec_naive_hifirst(T v) noexcept - -> typename std::enable_if::type -{ - return ((v >= 1000000000) ? 10u : (v >= 100000000) ? 9u : (v >= 10000000) ? 8u : - (v >= 1000000) ? 7u : (v >= 100000) ? 6u : (v >= 10000) ? 5u : - (v >= 1000) ? 4u : (v >= 100) ? 3u : (v >= 10) ? 2u : 1u); -} - -template -constexpr C4_ALWAYS_INLINE -auto digits_dec_naive_lofirst(T v) noexcept - -> typename std::enable_if::type -{ - return ((v < 10) ? 1u : (v < 100) ? 2u : (v < 1000) ? 3u : (v < 10000) ? 4u : - (v < 100000) ? 5u : (v < 1000000) ? 6u : (v < 10000000) ? 7u : - (v < 100000000) ? 8u : (v < 1000000000) ? 9u : 10u); -} - - -// 64 bit - -template -constexpr C4_ALWAYS_INLINE -auto digits_dec_naive_hifirst(T v) noexcept - -> typename std::enable_if::type -{ - return ((std::is_unsigned::value && v >= T(10000000000000000000u)) ? 20u : - (v >= 1000000000000000000) ? 19u : (v >= 100000000000000000) ? 18u : (v >= 10000000000000000) ? 17u : - (v >= 1000000000000000) ? 16u : (v >= 100000000000000) ? 15u : (v >= 10000000000000) ? 14u : - (v >= 1000000000000) ? 13u : (v >= 100000000000) ? 12u : (v >= 10000000000) ? 11u : - (v >= 1000000000) ? 10u : (v >= 100000000) ? 9u : (v >= 10000000) ? 8u : - (v >= 1000000) ? 7u : (v >= 100000) ? 6u : (v >= 10000) ? 5u : - (v >= 1000) ? 4u : (v >= 100) ? 3u : (v >= 10) ? 2u : 1u); -} - -template -constexpr C4_ALWAYS_INLINE -auto digits_dec_naive_lofirst(T v) noexcept - -> typename std::enable_if::type -{ - return ((v < 10) ? 1u : (v < 100) ? 2u : (v < 1000) ? 3u : - (v < 10000) ? 4u : (v < 100000) ? 5u : (v < 1000000) ? 6u : - (v < 10000000) ? 7u : (v < 100000000) ? 8u : (v < 1000000000) ? 9u : - (v < 10000000000) ? 10u : (v < 100000000000) ? 11u : (v < 1000000000000) ? 12u : - (v < 10000000000000) ? 13u : (v < 100000000000000) ? 14u : (v < 1000000000000000) ? 15u : - (v < 10000000000000000) ? 16u : (v < 100000000000000000) ? 17u : (v < 1000000000000000000) ? 18u : - ((typename std::make_unsigned::type)v < 10000000000000000000u) ? 19u : 20u); -} - -template -C4_CONSTEXPR14 C4_ALWAYS_INLINE -auto digits_dec_naive_hifirst64fallback32(T v) noexcept - -> typename std::enable_if::type -{ - if(v >= std::numeric_limits::max()) - return digits_glibc(v); - else - return ((v >= 1000000000) ? 10u : (v >= 100000000) ? 9u : (v >= 10000000) ? 8u : - (v >= 1000000) ? 7u : (v >= 100000) ? 6u : (v >= 10000) ? 5u : - (v >= 1000) ? 4u : (v >= 100) ? 3u : (v >= 10) ? 2u : 1u); -} - -template -C4_CONSTEXPR14 C4_ALWAYS_INLINE -auto digits_dec_naive_lofirst64fallback32(T v) noexcept - -> typename std::enable_if::type -{ - if(v < std::numeric_limits::max()) - return ((v < 10) ? 1u : (v < 100) ? 2u : (v < 1000) ? 3u : (v < 10000) ? 4u : - (v < 100000) ? 5u : (v < 1000000) ? 6u : (v < 10000000) ? 7u : - (v < 100000000) ? 8u : (v < 1000000000) ? 9u : 10u); - else - return digits_glibc(v); -} - -template -C4_CONSTEXPR14 C4_ALWAYS_INLINE -auto digits_dec_naive_fargies(T v) noexcept - -> typename std::enable_if::type -{ - // https://github.com/biojppm/c4core/pull/77#issuecomment-1063753568 - if(v >= 1000000000) // 10 - { - if(v >= 100000000000000) // 15 [15-20] range - { - if(v >= 100000000000000000) // 18 (15 + (20 - 15) / 2) - { - if((typename std::make_unsigned::type)v >= 10000000000000000000u) // 20 - return 20u; - else - return (v >= 1000000000000000000) ? 19u : 18u; - } - else if(v >= 10000000000000000) // 17 - return 17u; - else - return(v >= 1000000000000000) ? 16u : 15u; - } - else if(v >= 1000000000000) // 13 - return (v >= 10000000000000) ? 14u : 13u; - else if(v >= 100000000000) // 12 - return 12; - else - return(v >= 10000000000) ? 11u : 10u; - } - else if(v >= 10000) // 5 [5-9] range - { - if(v >= 10000000) // 8 - return (v >= 100000000) ? 9u : 8u; - else if(v >= 1000000) // 7 - return 7; - else - return (v >= 100000) ? 6u : 5u; - } - else if(v >= 100) - return (v >= 1000) ? 4u : 3u; - else - return (v >= 10) ? 2u : 1u; -} - - -//------------------------------------------- -namespace c4 { -namespace detail { -template -struct powers_of_10; - -#define _C4_POWERS_OF_10_FOR(cond, ...) \ -template \ -struct powers_of_10::type> \ -{ \ - static C4_INLINE_CONSTEXPR const T values[] = {__VA_ARGS__}; \ - static C4_INLINE_CONSTEXPR const T values_size = C4_COUNTOF(values); \ -}; \ -template \ -C4_INLINE_CONSTEXPR const T powers_of_10::type>::values[] - -_C4_POWERS_OF_10_FOR(sizeof(T)==1u, 1, 10, 100 ); -_C4_POWERS_OF_10_FOR(sizeof(T)==2u, 1, 10, 100, 1000, 10000 ); -_C4_POWERS_OF_10_FOR(sizeof(T)==4u, 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 ); -_C4_POWERS_OF_10_FOR(std::is_signed::value && - sizeof(T)==8u, 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000, 1000000000000, 10000000000000, 100000000000000, 1000000000000000, 10000000000000000, 100000000000000000, 1000000000000000000 ); -_C4_POWERS_OF_10_FOR(std::is_unsigned::value && - sizeof(T)==8u, 1u, 10u, 100u, 1000u, 10000u, 100000u, 1000000u, 10000000u, 100000000u, 1000000000u, 10000000000u, 100000000000u, 1000000000000u, 10000000000000u, 100000000000000u, 1000000000000000u, 10000000000000000u, 100000000000000000u, 1000000000000000000u, 10000000000000000000u ); -} // namespace detail -} // namespace c4 - - -template msbfunc> -C4_CONSTEXPR14 C4_ALWAYS_INLINE -unsigned digits_dec_log10_nocheck(T v) noexcept -{ - // https://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10 - const unsigned mag = ((unsigned)msbfunc(v) + 1u) * 1233u >> 12; - C4_ASSERT(mag < c4::detail::powers_of_10::values_size); - return 1u + mag - (v < c4::detail::powers_of_10::values[mag]); -} - -template msbfunc> -C4_CONSTEXPR14 C4_ALWAYS_INLINE -unsigned digits_dec_log10(T v) noexcept -{ - if(v) - { - // https://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10 - const unsigned mag = ((unsigned)msbfunc(v) + 1u) * 1233u >> 12; - C4_ASSERT(mag < c4::detail::powers_of_10::values_size); - return 1u + mag - (v < c4::detail::powers_of_10::values[mag]); - } - return 1u; -} - -} // namespace impl - - -template -void digits_dec_naive_fargies(bm::State &st) -{ - random_values_cref values = mkvals_positive(); - unsigned sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - sum += impl::digits_dec_naive_fargies(values.next()); - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -template -void digits_dec_naive_hifirst(bm::State &st) -{ - random_values_cref values = mkvals_positive(); - unsigned sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - sum += impl::digits_dec_naive_hifirst(values.next()); - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -template -void digits_dec_naive_lofirst(bm::State &st) -{ - random_values_cref values = mkvals_positive(); - unsigned sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - sum += impl::digits_dec_naive_lofirst(values.next()); - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -template -void digits_dec_naive_hifirst64fallback32(bm::State &st) -{ - random_values_cref values = mkvals_positive(); - unsigned sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - sum += impl::digits_dec_naive_hifirst64fallback32(values.next()); - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -template -void digits_dec_naive_lofirst64fallback32(bm::State &st) -{ - random_values_cref values = mkvals_positive(); - unsigned sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - sum += impl::digits_dec_naive_lofirst64fallback32(values.next()); - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - - -template -void digits_dec_glibc_tpl(bm::State &st) -{ - random_values_cref values = mkvals_positive(); - unsigned sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - sum += impl::digits_glibc(values.next()); - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -template -void digits_dec_glibc(bm::State &st) -{ - random_values_cref values = mkvals_positive(); - unsigned sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - sum += impl::digits_glibc(values.next(), 10); - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -template msbfunc> -void digits_dec_log10_nocheck(bm::State &st) -{ - random_values_cref values = mkvals_positive(); - unsigned sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - sum += impl::digits_dec_log10_nocheck(values.next()); - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -template msbfunc> -void digits_dec_log10(bm::State &st) -{ - random_values_cref values = mkvals_positive(); - unsigned sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - sum += impl::digits_dec_log10(values.next()); - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -#define C4_INSTANTIATE_DIGITS_DEC_BENCHMARKS(ty, num) \ -C4BM_TEMPLATE(digits_dec_naive_hifirst, ty); \ -C4BM_TEMPLATE(digits_dec_naive_lofirst, ty); \ -C4BM_TEMPLATE(digits_dec_log10_nocheck, ty, msb_intrinsic_##num##bit); \ -C4BM_TEMPLATE(digits_dec_log10_nocheck, ty, msb_divconq_##num##bit); \ -C4BM_TEMPLATE(digits_dec_log10_nocheck, ty, msb_loop); \ -C4BM_TEMPLATE(digits_dec_log10, ty, msb_intrinsic_##num##bit); \ -C4BM_TEMPLATE(digits_dec_log10, ty, msb_divconq_##num##bit); \ -C4BM_TEMPLATE(digits_dec_log10, ty, msb_loop); \ -C4BM_TEMPLATE(digits_dec_glibc_tpl, ty); \ -C4BM_TEMPLATE(digits_dec_glibc, ty) - - -C4_INSTANTIATE_DIGITS_DEC_BENCHMARKS(uint8_t, 8); -C4_INSTANTIATE_DIGITS_DEC_BENCHMARKS(int8_t, 8); -C4_INSTANTIATE_DIGITS_DEC_BENCHMARKS(uint16_t, 16); -C4_INSTANTIATE_DIGITS_DEC_BENCHMARKS(int16_t, 16); -C4_INSTANTIATE_DIGITS_DEC_BENCHMARKS(uint32_t, 32); -C4_INSTANTIATE_DIGITS_DEC_BENCHMARKS(int32_t, 32); -C4BM_TEMPLATE(digits_dec_naive_fargies, uint64_t); -C4BM_TEMPLATE(digits_dec_naive_hifirst64fallback32, uint64_t); -C4BM_TEMPLATE(digits_dec_naive_lofirst64fallback32, uint64_t); -C4_INSTANTIATE_DIGITS_DEC_BENCHMARKS(uint64_t, 64); -C4BM_TEMPLATE(digits_dec_naive_fargies, int64_t); -C4BM_TEMPLATE(digits_dec_naive_hifirst64fallback32, int64_t); -C4BM_TEMPLATE(digits_dec_naive_lofirst64fallback32, int64_t); -C4_INSTANTIATE_DIGITS_DEC_BENCHMARKS(int64_t, 64); - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -namespace impl { - -// LEGEND: - -// checkall: check buffer length on every insertion -// checkonce: check buffer length only once when entering the function -// checkoncemax: as above, and compare against a compile-time maxdigits for the type -// checkoncelog: as above, and compare against the exact digits each from the actual number - -// divrem: compute div with operator/ and rem with operator% -// singlediv: compute div with operator/ but rem without using operator% (explicitly compute the remainder) - -// write1: write 1 digit per division (divide by 10 on each step) -// write2: write 2 digits per division (divide by 100 on each step) - - -static constexpr const char digits0099[201] = - "0001020304050607080910111213141516171819" - "2021222324252627282930313233343536373839" - "4041424344454647484950515253545556575859" - "6061626364656667686970717273747576777879" - "8081828384858687888990919293949596979899"; - - -//------------------------------------------------------------------- - -template -C4_ALWAYS_INLINE size_t write_dec_checkall_divrem_write1(c4::substr buf, T v) noexcept -{ - C4_STATIC_ASSERT(std::is_integral::value); - C4_ASSERT(v >= 0); - size_t pos = 0; - do { - if(C4_LIKELY(pos < buf.len)) - buf.str[pos] = (char)('0' + (v % T(10))); - ++pos; - v /= T(10); - } while(v); - buf.reverse_range(0, pos); - return pos; -} - -template -C4_ALWAYS_INLINE size_t write_dec_checkall_divrem_write2(c4::substr buf, T v) noexcept -{ - C4_STATIC_ASSERT(std::is_integral::value); - C4_ASSERT(v >= 0); - size_t pos = 0; - while(v >= T(100)) - { - const auto num = (v % T(100)) << 1u; - v /= T(100); - if(C4_LIKELY(pos + 2 < buf.len)) - { - buf.str[pos++] = digits0099[num + 1]; - buf.str[pos++] = digits0099[num]; - } - } - if(v >= T(10)) - { - const auto num = v << 1u; - if(C4_LIKELY(pos + 2 < buf.len)) - { - buf.str[pos++] = digits0099[num + 1]; - buf.str[pos++] = digits0099[num]; - } - } - else - { - if(C4_LIKELY(pos < buf.len)) - buf.str[pos++] = (char)('0' + v); - } - buf.reverse_range(0, pos); - return pos; -} - - -//------------------------------------------------------------------- - -template -C4_ALWAYS_INLINE size_t write_dec_checkall_singlediv_write1(c4::substr buf, T v) noexcept -{ - C4_STATIC_ASSERT(std::is_integral::value); - C4_ASSERT(v >= 0); - size_t pos = 0; - do { - const T quo = v / T(10); - const auto rem = v - quo * T(10); - v = quo; - if(C4_LIKELY(pos < buf.len)) - buf.str[pos] = (char)('0' + rem); - ++pos; - } while(v); - buf.reverse_range(0, pos); - return pos; -} - -template -C4_ALWAYS_INLINE size_t write_dec_checkall_singlediv_write2(c4::substr buf, T v) noexcept -{ - C4_STATIC_ASSERT(std::is_integral::value); - C4_ASSERT(v >= 0); - size_t pos = 0; - while(v >= T(100)) - { - const T quo = v / T(100); - const auto num = (v - quo * T(100)) << 1u; - v = quo; - if(C4_LIKELY(pos+2 < buf.len)) - { - buf.str[pos++] = digits0099[num + 1]; - buf.str[pos++] = digits0099[num]; - } - } - if(v >= T(10)) - { - const auto num = v << 1u; - if(C4_LIKELY(pos+2 < buf.len)) - { - buf.str[pos++] = digits0099[num + 1]; - buf.str[pos++] = digits0099[num ]; - } - } - else - { - if(C4_LIKELY(pos < buf.len)) - buf.str[pos++] = (char)('0' + v); - } - buf.reverse_range(0, pos); - return pos; -} - - -//------------------------------------------------------------------- - -template -C4_ALWAYS_INLINE size_t write_dec_checkoncemax_divrem_write1(c4::substr buf, T v) noexcept -{ - C4_STATIC_ASSERT(std::is_integral::value); - C4_ASSERT(v >= 0); - if(C4_UNLIKELY(buf.len < c4::detail::charconv_digits::maxdigits_dec)) - return c4::detail::charconv_digits::maxdigits_dec; - size_t pos = 0; - do { - buf.str[pos++] = (char)('0' + (v % T(10))); - v /= T(10); - } while(v); - buf.reverse_range(0, pos); - return pos; -} - -template -C4_ALWAYS_INLINE size_t write_dec_checkoncemax_divrem_write2(c4::substr buf, T v) noexcept -{ - C4_STATIC_ASSERT(std::is_integral::value); - C4_ASSERT(v >= 0); - if(C4_UNLIKELY(buf.len < c4::detail::charconv_digits::maxdigits_dec)) - return c4::detail::charconv_digits::maxdigits_dec; - size_t pos = 0; - while(v >= T(100)) - { - const auto num = (v % T(100)) << 1u; - v /= T(100); - buf.str[pos++] = digits0099[num + 1]; - buf.str[pos++] = digits0099[num]; - } - if(v >= T(10)) - { - const auto num = v << 1u; - buf.str[pos++] = digits0099[num + 1]; - buf.str[pos++] = digits0099[num ]; - } - else - { - buf.str[pos++] = (char)('0' + v); - } - buf.reverse_range(0, pos); - return pos; -} - - -//------------------------------------------------------------------- - -template -C4_ALWAYS_INLINE size_t write_dec_checkoncemax_singlediv_write1(c4::substr buf, T v) noexcept -{ - C4_STATIC_ASSERT(std::is_integral::value); - C4_ASSERT(v >= 0); - if(C4_UNLIKELY(buf.len < c4::detail::charconv_digits::maxdigits_dec)) - return c4::detail::charconv_digits::maxdigits_dec; - size_t pos = 0; - do { - const T quo = v / T(10); - const auto rem = (v - quo * T(10)); - v = quo; - buf.str[pos++] = (char)('0' + rem); - } while(v); - buf.reverse_range(0, pos); - return pos; -} - -template -C4_ALWAYS_INLINE size_t write_dec_checkoncemax_singlediv_write2(c4::substr buf, T v) noexcept -{ - C4_STATIC_ASSERT(std::is_integral::value); - C4_ASSERT(v >= 0); - size_t pos = 0; - if(C4_UNLIKELY(buf.len < c4::detail::charconv_digits::maxdigits_dec)) - return c4::detail::charconv_digits::maxdigits_dec; - while(v >= T(100)) - { - const T quo = v / T(100); - const auto num = (v - quo * T(100)) << 1u; - v = quo; - buf.str[pos++] = digits0099[num + 1]; - buf.str[pos++] = digits0099[num]; - } - if(v >= T(10)) - { - const auto num = v << 1u; - buf.str[pos++] = digits0099[num + 1]; - buf.str[pos++] = digits0099[num ]; - } - else - { - buf.str[pos++] = (char)('0' + v); - } - buf.reverse_range(0, pos); - return pos; -} - - -//------------------------------------------------------------------- - -template digitsfunc> -C4_ALWAYS_INLINE size_t write_dec_checkoncelog_divrem_write1(c4::substr buf, T v) noexcept -{ - C4_STATIC_ASSERT(std::is_integral::value); - C4_ASSERT(v >= 0); - unsigned digits = digitsfunc(v); - if(C4_UNLIKELY(buf.len < digits)) - return digits; - size_t pos = digits; - do { - buf.str[--pos] = (char)('0' + (v % T(10))); - v /= T(10); - } while(v); - return digits; -} - -template digitsfunc> -C4_ALWAYS_INLINE size_t write_dec_checkoncelog_divrem_write2(c4::substr buf, T v) noexcept -{ - C4_STATIC_ASSERT(std::is_integral::value); - C4_ASSERT(v >= 0); - unsigned digits = digitsfunc(v); - if(C4_UNLIKELY(buf.len < digits)) - return digits; - size_t pos = digits; - while(v >= T(100)) - { - const auto num = (v % T(100)) << 1u; - v /= T(100); - buf.str[--pos] = digits0099[num + 1]; - buf.str[--pos] = digits0099[num]; - } - if(v >= T(10)) - { - const auto num = v << 1u; - buf.str[1] = digits0099[num + 1]; - buf.str[0] = digits0099[num]; - } - else - { - buf.str[0] = (char)('0' + v); - } - return digits; -} - - -//------------------------------------------------------------------- - -template digitsfunc> -C4_ALWAYS_INLINE size_t write_dec_checkoncelog_singlediv_write1(c4::substr buf, T v) noexcept -{ - C4_STATIC_ASSERT(std::is_integral::value); - C4_ASSERT(v >= 0); - unsigned digits = digitsfunc(v); - if(C4_UNLIKELY(buf.len < digits)) - return digits; - size_t pos = digits; - do { - const T quo = v / T(10); - const auto rem = (v - quo * T(10)); - v = quo; - buf.str[--pos] = (char)('0' + rem); - } while(v); - return digits; -} - -template digitsfunc> -C4_ALWAYS_INLINE size_t write_dec_checkoncelog_singlediv_write2(c4::substr buf, T v) noexcept -{ - C4_STATIC_ASSERT(std::is_integral::value); - C4_ASSERT(v >= 0); - unsigned digits = digitsfunc(v); - if(C4_UNLIKELY(buf.len < digits)) - return digits; - size_t pos = digits; - while(v >= T(100)) - { - const T quo = v / T(100); - const auto num = (v - quo * T(100)) << 1u; - v = quo; - buf.str[--pos] = digits0099[num + 1]; - buf.str[--pos] = digits0099[num]; - } - if(v >= T(10)) - { - const auto num = v << 1u; - buf.str[1] = digits0099[num + 1]; - buf.str[0] = digits0099[num ]; - } - else - { - buf.str[0] = (char)('0' + v); - } - return digits; -} -} // namespace impl - - - -#define C4_DEFINE_WRITE_DEC_BM(name) \ -template \ -void write_dec_##name(bm::State &st) \ -{ \ - random_values_cref values = mkvals_positive(); \ - string_buffer buf_ = {}; \ - c4::substr buf = buf_; \ - C4_ASSERT(buf.len > 11); \ - size_t sum = {}; \ - for(auto _ : st) \ - { \ - C4DOALL(kNumValues) \ - sum += impl::write_dec_##name(buf, values.next()); \ - } \ - bm::DoNotOptimize(sum); \ - report(st, kNumValues); \ -} - -#define C4_DEFINE_WRITE_DEC_BM_FUNC(name) \ -template msbfunc> \ -void write_dec_##name(bm::State &st) \ -{ \ - random_values_cref values = mkvals_positive(); \ - string_buffer buf_ = {}; \ - c4::substr buf = buf_; \ - C4_ASSERT(buf.len > 11); \ - size_t sum = {}; \ - for(auto _ : st) \ - { \ - C4DOALL(kNumValues) \ - sum += impl::write_dec_##name(buf, values.next()); \ - } \ - bm::DoNotOptimize(sum); \ - report(st, kNumValues); \ -} - - -C4FOR(T, isint) -write_dec_c4_write_dec(bm::State& st) -{ - random_values_cref values = mkvals_positive(); - string_buffer buf_ = {}; - c4::substr buf = buf_; - size_t sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - sum += c4::write_dec(buf, values.next()); - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} - -#if defined(__cpp_lib_to_chars) || (C4_CPP >= 17) -#define C4_TO_CHARS_BM(ty) C4BM_TEMPLATE(write_dec_std_to_chars, ty) -C4FOR(T, isint) -write_dec_std_to_chars(bm::State& st) -{ - random_values_cref values = mkvals_positive(); - string_buffer buf_ = {}; - c4::substr buf = buf_; - size_t sum = {}; - for(auto _ : st) - { - C4DOALL(kNumValues) - { - auto result = std::to_chars(buf.begin(), buf.end(), values.next()); - sum += (size_t)(result.ptr - buf.str); - } - } - bm::DoNotOptimize(sum); - report(st, kNumValues); -} -#else -#define C4_TO_CHARS_BM(ty) -#endif - - -C4_DEFINE_WRITE_DEC_BM_FUNC(checkoncelog_singlediv_write2) -C4_DEFINE_WRITE_DEC_BM_FUNC(checkoncelog_singlediv_write1) -C4_DEFINE_WRITE_DEC_BM_FUNC(checkoncelog_divrem_write2) -C4_DEFINE_WRITE_DEC_BM_FUNC(checkoncelog_divrem_write1) - -C4_DEFINE_WRITE_DEC_BM(checkoncemax_singlediv_write2) -C4_DEFINE_WRITE_DEC_BM(checkoncemax_singlediv_write1) -C4_DEFINE_WRITE_DEC_BM(checkoncemax_divrem_write2) -C4_DEFINE_WRITE_DEC_BM(checkoncemax_divrem_write1) - -C4_DEFINE_WRITE_DEC_BM(checkall_singlediv_write2) -C4_DEFINE_WRITE_DEC_BM(checkall_singlediv_write1) -C4_DEFINE_WRITE_DEC_BM(checkall_divrem_write2) -C4_DEFINE_WRITE_DEC_BM(checkall_divrem_write1) - - - -#define C4_INSTANTIATE_WRITE_DEC_BENCHMARKS(ty, num) \ - \ -/*compare against std::to_chars()*/ \ -C4_TO_CHARS_BM(ty); \ - \ -/*our versions*/ \ -C4BM_TEMPLATE(write_dec_c4_write_dec, ty); \ - \ -C4BM_TEMPLATE(write_dec_checkoncelog_singlediv_write2, ty, impl::digits_dec_naive_hifirst); \ -C4BM_TEMPLATE(write_dec_checkoncelog_singlediv_write2, ty, impl::digits_dec_naive_lofirst); \ -C4BM_TEMPLATE(write_dec_checkoncelog_singlediv_write2, ty, impl::digits_glibc); \ -C4BM_TEMPLATE(write_dec_checkoncelog_singlediv_write2, ty, impl::digits_dec_log10_nocheck>); \ -C4BM_TEMPLATE(write_dec_checkoncelog_singlediv_write2, ty, impl::digits_dec_log10_nocheck>); \ -C4BM_TEMPLATE(write_dec_checkoncelog_singlediv_write2, ty, impl::digits_dec_log10_nocheck>); \ -C4BM_TEMPLATE(write_dec_checkoncelog_singlediv_write2, ty, impl::digits_dec_log10>); \ -C4BM_TEMPLATE(write_dec_checkoncelog_singlediv_write2, ty, impl::digits_dec_log10>); \ -C4BM_TEMPLATE(write_dec_checkoncelog_singlediv_write2, ty, impl::digits_dec_log10>); \ - \ -C4BM_TEMPLATE(write_dec_checkoncelog_singlediv_write1, ty, impl::digits_dec_naive_hifirst); \ -C4BM_TEMPLATE(write_dec_checkoncelog_singlediv_write1, ty, impl::digits_dec_naive_lofirst); \ -C4BM_TEMPLATE(write_dec_checkoncelog_singlediv_write1, ty, impl::digits_glibc); \ -C4BM_TEMPLATE(write_dec_checkoncelog_singlediv_write1, ty, impl::digits_dec_log10_nocheck>); \ -C4BM_TEMPLATE(write_dec_checkoncelog_singlediv_write1, ty, impl::digits_dec_log10_nocheck>); \ -C4BM_TEMPLATE(write_dec_checkoncelog_singlediv_write1, ty, impl::digits_dec_log10_nocheck>); \ -C4BM_TEMPLATE(write_dec_checkoncelog_singlediv_write1, ty, impl::digits_dec_log10>); \ -C4BM_TEMPLATE(write_dec_checkoncelog_singlediv_write1, ty, impl::digits_dec_log10>); \ -C4BM_TEMPLATE(write_dec_checkoncelog_singlediv_write1, ty, impl::digits_dec_log10>); \ - \ -C4BM_TEMPLATE(write_dec_checkoncelog_divrem_write2, ty, impl::digits_dec_naive_hifirst); \ -C4BM_TEMPLATE(write_dec_checkoncelog_divrem_write2, ty, impl::digits_dec_naive_lofirst); \ -C4BM_TEMPLATE(write_dec_checkoncelog_divrem_write2, ty, impl::digits_glibc); \ -C4BM_TEMPLATE(write_dec_checkoncelog_divrem_write2, ty, impl::digits_dec_log10_nocheck>); \ -C4BM_TEMPLATE(write_dec_checkoncelog_divrem_write2, ty, impl::digits_dec_log10_nocheck>); \ -C4BM_TEMPLATE(write_dec_checkoncelog_divrem_write2, ty, impl::digits_dec_log10_nocheck>); \ -C4BM_TEMPLATE(write_dec_checkoncelog_divrem_write2, ty, impl::digits_dec_log10>); \ -C4BM_TEMPLATE(write_dec_checkoncelog_divrem_write2, ty, impl::digits_dec_log10>); \ -C4BM_TEMPLATE(write_dec_checkoncelog_divrem_write2, ty, impl::digits_dec_log10>); \ - \ -C4BM_TEMPLATE(write_dec_checkoncelog_divrem_write1, ty, impl::digits_dec_naive_hifirst); \ -C4BM_TEMPLATE(write_dec_checkoncelog_divrem_write1, ty, impl::digits_dec_naive_lofirst); \ -C4BM_TEMPLATE(write_dec_checkoncelog_divrem_write1, ty, impl::digits_glibc); \ -C4BM_TEMPLATE(write_dec_checkoncelog_divrem_write1, ty, impl::digits_dec_log10_nocheck>); \ -C4BM_TEMPLATE(write_dec_checkoncelog_divrem_write1, ty, impl::digits_dec_log10_nocheck>); \ -C4BM_TEMPLATE(write_dec_checkoncelog_divrem_write1, ty, impl::digits_dec_log10_nocheck>); \ -C4BM_TEMPLATE(write_dec_checkoncelog_divrem_write1, ty, impl::digits_dec_log10>); \ -C4BM_TEMPLATE(write_dec_checkoncelog_divrem_write1, ty, impl::digits_dec_log10>); \ -C4BM_TEMPLATE(write_dec_checkoncelog_divrem_write1, ty, impl::digits_dec_log10>); \ - \ -C4BM_TEMPLATE(write_dec_checkoncemax_singlediv_write2, ty); \ -C4BM_TEMPLATE(write_dec_checkoncemax_singlediv_write1, ty); \ -C4BM_TEMPLATE(write_dec_checkoncemax_divrem_write2, ty); \ -C4BM_TEMPLATE(write_dec_checkoncemax_divrem_write1, ty); \ - \ -C4BM_TEMPLATE(write_dec_checkall_singlediv_write2, ty); \ -C4BM_TEMPLATE(write_dec_checkall_singlediv_write1, ty); \ -C4BM_TEMPLATE(write_dec_checkall_divrem_write2, ty); \ -C4BM_TEMPLATE(write_dec_checkall_divrem_write1, ty) - - - -#define C4_INSTANTIATE_WRITE_DEC_BENCHMARKS64(ty) \ - \ -C4BM_TEMPLATE(write_dec_checkoncelog_singlediv_write2, ty, impl::digits_dec_naive_fargies); \ -C4BM_TEMPLATE(write_dec_checkoncelog_singlediv_write2, ty, impl::digits_dec_naive_hifirst64fallback32); \ -C4BM_TEMPLATE(write_dec_checkoncelog_singlediv_write2, ty, impl::digits_dec_naive_lofirst64fallback32); \ - \ -C4BM_TEMPLATE(write_dec_checkoncelog_singlediv_write1, ty, impl::digits_dec_naive_fargies); \ -C4BM_TEMPLATE(write_dec_checkoncelog_singlediv_write1, ty, impl::digits_dec_naive_hifirst64fallback32); \ -C4BM_TEMPLATE(write_dec_checkoncelog_singlediv_write1, ty, impl::digits_dec_naive_lofirst64fallback32); \ - \ -C4BM_TEMPLATE(write_dec_checkoncelog_divrem_write2, ty, impl::digits_dec_naive_fargies); \ -C4BM_TEMPLATE(write_dec_checkoncelog_divrem_write2, ty, impl::digits_dec_naive_hifirst64fallback32); \ -C4BM_TEMPLATE(write_dec_checkoncelog_divrem_write2, ty, impl::digits_dec_naive_lofirst64fallback32); \ - \ -C4BM_TEMPLATE(write_dec_checkoncelog_divrem_write1, ty, impl::digits_dec_naive_fargies); \ -C4BM_TEMPLATE(write_dec_checkoncelog_divrem_write1, ty, impl::digits_dec_naive_hifirst64fallback32); \ -C4BM_TEMPLATE(write_dec_checkoncelog_divrem_write1, ty, impl::digits_dec_naive_lofirst64fallback32) - - -C4_INSTANTIATE_WRITE_DEC_BENCHMARKS(uint8_t, 8); -C4_INSTANTIATE_WRITE_DEC_BENCHMARKS(int8_t, 8); -C4_INSTANTIATE_WRITE_DEC_BENCHMARKS(uint16_t, 16); -C4_INSTANTIATE_WRITE_DEC_BENCHMARKS(int16_t, 16); -C4_INSTANTIATE_WRITE_DEC_BENCHMARKS(uint32_t, 32); -C4_INSTANTIATE_WRITE_DEC_BENCHMARKS(int32_t, 32); -C4_INSTANTIATE_WRITE_DEC_BENCHMARKS64(uint64_t); -C4_INSTANTIATE_WRITE_DEC_BENCHMARKS(uint64_t, 64); -C4_INSTANTIATE_WRITE_DEC_BENCHMARKS64(int64_t); -C4_INSTANTIATE_WRITE_DEC_BENCHMARKS(int64_t, 64); - - -#if defined(__GNUC__) -# pragma GCC diagnostic pop -#endif - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -template struct xtoacase { c4::csubstr str; T val; }; -#define _(num) {c4::csubstr(#num), num##u} -xtoacase cases_8bit[] = { - _(0), - _(1), - _(9), - _(10), - _(11), - _(98), - _(99), - _(100), - _(101), -}; -xtoacase cases_16bit[] = { - _(999), - _(1000), - _(1001), - _(9999), - _(10000), - _(10001), -}; -xtoacase cases_32bit[] = { - _(99999), - _(100000), - _(100001), - _(999999), - _(1000000), - _(1000001), - _(9999999), - _(10000000), - _(10000001), - _(99999999), - _(100000000), - _(100000001), - _(999999999), - _(1000000000), - _(1000000001), -}; -xtoacase cases_64bit[] = { - _(9999999999), - _(10000000000), - _(10000000001), - _(99999999999), - _(100000000000), - _(100000000001), - _(999999999999), - _(1000000000000), - _(1000000000001), - _(9999999999999), - _(10000000000000), - _(10000000000001), - _(99999999999999), - _(100000000000000), - _(100000000000001), - _(999999999999999), - _(1000000000000000), - _(1000000000000001), - _(9999999999999999), - _(10000000000000000), - _(10000000000000001), - _(99999999999999999), - _(100000000000000000), - _(100000000000000001), - _(999999999999999999), - _(1000000000000000000), - _(1000000000000000001), - _(9223372036854775807), -}; -xtoacase cases_64bitu[] = { - _(9999999999999999999), - _(10000000000000000000), - _(18446744073709551615), -}; -#undef _ - -bool logtest = true; -bool printok = false; -bool testfail = false; -#define C4_CHECK_(lhs, op, rhs, ...) \ - { \ - if(!((lhs) op (rhs))) \ - { \ - std::cout << __FILE__ << ":" << __LINE__ \ - << ": failed! " << #lhs " " #op " " #rhs "\n" \ - << " " #lhs "=" << (lhs) << "\n" \ - << " " #rhs "=" << (rhs) << "\n" \ - << " " << __VA_ARGS__ << "\n"; \ - testfail = true; \ - } \ - else if(printok) \ - { \ - std::cout << __FILE__ << ":" << __LINE__ \ - << ": ok! " << #lhs " " #op " " #rhs \ - << " " << __VA_ARGS__ << "\n"; \ - } \ - } - -C4_SUPPRESS_WARNING_CLANG("-Wgnu-zero-variadic-macro-arguments") -#define C4_CHECK_LT(lhs, rhs, ...) C4_CHECK_(lhs, <, rhs, ## __VA_ARGS__) -#define C4_CHECK_LE(lhs, rhs, ...) C4_CHECK_(lhs, <=, rhs, ## __VA_ARGS__) -#define C4_CHECK_GT(lhs, rhs, ...) C4_CHECK_(lhs, >, rhs, ## __VA_ARGS__) -#define C4_CHECK_GE(lhs, rhs, ...) C4_CHECK_(lhs, >=, rhs, ## __VA_ARGS__) -#define C4_CHECK_EQ(lhs, rhs, ...) C4_CHECK_(lhs, ==, rhs, ## __VA_ARGS__) -#define C4_CHECK_NE(lhs, rhs, ...) C4_CHECK_(lhs, !=, rhs, ## __VA_ARGS__) - -#define DO_TEST_DIGITS_(ty, fn, num) \ - if(logtest) std::cout << "\ntesting: " #fn "\n"; \ - test_digits##num(); \ - if(logtest) std::cout << "success: " #fn "\n" - -#define DO_TEST_WRITE_(ty, fn, num) \ - if(logtest) std::cout << "\ntesting: " #fn "\n"; \ - test_write##num(&fn); \ - if(logtest) std::cout << "success: " #fn "\n" - - -template -void test_write(xtoacase c, Func fn) -{ - if(c.val == 0) - return; - C4_STATIC_ASSERT(sizeof(T) >= sizeof(U)); - char buf_[32] = {}; - c4::substr buf = buf_; - C4_CHECK_GT(c.val, 0, c.str << "/" << (uint64_t)c.val); - C4_CHECK_LE((U)c.val, (U)std::numeric_limits::max(), c.str << "/" << (uint64_t)c.val); - T val = (T)c.val; - size_t ret = fn(buf, val); - C4_CHECK_EQ(ret, c.str.len, c.str << "/" << (uint64_t)c.val << ": " << buf.first(ret)); - C4_CHECK_EQ(buf.first(ret), c.str, c.str << "/" << (uint64_t)c.val); -} - -template digitsfunc> -void test_digits8() -{ - for(auto c : cases_8bit) - C4_CHECK_EQ(digitsfunc((T)c.val), c.str.len, (uint64_t)c.val); -} -template -void test_write8(Func func) -{ - for(auto c : cases_8bit) - test_write(c, func); -} - -template digitsfunc> -void test_digits16() -{ - test_digits8(); - for(auto c : cases_16bit) - C4_CHECK_EQ(digitsfunc((T)c.val), c.str.len, (uint64_t)c.val); -} -template -void test_write16(Func func) -{ - test_write8(func); - for(auto c : cases_16bit) - test_write(c, func); -} - -template digitsfunc> -void test_digits32() -{ - test_digits8(); - test_digits16(); - for(auto c : cases_32bit) - C4_CHECK_EQ(digitsfunc((T)c.val), c.str.len, (uint64_t)c.val); -} -template -void test_write32(Func func) -{ - test_write8(func); - test_write16(func); - for(auto c : cases_32bit) - test_write(c, func); -} - -template digitsfunc> -void test_digits64() -{ - test_digits8(); - test_digits16(); - test_digits32(); - for(auto c : cases_64bit) - C4_CHECK_EQ(digitsfunc((T)c.val), c.str.len, (uint64_t)c.val); - if(std::is_unsigned::value) - for(auto c : cases_64bitu) - C4_CHECK_EQ(digitsfunc((T)c.val), c.str.len, (uint64_t)c.val << "/" << c.str); -} -template -auto test_write64(Func func) - -> typename std::enable_if::value, void>::type -{ - test_write8(func); - test_write16(func); - test_write32(func); - for(auto c : cases_64bit) - test_write(c, func); - for(auto c : cases_64bitu) - test_write(c, func); -} -template -auto test_write64(Func func) - -> typename std::enable_if::value, void>::type -{ - test_write8(func); - test_write16(func); - test_write32(func); - for(auto c : cases_64bit) - test_write(c, func); -} - -#define DO_TEST_DIGITS(ty, num) \ -DO_TEST_DIGITS_(ty, impl::digits_dec_naive_hifirst, num); \ -DO_TEST_DIGITS_(ty, impl::digits_dec_naive_lofirst, num); \ -DO_TEST_DIGITS_(ty, impl::digits_glibc, num); \ -DO_TEST_DIGITS_(ty, impl::digits_dec_log10>, num); \ -DO_TEST_DIGITS_(ty, impl::digits_dec_log10>, num); \ -DO_TEST_DIGITS_(ty, impl::digits_dec_log10>, num) - -#define DO_TEST_DIGITS_64(ty) \ -DO_TEST_DIGITS_(ty, impl::digits_dec_naive_fargies, 64); \ -DO_TEST_DIGITS_(ty, impl::digits_dec_naive_hifirst64fallback32, 64); \ -DO_TEST_DIGITS_(ty, impl::digits_dec_naive_lofirst64fallback32, 64); \ -DO_TEST_DIGITS_(ty, impl::digits_dec_naive_fargies, 64); \ -DO_TEST_DIGITS_(ty, impl::digits_dec_naive_hifirst64fallback32, 64); \ -DO_TEST_DIGITS_(ty, impl::digits_dec_naive_lofirst64fallback32, 64); \ -DO_TEST_DIGITS_(ty, impl::digits_dec_naive_fargies, 64); \ -DO_TEST_DIGITS_(ty, impl::digits_dec_naive_hifirst64fallback32, 64); \ -DO_TEST_DIGITS_(ty, impl::digits_dec_naive_lofirst64fallback32, 64); \ -DO_TEST_DIGITS_(ty, impl::digits_dec_naive_fargies, 64); \ -DO_TEST_DIGITS_(ty, impl::digits_dec_naive_hifirst64fallback32, 64); \ -DO_TEST_DIGITS_(ty, impl::digits_dec_naive_lofirst64fallback32, 64) - - -#define DO_TEST_WRITE(ty, num) \ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_singlediv_write2>, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_singlediv_write2>, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_singlediv_write2>, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_singlediv_write2>>, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_singlediv_write2>>, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_singlediv_write2>>, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_singlediv_write2>>, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_singlediv_write2>>, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_singlediv_write2>>, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_singlediv_write1>, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_singlediv_write1>, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_singlediv_write1>, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_singlediv_write1>>, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_singlediv_write1>>, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_singlediv_write1>>, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_singlediv_write1>>, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_singlediv_write1>>, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_singlediv_write1>>, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_divrem_write2>, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_divrem_write2>, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_divrem_write2>, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_divrem_write2>>, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_divrem_write2>>, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_divrem_write2>>, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_divrem_write2>>, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_divrem_write2>>, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_divrem_write2>>, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_divrem_write1>, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_divrem_write1>, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_divrem_write1>, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_divrem_write1>>, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_divrem_write1>>, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_divrem_write1>>, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_divrem_write1>>, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_divrem_write1>>, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_divrem_write1>>, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncemax_singlediv_write2, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncemax_singlediv_write1, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncemax_divrem_write2, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncemax_divrem_write1, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkall_singlediv_write2, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkall_singlediv_write1, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkall_divrem_write2, num);\ -DO_TEST_WRITE_(ty, impl::write_dec_checkall_divrem_write1, num) - - -#define DO_TEST_WRITE_64(ty) \ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_singlediv_write2>, 64); \ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_singlediv_write2>, 64); \ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_singlediv_write2>, 64); \ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_singlediv_write1>, 64); \ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_singlediv_write1>, 64); \ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_singlediv_write1>, 64); \ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_divrem_write2>, 64); \ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_divrem_write2>, 64); \ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_divrem_write2>, 64); \ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_divrem_write1>, 64); \ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_divrem_write1>, 64); \ -DO_TEST_WRITE_(ty, impl::write_dec_checkoncelog_divrem_write1>, 64) - - -void do_test() -{ - DO_TEST_DIGITS(uint8_t, 8); - DO_TEST_DIGITS(int8_t, 8); - DO_TEST_DIGITS(uint16_t, 16); - DO_TEST_DIGITS(int16_t, 16); - DO_TEST_DIGITS(uint32_t, 32); - DO_TEST_DIGITS(int32_t, 32); - DO_TEST_DIGITS(uint64_t, 64); - DO_TEST_DIGITS(int64_t, 64); - DO_TEST_DIGITS_64(uint64_t); - DO_TEST_DIGITS_64(int64_t); - printf("\n"); - DO_TEST_WRITE(uint8_t, 8); - DO_TEST_WRITE(int8_t, 8); - DO_TEST_WRITE(uint16_t, 16); - DO_TEST_WRITE(int16_t, 16); - DO_TEST_WRITE(uint32_t, 32); - DO_TEST_WRITE(int32_t, 32); - DO_TEST_WRITE(uint64_t, 64); - DO_TEST_WRITE(int64_t, 64); - DO_TEST_WRITE_64(uint64_t); - DO_TEST_WRITE_64(int64_t); - printf("\n"); - C4_CHECK(!testfail); -} - - -int main(int argc, char *argv[]) -{ - //do_test(); - bm::Initialize(&argc, argv); - bm::RunSpecifiedBenchmarks(); - return 0; -} diff --git a/thirdparty/ryml/ext/c4core/bm/float/measure.py b/thirdparty/ryml/ext/c4core/bm/float/measure.py deleted file mode 100644 index 253d03a45..000000000 --- a/thirdparty/ryml/ext/c4core/bm/float/measure.py +++ /dev/null @@ -1,65 +0,0 @@ -import time -import argparse -import os -import subprocess -import shlex -from ruamel import yaml - - -def runcmd(cmd, *cmd_args, **subprocess_args): - cmd = shlex.split(cmd) + list(cmd_args) - #print(" ".join([f"'{a}'" for a in cmd]), flush=True) - proc = subprocess.run(cmd, **subprocess_args) - return proc - - -def getoutput(cmd, *cmd_args, **subprocess_args): - proc = runcmd(cmd, *cmd_args, **subprocess_args, check=True, - stdout=subprocess.PIPE) - return proc.stdout.decode("utf8") - - -def start_build(args): - ts = time.time() - with open(args.out, "w") as f: - f.write(str(ts)) - - -def finish_build(args): - ts = time.time() - with open(args.out, "r") as f: - start = float(f.read()) - duration = ts - start - results = { - 'compile': f"{duration:.3f}s", - 'file_size': f"{os.path.getsize(args.exe)}B" - } - s = yaml.dump({args.target: results}) - print(s, flush=True, end="") - ## too much output: - #if args.unix: - # # https://stackoverflow.com/questions/35485 - # results['size'] = getoutput('size', args.exe) - # #results['symbols'] = getoutput('nm -t d -l -S --size-sort', args.exe) - s = yaml.dump({args.target: results}) - with open(args.out, "w") as f: - f.write(s) - - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - subparsers = parser.add_subparsers() - # - sp = subparsers.add_parser("start") - sp.set_defaults(func=start_build) - sp.add_argument('target', type=str, help='the target name') - # - sp = subparsers.add_parser("finish") - sp.set_defaults(func=finish_build) - sp.add_argument('target', type=str, help='the target name') - sp.add_argument('exe', type=str, help='the executable file') - sp.add_argument('-u', '--unix', action="store_true", help='use unix style size reporters') - # - args = parser.parse_args() - args.out = f"{args.target}.dat" - args.func(args) diff --git a/thirdparty/ryml/ext/c4core/bm/float/read.cpp b/thirdparty/ryml/ext/c4core/bm/float/read.cpp deleted file mode 100644 index 5401ff1bb..000000000 --- a/thirdparty/ryml/ext/c4core/bm/float/read.cpp +++ /dev/null @@ -1,170 +0,0 @@ -#include - - -#ifdef _MSC_VER -# pragma warning(push) -# pragma warning(disable : 4430) -# pragma warning(disable : 4305) -# pragma warning(disable : 4309) -# pragma warning(disable : 4838) -# pragma warning(disable : 4996) -#elif defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wsign-conversion" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wsign-conversion" -#endif - - -#if C4FLOAT_STD_ATOF -#include -double doit(const char *s) { return atof(s); } -#define C4_TO_REAL(s) doit(s) - -#elif C4FLOAT_SSCANF_F -float doit(const char *s) { float val; sscanf(s, "%f", &val); return val; } -#define C4_TO_REAL(s) doit(s) - -#elif C4FLOAT_SSCANF_D -double doit(const char *s) { double val; sscanf(s, "%lf", &val); return val; } -#define C4_TO_REAL(s) doit(s) - -#elif C4FLOAT_IOSTREAM_F -#include -float doit(const char *s) { std::stringstream ss; ss << s; float val; ss >> val; return val; } -#define C4_TO_REAL(s) doit(s) - -#elif C4FLOAT_IOSTREAM_D -#include -double doit(const char *s) { std::stringstream ss; ss << s; double val; ss >> val; return val; } -#define C4_TO_REAL(s) doit(s) - -#elif C4FLOAT_IOSTREAM_D -#include -double doit(const char *s) { std::stringstream ss; ss << s; double val; ss >> val; return val; } -#define C4_TO_REAL(s) doit(s) - -#elif C4FLOAT_FP_F_LIMITED -#include -float doit(const char *s) -{ - auto result = jkj::fp::from_chars_limited(s, s+strlen(s)); - return result.to_float(); -} -#define C4_TO_REAL(s) doit(s) - -#elif C4FLOAT_FP_D_LIMITED -#include -double doit(const char *s) -{ - auto result = jkj::fp::from_chars_limited(s, s+strlen(s)); - return result.to_float(); -} -#define C4_TO_REAL(s) doit(s) - -#elif C4FLOAT_FP_F_UNLIMITED -#include -float doit(const char *s) -{ - auto result = jkj::fp::from_chars_unlimited(s, s+strlen(s)); - return result.to_float(); -} -#define C4_TO_REAL(s) doit(s) - -#elif C4FLOAT_FP_D_UNLIMITED -#include -double doit(const char *s) -{ - auto result = jkj::fp::from_chars_unlimited(s, s+strlen(s)); - return result.to_float(); -} -#define C4_TO_REAL(s) doit(s) - -#elif C4FLOAT_FASTFLOAT_F -#include -#include -float doit(const char *s) -{ - float result; - fast_float::from_chars(s, s+strlen(s), result); - return result; -} -#define C4_TO_REAL(s) doit(s) - -#elif C4FLOAT_FASTFLOAT_D -#include -#include -double doit(const char *s) -{ - double result; - fast_float::from_chars(s, s+strlen(s), result); - return result; -} -#define C4_TO_REAL(s) doit(s) - -#elif C4FLOAT_STD_FROM_CHARS_F -#include -#include -float doit(const char *s) -{ - float result; - std::from_chars(s, s+strlen(s), result); - return result; -} -#define C4_TO_REAL(s) doit(s) - -#elif C4FLOAT_STD_FROM_CHARS_D -#include -#include -double doit(const char *s) -{ - double result; - std::from_chars(s, s+strlen(s), result); - return result; -} -#define C4_TO_REAL(s) doit(s) - -#elif C4FLOAT_RYU_F -#include -float doit(const char *s) -{ - float result; - s2f(s, &result); - return result; -} -#define C4_TO_REAL(s) doit(s) - -#elif C4FLOAT_RYU_D -#include -double doit(const char *s) -{ - double result; - s2d(s, &result); - return result; -} -#define C4_TO_REAL(s) doit(s) - -#else -#define C4_TO_REAL(s) 0 -#endif - -int main() -{ - #define BUFSIZE 128 - char buf[BUFSIZE]; - while(fgets(buf, BUFSIZE, stdin)) - { - fputs(buf, stdout); - (void) C4_TO_REAL(buf); - } -} - - -#ifdef _MSC_VER -# pragma warning(pop) -#elif defined(__clang__) -# pragma clang diagnostic pop -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#endif diff --git a/thirdparty/ryml/ext/c4core/bm/ryu.cmake b/thirdparty/ryml/ext/c4core/bm/ryu.cmake deleted file mode 100644 index 93079a489..000000000 --- a/thirdparty/ryml/ext/c4core/bm/ryu.cmake +++ /dev/null @@ -1,37 +0,0 @@ -# ryu does not have a cmakelists - -if(C4CORE_BM_USE_RYU) - enable_language(C) - - c4_download_remote_proj(ryu RYU_DIR - GIT_REPOSITORY https://github.com/ulfjack/ryu - GIT_TAG master GIT_SHALLOW ON) - set(RYU_HDR - ${RYU_DIR}/ryu/common.h - ${RYU_DIR}/ryu/d2fixed_full_table.h - ${RYU_DIR}/ryu/d2s_full_table.h - ${RYU_DIR}/ryu/d2s_intrinsics.h - ${RYU_DIR}/ryu/d2s_small_table.h - ${RYU_DIR}/ryu/digit_table.h - ${RYU_DIR}/ryu/f2s_full_table.h - ${RYU_DIR}/ryu/f2s_intrinsics.h - ${RYU_DIR}/ryu/ryu.h - ${RYU_DIR}/ryu/ryu_parse.h - ) - set(RYU_SRC - ${RYU_DIR}/ryu/d2fixed.c - ${RYU_DIR}/ryu/d2s.c - ${RYU_DIR}/ryu/f2s.c - ${RYU_DIR}/ryu/s2d.c - ${RYU_DIR}/ryu/s2f.c - ) - add_library(ryu_c4 ${RYU_SRC} ${RYU_HDR}) - target_include_directories(ryu_c4 PUBLIC $) - set_target_properties(ryu_c4 PROPERTIES LINKER_LANGUAGE CXX) - if(CMAKE_CXX_COMPILER_ID STREQUAL GNU) - target_compile_options(ryu_c4 PRIVATE -Wno-sign-conversion) - elseif(CMAKE_CXX_COMPILER_ID STREQUAL GNU) - target_compile_options(ryu_c4 -Wno-deprecated) - endif() - _c4_set_target_folder(ryu_c4 ext) -endif() diff --git a/thirdparty/ryml/ext/c4core/changelog/0.1.0.md b/thirdparty/ryml/ext/c4core/changelog/0.1.0.md deleted file mode 100644 index 7e9e8a67b..000000000 --- a/thirdparty/ryml/ext/c4core/changelog/0.1.0.md +++ /dev/null @@ -1,3 +0,0 @@ -# 0.1.0 - -First release. diff --git a/thirdparty/ryml/ext/c4core/changelog/0.1.1.md b/thirdparty/ryml/ext/c4core/changelog/0.1.1.md deleted file mode 100644 index 934c65f30..000000000 --- a/thirdparty/ryml/ext/c4core/changelog/0.1.1.md +++ /dev/null @@ -1,5 +0,0 @@ -# 0.1.1 - -- Fix parsing of hexadecimal floats ([2d5c3f0](https://github.com/biojppm/c4core/commits/2d5c3f0)) -- Fix `csubstr::reverse_sub()` ([902c5b9](https://github.com/biojppm/c4core/commits/902c5b9)) -- Fix [#35](https://github.com/biojppm/c4core/issues/35): add SO_VERSION diff --git a/thirdparty/ryml/ext/c4core/changelog/0.1.10.md b/thirdparty/ryml/ext/c4core/changelog/0.1.10.md deleted file mode 100644 index ce95aaee1..000000000 --- a/thirdparty/ryml/ext/c4core/changelog/0.1.10.md +++ /dev/null @@ -1,106 +0,0 @@ -### Changes - -Improved the performance of `c4/charconv.hpp` functions ([PR#77](https://github.com/biojppm/c4core/pull/77)): - - Added `digits_dec/hex/oct/bin()`. - - Optimized `write_dec/hex/oct/bin()`: - - these functions now return immediately without entering the loop if the output buffer is smaller than respectively `digits_dec/hex/oct/bin()`. This enables both: - - writing every character in its final position without having to revert the string at the end - - the need to check the buffer size on appending every character. - - `write_dec()` now writes two digits at once, thus halving the number of integer divisions. - - Added `write_dec/hex/oct/bin_unchecked()`, which receive precomputed `digits_dec/hex/oct/bin()`, thus speeding up the radix `itoa()/utoa()` overloads. - - Added `xtoa()` radix+digits overloads: - - `size_t xtoa(substr s, T v, T radix)` - - `size_t xtoa(substr s, T v, T radix, size_t num_digits)` - - `read_dec/hex/oct/bin()`: these functions no longer allow an empty input buffer. - - Use intrinsic functions `__builtin_clz()` (gcc) / `_BitScanReverse()` (msvc) in `c4::msb()` and `__builtin_ctz()` (gcc) / `_BitScanForward()` (msvc) in `c4::lsb()` when they are available. `msb()` is used by `digits_hex()/digits_bin()`. - - Refactored the charconv tests to improve consistency and thoroughness. - - Improved the charconv benchmarks to ensure full consistency across benchmarks. - - Special thanks and kudos to @fargies for being attentive and pinpointing several issues throughout the PR! - - Finding the best approach involved [writing a R&D benchmark for the several algorithm components](https://github.com/biojppm/c4core/tree/master/bm/bm_xtoa.cpp). This benchmark is disabled by default, and can be enabled with the flag `C4CORE_BM_XTOA_RND`. - - With the changes from this PR, the [charconv benchmark](https://github.com/biojppm/c4core/tree/master/bm_charconv.cpp) results show that on Linux/g++11.2, with integral types: - - `c4::to_chars()` can be expected to be roughly... - - ~40% to 2x faster than `std::to_chars()` - - ~10x-30x faster than `sprintf()` - - ~50x-100x faster than a naive `stringstream::operator<<()` followed by `stringstream::str()` - - `c4::from_chars()` can be expected to be roughly... - - ~10%-30% faster than `std::from_chars()` - - ~10x faster than `scanf()` - - ~30x-50x faster than a naive `stringstream::str()` followed by `stringstream::operator>>()` - - Here are the results from the run: - | Write throughput | | Read throughput | | - |:-------------------------|--------:|:-------------------------|---------:| - | **write `uint8_t`** | **MB/s**| **read `uint8_t`** | **MB/s**| - | `c4::to_chars` | 526.86 | `c4::from_chars` | 163.06 | - | `std::to_chars` | 379.03 | `std::from_chars` | 154.85 | - | `std::sprintf` | 20.49 | `std::scanf` | 15.75 | - | `std::stringstream` | 3.82 | `std::stringstream` | 3.83 | - | **write `int8_t`** | **MB/s**| **read `int8_t`** | **MB/s**| - | `c4::to_chars` | 599.98 | `c4::from_chars` | 184.20 | - | `std::to_chars` | 246.32 | `std::from_chars` | 156.40 | - | `std::sprintf` | 19.15 | `std::scanf` | 16.44 | - | `std::stringstream` | 3.83 | `std::stringstream` | 3.89 | - | **write `uint16_t`** | **MB/s**| **read `uint16_t`** | **MB/s**| - | `c4::to_chars` | 486.40 | `c4::from_chars` | 349.48 | - | `std::to_chars` | 454.24 | `std::from_chars` | 319.13 | - | `std::sprintf` | 38.74 | `std::scanf` | 28.12 | - | `std::stringstream` | 7.08 | `std::stringstream`| 6.73 | - | **write `int16_t`** | **MB/s**| **read `int16_t`** | **MB/s**| - | `c4::to_chars` | 507.44 | `c4::from_chars` | 282.95 | - | `std::to_chars` | 297.49 | `std::from_chars` | 186.18 | - | `std::sprintf` | 39.03 | `std::scanf` | 28.45 | - | `std::stringstream` | 6.98 | `std::stringstream`| 6.49 | - | **write `uint32_t`** | **MB/s**| **read `uint32_t`** | **MB/s**| - | `c4::to_chars` | 730.12 | `c4::from_chars` | 463.95 | - | `std::to_chars` | 514.76 | `std::from_chars` | 329.42 | - | `std::sprintf` | 71.19 | `std::scanf` | 44.97 | - | `std::stringstream` | 14.05 | `std::stringstream`| 12.57 | - | **write `int32_t`** | **MB/s**| **read `int32_t`** | **MB/s**| - | `c4::to_chars` | 618.76 | `c4::from_chars` | 345.53 | - | `std::to_chars` | 394.72 | `std::from_chars` | 224.46 | - | `std::sprintf` | 71.14 | `std::scanf` | 43.49 | - | `std::stringstream` | 13.91 | `std::stringstream`| 12.03 | - | **write `uint64_t`** | **MB/s**| **read `uint64_t`** | **MB/s**| - | `c4::to_chars` | 1118.87 | `c4::from_chars` | 928.49 | - | `std::to_chars` | 886.58 | `std::from_chars` | 759.03 | - | `std::sprintf` | 140.96 | `std::scanf` | 91.60 | - | `std::stringstream` | 28.01 | `std::stringstream`| 25.00 | - | **write `int64_t`** | **MB/s**| **read `int64_t`** | **MB/s**| - | `c4::to_chars` | 1198.78 | `c4::from_chars` | 713.76 | - | `std::to_chars` | 882.17 | `std::from_chars` | 646.18 | - | `std::sprintf` | 138.79 | `std::scanf` | 90.07 | - | `std::stringstream` | 27.62 | `std::stringstream`| 25.12 | - -If you feel suspicious about these bold claims, you can browse through [c4core's CI benchmark results](https://github.com/biojppm/c4core/actions/workflows/benchmarks.yml) which will hopefully give these more substance. - - -### New features - -- Added `bool c4::overflows(csubstr s)` for detecting whether a string overflows a given integral type. See [PR#78](https://github.com/biojppm/c4core/pull/78). - - Also, added `c4::fmt::overflow_checked()` (and the corresponding `from_chars()` overload) to enable a check for overflow before parsing from string: - ```c++ - c4::from_chars(str, &val); // no overflow check - c4::from_chars(str, c4::fmt::overflow_checked(val)); // enable overflow check - // as an example, the implementation looks like: - template - bool c4::from_chars(c4::csubstr str, c4::fmt::overflow_checked oc) - { - if(overflows(str)) - return false; - return c4::from_chars(str, oc.val); - } - ``` - -### Fixes - -- Fix missing endianess macro on windows arm/arm64 compilations [PR #76](https://github.com/biojppm/c4core/pull/76) -- Add missing `#define` for the include guard of the amalgamated header (see [rapidyaml#246](https://github.com/biojppm/rapidyaml/issues/246)). -- Fix CPU detection with ARMEL [PR #86](https://github.com/biojppm/c4core/pull/86). -- Fix GCC version detection [PR #87](https://github.com/biojppm/c4core/pull/87). -- Fix [cmake#8](https://github.com/biojppm/cmake/issues/8): `SOVERSION` missing from shared libraries. -- Update fastfloat to 3.5.1. - -### Thanks - -- @fargies -- @daichifukui -- @janisozaur diff --git a/thirdparty/ryml/ext/c4core/changelog/0.1.11.md b/thirdparty/ryml/ext/c4core/changelog/0.1.11.md deleted file mode 100644 index 7c5ce8600..000000000 --- a/thirdparty/ryml/ext/c4core/changelog/0.1.11.md +++ /dev/null @@ -1,59 +0,0 @@ - -### Breaking changes - -- `csubstr::operator==(std::nullptr_t)` now strictly checks if the pointer is null and no longer looks at the length ([rapidyaml#264](https://github.com/biojppm/rapidyaml/pull/264)): - ```diff - -bool csubstr::operator== (std::nullptr_t) const noexcept { return str == nullptr || len == 0; } - -bool csubstr::operator!= (std::nullptr_t) const noexcept { return str != nullptr || len == 0; } - +bool csubstr::operator== (std::nullptr_t) const noexcept { return str == nullptr; } - +bool csubstr::operator!= (std::nullptr_t) const noexcept { return str != nullptr; } - ``` -- `to_substr(std::string &s)` and `to_csubstr(std::string const& s)` now point at the first element when the string is empty ([rapidyaml#264](https://github.com/biojppm/rapidyaml/pull/264#issuecomment-1264421024)): - ```diff - - return c4::substr(!s.empty() ? &s[0] : nullptr, s.size()); - + return c4::substr(&s[0], s.size()); - ``` - This is OK because an empty `std::string` is guaranteed to have storage, so calling `s[0]` is safe. - - -### New features - -- `charconv.hpp`: added `xtoa()` floating-point overloads accepting precision and format ([PR#88](https://github.com/biojppm/c4core/pull/88)): - ```c++ - size_t xtoa(substr s, float v, int precision, RealFormat_e formatting=FTOA_FLEX) noexcept; - size_t xtoa(substr s, double v, int precision, RealFormat_e formatting=FTOA_FLEX) noexcept; - ``` -- `memory_util.hpp`: added `ipow()` overloads for computing powers with integral exponents ([PR#88](https://github.com/biojppm/c4core/pull/88)). -- Add `C4_NO_DEBUG_BREAK` preprocessor check to disable calls to `c4::debug_break()` (see [rapidyaml#326](https://github.com/biojppm/rapidyaml/issues/326)) - - The cmake project conditionally enables this macro if the cmake option `C4CORE_NO_DEBUG_BREAK` is set to `ON`. - - -### Fixes - -- `substr`, `to_chars()`, charconv: ensure `memcpy()` is not called when the length is zero. Doing this is UB and enabled the optimizer to wreak havoc in the branches of calling code. See comments at [rapidyaml#264](https://github.com/biojppm/rapidyaml/pull/264#issuecomment-1262133637) for an example and fix. See [Raymond Chen's blog](https://devblogs.microsoft.com/oldnewthing/20140627-00/?p=633) for an explanation. -- `atof()` and `atod()` ([PR#88](https://github.com/biojppm/c4core/pull/88)): - - Always use the fastest implementation available: `std::from_chars()` if available (C++17 or higher standard, with later compilers), `fast_float::from_chars()` otherwise. On Visual Studio, `fast_float::from_chars()` is preferred over `std::from_chars()`. - - If `std::from_chars()` is not available and `C4CORE_NO_FAST_FLOAT` is defined, then the fallback is based on `sscanf()`. - - Ensure hexadecimal floats are accepted. The current fast_float implementation does not accept hexadecimal floats, so an hexfloat scanner was added. -- Likewise for `ftoa()` and `dtoa()`. Prefer the fastest implementation available: `std::to_chars()`->`snprintf()`. - - Change the `FTOA_*` enum values and type to save a function call when converting format. From now on, only the symbols of this enum can be relied on; the values or type will change depending on the selected implementation (`std::to_chars()` or `snprintf()`) ([PR#91](https://github.com/biojppm/c4core/pull/91)). -- Fix [#84](https://github.com/biojppm/c4core/issues/84): `csubstr::compare(char)`: refactor to avoid false-positive warning from VS2022. -- `csubstr` methods: add `noexcept` and annotations `C4_PURE` and `C4_ALWAYS_INLINE` -- `csubstr`: add `C4_RESTRICT` to incoming string on `csubstr::compare()` -- `csubstr::first_real_span()` ([PR#89](https://github.com/biojppm/c4core/pull/89)): - - Refactor to fix number matching rules. Now fully valid for floating point numbers in decimal (eg `0.123/1.23e+01`), hexadecimal (eg `0x123.abc/0x1.23abcp+01`), binary (eg `0b101.10/0b1.0110p+01`) and octal format (eg `0o701.10/0o7.0110p+01`) , with or without exponent or power, in lower or upper case. - - Also, make the number parsing stateful to fix cases where repeated characters occur, (like e.g. `0.1.0` or `1.23e+e10`) which are no longer reported as numbers (see [biojppm/rapidyaml#291](https://github.com/biojppm/rapidyaml/issues/291)). -- `csubstr::first_int_span()`, `csubstr::first_uint_span()`: fix edge cases like e.g. `0xzz` which were wrongly reported as numbers. -- Add fully qualified ARM detection macros: - - `__ARM_ARCH_7EM__` ([PR#90](https://github.com/biojppm/c4core/pull/90)). - - `__ARM_ARCH_6KZ__` ([PR#93](https://github.com/biojppm/c4core/pull/93)). - - `__ARM_ARCH_8A__` ([#94](https://github.com/biojppm/c4core/issues/94)). -- Improve linux and unix platform detection: detect both `__linux` and `__linux__` ([PR#92](https://github.com/biojppm/c4core/pull/92)). - - -### Thanks - -- @mlondono74 -- @musicinmybrain -- @pkubaj -- @Gei0r diff --git a/thirdparty/ryml/ext/c4core/changelog/0.1.2.md b/thirdparty/ryml/ext/c4core/changelog/0.1.2.md deleted file mode 100644 index d9c2e9c6c..000000000 --- a/thirdparty/ryml/ext/c4core/changelog/0.1.2.md +++ /dev/null @@ -1,4 +0,0 @@ -- Fix error macros (ie `C4_ERROR()`, `C4_CHECK()`, `C4_ASSERT()`, etc) such that they are a single statement -- `is_debugger_attached()`: add MacOSX version -- Add support for Visual Studio 2022 -- Ensure `C4_LITTLE_ENDIAN` is always defined, even with mixed endianness diff --git a/thirdparty/ryml/ext/c4core/changelog/0.1.3.md b/thirdparty/ryml/ext/c4core/changelog/0.1.3.md deleted file mode 100644 index f98b88f75..000000000 --- a/thirdparty/ryml/ext/c4core/changelog/0.1.3.md +++ /dev/null @@ -1 +0,0 @@ -- Update fast_float to [3.2.1](https://github.com/fastfloat/fast_float/releases/tag/v3.2.0) diff --git a/thirdparty/ryml/ext/c4core/changelog/0.1.4.md b/thirdparty/ryml/ext/c4core/changelog/0.1.4.md deleted file mode 100644 index b8e88203e..000000000 --- a/thirdparty/ryml/ext/c4core/changelog/0.1.4.md +++ /dev/null @@ -1,6 +0,0 @@ -- [PR #38](https://github.com/biojppm/c4core/pull/38): add s390x architecture feature macros. -- Fix compiler warnings after update of fast_float to [3.2.1](https://github.com/fastfloat/fast_float/releases/tag/v3.2.0). - -### Thanks - -@musicinmybrain diff --git a/thirdparty/ryml/ext/c4core/changelog/0.1.5.md b/thirdparty/ryml/ext/c4core/changelog/0.1.5.md deleted file mode 100644 index e4884472e..000000000 --- a/thirdparty/ryml/ext/c4core/changelog/0.1.5.md +++ /dev/null @@ -1,2 +0,0 @@ -- Add support for aarch64, s390x, ppc64le CPU architectures -- Update debugbreak header (added support for the above architectures) diff --git a/thirdparty/ryml/ext/c4core/changelog/0.1.6.md b/thirdparty/ryml/ext/c4core/changelog/0.1.6.md deleted file mode 100644 index 296de1398..000000000 --- a/thirdparty/ryml/ext/c4core/changelog/0.1.6.md +++ /dev/null @@ -1,2 +0,0 @@ -- Fix wrong version names in version 0.1.5 (was saying 0.1.4, should be 0.1.5) - diff --git a/thirdparty/ryml/ext/c4core/changelog/0.1.7.md b/thirdparty/ryml/ext/c4core/changelog/0.1.7.md deleted file mode 100644 index 2b053a069..000000000 --- a/thirdparty/ryml/ext/c4core/changelog/0.1.7.md +++ /dev/null @@ -1,5 +0,0 @@ -- Fix build with C4CORE_NO_FAST_FLOAT ([#42](https://github.com/biojppm/c4core/pull/42)). -- Fix clang warning in AIX/xlclang ([#44](https://github.com/biojppm/c4core/pull/44)). - -### Thanks ---- @mbs-c diff --git a/thirdparty/ryml/ext/c4core/changelog/0.1.8.md b/thirdparty/ryml/ext/c4core/changelog/0.1.8.md deleted file mode 100644 index db77aaf97..000000000 --- a/thirdparty/ryml/ext/c4core/changelog/0.1.8.md +++ /dev/null @@ -1,45 +0,0 @@ - -### New features - -- Add amalgamation into a single header file ([PR #48](https://github.com/biojppm/c4core/pull/48)): - - The amalgamated header will be available together with the deliverables from each release. - - To generate the amalgamated header: - ``` - $ python tools/amalgamate.py c4core_all.hpp - ``` - - To use the amalgamated header: - - Include at will in any header of your project. - - In one - and only one - of your project source files, `#define C4CORE_SINGLE_HDR_DEFINE_NOW` and then `#include `. This will enable the function and class definitions in the header file. For example, here's a sample program: - ```c++ - #include - #define C4CORE_SINGLE_HDR_DEFINE_NOW // do this before the include - #include - int main() - { - for(c4::csubstr s : c4::csubstr("a/b/c/d").split('/')) - std::cout << s << "\n"; - } - ``` -- Add `csubstr::is_unsigned_integer()` and `csubstr::is_real()` ([PR #49](https://github.com/biojppm/c4core/pull/49)). -- CMake: add alias target c4core::c4core, guaranteeing that the same code can be used with `add_subdirectory()` and `find_package()`. (see [rapidyaml #173](https://github.com/biojppm/rapidyaml/issues/173)) -- Add support for compilation with emscripten (WebAssembly+javascript) ([PR #52](https://github.com/biojppm/c4core/pull/52)). - - -### Fixes - -- Fix edge cases with empty strings in `span::first()`, `span::last()` and `span::range()` ([PR #49](https://github.com/biojppm/c4core/pull/49)). -- Accept octal numbers in `substr::first_real_span()` and `substr::is_real()` ([PR #49](https://github.com/biojppm/c4core/pull/49)). -- `substr`: fix coverage misses in number query methods ([PR #49](https://github.com/biojppm/c4core/pull/49)). -- Use single-header version of fast_float ([PR #49](https://github.com/biojppm/c4core/pull/47)). -- Suppress warnings triggered from fast_float in clang (`-Wfortify-source`) ([PR #49](https://github.com/biojppm/c4core/pull/47)). -- Add missing `inline` in [src/c4/ext/rng/rng.hpp](src/c4/ext/rng/rng.hpp) ([PR #49](https://github.com/biojppm/c4core/pull/47)). -- Fix compilation of [src/c4/ext/rng/inplace_function.h](src/c4/ext/inplace_function.h) in C++11 ([PR #49](https://github.com/biojppm/c4core/pull/47)). -- Change order of headers, notably in `windows_push.hpp` ([PR #47](https://github.com/biojppm/c4core/pull/47)). -- In `c4/charconv.hpp`: do not use C4_ASSERT in `to_c_fmt()`, which is `constexpr`. -- Fix [#53](https://github.com/biojppm/c4core/issues/53): cmake install targets were missing call to `export()` ([PR #55](https://github.com/biojppm/c4core/pull/55)). -- Fix linking of subprojects with libc++: flags should be forwarded through `CMAKE_***_FLAGS` instead of being set explicitly per-target ([PR #54](https://github.com/biojppm/c4core/pull/54)). - - -### Thanks - -- @cschreib diff --git a/thirdparty/ryml/ext/c4core/changelog/0.1.9.md b/thirdparty/ryml/ext/c4core/changelog/0.1.9.md deleted file mode 100644 index 1ac5aa842..000000000 --- a/thirdparty/ryml/ext/c4core/changelog/0.1.9.md +++ /dev/null @@ -1,31 +0,0 @@ -### Breaking changes - -- fix [#63](https://github.com/biojppm/c4core/issues/63): remove `c4/time.hpp` and `c4/time.cpp` which prevented compilation in bare-metal mode ([PR #64](https://github.com/biojppm/c4core/issues/64)). - -### New features - -- Added decoding of UTF codepoints: `c4::decode_code_point()` ([PR #65](https://github.com/biojppm/c4core/issues/65)). -- Experimental feature: add formatted-dumping facilities: using semantics like `c4::cat()`, `c4::catsep()` and `c4::format()`, where the subject is not a string buffer but a dump callback accepting strings. This still requires a string buffer for serialization of non-string types, but the buffer's required size is now limited to the max serialized size of non-string arguments, in contrast to the requirement in `c4::cat()` et al which is the total serialized size of every argument. This enables very efficient and generic printf-like semantics with reuse of a single small buffer, and allows direct-printing to terminal or file ([PR #67](https://github.com/biojppm/c4core/issues/67)). This feature is still experimental and a minor amount of changes to the API is possible. -- Added macro `C4_IF_CONSTEXPR` resolving to `if constexpr (...)` if the c++ standard is at least c++17. -- `csubstr`: add `count(csubstr)` overload. -- Add support for RISC-V architectures ([PR #69](https://github.com/biojppm/c4core/issues/69)). -- Add support for bare-metal compilation ([PR #64](https://github.com/biojppm/c4core/issues/64)). -- gcc >= 4.8 support using polyfills for missing templates and features ([PR #74](https://github.com/biojppm/c4core/pull/74) and [PR #68](https://github.com/biojppm/c4core/pull/68)). - -### Fixes - -- `csubstr::operator==(std::nullptr_t)` now returns true if either `.str==nullptr` or `.len==0`. -- Fix: `bool operator==(const char (&s)[N], csubstr)` and `operator==(const char (&s)[N], substr)`. The template declaration for these functions had an extra `const` which prevented these functions to participate in overload resolution, which in some cases resulted in calls resolving to `operator==(std::string const&, csubstr)` if that header was visible ([PR #64](https://github.com/biojppm/c4core/issues/64)). -- Fix `csubstr::last_not_of()`: optional positional parameter was ignored [PR #62](https://github.com/biojppm/c4core/pull/62). -- `atof()`, `atod()`, `atox()`, `substr::is_real()`, `substr::first_real_span()`: accept `infinity`, `inf` and `nan` as valid reals [PR #60](https://github.com/biojppm/c4core/pull/60). -- Add missing export symbols [PR #56](https://github.com/biojppm/c4core/pull/56), [PR #57](https://github.com/biojppm/c4core/pull/57). -- `c4/substr_fwd.hpp`: fix compilation failure in Xcode 12 and earlier, where the forward declaration for `std::allocator` is inside the `inline namespace __1`, unlike later versions [PR #61](https://github.com/biojppm/c4core/pull/61), reported in [rapidyaml#185](https://github.com/biojppm/rapidyaml/issues/185). -- `c4/error.hpp`: fix compilation failure in debug mode in Xcode 12 and earlier: `__clang_major__` does not mean the same as in the common clang, and as a result the warning `-Wgnu-inline-cpp-without-extern` does not exist there. - - -### Thanks - -- @danngreen -- @Xeonacid -- @aviktorov -- @fargies diff --git a/thirdparty/ryml/ext/c4core/changelog/current.md b/thirdparty/ryml/ext/c4core/changelog/current.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/thirdparty/ryml/ext/c4core/cmake/.gitignore b/thirdparty/ryml/ext/c4core/cmake/.gitignore deleted file mode 100644 index ed8ebf583..000000000 --- a/thirdparty/ryml/ext/c4core/cmake/.gitignore +++ /dev/null @@ -1 +0,0 @@ -__pycache__ \ No newline at end of file diff --git a/thirdparty/ryml/ext/c4core/cmake/ConfigurationTypes.cmake b/thirdparty/ryml/ext/c4core/cmake/ConfigurationTypes.cmake deleted file mode 100644 index 45395ad1b..000000000 --- a/thirdparty/ryml/ext/c4core/cmake/ConfigurationTypes.cmake +++ /dev/null @@ -1,120 +0,0 @@ - - -# this function works both with multiconfig and single-config generators. -function(set_default_build_type which) - # CMAKE_CONFIGURATION_TYPES is available only for multiconfig generators. - # so set the build type only if CMAKE_CONFIGURATION_TYPES does not exist. - if(NOT CMAKE_CONFIGURATION_TYPES) # not a multiconfig generator? - if(NOT CMAKE_BUILD_TYPE) - if(NOT which) - set(which RelWithDebInfo) - endif() - message("Defaulting to ${which} build.") - set(CMAKE_BUILD_TYPE ${which} CACHE STRING "") - endif() - endif() -endfunction() - - -# https://stackoverflow.com/questions/31546278/where-to-set-cmake-configuration-types-in-a-project-with-subprojects -function(setup_configuration_types) - set(options0arg - ) - set(options1arg - DEFAULT - ) - set(optionsnarg - TYPES - ) - cmake_parse_arguments("" "${options0arg}" "${options1arg}" "${optionsnarg}" ${ARGN}) - - if(NOT TYPES) - set(TYPES Release Debug RelWithDebInfo MinSizeRel) - endif() - - # make it safe to call repeatedly - if(NOT _setup_configuration_types_done) - set(_setup_configuration_types_done 1 CACHE INTERNAL "") - - # No reason to set CMAKE_CONFIGURATION_TYPES if it's not a multiconfig generator - # Also no reason mess with CMAKE_BUILD_TYPE if it's a multiconfig generator. - - if(CMAKE_CONFIGURATION_TYPES) # multiconfig generator? - set(CMAKE_CONFIGURATION_TYPES "${TYPES}" CACHE STRING "") - else() # single-config generator - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY HELPSTRING "Choose the type of build") - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "${TYPES}") - # set the valid options for cmake-gui drop-down list - endif() - endif() -endfunction() - - -# https://stackoverflow.com/questions/31546278/where-to-set-cmake-configuration-types-in-a-project-with-subprojects -function(add_configuration_type name) - set(flag_vars - C_FLAGS - CXX_FLAGS - SHARED_LINKER_FLAGS - STATIC_LINKER_FLAGS - MODULE_LINKER_FLAGS - EXE_LINKER_FLAGS - RC_FLAGS - ) - - set(options0arg - PREPEND # when defaulting to a config, prepend to it instead of appending to it - SET_MAIN_FLAGS # eg, set CMAKE_CXX_FLAGS from CMAKE_CXX_FLAGS_${name} - ) - set(options1arg - DEFAULT_FROM # take the initial value of the flags from this config - ) - set(optionsnarg - C_FLAGS - CXX_FLAGS - SHARED_LINKER_FLAGS - STATIC_LINKER_FLAGS - MODULE_LINKER_FLAGS - EXE_LINKER_FLAGS - RC_FLAGS - ) - cmake_parse_arguments(_act "${options0arg}" "${options1arg}" "${optionsnarg}" ${ARGN}) - - string(TOUPPER ${name} UNAME) - - # make it safe to call repeatedly - if(NOT _add_configuration_type_${name}) - set(_add_configuration_type_${name} 1 CACHE INTERNAL "") - - setup_configuration_types() - - if(CMAKE_CONFIGURATION_TYPES) # multiconfig generator? - set(CMAKE_CONFIGURATION_TYPES "${CMAKE_CONFIGURATION_TYPES};${name}" CACHE STRING "" FORCE) - else() # single-config generator - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY HELPSTRING "Choose the type of build" FORCE) - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "${CMAKE_BUILD_TYPES};${name}" FORCE) - # set the valid options for cmake-gui drop-down list - endif() - - # now set up the configuration - message(STATUS "config: CMAKE_${f}_${UNAME} --- ${val}") - foreach(f ${flag_vars}) - set(val ${_act_${f}}) - message(STATUS "config: ${name}: ${f} --- ${val}") - if(_act_DEFAULT_FROM) - if(_act_PREPEND) - set(val "${val} ${CMAKE_${f}_${_act_DEFAULT_FROM}}") - else() - set(val "${CMAKE_${f}_${_act_DEFAULT_FROM}} ${val}") - endif() - endif() - message(STATUS "config: CMAKE_${f}_${UNAME} --- ${val}") - set(CMAKE_${f}_${UNAME} "${val}" CACHE STRING "" FORCE) - mark_as_advanced(CMAKE_${f}_${UNAME}) - if(_act_SET_MAIN_FLAGS) - set(CMAKE_${f} "${CMAKE_${f}_${UNAME}}" CACHE STRING "" FORCE) - endif() - endforeach() - endif() - -endfunction() diff --git a/thirdparty/ryml/ext/c4core/cmake/CreateSourceGroup.cmake b/thirdparty/ryml/ext/c4core/cmake/CreateSourceGroup.cmake deleted file mode 100644 index e8e144184..000000000 --- a/thirdparty/ryml/ext/c4core/cmake/CreateSourceGroup.cmake +++ /dev/null @@ -1,31 +0,0 @@ -# create hierarchical source groups based on a dir tree -# -# EXAMPLE USAGE: -# -# create_source_group("src" "${SRC_ROOT}" "${SRC_LIST}") -# -# Visual Studio usually has the equivalent to this: -# -# create_source_group("Header Files" ${PROJ_SRC_DIR} "${PROJ_HEADERS}") -# create_source_group("Source Files" ${PROJ_SRC_DIR} "${PROJ_SOURCES}") -# -# TODO: this was taken from a stack overflow answer. Need to find it -# and add a link here. - -macro(create_source_group GroupPrefix RootDir ProjectSources) - set(DirSources ${ProjectSources}) - foreach(Source ${DirSources}) - #message(STATUS "s=${Source}") - string(REGEX REPLACE "([\\^\\$*+?|])" "\\\\\\1" RootDirRegex "${RootDir}") - string(REGEX REPLACE "${RootDirRegex}" "" RelativePath "${Source}") - #message(STATUS " ${RelativePath}") - string(REGEX REPLACE "[\\\\/][^\\\\/]*$" "" RelativePath "${RelativePath}") - #message(STATUS " ${RelativePath}") - string(REGEX REPLACE "^[\\\\/]" "" RelativePath "${RelativePath}") - #message(STATUS " ${RelativePath}") - string(REGEX REPLACE "/" "\\\\\\\\" RelativePath "${RelativePath}") - #message(STATUS " ${RelativePath}") - source_group("${GroupPrefix}\\${RelativePath}" FILES ${Source}) - #message(STATUS " ${Source}") - endforeach(Source) -endmacro(create_source_group) diff --git a/thirdparty/ryml/ext/c4core/cmake/Doxyfile.full.in b/thirdparty/ryml/ext/c4core/cmake/Doxyfile.full.in deleted file mode 100644 index f444cb742..000000000 --- a/thirdparty/ryml/ext/c4core/cmake/Doxyfile.full.in +++ /dev/null @@ -1,2566 +0,0 @@ -# Doxyfile 1.8.15 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project. -# -# All text after a double hash (##) is considered a comment and is placed in -# front of the TAG it is preceding. -# -# All text after a single hash (#) is considered a comment and will be ignored. -# The format is: -# TAG = value [value, ...] -# For lists, items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (\" \"). - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# This tag specifies the encoding used for all characters in the configuration -# file that follow. The default is UTF-8 which is also the encoding used for all -# text before the first occurrence of this tag. Doxygen uses libiconv (or the -# iconv built into libc) for the transcoding. See -# https://www.gnu.org/software/libiconv/ for the list of possible encodings. -# The default value is: UTF-8. - -DOXYFILE_ENCODING = UTF-8 - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by -# double-quotes, unless you are using Doxywizard) that should identify the -# project for which the documentation is generated. This name is used in the -# title of most generated pages and in a few other places. -# The default value is: My Project. - -PROJECT_NAME = @_PROJ@ - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. This -# could be handy for archiving the generated documentation or if some version -# control system is used. - -PROJECT_NUMBER = @_VERSION@ - -# Using the PROJECT_BRIEF tag one can provide an optional one line description -# for a project that appears at the top of each page and should give viewer a -# quick idea about the purpose of the project. Keep the description short. - -PROJECT_BRIEF = @_PROJ_BRIEF@ - -# With the PROJECT_LOGO tag one can specify a logo or an icon that is included -# in the documentation. The maximum height of the logo should not exceed 55 -# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy -# the logo to the output directory. - -PROJECT_LOGO = - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path -# into which the generated documentation will be written. If a relative path is -# entered, it will be relative to the location where doxygen was started. If -# left blank the current directory will be used. - -OUTPUT_DIRECTORY = @_OUTPUT_DIR@ - -# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- -# directories (in 2 levels) under the output directory of each output format and -# will distribute the generated files over these directories. Enabling this -# option can be useful when feeding doxygen a huge amount of source files, where -# putting all generated files in the same directory would otherwise causes -# performance problems for the file system. -# The default value is: NO. - -CREATE_SUBDIRS = NO - -# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII -# characters to appear in the names of generated files. If set to NO, non-ASCII -# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode -# U+3044. -# The default value is: NO. - -ALLOW_UNICODE_NAMES = YES - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, -# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), -# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, -# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), -# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, -# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, -# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, -# Ukrainian and Vietnamese. -# The default value is: English. - -OUTPUT_LANGUAGE = English - -# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all generated output in the proper direction. -# Possible values are: None, LTR, RTL and Context. -# The default value is: None. - -OUTPUT_TEXT_DIRECTION = None - -# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member -# descriptions after the members that are listed in the file and class -# documentation (similar to Javadoc). Set to NO to disable this. -# The default value is: YES. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief -# description of a member or function before the detailed description -# -# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. -# The default value is: YES. - -REPEAT_BRIEF = YES - -# This tag implements a quasi-intelligent brief description abbreviator that is -# used to form the text in various listings. Each string in this list, if found -# as the leading text of the brief description, will be stripped from the text -# and the result, after processing the whole list, is used as the annotated -# text. Otherwise, the brief description is used as-is. If left blank, the -# following values are used ($name is automatically replaced with the name of -# the entity):The $name class, The $name widget, The $name file, is, provides, -# specifies, contains, represents, a, an and the. - -ABBREVIATE_BRIEF = "The $name class" \ - "The $name widget" \ - "The $name file" \ - is \ - provides \ - specifies \ - contains \ - represents \ - a \ - an \ - the - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# doxygen will generate a detailed section even if there is only a brief -# description. -# The default value is: NO. - -ALWAYS_DETAILED_SEC = NO - -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all -# inherited members of a class in the documentation of that class as if those -# members were ordinary class members. Constructors, destructors and assignment -# operators of the base classes will not be shown. -# The default value is: NO. - -INLINE_INHERITED_MEMB = YES - -# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path -# before files name in the file list and in the header files. If set to NO the -# shortest path that makes the file name unique will be used -# The default value is: YES. - -FULL_PATH_NAMES = YES - -# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. -# Stripping is only done if one of the specified strings matches the left-hand -# part of the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the path to -# strip. -# -# Note that you can specify absolute paths here, but also relative paths, which -# will be relative from the directory where doxygen is started. -# This tag requires that the tag FULL_PATH_NAMES is set to YES. - -STRIP_FROM_PATH = @_STRIP_FROM_PATH@ - -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the -# path mentioned in the documentation of a class, which tells the reader which -# header file to include in order to use a class. If left blank only the name of -# the header file containing the class definition is used. Otherwise one should -# specify the list of include paths that are normally passed to the compiler -# using the -I flag. - -STRIP_FROM_INC_PATH = @_STRIP_FROM_INC_PATH@ - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but -# less readable) file names. This can be useful is your file systems doesn't -# support long names like on DOS, Mac, or CD-ROM. -# The default value is: NO. - -SHORT_NAMES = NO - -# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the -# first line (until the first dot) of a Javadoc-style comment as the brief -# description. If set to NO, the Javadoc-style will behave just like regular Qt- -# style comments (thus requiring an explicit @brief command for a brief -# description.) -# The default value is: NO. - -JAVADOC_AUTOBRIEF = YES - -# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first -# line (until the first dot) of a Qt-style comment as the brief description. If -# set to NO, the Qt-style will behave just like regular Qt-style comments (thus -# requiring an explicit \brief command for a brief description.) -# The default value is: NO. - -QT_AUTOBRIEF = YES - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a -# multi-line C++ special comment block (i.e. a block of //! or /// comments) as -# a brief description. This used to be the default behavior. The new default is -# to treat a multi-line C++ comment block as a detailed description. Set this -# tag to YES if you prefer the old behavior instead. -# -# Note that setting this tag to YES also means that rational rose comments are -# not recognized any more. -# The default value is: NO. - -MULTILINE_CPP_IS_BRIEF = YES - -# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the -# documentation from any documented member that it re-implements. -# The default value is: YES. - -INHERIT_DOCS = YES - -# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new -# page for each member. If set to NO, the documentation of a member will be part -# of the file/class/namespace that contains it. -# The default value is: NO. - -SEPARATE_MEMBER_PAGES = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen -# uses this value to replace tabs by spaces in code fragments. -# Minimum value: 1, maximum value: 16, default value: 4. - -TAB_SIZE = 4 - -# This tag can be used to specify a number of aliases that act as commands in -# the documentation. An alias has the form: -# name=value -# For example adding -# "sideeffect=@par Side Effects:\n" -# will allow you to put the command \sideeffect (or @sideeffect) in the -# documentation, which will result in a user-defined paragraph with heading -# "Side Effects:". You can put \n's in the value part of an alias to insert -# newlines (in the resulting output). You can put ^^ in the value part of an -# alias to insert a newline as if a physical newline was in the original file. -# When you need a literal { or } or , in the value part of an alias you have to -# escape them by means of a backslash (\), this can lead to conflicts with the -# commands \{ and \} for these it is advised to use the version @{ and @} or use -# a double escape (\\{ and \\}) - -ALIASES = - -# This tag can be used to specify a number of word-keyword mappings (TCL only). -# A mapping has the form "name=value". For example adding "class=itcl::class" -# will allow you to use the command class in the itcl::class meaning. - -TCL_SUBST = - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources -# only. Doxygen will then generate output that is more tailored for C. For -# instance, some of the names that are used will be different. The list of all -# members will be omitted, etc. -# The default value is: NO. - -OPTIMIZE_OUTPUT_FOR_C = NO - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or -# Python sources only. Doxygen will then generate output that is more tailored -# for that language. For instance, namespaces will be presented as packages, -# qualified scopes will look different, etc. -# The default value is: NO. - -OPTIMIZE_OUTPUT_JAVA = NO - -# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources. Doxygen will then generate output that is tailored for Fortran. -# The default value is: NO. - -OPTIMIZE_FOR_FORTRAN = NO - -# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for VHDL. -# The default value is: NO. - -OPTIMIZE_OUTPUT_VHDL = NO - -# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice -# sources only. Doxygen will then generate output that is more tailored for that -# language. For instance, namespaces will be presented as modules, types will be -# separated into more groups, etc. -# The default value is: NO. - -OPTIMIZE_OUTPUT_SLICE = NO - -# Doxygen selects the parser to use depending on the extension of the files it -# parses. With this tag you can assign which parser to use for a given -# extension. Doxygen has a built-in mapping, but you can override or extend it -# using this tag. The format is ext=language, where ext is a file extension, and -# language is one of the parsers supported by doxygen: IDL, Java, Javascript, -# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, -# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: -# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser -# tries to guess whether the code is fixed or free formatted code, this is the -# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat -# .inc files as Fortran files (default is PHP), and .f files as C (default is -# Fortran), use: inc=Fortran f=C. -# -# Note: For files without extension you can use no_extension as a placeholder. -# -# Note that for custom extensions you also need to set FILE_PATTERNS otherwise -# the files are not read by doxygen. - -EXTENSION_MAPPING = - -# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments -# according to the Markdown format, which allows for more readable -# documentation. See https://daringfireball.net/projects/markdown/ for details. -# The output of markdown processing is further processed by doxygen, so you can -# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in -# case of backward compatibilities issues. -# The default value is: YES. - -MARKDOWN_SUPPORT = YES - -# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up -# to that level are automatically included in the table of contents, even if -# they do not have an id attribute. -# Note: This feature currently applies only to Markdown headings. -# Minimum value: 0, maximum value: 99, default value: 0. -# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. - -TOC_INCLUDE_HEADINGS = 4 - -# When enabled doxygen tries to link words that correspond to documented -# classes, or namespaces to their corresponding documentation. Such a link can -# be prevented in individual cases by putting a % sign in front of the word or -# globally by setting AUTOLINK_SUPPORT to NO. -# The default value is: YES. - -AUTOLINK_SUPPORT = YES - -# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should set this -# tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); -# versus func(std::string) {}). This also make the inheritance and collaboration -# diagrams that involve STL classes more complete and accurate. -# The default value is: NO. - -BUILTIN_STL_SUPPORT = YES - -# If you use Microsoft's C++/CLI language, you should set this option to YES to -# enable parsing support. -# The default value is: NO. - -CPP_CLI_SUPPORT = NO - -# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: -# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen -# will parse them like normal C++ but will assume all classes use public instead -# of private inheritance when no explicit protection keyword is present. -# The default value is: NO. - -SIP_SUPPORT = NO - -# For Microsoft's IDL there are propget and propput attributes to indicate -# getter and setter methods for a property. Setting this option to YES will make -# doxygen to replace the get and set methods by a property in the documentation. -# This will only work if the methods are indeed getting or setting a simple -# type. If this is not the case, or you want to show the methods anyway, you -# should set this option to NO. -# The default value is: YES. - -IDL_PROPERTY_SUPPORT = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. -# The default value is: NO. - -DISTRIBUTE_GROUP_DOC = NO - -# If one adds a struct or class to a group and this option is enabled, then also -# any nested class or struct is added to the same group. By default this option -# is disabled and one has to add nested compounds explicitly via \ingroup. -# The default value is: NO. - -GROUP_NESTED_COMPOUNDS = YES - -# Set the SUBGROUPING tag to YES to allow class member groups of the same type -# (for instance a group of public functions) to be put as a subgroup of that -# type (e.g. under the Public Functions section). Set it to NO to prevent -# subgrouping. Alternatively, this can be done per class using the -# \nosubgrouping command. -# The default value is: YES. - -SUBGROUPING = YES - -# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions -# are shown inside the group in which they are included (e.g. using \ingroup) -# instead of on a separate page (for HTML and Man pages) or section (for LaTeX -# and RTF). -# -# Note that this feature does not work in combination with -# SEPARATE_MEMBER_PAGES. -# The default value is: NO. - -INLINE_GROUPED_CLASSES = NO - -# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions -# with only public data fields or simple typedef fields will be shown inline in -# the documentation of the scope in which they are defined (i.e. file, -# namespace, or group documentation), provided this scope is documented. If set -# to NO, structs, classes, and unions are shown on a separate page (for HTML and -# Man pages) or section (for LaTeX and RTF). -# The default value is: NO. - -INLINE_SIMPLE_STRUCTS = YES - -# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or -# enum is documented as struct, union, or enum with the name of the typedef. So -# typedef struct TypeS {} TypeT, will appear in the documentation as a struct -# with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically be -# useful for C code in case the coding convention dictates that all compound -# types are typedef'ed and only the typedef is referenced, never the tag name. -# The default value is: NO. - -TYPEDEF_HIDES_STRUCT = NO - -# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This -# cache is used to resolve symbols given their name and scope. Since this can be -# an expensive process and often the same symbol appears multiple times in the -# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small -# doxygen will become slower. If the cache is too large, memory is wasted. The -# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range -# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 -# symbols. At the end of a run doxygen will report the cache usage and suggest -# the optimal cache size from a speed point of view. -# Minimum value: 0, maximum value: 9, default value: 0. - -LOOKUP_CACHE_SIZE = 0 - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in -# documentation are documented, even if no documentation was available. Private -# class members and static file members will be hidden unless the -# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. -# Note: This will also disable the warnings about undocumented members that are -# normally produced when WARNINGS is set to YES. -# The default value is: NO. - -EXTRACT_ALL = YES - -# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will -# be included in the documentation. -# The default value is: NO. - -EXTRACT_PRIVATE = YES - -# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal -# scope will be included in the documentation. -# The default value is: NO. - -EXTRACT_PACKAGE = YES - -# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be -# included in the documentation. -# The default value is: NO. - -EXTRACT_STATIC = YES - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined -# locally in source files will be included in the documentation. If set to NO, -# only classes defined in header files are included. Does not have any effect -# for Java sources. -# The default value is: YES. - -EXTRACT_LOCAL_CLASSES = YES - -# This flag is only useful for Objective-C code. If set to YES, local methods, -# which are defined in the implementation section but not in the interface are -# included in the documentation. If set to NO, only methods in the interface are -# included. -# The default value is: NO. - -EXTRACT_LOCAL_METHODS = YES - -# If this flag is set to YES, the members of anonymous namespaces will be -# extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base name of -# the file that contains the anonymous namespace. By default anonymous namespace -# are hidden. -# The default value is: NO. - -EXTRACT_ANON_NSPACES = YES - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all -# undocumented members inside documented classes or files. If set to NO these -# members will be included in the various overviews, but no documentation -# section is generated. This option has no effect if EXTRACT_ALL is enabled. -# The default value is: NO. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. If set -# to NO, these classes will be included in the various overviews. This option -# has no effect if EXTRACT_ALL is enabled. -# The default value is: NO. - -HIDE_UNDOC_CLASSES = NO - -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend -# (class|struct|union) declarations. If set to NO, these declarations will be -# included in the documentation. -# The default value is: NO. - -HIDE_FRIEND_COMPOUNDS = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any -# documentation blocks found inside the body of a function. If set to NO, these -# blocks will be appended to the function's detailed documentation block. -# The default value is: NO. - -HIDE_IN_BODY_DOCS = NO - -# The INTERNAL_DOCS tag determines if documentation that is typed after a -# \internal command is included. If the tag is set to NO then the documentation -# will be excluded. Set it to YES to include the internal documentation. -# The default value is: NO. - -INTERNAL_DOCS = YES - -# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file -# names in lower-case letters. If set to YES, upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. -# The default value is: system dependent. - -CASE_SENSE_NAMES = NO - -# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with -# their full class and namespace scopes in the documentation. If set to YES, the -# scope will be hidden. -# The default value is: NO. - -HIDE_SCOPE_NAMES = NO - -# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will -# append additional text to a page's title, such as Class Reference. If set to -# YES the compound reference will be hidden. -# The default value is: NO. - -HIDE_COMPOUND_REFERENCE= NO - -# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of -# the files that are included by a file in the documentation of that file. -# The default value is: YES. - -SHOW_INCLUDE_FILES = YES - -# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each -# grouped member an include statement to the documentation, telling the reader -# which file to include in order to use the member. -# The default value is: NO. - -SHOW_GROUPED_MEMB_INC = YES - -# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include -# files with double quotes in the documentation rather than with sharp brackets. -# The default value is: NO. - -FORCE_LOCAL_INCLUDES = NO - -# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the -# documentation for inline members. -# The default value is: YES. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the -# (detailed) documentation of file and class members alphabetically by member -# name. If set to NO, the members will appear in declaration order. -# The default value is: YES. - -SORT_MEMBER_DOCS = NO - -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief -# descriptions of file, namespace and class members alphabetically by member -# name. If set to NO, the members will appear in declaration order. Note that -# this will also influence the order of the classes in the class list. -# The default value is: NO. - -SORT_BRIEF_DOCS = NO - -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the -# (brief and detailed) documentation of class members so that constructors and -# destructors are listed first. If set to NO the constructors will appear in the -# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. -# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief -# member documentation. -# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting -# detailed member documentation. -# The default value is: NO. - -SORT_MEMBERS_CTORS_1ST = NO - -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy -# of group names into alphabetical order. If set to NO the group names will -# appear in their defined order. -# The default value is: NO. - -SORT_GROUP_NAMES = NO - -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by -# fully-qualified names, including namespaces. If set to NO, the class list will -# be sorted only by class name, not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the alphabetical -# list. -# The default value is: NO. - -SORT_BY_SCOPE_NAME = NO - -# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper -# type resolution of all parameters of a function it will reject a match between -# the prototype and the implementation of a member function even if there is -# only one candidate or it is obvious which candidate to choose by doing a -# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still -# accept a match between prototype and implementation in such cases. -# The default value is: NO. - -STRICT_PROTO_MATCHING = NO - -# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo -# list. This list is created by putting \todo commands in the documentation. -# The default value is: YES. - -GENERATE_TODOLIST = YES - -# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test -# list. This list is created by putting \test commands in the documentation. -# The default value is: YES. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug -# list. This list is created by putting \bug commands in the documentation. -# The default value is: YES. - -GENERATE_BUGLIST = YES - -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) -# the deprecated list. This list is created by putting \deprecated commands in -# the documentation. -# The default value is: YES. - -GENERATE_DEPRECATEDLIST= YES - -# The ENABLED_SECTIONS tag can be used to enable conditional documentation -# sections, marked by \if ... \endif and \cond -# ... \endcond blocks. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the -# initial value of a variable or macro / define can have for it to appear in the -# documentation. If the initializer consists of more lines than specified here -# it will be hidden. Use a value of 0 to hide initializers completely. The -# appearance of the value of individual variables and macros / defines can be -# controlled using \showinitializer or \hideinitializer command in the -# documentation regardless of this setting. -# Minimum value: 0, maximum value: 10000, default value: 30. - -MAX_INITIALIZER_LINES = 30 - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at -# the bottom of the documentation of classes and structs. If set to YES, the -# list will mention the files that were used to generate the documentation. -# The default value is: YES. - -SHOW_USED_FILES = YES - -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This -# will remove the Files entry from the Quick Index and from the Folder Tree View -# (if specified). -# The default value is: YES. - -SHOW_FILES = YES - -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces -# page. This will remove the Namespaces entry from the Quick Index and from the -# Folder Tree View (if specified). -# The default value is: YES. - -SHOW_NAMESPACES = YES - -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from -# the version control system). Doxygen will invoke the program by executing (via -# popen()) the command command input-file, where command is the value of the -# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided -# by doxygen. Whatever the program writes to standard output is used as the file -# version. For an example see the documentation. - -FILE_VERSION_FILTER = - -# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed -# by doxygen. The layout file controls the global structure of the generated -# output files in an output format independent way. To create the layout file -# that represents doxygen's defaults, run doxygen with the -l option. You can -# optionally specify a file name after the option, if omitted DoxygenLayout.xml -# will be used as the name of the layout file. -# -# Note that if you run doxygen from a directory containing a file called -# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE -# tag is left empty. - -LAYOUT_FILE = - -# The CITE_BIB_FILES tag can be used to specify one or more bib files containing -# the reference definitions. This must be a list of .bib files. The .bib -# extension is automatically appended if omitted. This requires the bibtex tool -# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. -# For LaTeX the style of the bibliography can be controlled using -# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the -# search path. See also \cite for info how to create references. - -CITE_BIB_FILES = - -#--------------------------------------------------------------------------- -# Configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated to -# standard output by doxygen. If QUIET is set to YES this implies that the -# messages are off. -# The default value is: NO. - -QUIET = NO - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES -# this implies that the warnings are on. -# -# Tip: Turn warnings on while writing the documentation. -# The default value is: YES. - -WARNINGS = YES - -# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate -# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag -# will automatically be disabled. -# The default value is: YES. - -WARN_IF_UNDOCUMENTED = YES - -# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some parameters -# in a documented function, or documenting parameters that don't exist or using -# markup commands wrongly. -# The default value is: YES. - -WARN_IF_DOC_ERROR = YES - -# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that -# are documented, but have no documentation for their parameters or return -# value. If set to NO, doxygen will only warn about wrong or incomplete -# parameter documentation, but not about the absence of documentation. If -# EXTRACT_ALL is set to YES then this flag will automatically be disabled. -# The default value is: NO. - -WARN_NO_PARAMDOC = NO - -# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when -# a warning is encountered. -# The default value is: NO. - -WARN_AS_ERROR = NO - -# The WARN_FORMAT tag determines the format of the warning messages that doxygen -# can produce. The string should contain the $file, $line, and $text tags, which -# will be replaced by the file and line number from which the warning originated -# and the warning text. Optionally the format may contain $version, which will -# be replaced by the version of the file (if it could be obtained via -# FILE_VERSION_FILTER) -# The default value is: $file:$line: $text. - -WARN_FORMAT = "$file:$line: $text" - -# The WARN_LOGFILE tag can be used to specify a file to which warning and error -# messages should be written. If left blank the output is written to standard -# error (stderr). - -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# Configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag is used to specify the files and/or directories that contain -# documented source files. You may enter file names like myfile.cpp or -# directories like /usr/src/myproject. Separate the files or directories with -# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING -# Note: If this tag is empty the current directory is searched. - -INPUT = @_INPUT@ - -# This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses -# libiconv (or the iconv built into libc) for the transcoding. See the libiconv -# documentation (see: https://www.gnu.org/software/libiconv/) for the list of -# possible encodings. -# The default value is: UTF-8. - -INPUT_ENCODING = UTF-8 - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and -# *.h) to filter out the source-files in the directories. -# -# Note that for custom extensions or not directly supported extensions you also -# need to set EXTENSION_MAPPING for the extension otherwise the files are not -# read by doxygen. -# -# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, -# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, -# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, -# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, -# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice. - -FILE_PATTERNS = *.c \ - *.cc \ - *.cxx \ - *.cpp \ - *.c++ \ - *.java \ - *.ii \ - *.ixx \ - *.ipp \ - *.i++ \ - *.inl \ - *.idl \ - *.ddl \ - *.odl \ - *.h \ - *.hh \ - *.hxx \ - *.hpp \ - *.h++ \ - *.cs \ - *.d \ - *.php \ - *.php4 \ - *.php5 \ - *.phtml \ - *.inc \ - *.m \ - *.markdown \ - *.md \ - *.mm \ - *.dox \ - *.py \ - *.pyw \ - *.f90 \ - *.f95 \ - *.f03 \ - *.f08 \ - *.f \ - *.for \ - *.tcl \ - *.vhd \ - *.vhdl \ - *.ucf \ - *.qsf \ - *.ice \ - @_FILE_PATTERNS@ - -# The RECURSIVE tag can be used to specify whether or not subdirectories should -# be searched for input files as well. -# The default value is: NO. - -RECURSIVE = YES - -# The EXCLUDE tag can be used to specify files and/or directories that should be -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. -# -# Note that relative paths are relative to the directory from which doxygen is -# run. - -EXCLUDE = @_EXCLUDE@ - -# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or -# directories that are symbolic links (a Unix file system feature) are excluded -# from the input. -# The default value is: NO. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. -# -# Note that the wildcards are matched against the file with absolute path, so to -# exclude all test directories for example use the pattern */test/* - -EXCLUDE_PATTERNS = @_EXCLUDE_PATTERNS@ - -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the -# output. The symbol name can be a fully qualified name, a word, or if the -# wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test -# -# Note that the wildcards are matched against the file with absolute path, so to -# exclude all test directories use the pattern */test/* - -EXCLUDE_SYMBOLS = @_EXCLUDE_SYMBOLS@ - -# The EXAMPLE_PATH tag can be used to specify one or more files or directories -# that contain example code fragments that are included (see the \include -# command). - -EXAMPLE_PATH = @_EXAMPLE_PATH@ - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and -# *.h) to filter out the source-files in the directories. If left blank all -# files are included. - -EXAMPLE_PATTERNS = * - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude commands -# irrespective of the value of the RECURSIVE tag. -# The default value is: NO. - -EXAMPLE_RECURSIVE = YES - -# The IMAGE_PATH tag can be used to specify one or more files or directories -# that contain images that are to be included in the documentation (see the -# \image command). - -IMAGE_PATH = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command: -# -# -# -# where is the value of the INPUT_FILTER tag, and is the -# name of an input file. Doxygen will then use the output that the filter -# program writes to standard output. If FILTER_PATTERNS is specified, this tag -# will be ignored. -# -# Note that the filter must not add or remove lines; it is applied before the -# code is scanned, but not when the output code is generated. If lines are added -# or removed, the anchors will not be placed correctly. -# -# Note that for custom extensions or not directly supported extensions you also -# need to set EXTENSION_MAPPING for the extension otherwise the files are not -# properly processed by doxygen. - -INPUT_FILTER = - -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. The filters are a list of the form: pattern=filter -# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how -# filters are used. If the FILTER_PATTERNS tag is empty or if none of the -# patterns match the file name, INPUT_FILTER is applied. -# -# Note that for custom extensions or not directly supported extensions you also -# need to set EXTENSION_MAPPING for the extension otherwise the files are not -# properly processed by doxygen. - -FILTER_PATTERNS = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will also be used to filter the input files that are used for -# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). -# The default value is: NO. - -FILTER_SOURCE_FILES = NO - -# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file -# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and -# it is also possible to disable source filtering for a specific pattern using -# *.ext= (so without naming a filter). -# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. - -FILTER_SOURCE_PATTERNS = - -# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that -# is part of the input, its contents will be placed on the main page -# (index.html). This can be useful if you have a project on for instance GitHub -# and want to reuse the introduction page also for the doxygen output. - -USE_MDFILE_AS_MAINPAGE = - -#--------------------------------------------------------------------------- -# Configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will be -# generated. Documented entities will be cross-referenced with these sources. -# -# Note: To get rid of all source code in the generated output, make sure that -# also VERBATIM_HEADERS is set to NO. -# The default value is: NO. - -SOURCE_BROWSER = YES - -# Setting the INLINE_SOURCES tag to YES will include the body of functions, -# classes and enums directly into the documentation. -# The default value is: NO. - -INLINE_SOURCES = YES - -# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any -# special comment blocks from generated source code fragments. Normal C, C++ and -# Fortran comments will always remain visible. -# The default value is: YES. - -STRIP_CODE_COMMENTS = NO - -# If the REFERENCED_BY_RELATION tag is set to YES then for each documented -# entity all documented functions referencing it will be listed. -# The default value is: NO. - -REFERENCED_BY_RELATION = YES - -# If the REFERENCES_RELATION tag is set to YES then for each documented function -# all documented entities called/used by that function will be listed. -# The default value is: NO. - -REFERENCES_RELATION = YES - -# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set -# to YES then the hyperlinks from functions in REFERENCES_RELATION and -# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will -# link to the documentation. -# The default value is: YES. - -REFERENCES_LINK_SOURCE = YES - -# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the -# source code will show a tooltip with additional information such as prototype, -# brief description and links to the definition and documentation. Since this -# will make the HTML file larger and loading of large files a bit slower, you -# can opt to disable this feature. -# The default value is: YES. -# This tag requires that the tag SOURCE_BROWSER is set to YES. - -SOURCE_TOOLTIPS = YES - -# If the USE_HTAGS tag is set to YES then the references to source code will -# point to the HTML generated by the htags(1) tool instead of doxygen built-in -# source browser. The htags tool is part of GNU's global source tagging system -# (see https://www.gnu.org/software/global/global.html). You will need version -# 4.8.6 or higher. -# -# To use it do the following: -# - Install the latest version of global -# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file -# - Make sure the INPUT points to the root of the source tree -# - Run doxygen as normal -# -# Doxygen will invoke htags (and that will in turn invoke gtags), so these -# tools must be available from the command line (i.e. in the search path). -# -# The result: instead of the source browser generated by doxygen, the links to -# source code will now point to the output of htags. -# The default value is: NO. -# This tag requires that the tag SOURCE_BROWSER is set to YES. - -USE_HTAGS = NO - -# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a -# verbatim copy of the header file for each class for which an include is -# specified. Set to NO to disable this. -# See also: Section \class. -# The default value is: YES. - -VERBATIM_HEADERS = YES - -# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the -# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the -# cost of reduced performance. This can be particularly helpful with template -# rich C++ code for which doxygen's built-in parser lacks the necessary type -# information. -# Note: The availability of this option depends on whether or not doxygen was -# generated with the -Duse_libclang=ON option for CMake. -# The default value is: NO. - -CLANG_ASSISTED_PARSING = YES - -# If clang assisted parsing is enabled you can provide the compiler with command -# line options that you would normally use when invoking the compiler. Note that -# the include paths will already be set by doxygen for the files and directories -# specified with INPUT and INCLUDE_PATH. -# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. - -CLANG_OPTIONS = - -# If clang assisted parsing is enabled you can provide the clang parser with the -# path to the compilation database (see: -# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) used when the files -# were built. This is equivalent to specifying the "-p" option to a clang tool, -# such as clang-check. These options will then be passed to the parser. -# Note: The availability of this option depends on whether or not doxygen was -# generated with the -Duse_libclang=ON option for CMake. - -CLANG_DATABASE_PATH = @_CLANG_DATABASE_PATH@ - -#--------------------------------------------------------------------------- -# Configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all -# compounds will be generated. Enable this if the project contains a lot of -# classes, structs, unions or interfaces. -# The default value is: YES. - -ALPHABETICAL_INDEX = YES - -# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in -# which the alphabetical index list will be split. -# Minimum value: 1, maximum value: 20, default value: 5. -# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. - -COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all classes will -# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag -# can be used to specify a prefix (or a list of prefixes) that should be ignored -# while generating the index headers. -# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output -# The default value is: YES. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a -# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of -# it. -# The default directory is: html. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_OUTPUT = html - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each -# generated HTML page (for example: .htm, .php, .asp). -# The default value is: .html. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_FILE_EXTENSION = .html - -# The HTML_HEADER tag can be used to specify a user-defined HTML header file for -# each generated HTML page. If the tag is left blank doxygen will generate a -# standard header. -# -# To get valid HTML the header file that includes any scripts and style sheets -# that doxygen needs, which is dependent on the configuration options used (e.g. -# the setting GENERATE_TREEVIEW). It is highly recommended to start with a -# default header using -# doxygen -w html new_header.html new_footer.html new_stylesheet.css -# YourConfigFile -# and then modify the file new_header.html. See also section "Doxygen usage" -# for information on how to generate the default header that doxygen normally -# uses. -# Note: The header is subject to change so you typically have to regenerate the -# default header when upgrading to a newer version of doxygen. For a description -# of the possible markers and block names see the documentation. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each -# generated HTML page. If the tag is left blank doxygen will generate a standard -# footer. See HTML_HEADER for more information on how to generate a default -# footer and what special commands can be used inside the footer. See also -# section "Doxygen usage" for information on how to generate the default footer -# that doxygen normally uses. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style -# sheet that is used by each HTML page. It can be used to fine-tune the look of -# the HTML output. If left blank doxygen will generate a default style sheet. -# See also section "Doxygen usage" for information on how to generate the style -# sheet that doxygen normally uses. -# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as -# it is more robust and this tag (HTML_STYLESHEET) will in the future become -# obsolete. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_STYLESHEET = - -# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined -# cascading style sheets that are included after the standard style sheets -# created by doxygen. Using this option one can overrule certain style aspects. -# This is preferred over using HTML_STYLESHEET since it does not replace the -# standard style sheet and is therefore more robust against future updates. -# Doxygen will copy the style sheet files to the output directory. -# Note: The order of the extra style sheet files is of importance (e.g. the last -# style sheet in the list overrules the setting of the previous ones in the -# list). For an example see the documentation. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_EXTRA_STYLESHEET = - -# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or -# other source files which should be copied to the HTML output directory. Note -# that these files will be copied to the base HTML output directory. Use the -# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these -# files. In the HTML_STYLESHEET file, use the file name only. Also note that the -# files will be copied as-is; there are no commands or markers available. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_EXTRA_FILES = - -# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen -# will adjust the colors in the style sheet and background images according to -# this color. Hue is specified as an angle on a colorwheel, see -# https://en.wikipedia.org/wiki/Hue for more information. For instance the value -# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 -# purple, and 360 is red again. -# Minimum value: 0, maximum value: 359, default value: 220. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COLORSTYLE_HUE = 220 - -# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors -# in the HTML output. For a value of 0 the output will use grayscales only. A -# value of 255 will produce the most vivid colors. -# Minimum value: 0, maximum value: 255, default value: 100. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COLORSTYLE_SAT = 100 - -# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the -# luminance component of the colors in the HTML output. Values below 100 -# gradually make the output lighter, whereas values above 100 make the output -# darker. The value divided by 100 is the actual gamma applied, so 80 represents -# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not -# change the gamma. -# Minimum value: 40, maximum value: 240, default value: 80. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COLORSTYLE_GAMMA = 80 - -# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting this -# to YES can help to show when doxygen was last run and thus if the -# documentation is up to date. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_TIMESTAMP = YES - -# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML -# documentation will contain a main index with vertical navigation menus that -# are dynamically created via Javascript. If disabled, the navigation index will -# consists of multiple levels of tabs that are statically embedded in every HTML -# page. Disable this option to support browsers that do not have Javascript, -# like the Qt help browser. -# The default value is: YES. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_DYNAMIC_MENUS = YES - -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_DYNAMIC_SECTIONS = NO - -# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries -# shown in the various tree structured indices initially; the user can expand -# and collapse entries dynamically later on. Doxygen will expand the tree to -# such a level that at most the specified number of entries are visible (unless -# a fully collapsed tree already exceeds this amount). So setting the number of -# entries 1 will produce a full collapsed tree by default. 0 is a special value -# representing an infinite number of entries and will result in a full expanded -# tree by default. -# Minimum value: 0, maximum value: 9999, default value: 100. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_INDEX_NUM_ENTRIES = 100 - -# If the GENERATE_DOCSET tag is set to YES, additional index files will be -# generated that can be used as input for Apple's Xcode 3 integrated development -# environment (see: https://developer.apple.com/xcode/), introduced with OSX -# 10.5 (Leopard). To create a documentation set, doxygen will generate a -# Makefile in the HTML output directory. Running make will produce the docset in -# that directory and running make install will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at -# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy -# genXcode/_index.html for more information. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_DOCSET = NO - -# This tag determines the name of the docset feed. A documentation feed provides -# an umbrella under which multiple documentation sets from a single provider -# (such as a company or product suite) can be grouped. -# The default value is: Doxygen generated docs. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_FEEDNAME = "Doxygen generated docs" - -# This tag specifies a string that should uniquely identify the documentation -# set bundle. This should be a reverse domain-name style string, e.g. -# com.mycompany.MyDocSet. Doxygen will append .docset to the name. -# The default value is: org.doxygen.Project. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_BUNDLE_ID = org.doxygen.Project - -# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify -# the documentation publisher. This should be a reverse domain-name style -# string, e.g. com.mycompany.MyDocSet.documentation. -# The default value is: org.doxygen.Publisher. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_PUBLISHER_ID = org.doxygen.Publisher - -# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. -# The default value is: Publisher. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_PUBLISHER_NAME = Publisher - -# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three -# additional HTML index files: index.hhp, index.hhc, and index.hhk. The -# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop -# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on -# Windows. -# -# The HTML Help Workshop contains a compiler that can convert all HTML output -# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML -# files are now used as the Windows 98 help format, and will replace the old -# Windows help format (.hlp) on all Windows platforms in the future. Compressed -# HTML files also contain an index, a table of contents, and you can search for -# words in the documentation. The HTML workshop also contains a viewer for -# compressed HTML files. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_HTMLHELP = NO - -# The CHM_FILE tag can be used to specify the file name of the resulting .chm -# file. You can add a path in front of the file if the result should not be -# written to the html output directory. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -CHM_FILE = - -# The HHC_LOCATION tag can be used to specify the location (absolute path -# including file name) of the HTML help compiler (hhc.exe). If non-empty, -# doxygen will try to run the HTML help compiler on the generated index.hhp. -# The file has to be specified with full path. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -HHC_LOCATION = - -# The GENERATE_CHI flag controls if a separate .chi index file is generated -# (YES) or that it should be included in the master .chm file (NO). -# The default value is: NO. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -GENERATE_CHI = NO - -# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) -# and project file content. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -CHM_INDEX_ENCODING = - -# The BINARY_TOC flag controls whether a binary table of contents is generated -# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it -# enables the Previous and Next buttons. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members to -# the table of contents of the HTML help documentation and to the tree view. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -TOC_EXPAND = NO - -# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and -# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that -# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help -# (.qch) of the generated HTML documentation. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_QHP = NO - -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify -# the file name of the resulting .qch file. The path specified is relative to -# the HTML output folder. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QCH_FILE = - -# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help -# Project output. For more information please see Qt Help Project / Namespace -# (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). -# The default value is: org.doxygen.Project. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_NAMESPACE = org.doxygen.Project - -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt -# Help Project output. For more information please see Qt Help Project / Virtual -# Folders (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual- -# folders). -# The default value is: doc. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_VIRTUAL_FOLDER = doc - -# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom -# filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- -# filters). -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_CUST_FILTER_NAME = - -# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the -# custom filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- -# filters). -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_CUST_FILTER_ATTRS = - -# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this -# project's filter section matches. Qt Help Project / Filter Attributes (see: -# http://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_SECT_FILTER_ATTRS = - -# The QHG_LOCATION tag can be used to specify the location of Qt's -# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the -# generated .qhp file. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHG_LOCATION = - -# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be -# generated, together with the HTML files, they form an Eclipse help plugin. To -# install this plugin and make it available under the help contents menu in -# Eclipse, the contents of the directory containing the HTML and XML files needs -# to be copied into the plugins directory of eclipse. The name of the directory -# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. -# After copying Eclipse needs to be restarted before the help appears. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_ECLIPSEHELP = NO - -# A unique identifier for the Eclipse help plugin. When installing the plugin -# the directory name containing the HTML and XML files should also have this -# name. Each documentation set should have its own identifier. -# The default value is: org.doxygen.Project. -# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. - -ECLIPSE_DOC_ID = org.doxygen.Project - -# If you want full control over the layout of the generated HTML pages it might -# be necessary to disable the index and replace it with your own. The -# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top -# of each HTML page. A value of NO enables the index and the value YES disables -# it. Since the tabs in the index contain the same information as the navigation -# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -DISABLE_INDEX = NO - -# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. If the tag -# value is set to YES, a side panel will be generated containing a tree-like -# index structure (just like the one that is generated for HTML Help). For this -# to work a browser that supports JavaScript, DHTML, CSS and frames is required -# (i.e. any modern browser). Windows users are probably better off using the -# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can -# further fine-tune the look of the index. As an example, the default style -# sheet generated by doxygen has an example that shows how to put an image at -# the root of the tree instead of the PROJECT_NAME. Since the tree basically has -# the same information as the tab index, you could consider setting -# DISABLE_INDEX to YES when enabling this option. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_TREEVIEW = NO - -# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that -# doxygen will group on one line in the generated HTML documentation. -# -# Note that a value of 0 will completely suppress the enum values from appearing -# in the overview section. -# Minimum value: 0, maximum value: 20, default value: 4. -# This tag requires that the tag GENERATE_HTML is set to YES. - -ENUM_VALUES_PER_LINE = 4 - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used -# to set the initial width (in pixels) of the frame in which the tree is shown. -# Minimum value: 0, maximum value: 1500, default value: 250. -# This tag requires that the tag GENERATE_HTML is set to YES. - -TREEVIEW_WIDTH = 250 - -# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to -# external symbols imported via tag files in a separate window. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -EXT_LINKS_IN_WINDOW = NO - -# Use this tag to change the font size of LaTeX formulas included as images in -# the HTML documentation. When you change the font size after a successful -# doxygen run you need to manually remove any form_*.png images from the HTML -# output directory to force them to be regenerated. -# Minimum value: 8, maximum value: 50, default value: 10. -# This tag requires that the tag GENERATE_HTML is set to YES. - -FORMULA_FONTSIZE = 10 - -# Use the FORMULA_TRANSPARENT tag to determine whether or not the images -# generated for formulas are transparent PNGs. Transparent PNGs are not -# supported properly for IE 6.0, but are supported on all modern browsers. -# -# Note that when changing this option you need to delete any form_*.png files in -# the HTML output directory before the changes have effect. -# The default value is: YES. -# This tag requires that the tag GENERATE_HTML is set to YES. - -FORMULA_TRANSPARENT = YES - -# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see -# https://www.mathjax.org) which uses client side Javascript for the rendering -# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX -# installed or if you want to formulas look prettier in the HTML output. When -# enabled you may also need to install MathJax separately and configure the path -# to it using the MATHJAX_RELPATH option. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -USE_MATHJAX = NO - -# When MathJax is enabled you can set the default output format to be used for -# the MathJax output. See the MathJax site (see: -# http://docs.mathjax.org/en/latest/output.html) for more details. -# Possible values are: HTML-CSS (which is slower, but has the best -# compatibility), NativeMML (i.e. MathML) and SVG. -# The default value is: HTML-CSS. -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_FORMAT = HTML-CSS - -# When MathJax is enabled you need to specify the location relative to the HTML -# output directory using the MATHJAX_RELPATH option. The destination directory -# should contain the MathJax.js script. For instance, if the mathjax directory -# is located at the same level as the HTML output directory, then -# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax -# Content Delivery Network so you can quickly see the result without installing -# MathJax. However, it is strongly recommended to install a local copy of -# MathJax from https://www.mathjax.org before deployment. -# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/. -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/ - -# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax -# extension names that should be enabled during MathJax rendering. For example -# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_EXTENSIONS = - -# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces -# of code that will be used on startup of the MathJax code. See the MathJax site -# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an -# example see the documentation. -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_CODEFILE = - -# When the SEARCHENGINE tag is enabled doxygen will generate a search box for -# the HTML output. The underlying search engine uses javascript and DHTML and -# should work on any modern browser. Note that when using HTML help -# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) -# there is already a search function so this one should typically be disabled. -# For large projects the javascript based search engine can be slow, then -# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to -# search using the keyboard; to jump to the search box use + S -# (what the is depends on the OS and browser, but it is typically -# , /${specs.projname}`); - bmSpecs = specs; - var toc = $("#toc"); - /*toc.append(`
  • Load all
  • `);*/ - iterBms(function(key, bm) { - toc.append(`
  • ${key}: ${bm.specs.desc}
  • `) - bm.name = key; - }); - // load if required - currBm = getParam("bm", ""); - dbg("params=", _curr_url_params, currBm); - if(currBm != "") { - dbg("loading BM from URL:", currBm) - loadBm(currBm); - } -} - -function normalizeBy(results, column_name, best_fn) -{ - var best = best_fn(results.benchmarks, column_name); - results.benchmarks.forEach(function(item, index){ - item[`${column_name}_normalized`] = item[column_name] / best; - }); -} - - -function loadAll() -{ - var id = "#bm-results"; - $(id).empty(); - var i = 0; - iterBms(function(key, bm){ - if(i++ > 0) $(id).append("

    "); - appendBm(key); - }); -} - - -function loadBm(key) -{ - dbg("loading-.....", key); - /*if(key == "all") { - loadAll(); - }*/ - $("#bm-results").empty(); - var bm = bmSpecs.bm[key]; - if(bm.src != "") { - fileContents(bm.src, function(data){ - dbg(`${key}: got src data!`) - bm.src_data = data; - }); - } - var latestRun = last(bm.entries); - var bmfile = `${latestRun}/${key}.json`; - dbg("bmfile=", bmfile); - fileContents("bm/"+bmfile, function(data){ - dbg(`${key}: got bm data!`) - bm.results_data = new BmResults(JSON.parse(data)); - bm.results_data.benchmarks.forEach(function(item, index){ - item.id = index; - }); - normalizeBy(bm.results_data, 'iterations', colMin); - normalizeBy(bm.results_data, 'real_time', colMin, ); - normalizeBy(bm.results_data, 'cpu_time', colMin); - normalizeBy(bm.results_data, 'bytes_per_second', colMin); - normalizeBy(bm.results_data, 'items_per_second', colMin); - appendBm(latestRun, key, bm); - }); -} - - -function appendBm(run_id, id, bm) -{ - if($(document).find(`bm-results-${id}`).length == 0) - { - $("#bm-results").append(` -
    -

    ${id}

    - -

    Run details

    - -

    Result tables

    -

    Results

    -

    Normalized by column min

    - -

    Chart

    -
    - -

    Code

    -
    -
    -`); - } - var results = bm.results_data; - var code = bm.src_data; - loadDetailsTable(run_id, id, bm, results); - loadTable(id, bm, results); - loadChart(id, bm, results); - loadCode(id, bm, code); -} - - -function loadCode(elmId, bm, code) -{ - var elm = $(`#code-${elmId}`); - elm.text(code); - /* hljs.highlightBlock(elm); // this doesn't work */ - /* ... and this is very inefficient: */ - document.querySelectorAll('pre code').forEach((block) => { - hljs.highlightBlock(block); - }); -} - -function parseRunId(run_id) -{ - // example: - // commit id / cpu id - system id - build id - // git20201204_202919-b3f7fa7/x86_64_b9db3176-linux_4e9326b4-64bit_Debug_gcc10.2.0_10c5d03c - // git20201203_193348-2974fb0/x86_64_16ac0500-win32_59f3579c-64bit_MinSizeRel_msvc19.28.29304.1_32f6fc66 - // to tune the regex: https://regex101.com/r/rdkPi8/1 - // commit / cpu - system - build - var rx = /^(.+?)-([0-9a-f]{7})\/(.+?)_([0-9a-f]{8})-(.+?)_([0-9a-f]{8})-(.+?)_([0-9a-f]{8})$/gim; - var tag = rx.exec(run_id); - dbg("fdx: run_id=", run_id); - dbg("fdx: tag=", tag); - dbg("fdx: len=", tag.length); - return { - commit_id: `${tag[2]}: ${tag[1]}`, - cpu_id: `${tag[4]}: ${tag[3]} `, - system_id: `${tag[6]}: ${tag[5]}`, - build_id: `${tag[8]}: ${tag[7]}`, - }; -} - -function getBuildId(run_id) -{ - return parseRunId(run_id).build_id; -} - -function loadDetailsTable(run_id, id, bm, results) -{ - var url = bmSpecs.url; - var run = bmSpecs.runs[run_id]; - var commit = bmSpecs.commit[run.commit].specs; - var cpu = bmSpecs.cpu[run.cpu].specs; - var system = bmSpecs.system[run.system].specs; - - let other_commit_entries = bmSpecs.commit[run.commit].entries.filter( - entry_run => entry_run != run_id - ).map(entry_run => getBuildId(entry_run)).join('
    '); - - /* https://datatables.net/ */ - $(`#table-details-${id}`).DataTable({ - data: results.benchmarks, - info: false, - paging: false, - searching: false, - retrieve: false, - order: [], - columns: [ - {title: "", data: "desc"}, - {title: "", data: "contents"}, - ], - data: [ - {desc: "benchmark id" , contents: id}, - {desc: "commit" , contents: ahref(`${url}/commit/${commit.sha1}`, commit.sha1)}, - {desc: "commit date" , contents: ahref(`${url}/commit/${commit.sha1}`, commit.committed_datetime)}, - {desc: "commit summary", contents: ahref(`${url}/commit/${commit.sha1}`, commit.summary)}, - {desc: "source tree" , contents: ahref(`${url}/tree/${commit.sha1}`, `tree @ ${commit.sha1}`)}, - {desc: "benchmark" , contents: ahref(`${url}/tree/${commit.sha1}/${bm.specs.src}`, `source @ ${commit.sha1}`)}, - {desc: "cpu used" , contents: `${cpu.arch} ${cpu.brand_raw}`}, - {desc: "system used" , contents: `${system.uname.system} ${system.uname.release}`}, - {desc: "this build" , contents: `
    ${getBuildId(run_id)}
    `}, - {desc: "commit builds" , contents: `
    ${other_commit_entries}
    `}, - ] - }); - function ahref(url, txt) { return `${txt}`; } -} - - -function loadTable(id, bm, results) -{ - function render_int(data, type, row, meta) { return toFixedNumber(data, 0); } - function render_megas(data, type, row, meta) { return toFixedNumber(data / 1.e6, 3); } - function render_fixed(data, type, row, meta) { return toFixedNumber(data, 3); } - function render_human(data, type, row, meta) { return humanReadable(data, 1000, 3); } - - addTable("_pretty" , "" , {ns: render_int, iters: render_megas, rates: render_megas}); - addTable("_normalized", "_normalized", {ns: render_fixed, iters: render_fixed, rates: render_fixed}); - - function addTable(suffix, data_suffix, renderers) { - /* https://datatables.net/ */ - var searching = (results.benchmarks.count > 20); - var ratePrefix = renderers.rates == render_megas ? "M" : ""; - var iterPrefix = renderers.iters == render_megas ? "M" : ""; - var clockSuffix = data_suffix == "_normalized" ? "" : "(ns)"; - $(`#table-${id}${suffix}`).DataTable( { - data: results.benchmarks, - info: false, - paging: false, - searching: searching, - retrieve: searching, - /* https://datatables.net/reference/option/columns.type */ - columns: [ - {title: "ID", data: "id", type: "num"}, - {title: "Name", data: "name", render: function(data, type, row, meta) { return escapeHtml(data); }}, - {title: `${ratePrefix}B/s` , data: `bytes_per_second${data_suffix}`, type: "num", className: "text-right", render: renderers.rates}, - {title: `${ratePrefix}items/s` , data: `items_per_second${data_suffix}`, type: "num", className: "text-right", render: renderers.rates}, - {title: `Clock${clockSuffix}` , data: `real_time${data_suffix}` , type: "num", className: "text-right", render: renderers.ns}, - {title: `CPU${clockSuffix}` , data: `cpu_time${data_suffix}` , type: "num", className: "text-right", render: renderers.ns}, - {title: `${ratePrefix}Iterations`, data: `iterations${data_suffix}` , type: "num", className: "text-right", render: renderers.iters}, - ]}); - } -} - -function loadChart(id, bm, results) -{ - - addChartFromColumn('bytes_per_second_normalized', "B/s", "(more is better)"); - addChartFromColumn('items_per_second_normalized', "items/s", "(more is better)"); - addChartFromColumn('iterations_normalized', "Iterations", "(more is better)"); - addChartFromColumn('real_time_normalized', "Clock time", "(less is better)"); - addChartFromColumn('cpu_time_normalized', "CPU time", "(less is better)"); - - function addChartFromColumn(column, column_name, obs) { - var elmId = `chart-${id}-${column}`; - var canvas = `${elmId}-canvas`; - - $(`#chart-container-${id}`).append(` -
    - -
    -`); - - var chart = new CanvasJS.Chart(elmId, { - animationEnabled: false, - title:{ - fontSize: 24, - /* text: `${id}: ${column_name}\n${obs}` */ - text: `${column_name}\n${obs}` - }, - axisX: { - labelFontSize: 12, - }, - data: [{ - type: "bar", - axisYType: "secondary", - color: "#eb7434",/*"#014D65",*/ - dataPoints: results.benchmarks.map(function(item){ - return { - indexLabelFormatter: function(e) { return e.dataPoint.indexLabel; }, - indexLabelFontSize: 16, - indexLabel: item.name, - /* label: item.name, */ - y: item[column], - /* save the result here: the tooltip will show the full thing */ - benchmark_results: item - }; - }), - }], - toolTip: { - /*content: "{indexLabel}: {y}",*/ - contentFormatter: function(e){ - function hr(val) { return humanReadable(val, 1000, 3); } - function fx(val) { return toFixedNumber(val, 3); } - function fxi(val) { return toFixedNumber(val, 0); } - function getRow(name, abs, rel) { return `${name}${abs}${rel}x min`; } - var r = e.entries[0].dataPoint.benchmark_results; - var hdrRow = `AbsoluteNormalized`; - var bpsRow = getRow("B/s", hr(r.bytes_per_second), fx(r.bytes_per_second_normalized)); - var ipsRow = getRow("items/s", hr(r.items_per_second), fx(r.items_per_second_normalized)); - var cpuRow = getRow("CPU", fxi(r.cpu_time) + "ns", fx(r.cpu_time_normalized)); - var clockRow = getRow("Clock", fxi(r.real_time) + "ns", fx(r.real_time_normalized)); - var itersRow = getRow("Iterations", hr(r.iterations), fx(r.iterations_normalized)); - var table = `${hdrRow}${bpsRow}${ipsRow}${cpuRow}${clockRow}${itersRow}
    `; - return `

    ${escapeHtml(r.name)}

    ${table}`; - } - } - }); - chart.render(); - } -} diff --git a/thirdparty/ryml/ext/c4core/cmake/bm-xp/bm_plot.py b/thirdparty/ryml/ext/c4core/cmake/bm-xp/bm_plot.py deleted file mode 100644 index 3bcab5f4d..000000000 --- a/thirdparty/ryml/ext/c4core/cmake/bm-xp/bm_plot.py +++ /dev/null @@ -1,746 +0,0 @@ -import os -import sys -import copy -import re -import itertools -import typing -import enum - -# https://stackoverflow.com/questions/11351032/named-tuple-and-default-values-for-optional-keyword-arguments -from dataclasses import dataclass - -from munch import Munch, munchify - -import bokeh.io as bki -import bokeh.models as bkm -import bokeh.plotting as bkp -import bokeh.transform as bkt -import bokeh.layouts as bkl -from bokeh.models.markers import marker_types as bk_markers -# https://docs.bokeh.org/en/latest/docs/reference/palettes.html -from bokeh.palettes import d3 as bk_palette_d3 -bk_palette = bk_palette_d3['Category20c'][20] - -# saving bokeh to png is not working, so we save png using matplotlib -import matplotlib.pyplot as plt -import matplotlib.ticker as plttck -plt_markers = [c for c in ".,ov^<>1234spP*hH+xXDdl"] - -from bm_util import _enum -from bm_util import * -from bm_run import BenchmarkRun, BenchmarkPanel - - -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ - - -# https://stackoverflow.com/questions/11351032/named-tuple-and-default-values-for-optional-keyword-arguments -@dataclass -class BarChartSpecs: - horizontal: bool = True - bar_width: float = 0.9 - - -@dataclass -class LineChartSpecs: - width: int = 1000 - xlog: bool = False - ylog: bool = False - xlabel: str = "" - ylabel: str = "" - - -def _plt_save_png(name): - log(name) - plt.savefig(name, bbox_inches='tight', dpi=100) - - -def _plt_clear(): - plt.clf() - - -def _bokeh_save_html(name, p): - log(name) - bki.save(p, name) - - -def _bokeh_adjust_figure_props(p): - p.toolbar.autohide = True - #p.toolbar.active_inspect = [hover_tool, crosshair_tool] - p.toolbar.active_drag = "auto" - p.toolbar.active_scroll = "auto" - p.legend - p.legend.click_policy = "hide" - p.legend.label_text_font_size = "10px" - - -def bokeh_plot_many(plots, name: str, ncols: int = 2): - layout = bkl.gridplot(plots, ncols=ncols) - _bokeh_save_html(name, layout) - #bkp.show(layout) - - -def plot_benchmark_run_as_bars(bm: BenchmarkRun, title: str, - bar_names, bar_values, bar_label, - **kwargs): - kwargs = BarChartSpecs(**kwargs) - # - palette = itertools.cycle(bk_palette) - colors = [next(palette) for _ in bar_names] - # - fig_args_bokeh = { - "title": title, - #"toolbar_location": None, - #"tools": "" - } - if kwargs.horizontal: - # - # plot with bokeh (interactive, but cannot export png) - rnames = list(reversed(bar_names)) - rvalues = list(reversed(bar_values)) - rcolors = list(reversed(colors)) - p = bkp.figure(y_range=rnames, **fig_args_bokeh) - p.hbar(y=rnames, right=rvalues, fill_color=rcolors, - line_color=rcolors, height=kwargs.bar_width) - p.ygrid.grid_line_color = None - p.x_range.start = 0 - p.xaxis.axis_label = bar_label - # - # plot with matplotlib (to export png) - p_ = plt.barh(y=rnames, width=rvalues, color=rcolors, - height=kwargs.bar_width) - plt.gca().xaxis.grid(True) - plt.gca().xaxis.set_minor_locator(plttck.AutoMinorLocator()) - plt.xlabel(bar_label, fontsize='small') - plt.yticks(fontsize='x-small') - plt.title(title) - else: - # - # plot with bokeh (interactive, but cannot export png) - p = bkp.figure(x_range=bar_names, **fig_args_bokeh) - p.vbar(x=bar_names, top=bar_values, fill_color=colors, - line_color=colors, width=kwargs.bar_width) - p.xaxis.major_label_orientation = 1 - p.xgrid.grid_line_color = None - p.y_range.start = 0 - p.yaxis.axis_label = bar_label - # - # plot with matplotlib (to export png) - p_ = plt.bar(x=bar_names, height=bar_values, color=colors, - width=kwargs.bar_width) - plt.gca().yaxis.grid(True) - plt.gca().yaxis.set_minor_locator(plttck.AutoMinorLocator()) - plt.ylabel(bar_label, fontsize='small') - plt.xticks(fontsize='x-small') - plt.title(title) - _bokeh_adjust_figure_props(p) - return p, p_ - - -def plot_benchmark_panel_as_lines(bm_panel: BenchmarkPanel, title: str, - xget, yget, nameget, - **kwargs): - kwargs = LineChartSpecs(**kwargs) - # - colors = itertools.cycle(bk_palette) - markers = itertools.cycle(bk_markers) - markers_ = itertools.cycle(plt_markers) - # - # plot with bokeh (interactive, but cannot export png) - p = bkp.figure(title=title, - x_axis_type="log" if kwargs.xlog else "linear", - y_axis_type="log" if kwargs.ylog else "linear", - #background_fill_color="#fafafa", - x_axis_label=kwargs.xlabel, - y_axis_label=kwargs.ylabel, - plot_width=kwargs.width, - ) - # plot with matplotlib (to export png) - plt.title(title) - for bm in bm_panel.runs: - x = xget(bm) - y = yget(bm) - line_name = nameget(bm) - color = next(colors) - marker = next(markers) - marker_ = next(markers_) - # plot with bokeh (interactive, but cannot export png) - #legends.append(LegendItem(name=c, label=line_name)) - p.scatter(x, y, marker=marker, size=8, color=color, - legend_label=line_name) - p.line(x, y, color=color, alpha=0.9, - #muted_color=c, muted_alpha=0.05, - legend_label=line_name) - # - # plot with matplotlib (to export png) - plt.plot(x, y, f'-{marker_}', color=color, label=line_name) - plt.gca().xaxis.grid(True) - plt.gca().yaxis.grid(True) - plt.xscale("log" if kwargs.xlog else "linear") - plt.yscale("log" if kwargs.ylog else "linear") - plt.xlabel(kwargs.xlabel, fontsize='small') - plt.ylabel(kwargs.ylabel, fontsize='small') - plt.gca().legend(loc='center left', bbox_to_anchor=(1, 0.5), fontsize='x-small') - _bokeh_adjust_figure_props(p) - return p - - -# ----------------------------------------------------------------------------- -# ----------------------------------------------------------------------------- -# ----------------------------------------------------------------------------- - -####### old code: to remove and tidy up - -@dataclass -class CharconvMeta: # also for atox - title: str - subject: str - function: str - data_type: FundamentalTypes - - @classmethod - def make(cls, bm_title: str): - # eg: - # xtoa_c4_write_dec - # xtoa_c4_utoa - # xtoa_c4_xtoa - # xtoa_c4_to_chars - # xtoa_std_to_chars - # xtoa_std_to_string - # xtoa_sprintf - # xtoa_sstream_reuse - # xtoa_sstream - rx = re.compile(r'(atox|xtoa|xtoahex|xtoaoct|xtoabin)_(.*?)<(u?int\d+_t)>') - if not rx.fullmatch(bm_title): - raise Exception(f"cannot understand bm title: {bm_title}") - subject = rx.sub(r'\1', bm_title) - function = rx.sub(r'\2', bm_title) - data_type = rx.sub(r'\3', bm_title) - return cls( - title=bm_title, - subject=subject, - function=function.replace("c4_", "c4::").replace("std_", "std::"), - data_type=FundamentalTypes.make(data_type) - ) - - def checkbox_groups(self): - return { - 'data_type': [t for t in FundamentalTypes], - } - - @property - def shortname(self): - return self.function - - @property - def shortparams(self): - return str(self.data_type.short) - - @property - def shorttitle(self): - return f"{self.shortname}<{self.shortparams}>" - - -@dataclass -class CharconvThreadsMeta: - function: str - num_threads: int - - @classmethod - def make(cls, bm_title: str): - # eg: - # c4_itoa/real_time/threads:4 - rx = re.compile(r'(.*?)/real_time/threads:(\d+)') - if not rx.fullmatch(bm_title): - raise Exception(f"cannot understand bm title: {bm_title}") - function = rx.sub(r'\1', bm_title) - num_threads = int(rx.sub(r'\2', bm_title)) - return cls( - function=function.replace("c4_", "c4::").replace("std_", "std::"), - num_threads=num_threads - ) - - def checkbox_groups(self): - return {} - - @property - def shortname(self): - return self.function - - @property - def shorttitle(self): - return self.shortname - - -def plot_charconv_bars(bm_panel: BenchmarkPanel, panel_title_human: str, outputfile_prefix: str): - assert os.path.isabs(outputfile_prefix), outputfile_prefix - for prop in ("mega_bytes_per_second", "cpu_time_ms"): - ps, ps_ = [], [] - pd = bm_panel.first_run.property_plot_data(prop) - bar_label = f"{pd.human_name_short}{pd.what_is_better}" - outfilename = f"{outputfile_prefix}-{prop}" - for bm in bm_panel.runs: - bar_names = [m.shorttitle for m in bm.meta] - bar_values = list(getattr(bm, prop)) - data_type = first(bm.meta).data_type - # to save each bokeh plot separately and also - # a grid plot with all of them, we have to plot - # twice because bokeh does not allow saving twice - # the same plot from multiple pictures. - plotit = lambda: plot_benchmark_run_as_bars(bm, title=f"{panel_title_human}: {data_type}\n{bar_label}", - bar_names=bar_names, bar_values=bar_values, bar_label=bar_label) - # make one plot to save: - p, p_ = plotit() - _bokeh_save_html(f"{outfilename}-{data_type.short}.html", p) - _plt_save_png_and_clear(f"{outfilename}-{data_type.short}.png") - # and another to gather: - p, p_ = plotit() - ps.append(p) - ps_.append(p_) - layout = bkl.gridplot(ps, ncols=2) - _bokeh_save_html(f"{outfilename}.html", layout) - # now show - #bkp.show(layout) - - -def plot_charconv_threads_(bm_panel: BenchmarkPanel, panel_title_human: str, outputfile_prefix: str): - assert os.path.isabs(outputfile_prefix), outputfile_prefix - orig = lambda yprop: lambda bm: list(bm.extract_plot_series(yprop)) - divnt = lambda yprop: lambda bm: [v / n for v, n in bm.extract_plot_series_with_threads(yprop)] - mulnt = lambda yprop: lambda bm: [v * n for v, n in bm.extract_plot_series_with_threads(yprop)] - xprop = "threads" - xpd = bm_panel.first_run.property_plot_data(xprop) - xlabel = f"{xpd.human_name_short}" - for yprop, ylog, yget in ( - #("mega_items_per_second", False, orig), - ("mega_bytes_per_second", False, orig), - #("iterations", False, divnt), - #("real_time_ms", True, mulnt), - ("cpu_time_ms", True, orig),): - ypd = bm_panel.first_run.property_plot_data(yprop) - ylabel = f"{ypd.human_name_short}{ypd.what_is_better}" - p = plot_benchmark_panel_as_lines( - bm_panel, f"{panel_title_human}\n{ylabel}", - xget=orig("threads"), - yget=yget(yprop), - nameget=lambda bm: first(bm.meta).function, - ylog=ylog, - xlabel=xlabel, - ylabel=ylabel - ) - name = f"{outputfile_prefix}-lines-{yprop}" - # save png using matplotlib - _plt_save_png_and_clear(f"{name}.png") - # save html using bokeh - _bokeh_save_html(f"{name}.html", p) - #bkp.show(p) - return p - - -def plot_charconv_threads(json_files, case: str = ""): - case = f" [{case}]" if case else "" - dir_ = os.path.dirname(first(json_files)) - panel = BenchmarkPanel(json_files, CharconvThreadsMeta) - plot_charconv_threads_(panel, - f"itoa benchmark: convert 2M 32b integers to string{case}", - f"{dir_}/c4core-bm-charconv_threads") - - -def plot_charconv_xtoa(json_files, case: str = ""): - case = f" [{case}]" if case else "" - dir_ = os.path.dirname(first(json_files)) - panel = BenchmarkPanel(json_files, CharconvMeta) - plot_charconv_bars(panel, - f"xtoa benchmark: convert 2M numbers to strings{case}", - f"{dir_}/c4core-bm-charconv-xtoa") - - -def plot_charconv_atox(json_files, case: str = ""): - case = f" [{case}]" if case else "" - dir_ = os.path.dirname(first(json_files)) - panel = BenchmarkPanel(json_files, CharconvMeta) - plot_charconv_bars(panel, - f"atox benchmark: convert 2M strings to numbers{case}", - f"{dir_}/c4core-bm-charconv-atox") - - -def threads_data(dir_: str): - assert os.path.exists(dir_), dir_ - return [ - f"{dir_}/c4core-bm-charconv_threads-c4_write_dec.json", - f"{dir_}/c4core-bm-charconv_threads-c4_itoa.json", - f"{dir_}/c4core-bm-charconv_threads-c4_xtoa.json", - f"{dir_}/c4core-bm-charconv_threads-c4_to_chars.json", - f"{dir_}/c4core-bm-charconv_threads-fmtlib_format_to.json", - f"{dir_}/c4core-bm-charconv_threads-std_to_chars.json", - f"{dir_}/c4core-bm-charconv_threads-snprintf.json", - f"{dir_}/c4core-bm-charconv_threads-stb_snprintf.json", - f"{dir_}/c4core-bm-charconv_threads-sstream.json", - f"{dir_}/c4core-bm-charconv_threads-sstream_naive_reuse.json", - f"{dir_}/c4core-bm-charconv_threads-sstream_naive.json", - ] - - -def xtoa_data(dir_: str): - assert os.path.exists(dir_), dir_ - return [ - f"{dir_}/c4core-bm-charconv-xtoa-int8.json", - f"{dir_}/c4core-bm-charconv-xtoa-uint8.json", - f"{dir_}/c4core-bm-charconv-xtoa-int16.json", - f"{dir_}/c4core-bm-charconv-xtoa-uint16.json", - f"{dir_}/c4core-bm-charconv-xtoa-int32.json", - f"{dir_}/c4core-bm-charconv-xtoa-uint32.json", - f"{dir_}/c4core-bm-charconv-xtoa-int64.json", - f"{dir_}/c4core-bm-charconv-xtoa-uint64.json", - ] - - -def atox_data(dir_: str): - assert os.path.exists(dir_), dir_ - return [ - f"{dir_}/c4core-bm-charconv-atox-int8.json", - f"{dir_}/c4core-bm-charconv-atox-uint8.json", - f"{dir_}/c4core-bm-charconv-atox-int16.json", - f"{dir_}/c4core-bm-charconv-atox-uint16.json", - f"{dir_}/c4core-bm-charconv-atox-int32.json", - f"{dir_}/c4core-bm-charconv-atox-uint32.json", - f"{dir_}/c4core-bm-charconv-atox-int64.json", - f"{dir_}/c4core-bm-charconv-atox-uint64.json", - ] - - -def examples_dir(): - this_dir = os.path.dirname(os.path.abspath(__file__)) - exdir = f"{this_dir}/examples" - assert os.path.exists(exdir), exdir - return exdir - - -if __name__ == '__main__': - xdir = examples_dir() - # - plot_charconv_threads(threads_data(f"{xdir}/lines/gcc11.2"), "gcc11.2") - plot_charconv_threads(threads_data(f"{xdir}/lines/vs2022"), "vs2022") - # - plot_charconv_xtoa(xtoa_data(f"{xdir}/bars/xtoa/gcc11.2"), "gcc11.2") - plot_charconv_xtoa(xtoa_data(f"{xdir}/bars/xtoa/vs2022"), "vs2022") - # - plot_charconv_atox(atox_data(f"{xdir}/bars/atox/gcc11.2"), "gcc11.2") - plot_charconv_atox(atox_data(f"{xdir}/bars/atox/vs2022"), "vs2022") - # - exit() - - -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ - - -def plot_benchmarks_as_lines(title, *bm, transform=None, - line_title_transform=None, - logx=True, logy=True): - import bokeh - from bokeh.plotting import figure, output_file, show - from bokeh.palettes import Dark2_5 as palette - from bokeh.layouts import row, column - from bokeh.models import (Legend, LegendItem, CheckboxGroup, CustomJS, Div, - RadioGroup, Toggle, - ColumnDataSource, DataTable, TableColumn) - from bokeh.models.markers import marker_types - # - ids = entry_ids(*bm, transform=transform) - colors = itertools.cycle(palette) - markers = itertools.cycle(marker_types) - p = figure(title=title, - x_axis_type="log" if logx else "linear", - y_axis_type="log" if logy else "linear", - #background_fill_color="#fafafa", - plot_width=1000, - x_axis_label="Number of pixels", - y_axis_label="Throughput (MB/s)", - ) - p.toolbar.autohide = True - #p.toolbar.active_inspect = [hover_tool, crosshair_tool] - p.toolbar.active_drag = "auto" - p.toolbar.active_scroll = "auto" - # - def dft(v): return v if v else (lambda n: n) - tr = dft(transform) - lttr = dft(line_title_transform) - # - for results in bm: - x = [ids[name] for name in results.names] - y = [bps/1e6 for bps in results.bytes_per_second] - c = next(colors) - marker = next(markers) - next(markers) # advance two - line_name = lttr(results.first) - #legends.append(LegendItem(name=c, label=line_name)) - p.scatter(x, y, marker=marker, size=8, color=c, legend_label=line_name) - p.line(x, y, - color=c, alpha=0.9, - #muted_color=c, muted_alpha=0.05, - legend_label=line_name) - p.legend.click_policy = "hide" - p.legend.label_text_font_size = "10px" - # - def input_title(title): - return Div(text=f"

    {title}

    ") - inputs = [] - first = bm[0].first.meta - for k, g in first.checkbox_groups().items(): - cb = CheckboxGroup(labels=[str(v) for v in g], - active=[i for i in range(len(g))], - inline=True) - inputs.append(input_title(k)) - inputs.append(cb) - # - # https://github.com/bokeh/bokeh/blob/branch-2.3/examples/app/export_csv/main.py - x_axis_values = [f"{m.num_pixels}px" for m in bm[0].meta] - table_sources = [] - for i, px in enumerate(x_axis_values): - c = ColumnDataSource(data={ - 'name': [nth(results.filtered_names, i) for results in bm], - 'bytes_per_second': [nth(results.bytes_per_second, i) for results in bm], - 'items_per_second': [nth(results.items_per_second, i) for results in bm], - 'cpu_time': [nth(results.real_time, i) for results in bm], - 'real_time': [nth(results.real_time, i) for results in bm], - 'iterations': [nth(results.iterations, i) for results in bm], - 'threads': [nth(results.threads, i) for results in bm], - }) - table_sources.append(c) - selected_x_index = 8 # FIXME (currently 2000 pixels) - table_source = copy.deepcopy(table_sources[selected_x_index]) - relvalues = Toggle(label="Table: Relative values") - px_title = input_title("Table: number of pixels") - px_radiogroup = RadioGroup(labels=x_axis_values, active=selected_x_index) - table_inputs = [relvalues, px_title, px_radiogroup] - # - table_cols = [ - TableColumn(field='name', title='Name'), - TableColumn(field='bytes_per_second', title='Bytes/second'), - TableColumn(field='items_per_second', title='Items/second'), - TableColumn(field='cpu_time', title='CPU time'), - TableColumn(field='real_time', title='Real time'), - TableColumn(field='iterations', title='Iterations'), - TableColumn(field='threads', title='Threads'), - ] - data_table = DataTable(source=table_source, columns=table_cols, width=1200) - callback = CustomJS(args=dict( - radiogroup=px_radiogroup, - source=table_source, - table=table_sources - ), code=""" - console.log(`active=${radiogroup.active}`); - /*source.data=table[radiogroup.active];*/ - var nrows = source.data['name'].length; - var ts = table[radiogroup.active].data; - var names = ["name", "bytes_per_second", "items_per_second", "cpu_time", "real_time", "iterations", "threads"]; - var ncols = names.length; - console.log(`names=${names} nrows=${nrows} ncols=${ncols}`); - for(var i = 0; i < nrows; i++) { - for(var j = 0; j < ncols; ++j) { - var name = names[j]; - /*console.log(`i=${i} j=${j} name=${name}`);*/ - source.data[name][i] = ts[name][i]; - } - } - source.change.emit(); - """) - px_radiogroup.js_on_change('active', callback) - # lambda attr, old, new: log(f"attr={attr} old={old} new={new} active={px_radiogroup.active}")) - # - layout = column( - row(column(*inputs), p), - row(column(*table_inputs), data_table)) - show(layout) - - -def entry_ids(*bm, transform=None): - ids = {} - curr = 0 - for results in bm: - log(os.path.basename(results.filename), "------------------------------") - for entry in results.entries: - log(entry.name) - if transform is not None: - ids[entry.name] = transform(entry) - else: - if ids.get(entry.name) is None: - ids[entry.name] = curr - curr += 1 - return ids - - -class MatrixOrder(_enum): - row_major = "row_major" - col_major = "col_major" - @property - def short(self): - return "rm" if self is MatrixOrder.row_major else "cm" - @classmethod - def make(cls, s): - try: - return {"rm": cls.row_major, "cm": cls.col_major}[s] - except: - cls.err_unknown(s) - - -class MatrixLayout(_enum): - compact = "compact" - strided = "strided" - @classmethod - def make(cls, s): - try: - return cls[s] - except: - cls.err_unknown(s) - - -class DimensionBinding(_enum): - compile_time = "compile_time" - run_time = "run_time" - @property - def short(self): - return "ct" if self is DimensionBinding.compile_time else "rt" - @classmethod - def make(cls, s): - try: - return {"ct": cls.compile_time, "rt": cls.run_time}[s] - except: - cls.err_unknown(s) - - -class MultType(_enum): - naive = "naive" - avx2 = "avx2" - avx2_unroll2 = "avx2_unroll2" - avx2_unroll4 = "avx2_unroll4" - avx2_unroll8 = "avx2_unroll8" - @classmethod - def make(cls, s): - try: - s = s.replace("dotprod_", "").replace("_naive", "") - return cls[s] - except: - cls.err_unknown(s) - - -class MatrixMult(typing.NamedTuple): - title: str - num_pixels: int - num_channels: int - num_features: int - mult_type: MultType - layout: MatrixLayout - dim_binding: DimensionBinding - ret_order: MatrixOrder - lhs_order: MatrixOrder - rhs_order: MatrixOrder - - @classmethod - def make(cls, bm_title: str): - # eg: - # mult_naive_strided_ct_rm_cmcm<250, 8, 16> - # mult_naive_compact_rt_rm_rmrm/4000/8/16 - rxline = r'mult_(.*)[") - expect(v, 'title', 'naive_strided_ct_rm_cmcm') - expect(v, 'num_pixels', 250) - expect(v, 'num_channels', 8) - expect(v, 'num_features', 16) - expect(v, 'mult_type', MultType.naive) - expect(v, 'layout', MatrixLayout.strided) - expect(v, 'dim_binding', DimensionBinding.compile_time) - expect(v, 'ret_order', MatrixOrder.row_major) - expect(v, 'lhs_order', MatrixOrder.col_major) - expect(v, 'rhs_order', MatrixOrder.col_major) - v = MatrixMult.make("mult_dotprod_avx2_compact_rt_cm_rmcm/4000/16/8") - expect(v, 'title', 'dotprod_avx2_compact_rt_cm_rmcm') - expect(v, 'num_pixels', 4000) - expect(v, 'num_channels', 16) - expect(v, 'num_features', 8) - expect(v, 'mult_type', MultType.avx2) - expect(v, 'layout', MatrixLayout.compact) - expect(v, 'dim_binding', DimensionBinding.run_time) - expect(v, 'ret_order', MatrixOrder.col_major) - expect(v, 'lhs_order', MatrixOrder.row_major) - expect(v, 'rhs_order', MatrixOrder.col_major) - -_test() - - - -def formatMBps(value): - return value / 1e6 - - - -if __name__ == '__main__': - bms = sorted(sys.argv[2:]) - log(bms) - bms = BenchmarkPanel(bms, bm_meta_cls=MatrixMult.make) - fm = bms.runs[0].first.meta - title = f"Classifier multiplication, {fm.num_channels} channels, {fm.num_features} features: throughput (MB/s)" - bms.plot_all_lines(title) - exit() - main() diff --git a/thirdparty/ryml/ext/c4core/cmake/bm-xp/bm_run.py b/thirdparty/ryml/ext/c4core/cmake/bm-xp/bm_run.py deleted file mode 100644 index 812b64abe..000000000 --- a/thirdparty/ryml/ext/c4core/cmake/bm-xp/bm_run.py +++ /dev/null @@ -1,248 +0,0 @@ -import copy -import os.path - -# https://stackoverflow.com/questions/11351032/named-tuple-and-default-values-for-optional-keyword-arguments -from dataclasses import dataclass - -from munch import Munch - -from bm_util import load_json, first, _enum - - -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ - -class QuantityType(_enum): - neutral = "" - more_is_better = "more is better" - less_is_better = "less is better" - - @property - def comment(self): - return f" ({self.value})" if self.name else "" - - -_more = QuantityType.more_is_better -_less = QuantityType.less_is_better - - -@dataclass -class BenchmarkPropertyPlotData: - human_name: str = "" - human_name_short: str = "" - qty_type: QuantityType = QuantityType.neutral - - -class BenchmarkRun(Munch): - """results of an individual run""" - - def __init__(self, json_file: str, meta_class): - """ - meta_class is a class to extract property values from the benchmark run - """ - self._filename = json_file - props = load_json(json_file) - assert hasattr(props, "context") - assert hasattr(props, "benchmarks") - super().__init__(**props) - setattr(self, 'property_names', list(__class__._properties.keys())) - for bm in self.benchmarks: - if meta_class is not None: - setattr(bm, 'meta', meta_class.make(bm.name)) - else: - setattr(bm, 'meta', None) - - _properties = { - 'filename': None, - 'basename': None, - 'dirname': None, - 'meta': None, - 'shorttitle': None, - 'name': None, - 'run_name': None, - 'run_type': None, - 'repetitions': None, - 'repetition_index': None, - 'threads': BenchmarkPropertyPlotData('number of threads', 'threads'), - 'iterations': BenchmarkPropertyPlotData('number of iterations', 'iterations', _more), - 'real_time': BenchmarkPropertyPlotData('real time', 'real time', _less), - 'cpu_time': BenchmarkPropertyPlotData('CPU time', 'cpu time', _less), - 'real_time_ms': BenchmarkPropertyPlotData('real time', 'real time', _less), - 'cpu_time_ms': BenchmarkPropertyPlotData('CPU time', 'cpu time', _less), - 'time_unit': None, - 'bytes_per_second': BenchmarkPropertyPlotData('Bytes/s', 'B/s', _more), - 'items_per_second': BenchmarkPropertyPlotData('items/s', 'items/s', _more), - 'mega_bytes_per_second': BenchmarkPropertyPlotData('MBytes/s', 'MB/s', _more), - 'mega_items_per_second': BenchmarkPropertyPlotData('Mega items/s', 'Mega items/s', _more), - 'counters': None, - } - - def property_plot_data(self, property_name: str): - pd = copy.deepcopy(__class__._properties.get(property_name, BenchmarkPropertyPlotData())) - if property_name.endswith('_time'): - time_unit = first(self.entries).time_unit - pd.human_name += f' ({time_unit})' - pd.human_name_short += f' ({time_unit})' - elif property_name.endswith('_time_ms'): - pd.human_name += ' (ms)' - pd.human_name_short += ' (ms)' - return pd - - def extract_plot_series(self, property_name_or_getter, - relative_to_entry = None, - percent_of_entry = None, - ): - if isinstance(property_name_or_getter, str): - series = getattr(self, property_name_or_getter) - else: - series = property_name_or_getter(self) - series = list(series) - def getrefval(ref): - assert ref in self.entries, ref.name - pos = self.pos(ref) - assert pos in range(len(series)), (pos, len(series)) - return series[pos] - if relative_to_entry: - refval = getrefval(relative_to_entry) - for v in series: - yield v / refval - elif percent_of_entry: - refval = getrefval(percent_of_entry) - for v in series: - yield 100.0 * ((v - refval) / refval) - else: - for v in series: - yield v - - def extract_plot_series_with_threads(self, property_name_or_getter, - relative_to: str = None, - percent_of: str = None, - ): - series = self.extract_plot_series(property_name_or_getter, relative_to=relative_to, percent_of=percent_of) - for y, n in zip(series, self.threads): - yield y, n - - def pos(self, entry): - for i, e in enumerate(self.entries): - if e == entry: - return i - raise Exception("entry not found") - - @property - def filename(self): - return self._filename - - @property - def basename(self): - return os.path.basename(self._filename) - - @property - def dirname(self): - return os.path.dirname(self._filename) - - @property - def entries(self): - for entry in self.benchmarks: - yield entry - - @property - def meta(self): - for entry in self.benchmarks: - yield entry.meta - - @property - def names(self): - for entry in self.benchmarks: - yield entry.name - - @property - def run_names(self): - for entry in self.benchmarks: - yield entry.run_name - - @property - def run_types(self): - for entry in self.benchmarks: - yield entry.run_type - - @property - def repetitions(self): - for entry in self.benchmarks: - yield entry.repetitions - - @property - def repetition_indices(self): - for entry in self.benchmarks: - yield entry.repetition_index - - @property - def threads(self): - for entry in self.benchmarks: - yield entry.threads - - @property - def iterations(self): - for entry in self.benchmarks: - yield entry.iterations - - @property - def real_time(self): - for entry in self.benchmarks: - yield entry.real_time - - @property - def cpu_time(self): - for entry in self.benchmarks: - yield entry.cpu_time - - @property - def real_time_ms(self): - for entry in self.benchmarks: - assert entry.time_unit == "ns" - yield entry.real_time / 1e6 - - @property - def cpu_time_ms(self): - for entry in self.benchmarks: - assert entry.time_unit == "ns" - yield entry.cpu_time / 1e6 - - @property - def time_unit(self): - for entry in self.benchmarks: - yield entry.time_unit - - @property - def bytes_per_second(self): - for entry in self.benchmarks: - yield entry.bytes_per_second - - @property - def items_per_second(self): - for entry in self.benchmarks: - yield entry.items_per_second - - @property - def mega_bytes_per_second(self): - for entry in self.benchmarks: - yield entry.bytes_per_second / 1e6 - - @property - def mega_items_per_second(self): - for entry in self.benchmarks: - yield entry.items_per_second / 1e6 - - -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ - -class BenchmarkPanel: - - def __init__(self, runs, bm_meta_cls=None): - self.runs = [BenchmarkRun(a, bm_meta_cls) for a in runs] - - @property - def first_run(self): - return first(self.runs) diff --git a/thirdparty/ryml/ext/c4core/cmake/bm-xp/bm_serve.py b/thirdparty/ryml/ext/c4core/cmake/bm-xp/bm_serve.py deleted file mode 100644 index 6fc683b84..000000000 --- a/thirdparty/ryml/ext/c4core/cmake/bm-xp/bm_serve.py +++ /dev/null @@ -1,502 +0,0 @@ -import os -import sys -import argparse -import copy -import requests -import flask -import json -import re -import yaml -import shutil -import mmh3 -import itertools -import typing -import enum - -# https://stackoverflow.com/questions/11351032/named-tuple-and-default-values-for-optional-keyword-arguments -from dataclasses import dataclass - -from munch import Munch, munchify -from flask import render_template, redirect, url_for, send_from_directory -from markupsafe import escape - -from bm_util import * - - -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ - -class BenchmarkCollection: - - @staticmethod - def create_new(args): - dir = args.target - filename = os.path.join(dir, "bm.yml") - manifest = os.path.join(dir, "manifest.yml") - if not os.path.exists(dir): - os.makedirs(dir) - shutil.copyfile(args.filename, filename) - dump_yml(load_yml("""{runs: {}, bm: {}}"""), manifest) - return __class__(dir) - - def __init__(self, dir): - if not os.path.exists(dir): - raise Exception(f"not found: {dir}") - self.dir = os.path.abspath(dir) - self.runs_dir = os.path.join(self.dir, "runs") - self.manifest = os.path.join(self.dir, "manifest.yml") - self.filename = os.path.join(self.dir, "bm.yml") - self.specs = munchify(load_yml_file(self.filename)) - self.manif = munchify(load_yml_file(self.manifest)) - - def add(self, results_dir): - results_dir = os.path.abspath(results_dir) - dst_dir, meta = self._read_run(results_dir) - self._add_run(results_dir, dst_dir, meta) - dump_yml(self.manif, self.manifest) - - def _read_run(self, results_dir): - log("adding run...") - id = f"{len(self.manif.runs.keys()):05d}" - log(f"adding run: id={id}") - meta = ResultMeta.load(results_dir) - dst_dir = os.path.join(self.runs_dir, meta.name) - return dst_dir, meta - - def _add_run(self, results_dir, dst_dir, meta): - cats = self._add_meta_categories(meta) - for filename in ("meta.yml", - "CMakeCCompiler.cmake", - "CMakeCXXCompiler.cmake", - "CMakeSystem.cmake", - "compile_commands.json"): - filename = os.path.join(results_dir, filename) - if os.path.exists(filename): - copy_file_to_dir(filename, dst_dir) - else: - if not filename.endswith("compile_commands.json"): - raise Exception(f"wtf???? {filename}") - for name, specs in self.specs.bm.items(): - if not hasattr(specs, 'variants'): - filename = chk(f"{results_dir}/{name}.json") - dst = copy_file_to_dir(filename, dst_dir) - self._add_bm_run(name, specs, meta) - else: - for t in specs.variants: - tname = f"{name}-{t}" - filename = chk(f"{results_dir}/{tname}.json") - dst = copy_file_to_dir(filename, dst_dir) - self._add_bm_run(tname, specs, meta) - - def _add_bm_run(self, name, specs, meta): - if name not in self.manif.bm.keys(): - self.manif.bm[name] = Munch(specs=specs, entries=[]) - entry = self.manif.bm[name] - entry.specs = specs - if meta.name not in entry.entries: - entry.entries.append(meta.name) - - def _add_meta_categories(self, meta): - run = Munch() - for catname in ('commit', 'cpu', 'system', 'build'): - meta_item = getattr(meta, catname) - self._add_item_to_category(meta.name, catname, meta_item) - run[catname] = meta_item.storage_id - # build specs are too verbose; remove them - self.manif.build[meta.build.storage_id].specs = Munch() - self.manif.runs[meta.name] = run - - def _add_item_to_category(self, run, category_name, item): - if not hasattr(self.manif, category_name): - setattr(self.manif, category_name, Munch()) - category = getattr(self.manif, category_name) - if item.storage_id not in category.keys(): - category[item.storage_id] = Munch(specs=item, entries=[]) - entry = category[item.storage_id] - entry.specs = item - if run not in entry.entries: - entry.entries.append(run) - - -# ----------------------------------------------------------------------------- -# ----------------------------------------------------------------------------- -# ----------------------------------------------------------------------------- - -class ResultMeta(Munch): - - def __init__(self, results_dir, cmakecache, build_type): - super().__init__(self) - self.date = __class__.get_date() - self.commit = __class__.get_commit(results_dir) - self.cpu = __class__.get_cpu_info() - self.system = __class__.get_sys_info() - self.build = __class__.get_build_info(cmakecache, build_type) - self.name = self._get_name() - - @staticmethod - def load(results_dir): - results_dir = os.path.join(os.path.abspath(results_dir), "meta.yml") - data = load_yml_file(results_dir) - return munchify(data) - - def save(self, results_dir): - out = os.path.join(results_dir, "meta.yml") - log("saving meta:", out) - dump_yml(self, out) - self.build.save(results_dir) - - @staticmethod - def get_date(): - import datetime - now = datetime.datetime.now() - return now.strftime("%Y%m%d-%H%M%S") - - def _get_name(self): - commit = self.commit.storage_name - cpu = self.cpu.storage_name - sys = self.system.storage_name - build = self.build.storage_name - name = f"{commit}/{cpu}-{sys}-{build}" - return name - - @staticmethod - def get_commit(results_dir): - import git - repo = git.Repo(results_dir, search_parent_directories=True) - commit = repo.head.commit - commit = {p: str(getattr(commit, p)) - for p in ('message', 'summary', 'name_rev', - 'author', - 'authored_datetime', - 'committer', - 'committed_datetime',)} - commit = Munch(commit) - commit.message = commit.message.strip() - commit.sha1 = commit.name_rev[:7] - spl = commit.authored_datetime.split(" ") - date = re.sub(r'-', '', spl[0]) - time = re.sub(r'(\d+):(\d+):(\d+).*', r'\1\2\3', spl[1]) - commit.storage_id = commit.sha1 - commit.storage_name = f"git{date}_{time}-{commit.sha1}" - return commit - - @staticmethod - def get_cpu_info(): - import cpuinfo - nfo = cpuinfo.get_cpu_info() - nfo = Munch(nfo) - for a in ('cpu_version', 'cpu_version_string', 'python_version'): - if hasattr(nfo, a): - delattr(nfo, a) - for a in ('arch_string_raw', 'brand_raw', 'hardware_raw', 'vendor_id_raw'): - if not hasattr(nfo, a): - setattr(nfo, a, '') - nfo.storage_id = myhash( - nfo.arch_string_raw, nfo.brand_raw, nfo.hardware_raw, nfo.vendor_id_raw, - nfo.arch, nfo.bits, nfo.count, nfo.family, nfo.model, nfo.stepping, - ",".join(nfo.flags), nfo.hz_advertised_friendly, - nfo.l2_cache_associativity, - nfo.l2_cache_line_size, - nfo.l2_cache_size, - nfo.l3_cache_size, - *optionals('l1_data_cache_size', 'l1_instruction_cache_size') - ) - nfo.storage_name = f"{nfo.arch.lower()}_{nfo.storage_id}" - return nfo - - @staticmethod - def get_sys_info(): - import platform - uname = platform.uname() - nfo = Munch( - sys_platform=sys.platform, - sys=platform.system(), - uname=Munch( - machine=uname.machine, - node=uname.node, - release=uname.release, - system=uname.system, - version=uname.version, - ) - ) - nfo.storage_id = myhash( - nfo.sys_platform, - nfo.uname.machine, - ) - nfo.storage_name = f"{nfo.sys_platform}_{nfo.storage_id}" - return nfo - - @staticmethod - def get_build_info(cmakecache_txt, buildtype): - nfo = CMakeCache(cmakecache_txt) - def _btflags(name): - return (getattr(nfo, name), getattr(nfo, f"{name}_{buildtype.upper()}")) - nfo.storage_id = myhash( - buildtype, - nfo.CMAKE_CXX_COMPILER_ID, - nfo.CMAKE_CXX_COMPILER_VERSION, - nfo.CMAKE_CXX_COMPILER_VERSION_INTERNAL, - nfo.CMAKE_CXX_COMPILER_ABI, - nfo.CMAKE_CXX_SIZEOF_DATA_PTR, - nfo.CMAKE_C_COMPILER_ID, - nfo.CMAKE_C_COMPILER_VERSION, - nfo.CMAKE_C_COMPILER_VERSION_INTERNAL, - nfo.CMAKE_C_COMPILER_ABI, - nfo.CMAKE_C_SIZEOF_DATA_PTR, - *_btflags("CMAKE_CXX_FLAGS"), - *_btflags("CMAKE_C_FLAGS"), - *_btflags("CMAKE_STATIC_LINKER_FLAGS"), - *_btflags("CMAKE_SHARED_LINKER_FLAGS"), - ) - # - ccname = nfo.CMAKE_CXX_COMPILER_ID.lower() - if ccname == "gnu": - ccname = "gcc" - ccname += nfo.CMAKE_CXX_COMPILER_VERSION.lower() - # - if nfo.CMAKE_C_SIZEOF_DATA_PTR == "4": - bits = "32bit" - elif nfo.CMAKE_C_SIZEOF_DATA_PTR == "8": - bits = "64bit" - else: - raise Exception("unknown architecture") - # - nfo.storage_name = f"{bits}_{buildtype}_{ccname}_{nfo.storage_id}" - return nfo - - -# ----------------------------------------------------------------------------- -# ----------------------------------------------------------------------------- -# ----------------------------------------------------------------------------- - -class CMakeCache(Munch): - - def __init__(self, cmakecache_txt): - import glob - for line in iter_cmake_lines(cmakecache_txt): - spl = line.split("=") - if len(spl) < 2: - continue - k, ty = spl[0].split(":") - v = "=".join(spl[1:]).strip() - setattr(self, k, v) - bdir = os.path.dirname(os.path.abspath(cmakecache_txt)) - self._c_compiler_file = sorted(glob.glob(f"{bdir}/CMakeFiles/*/CMakeCCompiler.cmake"))[-1] # get the last - self._cxx_compiler_file = sorted(glob.glob(f"{bdir}/CMakeFiles/*/CMakeCXXCompiler.cmake"))[-1] # get the last - self._system_file = sorted(glob.glob(f"{bdir}/CMakeFiles/*/CMakeSystem.cmake"))[-1] # get the last - self._load_cmake_file(self._c_compiler_file) - self._load_cmake_file(self._cxx_compiler_file) - ccomfile = f"{bdir}/compile_commands.json" - self._compile_commands_file = ccomfile if os.path.exists(ccomfile) else None - - def _load_cmake_file(self, filename): - for line in iter_cmake_lines(filename): - if not line.startswith("set("): - continue - k = re.sub(r"set\((.*)\ +(.*)\)", r"\1", line) - v = re.sub(r"set\((.*)\ +(.*)\)", r"\2", line) - v = v.strip('"').strip("'").strip() - setattr(self, k, v) - - def save(self, results_dir): - copy_file_to_dir(self._c_compiler_file, results_dir) - copy_file_to_dir(self._cxx_compiler_file, results_dir) - copy_file_to_dir(self._system_file, results_dir) - if self._compile_commands_file is not None: - copy_file_to_dir(self._compile_commands_file, results_dir) - - -def iter_cmake_lines(filename): - with open(filename) as f: - for line in f.readlines(): - line = line.strip() - if line.startswith("#") or line.startswith("//") or len(line) == 0: - continue - yield line - - -# -------------------------------------------------------- - - -def get_manifest(args): - bmdir = os.path.abspath(args.bmdir) - if not args.manifest: - manifest_yml = os.path.join(bmdir, "manifest.yml") - else: - if not os.path.isabs(args.manifest): - manifest_yml = os.path.join(os.getcwd(), args.manifest) - manifest_json = os.path.join(os.path.dirname(manifest.yml), "manifest.json") - manifest = load_yml_file(manifest_yml) - dump_json(manifest, manifest_json) - return manifest - - -def add_results(args): - log("adding results:", args.results) - col = BenchmarkCollection(args.target) - col.add(args.results) - - -def add_meta(args): - log("adding bm run metadata to results dir:", args.results) - meta = ResultMeta(results_dir=args.results, - cmakecache=args.cmakecache, - build_type=args.build_type) - meta.save(args.results) - log("adding bm run metadata to results dir: success!") - - -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ - -app = flask.Flask(__name__, template_folder='template') - -def _setup_app(args): - def _s(prop, val): - assert not hasattr(app, prop), prop - setattr(app, prop, val) - _s('args', args) - _s('manifest', get_manifest(args)) - if args.debug: - app.config["DEBUG"] = True - - -def freeze(args): - "https://pythonhosted.org/Frozen-Flask/" - from flask_frozen import Freezer - _setup_app(args) - freezer = Freezer(app) - freezer.freeze(debug=args.debug) - - -def serve(args): - _setup_app(args) - app.run(host=args.host, port=args.port, debug=args.debug) - - -@app.route("/") -def home(): - log("requested home") - return render_template("index.html") - - -@app.route("/") -def other_(path): - path = escape(path) - d = app.args.bmdir - log("requested other path:", path, "---", os.path.join(d, path)) - return send_from_directory(d, path) - - -@app.route("/static/") -def static_(path): - path = escape(path) - d = os.path.join(app.args.bmdir, "static") - log("requested static path:", path, "---", os.path.join(d, path)) - return send_from_directory(d, path, cache_timeout=1) # timeout in seconds - - -@app.route("/bm///") -def bm_(commit, run, resultjson): - commit = escape(commit) - run = escape(run) - resultjson = escape(resultjson) - d = os.path.join(app.args.bmdir, "runs", commit, run) - log("requested result:", os.path.join(d, resultjson)) - return send_from_directory(d, resultjson, cache_timeout=1) # timeout in seconds - - -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ - -def download_deps(): - deps = [ - "https://code.jquery.com/jquery-3.3.1.js", - "https://code.jquery.com/jquery-3.3.1.js", - "https://code.jquery.com/ui/1.12.1/jquery-ui.js", - "https://cdn.datatables.net/1.10.20/js/jquery.dataTables.js", - "https://cdn.datatables.net/1.10.20/js/jquery.dataTables.min.js", - "https://cdn.datatables.net/1.10.20/css/jquery.dataTables.css", - "https://cdn.datatables.net/1.10.20/css/jquery.dataTables.min.css", - "https://www.chartjs.org/dist/2.9.1/Chart.min.js", - #("https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.3.2/styles/github.css", "highlight.github.css"), - ("https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.3.2/styles/github.min.css", "highlight.github.min.css"), - #"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.3.2/highlight.js", - "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.3.2/highlight.min.js", - ] - for src in deps: - if type(src) == str: - base = os.path.basename(src) - else: - src, base = src - dst = f"{os.getcwd()}/static/{base}" - download_url(src, dst) - - -def download_url(url, dst): - log("download url:", url, "--->", dst) - req = requests.get(url, stream=True) - if req.status_code == 200: - sz = 0 - with open(dst, 'wb') as f: - for chunk in req: - f.write(chunk) - sz += len(chunk) - log(f"........ finished: {sz}B") - else: - log(f" error:", req.status_code, url) - - - -def main(): - def _common_args(parser): - parser.add_argument("-m", "--manifest", type=str, default="", help="enable debug mode") - parser.add_argument("--debug", action="store_true", help="enable debug mode") - # - parser = argparse.ArgumentParser(description="Browse benchmark results", prog="bm") - _common_args(parser) - subparsers = parser.add_subparsers() - # - sp = subparsers.add_parser("create", help="create benchmark collection") - _common_args(sp) - sp.add_argument("--debug", action="store_true", help="enable debug mode") - sp.add_argument("filename", type=str, help="the YAML file with the benchmark specs") - sp.add_argument("target", type=str, help="the directory to store the results") - # - sp = subparsers.add_parser("meta", help="get the required meta-information: cpu info, commit data") - _common_args(sp) - sp.add_argument("--debug", action="store_true", help="enable debug mode") - sp.add_argument("results", type=str, help="the directory with the results") - sp.add_argument("cmakecache", type=str, help="the path to the CMakeCache.txt file used to build the benchmark binaries") - sp.add_argument("build_type", type=str, help="the build type, eg Release Debug MinSizeRel RelWithDebInfo") - # - sp = subparsers.add_parser("add", help="add benchmark results") - _common_args(sp) - sp.add_argument("--debug", action="store_true", help="enable debug mode") - sp.add_argument("results", type=str, help="the directory with the results") - sp.add_argument("target", type=str, help="the directory to store the results") - # - sp = subparsers.add_parser("serve", help="serve benchmark results") - _common_args(sp) - sp.add_argument("--debug", action="store_true", help="enable debug mode") - sp.add_argument("bmdir", type=os.path.abspath, default=os.getcwd(), help="the directory with the results. default=.") - sp.add_argument("-H", "--host", type=str, default="localhost", help="host. default=%(default)s") - sp.add_argument("-p", "--port", type=int, default=8000, help="port. default=%(default)s") - # - sp = subparsers.add_parser("export", help="export static html") - sp.set_defaults(func=freeze) - sp.add_argument("bmdir", type=os.path.abspath, default=os.getcwd(), help="the directory with the results. default=.") - _common_args(sp) - # - sp = subparsers.add_parser("deps", help="install server dependencies") - sp.set_defaults(func=lambda _: download_deps()) - sp.add_argument("--debug", action="store_true", help="enable debug mode") - _common_args(sp) - # - args = parser.parse_args(sys.argv[1:] if len(sys.argv) > 1 else ["serve"]) - if args.debug: - log(args) - args.func(args) diff --git a/thirdparty/ryml/ext/c4core/cmake/bm-xp/bm_util.py b/thirdparty/ryml/ext/c4core/cmake/bm-xp/bm_util.py deleted file mode 100644 index 7c7c2891e..000000000 --- a/thirdparty/ryml/ext/c4core/cmake/bm-xp/bm_util.py +++ /dev/null @@ -1,147 +0,0 @@ -import os -import json -import yaml -import shutil -import mmh3 -import itertools -import munch -import enum - - -# -------------------------------------------------------- - -class _enum(enum.Enum): - def __str__(self): - return str(self.name) - - @property - def short(self): - return self.name - - @classmethod - def make(cls, s): - try: - return cls[s] - except: - cls.err_unknown(s) - - @classmethod - def err_unknown(cls, s): - raise Exception(f"unknown {__class__.__name__}: {s}") - - -class FundamentalTypes(_enum): - float = "float" - double = "double" - int8_t = "int8_t" - uint8_t = "uint8_t" - int16_t = "int16_t" - uint16_t = "uint16_t" - int32_t = "int32_t" - uint32_t = "uint32_t" - int64_t = "int64_t" - uint64_t = "uint64_t" - @property - def short(self): - return self.name.replace("uint", "u").replace("int", "i").replace("_t", "") - - -# -------------------------------------------------------- - -def log(*args, **kwargs): - print(*args, **kwargs, flush=True) - - -def myhash_combine(curr, value): - return curr ^ (value + 0x9e3779b9 + (curr << 6) + (curr >> 2)) - - -def first(iterable): - """Returns the first item""" - if isinstance(iterable, list): - return iterable[0] - return next(iterable) - - -def chain(*iterables): - for it in iterables: - for elm in it: - yield elm - - -def nth(iterable, n, default=None): - """Returns the nth item or a default value""" - return next(itertools.islice(iterable, n, None), default) - - -def optionals(obj, *attrs): - ret = [] - for attr in attrs: - if not hasattr(obj, attr): - log("attr not present:", attr) - continue - ret.append(getattr(obj, attr)) - return ret - - -def myhash(*args): - h = 137597 - for a in args: - if isinstance(a, str): - if a == "": - continue - b = bytes(a, "utf8") - else: - b = bytes(a) - hb = mmh3.hash(b, signed=False) - h = myhash_combine(h, hb) - s = hex(h) - return s[2:min(10, len(s))] - - -def copy_file_to_dir(file, dir): - dir = os.path.abspath(dir) - src = os.path.abspath(file) - dst = f"{dir}/{os.path.basename(src)}" - if not os.path.exists(dir): - os.makedirs(dir) - if os.path.exists(dst): - os.remove(dst) - log("copy:", src, "-->", dst) - shutil.copy(src, dst) - return dst - - -def chk(f): - log("looking for file:", f) - assert os.path.exists(f), f - return f - - -def load_yml_file(filename): - if not os.path.exists(filename): - raise Exception(f"not found: {filename}") - with open(filename) as f: - return load_yml(f.read()) - - -def dump_yml(data, filename): - with open(filename, "w") as f: - yaml.safe_dump(data, f) - - -def load_yml(yml): - return munch.munchify(yaml.safe_load(yml)) - - -def dump_json(data, filename): - with open(filename, "w") as f: - f.write(json.dumps(data, indent=2, sort_keys=True)) - - -def load_json(filename): - with open(filename, "r") as f: - try: - return munch.munchify(json.load(f)) - except Exception as exc: - raise Exception(f"could not load file: {filename}: {exc}") diff --git a/thirdparty/ryml/ext/c4core/cmake/bm-xp/example_c4core.py b/thirdparty/ryml/ext/c4core/cmake/bm-xp/example_c4core.py deleted file mode 100644 index 3db4175cb..000000000 --- a/thirdparty/ryml/ext/c4core/cmake/bm-xp/example_c4core.py +++ /dev/null @@ -1,1061 +0,0 @@ -import os -import sys -import argparse -import copy -import requests -import flask -import json -import re -import yaml -import shutil -import mmh3 -from itertools import islice - -from munch import Munch, munchify -from flask import render_template, redirect, url_for, send_from_directory -from markupsafe import escape - - -def log(*args, **kwargs): - print(*args, **kwargs, flush=True) - - -def myhash_combine(curr, value): - return curr ^ (value + 0x9e3779b9 + (curr<<6) + (curr>>2)) - - -def nth(iterable, n, default=None): - "Returns the nth item or a default value" - return next(islice(iterable, n, None), default) - - -def optionals(obj, *attrs): - ret = [] - for attr in attrs: - if not hasattr(obj, attr): - log("attr not present:", attr) - continue - ret.append(getattr(obj, attr)) - return ret - - -def myhash(*args): - h = 137597 - for a in args: - if isinstance(a, str): - if a == "": - continue - b = bytes(a, "utf8") - else: - b = bytes(a) - hb = mmh3.hash(b, signed=False) - h = myhash_combine(h, hb) - s = hex(h) - return s[2:min(10, len(s))] - - -def copy_file_to_dir(file, dir): - dir = os.path.abspath(dir) - src = os.path.abspath(file) - dst = f"{dir}/{os.path.basename(src)}" - if not os.path.exists(dir): - os.makedirs(dir) - if os.path.exists(dst): - os.remove(dst) - log("copy:", src, "-->", dst) - shutil.copy(src, dst) - return dst - - -def chk(f): - log(f"looking for file:", f) - assert os.path.exists(f), f - return f - - -def load_yml_file(filename): - if not os.path.exists(filename): - raise Exception(f"not found: {filename}") - with open(filename) as f: - return load_yml(f.read()) - - -def dump_yml(data, filename): - with open(filename, "w") as f: - yaml.safe_dump(data, f) - - -def load_yml(yml): - return munchify(yaml.safe_load(yml)) - - -def dump_json(data, filename): - with open(filename, "w") as f: - f.write(json.dumps(data, indent=2, sort_keys=True)) - - -def load_json(filename): - with open(filename, "r") as f: - try: - return munchify(json.load(f)) - except Exception as exc: - raise Exception(f"could not load file: {filename}: {exc}") - - -def main(): - def _common_args(parser): - parser.add_argument("-m", "--manifest", type=str, default="", help="enable debug mode") - parser.add_argument("--debug", action="store_true", help="enable debug mode") - # - parser = argparse.ArgumentParser(description="Browse benchmark results", prog="bm") - _common_args(parser) - subparsers = parser.add_subparsers() - # - sp = subparsers.add_parser("create", help="create benchmark collection") - _common_args(sp) - sp.add_argument("--debug", action="store_true", help="enable debug mode") - sp.add_argument("filename", type=str, help="the YAML file with the benchmark specs") - sp.add_argument("target", type=str, help="the directory to store the results") - # - sp = subparsers.add_parser("meta", help="get the required meta-information: cpu info, commit data") - _common_args(sp) - sp.add_argument("--debug", action="store_true", help="enable debug mode") - sp.add_argument("results", type=str, help="the directory with the results") - sp.add_argument("cmakecache", type=str, help="the path to the CMakeCache.txt file used to build the benchmark binaries") - sp.add_argument("build_type", type=str, help="the build type, eg Release Debug MinSizeRel RelWithDebInfo") - # - sp = subparsers.add_parser("add", help="add benchmark results") - _common_args(sp) - sp.add_argument("--debug", action="store_true", help="enable debug mode") - sp.add_argument("results", type=str, help="the directory with the results") - sp.add_argument("target", type=str, help="the directory to store the results") - # - sp = subparsers.add_parser("serve", help="serve benchmark results") - _common_args(sp) - sp.add_argument("--debug", action="store_true", help="enable debug mode") - sp.add_argument("bmdir", type=os.path.abspath, default=os.getcwd(), help="the directory with the results. default=.") - sp.add_argument("-H", "--host", type=str, default="localhost", help="host. default=%(default)s") - sp.add_argument("-p", "--port", type=int, default=8000, help="port. default=%(default)s") - # - sp = subparsers.add_parser("export", help="export static html") - sp.set_defaults(func=freeze) - sp.add_argument("bmdir", type=os.path.abspath, default=os.getcwd(), help="the directory with the results. default=.") - _common_args(sp) - # - sp = subparsers.add_parser("deps", help="install server dependencies") - sp.set_defaults(func=lambda _: download_deps()) - sp.add_argument("--debug", action="store_true", help="enable debug mode") - _common_args(sp) - # - args = parser.parse_args(sys.argv[1:] if len(sys.argv) > 1 else ["serve"]) - if args.debug: - log(args) - args.func(args) - - -def get_manifest(args): - bmdir = os.path.abspath(args.bmdir) - if not args.manifest: - manifest_yml = os.path.join(bmdir, "manifest.yml") - else: - if not os.path.isabs(args.manifest): - manifest_yml = os.path.join(os.getcwd(), args.manifest) - manifest_json = os.path.join(os.path.dirname(manifest.yml), "manifest.json") - manifest = load_yml_file(manifest_yml) - dump_json(manifest, manifest_json) - return manifest - - -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ - -app = flask.Flask(__name__, - template_folder='template') - - -def _setup_app(args): - def _s(prop, val): - assert not hasattr(app, prop), prop - setattr(app, prop, val) - _s('args', args) - _s('manifest', get_manifest(args)) - if args.debug: - app.config["DEBUG"] = True - - -def freeze(args): - "https://pythonhosted.org/Frozen-Flask/" - from flask_frozen import Freezer - _setup_app(args) - freezer = Freezer(app) - freezer.freeze(debug=args.debug) - - -def serve(args): - _setup_app(args) - app.run(host=args.host, port=args.port, debug=args.debug) - - -@app.route("/") -def home(): - log("requested home") - return render_template("index.html") - - -@app.route("/") -def other_(path): - path = escape(path) - d = app.args.bmdir - log("requested other path:", path, "---", os.path.join(d, path)) - return send_from_directory(d, path) - - -@app.route("/static/") -def static_(path): - path = escape(path) - d = os.path.join(app.args.bmdir, "static") - log("requested static path:", path, "---", os.path.join(d, path)) - return send_from_directory(d, path, cache_timeout=1) # timeout in seconds - - -@app.route("/bm///") -def bm_(commit, run, resultjson): - commit = escape(commit) - run = escape(run) - resultjson = escape(resultjson) - d = os.path.join(app.args.bmdir, "runs", commit, run) - log("requested result:", os.path.join(d, resultjson)) - return send_from_directory(d, resultjson, cache_timeout=1) # timeout in seconds - - -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ - -def download_deps(): - deps = [ - "https://code.jquery.com/jquery-3.3.1.js", - "https://code.jquery.com/jquery-3.3.1.js", - "https://code.jquery.com/ui/1.12.1/jquery-ui.js", - "https://cdn.datatables.net/1.10.20/js/jquery.dataTables.js", - "https://cdn.datatables.net/1.10.20/js/jquery.dataTables.min.js", - "https://cdn.datatables.net/1.10.20/css/jquery.dataTables.css", - "https://cdn.datatables.net/1.10.20/css/jquery.dataTables.min.css", - "https://www.chartjs.org/dist/2.9.1/Chart.min.js", - #("https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.3.2/styles/github.css", "highlight.github.css"), - ("https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.3.2/styles/github.min.css", "highlight.github.min.css"), - #"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.3.2/highlight.js", - "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.3.2/highlight.min.js", - ] - for src in deps: - if type(src) == str: - base = os.path.basename(src) - else: - src, base = src - dst = f"{os.getcwd()}/static/{base}" - download_url(src, dst) - - -def download_url(url, dst): - log("download url:", url, "--->", dst) - req = requests.get(url, stream=True) - if req.status_code == 200: - sz = 0 - with open(dst, 'wb') as f: - for chunk in req: - f.write(chunk) - sz += len(chunk) - log(f"........ finished: {sz}B") - else: - log(f" error:", req.status_code, url) - - -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ - -class BenchmarkCollection: - - @staticmethod - def create_new(args): - dir = args.target - filename = os.path.join(dir, "bm.yml") - manifest = os.path.join(dir, "manifest.yml") - if not os.path.exists(dir): - os.makedirs(dir) - shutil.copyfile(args.filename, filename) - dump_yml(load_yml("""{runs: {}, bm: {}}"""), manifest) - return __class__(dir) - - def __init__(self, dir): - if not os.path.exists(dir): - raise Exception(f"not found: {dir}") - self.dir = os.path.abspath(dir) - self.runs_dir = os.path.join(self.dir, "runs") - self.manifest = os.path.join(self.dir, "manifest.yml") - self.filename = os.path.join(self.dir, "bm.yml") - self.specs = munchify(load_yml_file(self.filename)) - self.manif = munchify(load_yml_file(self.manifest)) - - def add(self, results_dir): - results_dir = os.path.abspath(results_dir) - dst_dir, meta = self._read_run(results_dir) - self._add_run(results_dir, dst_dir, meta) - dump_yml(self.manif, self.manifest) - - def _read_run(self, results_dir): - log("adding run...") - id = f"{len(self.manif.runs.keys()):05d}" - log(f"adding run: id={id}") - meta = ResultMeta.load(results_dir) - dst_dir = os.path.join(self.runs_dir, meta.name) - return dst_dir, meta - - def _add_run(self, results_dir, dst_dir, meta): - cats = self._add_meta_categories(meta) - for filename in ("meta.yml", - "CMakeCCompiler.cmake", - "CMakeCXXCompiler.cmake", - "CMakeSystem.cmake", - "compile_commands.json"): - filename = os.path.join(results_dir, filename) - if os.path.exists(filename): - copy_file_to_dir(filename, dst_dir) - else: - if not filename.endswith("compile_commands.json"): - raise Exception(f"wtf???? {filename}") - for name, specs in self.specs.bm.items(): - if not hasattr(specs, 'variants'): - filename = chk(f"{results_dir}/{name}.json") - dst = copy_file_to_dir(filename, dst_dir) - self._add_bm_run(name, specs, meta) - else: - for t in specs.variants: - tname = f"{name}-{t}" - filename = chk(f"{results_dir}/{tname}.json") - dst = copy_file_to_dir(filename, dst_dir) - self._add_bm_run(tname, specs, meta) - - def _add_bm_run(self, name, specs, meta): - if name not in self.manif.bm.keys(): - self.manif.bm[name] = Munch(specs=specs, entries=[]) - entry = self.manif.bm[name] - entry.specs = specs - if meta.name not in entry.entries: - entry.entries.append(meta.name) - - def _add_meta_categories(self, meta): - run = Munch() - for catname in ('commit', 'cpu', 'system', 'build'): - meta_item = getattr(meta, catname) - self._add_item_to_category(meta.name, catname, meta_item) - run[catname] = meta_item.storage_id - # build specs are too verbose; remove them - self.manif.build[meta.build.storage_id].specs = Munch() - self.manif.runs[meta.name] = run - - def _add_item_to_category(self, run, category_name, item): - if not hasattr(self.manif, category_name): - setattr(self.manif, category_name, Munch()) - category = getattr(self.manif, category_name) - if item.storage_id not in category.keys(): - category[item.storage_id] = Munch(specs=item, entries=[]) - entry = category[item.storage_id] - entry.specs = item - if run not in entry.entries: - entry.entries.append(run) - - -# ----------------------------------------------------------------------------- -# ----------------------------------------------------------------------------- -# ----------------------------------------------------------------------------- - -class ResultMeta(Munch): - - def __init__(self, results_dir, cmakecache, build_type): - super().__init__(self) - self.date = __class__.get_date() - self.commit = __class__.get_commit(results_dir) - self.cpu = __class__.get_cpu_info() - self.system = __class__.get_sys_info() - self.build = __class__.get_build_info(cmakecache, build_type) - self.name = self._get_name() - - @staticmethod - def load(results_dir): - results_dir = os.path.join(os.path.abspath(results_dir), "meta.yml") - data = load_yml_file(results_dir) - return munchify(data) - - def save(self, results_dir): - out = os.path.join(results_dir, "meta.yml") - log("saving meta:", out) - dump_yml(self, out) - self.build.save(results_dir) - - @staticmethod - def get_date(): - import datetime - now = datetime.datetime.now() - return now.strftime("%Y%m%d-%H%M%S") - - def _get_name(self): - commit = self.commit.storage_name - cpu = self.cpu.storage_name - sys = self.system.storage_name - build = self.build.storage_name - name = f"{commit}/{cpu}-{sys}-{build}" - return name - - @staticmethod - def get_commit(results_dir): - import git - repo = git.Repo(results_dir, search_parent_directories=True) - commit = repo.head.commit - commit = {p: str(getattr(commit, p)) - for p in ('message', 'summary', 'name_rev', - 'author', - 'authored_datetime', - 'committer', - 'committed_datetime',)} - commit = Munch(commit) - commit.message = commit.message.strip() - commit.sha1 = commit.name_rev[:7] - spl = commit.authored_datetime.split(" ") - date = re.sub(r'-', '', spl[0]) - time = re.sub(r'(\d+):(\d+):(\d+).*', r'\1\2\3', spl[1]) - commit.storage_id = commit.sha1 - commit.storage_name = f"git{date}_{time}-{commit.sha1}" - return commit - - @staticmethod - def get_cpu_info(): - import cpuinfo - nfo = cpuinfo.get_cpu_info() - nfo = Munch(nfo) - for a in ('cpu_version', 'cpu_version_string', 'python_version'): - if hasattr(nfo, a): - delattr(nfo, a) - for a in ('arch_string_raw', 'brand_raw', 'hardware_raw', 'vendor_id_raw'): - if not hasattr(nfo, a): - setattr(nfo, a, '') - nfo.storage_id = myhash( - nfo.arch_string_raw, nfo.brand_raw, nfo.hardware_raw, nfo.vendor_id_raw, - nfo.arch, nfo.bits, nfo.count, nfo.family, nfo.model, nfo.stepping, - ",".join(nfo.flags), nfo.hz_advertised_friendly, - nfo.l2_cache_associativity, - nfo.l2_cache_line_size, - nfo.l2_cache_size, - nfo.l3_cache_size, - *optionals('l1_data_cache_size', 'l1_instruction_cache_size') - ) - nfo.storage_name = f"{nfo.arch.lower()}_{nfo.storage_id}" - return nfo - - @staticmethod - def get_sys_info(): - import platform - uname = platform.uname() - nfo = Munch( - sys_platform=sys.platform, - sys=platform.system(), - uname=Munch( - machine=uname.machine, - node=uname.node, - release=uname.release, - system=uname.system, - version=uname.version, - ) - ) - nfo.storage_id = myhash( - nfo.sys_platform, - nfo.uname.machine, - ) - nfo.storage_name = f"{nfo.sys_platform}_{nfo.storage_id}" - return nfo - - @staticmethod - def get_build_info(cmakecache_txt, buildtype): - nfo = CMakeCache(cmakecache_txt) - def _btflags(name): - return (getattr(nfo, name), getattr(nfo, f"{name}_{buildtype.upper()}")) - nfo.storage_id = myhash( - buildtype, - nfo.CMAKE_CXX_COMPILER_ID, - nfo.CMAKE_CXX_COMPILER_VERSION, - nfo.CMAKE_CXX_COMPILER_VERSION_INTERNAL, - nfo.CMAKE_CXX_COMPILER_ABI, - nfo.CMAKE_CXX_SIZEOF_DATA_PTR, - nfo.CMAKE_C_COMPILER_ID, - nfo.CMAKE_C_COMPILER_VERSION, - nfo.CMAKE_C_COMPILER_VERSION_INTERNAL, - nfo.CMAKE_C_COMPILER_ABI, - nfo.CMAKE_C_SIZEOF_DATA_PTR, - *_btflags("CMAKE_CXX_FLAGS"), - *_btflags("CMAKE_C_FLAGS"), - *_btflags("CMAKE_STATIC_LINKER_FLAGS"), - *_btflags("CMAKE_SHARED_LINKER_FLAGS"), - ) - # - ccname = nfo.CMAKE_CXX_COMPILER_ID.lower() - if ccname == "gnu": - ccname = "gcc" - ccname += nfo.CMAKE_CXX_COMPILER_VERSION.lower() - # - if nfo.CMAKE_C_SIZEOF_DATA_PTR == "4": - bits = "32bit" - elif nfo.CMAKE_C_SIZEOF_DATA_PTR == "8": - bits = "64bit" - else: - raise Exception("unknown architecture") - # - nfo.storage_name = f"{bits}_{buildtype}_{ccname}_{nfo.storage_id}" - return nfo - - -# ----------------------------------------------------------------------------- -# ----------------------------------------------------------------------------- -# ----------------------------------------------------------------------------- - -class CMakeCache(Munch): - - def __init__(self, cmakecache_txt): - import glob - for line in iter_cmake_lines(cmakecache_txt): - spl = line.split("=") - if len(spl) < 2: - continue - k, ty = spl[0].split(":") - v = "=".join(spl[1:]).strip() - setattr(self, k, v) - bdir = os.path.dirname(os.path.abspath(cmakecache_txt)) - self._c_compiler_file = sorted(glob.glob(f"{bdir}/CMakeFiles/*/CMakeCCompiler.cmake"))[-1] # get the last - self._cxx_compiler_file = sorted(glob.glob(f"{bdir}/CMakeFiles/*/CMakeCXXCompiler.cmake"))[-1] # get the last - self._system_file = sorted(glob.glob(f"{bdir}/CMakeFiles/*/CMakeSystem.cmake"))[-1] # get the last - self._load_cmake_file(self._c_compiler_file) - self._load_cmake_file(self._cxx_compiler_file) - ccomfile = f"{bdir}/compile_commands.json" - self._compile_commands_file = ccomfile if os.path.exists(ccomfile) else None - - def _load_cmake_file(self, filename): - for line in iter_cmake_lines(filename): - if not line.startswith("set("): - continue - k = re.sub(r"set\((.*)\ +(.*)\)", r"\1", line) - v = re.sub(r"set\((.*)\ +(.*)\)", r"\2", line) - v = v.strip('"').strip("'").strip() - setattr(self, k, v) - - def save(self, results_dir): - copy_file_to_dir(self._c_compiler_file, results_dir) - copy_file_to_dir(self._cxx_compiler_file, results_dir) - copy_file_to_dir(self._system_file, results_dir) - if self._compile_commands_file is not None: - copy_file_to_dir(self._compile_commands_file, results_dir) - - -def iter_cmake_lines(filename): - with open(filename) as f: - for line in f.readlines(): - line = line.strip() - if line.startswith("#") or line.startswith("//") or len(line) == 0: - continue - yield line - - -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ - -class BenchmarkRun(Munch): - "results of an individual run" - - def __init__(self, json_file, meta_class): - props = load_json(json_file) - setattr(self, "filename", json_file) - assert hasattr(props, "context") - assert hasattr(props, "benchmarks") - super().__init__(**props) - for e in self.benchmarks: - setattr(e, 'meta', meta_class(e.name)) - setattr(self, 'property_names', ( - 'meta', - 'shorttitle', - 'name', - 'run_name', - 'run_type', - 'repetitions', - 'repetition_index', - 'repetition_index', - 'threads', - 'iterations', - 'real_time', - 'cpu_time', - 'time_unit', - 'bytes_per_second', - 'items_per_second', - 'counters', - )) - - @property - def first(self): - return self.benchmarks[0] - - @property - def entries(self): - for entry in self.benchmarks: - yield entry - - @property - def meta(self): - for entry in self.benchmarks: - yield entry.meta - - @property - def filtered_names(self): - for entry in self.benchmarks: - yield entry.meta.shorttitle - - @property - def names(self): - for entry in self.benchmarks: - yield entry.name - - @property - def run_names(self): - for entry in self.benchmarks: - yield entry.run_name - - @property - def run_types(self): - for entry in self.benchmarks: - yield entry.run_type - - @property - def repetitions(self): - for entry in self.benchmarks: - yield entry.repetitions - - @property - def repetition_indices(self): - for entry in self.benchmarks: - yield entry.repetition_index - - @property - def threads(self): - for entry in self.benchmarks: - yield entry.threads - - @property - def iterations(self): - for entry in self.benchmarks: - yield entry.iterations - - @property - def real_time(self): - for entry in self.benchmarks: - yield entry.real_time - - @property - def cpu_time(self): - for entry in self.benchmarks: - yield entry.cpu_time - - @property - def time_unit(self): - for entry in self.benchmarks: - yield entry.time_unit - - @property - def bytes_per_second(self): - for entry in self.benchmarks: - yield entry.bytes_per_second - - @property - def items_per_second(self): - for entry in self.benchmarks: - yield entry.items_per_second - - -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ - -class BenchmarkPanel: - - def __init__(self, runs, bm_meta_cls=None): - self.runs = [BenchmarkRun(a, bm_meta_cls) for a in runs] - - def plot_bars(self, title): - plot_benchmarks_as_lines(title, *self.runs) - - - def plot_all_lines(self, title): - plot_benchmarks_as_lines(title, *self.runs, - transform=lambda r: r.meta.num_pixels, - line_title_transform=lambda r: r.meta.shortname) - - -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ - - -def plot_benchmarks_as_bars(title, *bm, transform=None): - from bokeh.models import ColumnDataSource, FactorRange - from bokeh.plotting import figure, show - from bokeh.transform import factor_cmap - pass - - - - -def plot_benchmarks_as_lines(title, *bm, transform=None, - line_title_transform=None, - logx=True, logy=True): - import bokeh - from bokeh.plotting import figure, output_file, show - from bokeh.palettes import Dark2_5 as palette - from bokeh.layouts import row, column - from bokeh.models import (Legend, LegendItem, CheckboxGroup, CustomJS, Div, - RadioGroup, Toggle, - ColumnDataSource, DataTable, TableColumn) - from bokeh.models.markers import marker_types - import itertools - # - ids = entry_ids(*bm, transform=transform) - colors = itertools.cycle(palette) - markers = itertools.cycle(marker_types) - p = figure(title=title, - x_axis_type="log" if logx else "linear", - y_axis_type="log" if logy else "linear", - #background_fill_color="#fafafa", - plot_width=1000, - x_axis_label="Number of pixels", - y_axis_label="Throughput (MB/s)", - ) - p.toolbar.autohide = True - #p.toolbar.active_inspect = [hover_tool, crosshair_tool] - p.toolbar.active_drag = "auto" - p.toolbar.active_scroll = "auto" - # - def dft(v): return v if v else (lambda n: n) - tr = dft(transform) - lttr = dft(line_title_transform) - # - for results in bm: - x = [ids[name] for name in results.names] - y = [bps/1e6 for bps in results.bytes_per_second] - c = next(colors) - marker = next(markers) - next(markers) # advance two - line_name = lttr(results.first) - #legends.append(LegendItem(name=c, label=line_name)) - p.scatter(x, y, marker=marker, size=8, color=c, legend_label=line_name) - p.line(x, y, - color=c, alpha=0.9, - #muted_color=c, muted_alpha=0.05, - legend_label=line_name) - p.legend.click_policy = "hide" - p.legend.label_text_font_size = "10px" - # - def input_title(title): - return Div(text=f"

    {title}

    ") - inputs = [] - first = bm[0].first.meta - for k, g in first.checkbox_groups().items(): - cb = CheckboxGroup(labels=[str(v) for v in g], - active=[i for i in range(len(g))], - inline=True) - inputs.append(input_title(k)) - inputs.append(cb) - # - # https://github.com/bokeh/bokeh/blob/branch-2.3/examples/app/export_csv/main.py - x_axis_values = [f"{m.num_pixels}px" for m in bm[0].meta] - table_sources = [] - for i, px in enumerate(x_axis_values): - c = ColumnDataSource(data={ - 'name': [nth(results.filtered_names, i) for results in bm], - 'bytes_per_second': [nth(results.bytes_per_second, i) for results in bm], - 'items_per_second': [nth(results.items_per_second, i) for results in bm], - 'cpu_time': [nth(results.real_time, i) for results in bm], - 'real_time': [nth(results.real_time, i) for results in bm], - 'iterations': [nth(results.iterations, i) for results in bm], - 'threads': [nth(results.threads, i) for results in bm], - }) - table_sources.append(c) - selected_x_index = 8 # FIXME (currently 2000 pixels) - table_source = copy.deepcopy(table_sources[selected_x_index]) - relvalues = Toggle(label="Table: Relative values") - px_title = input_title("Table: number of pixels") - px_radiogroup = RadioGroup(labels=x_axis_values, active=selected_x_index) - table_inputs = [relvalues, px_title, px_radiogroup] - # - table_cols = [ - TableColumn(field='name', title='Name'), - TableColumn(field='bytes_per_second', title='Bytes/second'), - TableColumn(field='items_per_second', title='Items/second'), - TableColumn(field='cpu_time', title='CPU time'), - TableColumn(field='real_time', title='Real time'), - TableColumn(field='iterations', title='Iterations'), - TableColumn(field='threads', title='Threads'), - ] - data_table = DataTable(source=table_source, columns=table_cols, width=1200) - callback = CustomJS(args=dict( - radiogroup=px_radiogroup, - source=table_source, - table=table_sources - ), code=""" - console.log(`active=${radiogroup.active}`); - /*source.data=table[radiogroup.active];*/ - var nrows = source.data['name'].length; - var ts = table[radiogroup.active].data; - var names = ["name", "bytes_per_second", "items_per_second", "cpu_time", "real_time", "iterations", "threads"]; - var ncols = names.length; - console.log(`names=${names} nrows=${nrows} ncols=${ncols}`); - for(var i = 0; i < nrows; i++) { - for(var j = 0; j < ncols; ++j) { - var name = names[j]; - /*console.log(`i=${i} j=${j} name=${name}`);*/ - source.data[name][i] = ts[name][i]; - } - } - source.change.emit(); - """) - px_radiogroup.js_on_change('active', callback) - # lambda attr, old, new: log(f"attr={attr} old={old} new={new} active={px_radiogroup.active}")) - # - layout = column( - row(column(*inputs), p), - row(column(*table_inputs), data_table)) - show(layout) - - -def chain(*iterables): - for it in iterables: - for elm in it: - yield elm - - -def entry_ids(*bm, transform=None): - ids = {} - curr = 0 - for results in bm: - log(os.path.basename(results.filename), "------------------------------") - for entry in results.entries: - log(entry.name) - if transform is not None: - ids[entry.name] = transform(entry) - else: - if ids.get(entry.name) is None: - ids[entry.name] = curr - curr += 1 - return ids - - -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ - -def add_results(args): - log("adding results:", args.results) - col = BenchmarkCollection(args.target) - col.add(args.results) - - -def add_meta(args): - log("adding bm run metadata to results dir:", args.results) - meta = ResultMeta(results_dir=args.results, - cmakecache=args.cmakecache, - build_type=args.build_type) - meta.save(args.results) - log("adding bm run metadata to results dir: success!") - - -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ - -import typing -import enum - - -class _enum(enum.Enum): - def __str__(self): - return str(self.name) - @classmethod - def err_unknown(cls, s): - raise Exception(f"unknown {__class__.__name__}: {s}") - - -class MatrixOrder(_enum): - row_major = "row_major" - col_major = "col_major" - @property - def short(self): - return "rm" if self is MatrixOrder.row_major else "cm" - @classmethod - def make(cls, s): - try: - return {"rm": cls.row_major, "cm": cls.col_major}[s] - except: - cls.err_unknown(s) - - -class MatrixLayout(_enum): - compact = "compact" - strided = "strided" - @classmethod - def make(cls, s): - try: - return cls[s] - except: - cls.err_unknown(s) - - -class DimensionBinding(_enum): - compile_time = "compile_time" - run_time = "run_time" - @property - def short(self): - return "ct" if self is DimensionBinding.compile_time else "rt" - @classmethod - def make(cls, s): - try: - return {"ct": cls.compile_time, "rt": cls.run_time}[s] - except: - cls.err_unknown(s) - - -class MultType(_enum): - naive = "naive" - avx2 = "avx2" - avx2_unroll2 = "avx2_unroll2" - avx2_unroll4 = "avx2_unroll4" - avx2_unroll8 = "avx2_unroll8" - @classmethod - def make(cls, s): - try: - s = s.replace("dotprod_", "").replace("_naive", "") - return cls[s] - except: - cls.err_unknown(s) - - -class MatrixMult(typing.NamedTuple): - title: str - num_pixels: int - num_channels: int - num_features: int - mult_type: MultType - layout: MatrixLayout - dim_binding: DimensionBinding - ret_order: MatrixOrder - lhs_order: MatrixOrder - rhs_order: MatrixOrder - - @classmethod - def make(cls, bm_title: str): - # eg: - # mult_naive_strided_ct_rm_cmcm<250, 8, 16> - # mult_naive_compact_rt_rm_rmrm/4000/8/16 - rxline = r'mult_(.*)[") - expect(v, 'title', 'naive_strided_ct_rm_cmcm') - expect(v, 'num_pixels', 250) - expect(v, 'num_channels', 8) - expect(v, 'num_features', 16) - expect(v, 'mult_type', MultType.naive) - expect(v, 'layout', MatrixLayout.strided) - expect(v, 'dim_binding', DimensionBinding.compile_time) - expect(v, 'ret_order', MatrixOrder.row_major) - expect(v, 'lhs_order', MatrixOrder.col_major) - expect(v, 'rhs_order', MatrixOrder.col_major) - v = MatrixMult.make("mult_dotprod_avx2_compact_rt_cm_rmcm/4000/16/8") - expect(v, 'title', 'dotprod_avx2_compact_rt_cm_rmcm') - expect(v, 'num_pixels', 4000) - expect(v, 'num_channels', 16) - expect(v, 'num_features', 8) - expect(v, 'mult_type', MultType.avx2) - expect(v, 'layout', MatrixLayout.compact) - expect(v, 'dim_binding', DimensionBinding.run_time) - expect(v, 'ret_order', MatrixOrder.col_major) - expect(v, 'lhs_order', MatrixOrder.row_major) - expect(v, 'rhs_order', MatrixOrder.col_major) - -_test() - - - -def formatMBps(value): - return value / 1e6 - - - -if __name__ == '__main__': - bms = sorted(sys.argv[2:]) - log(bms) - bms = BenchmarkPanel(bms, bm_meta_cls=MatrixMult.make) - fm = bms.runs[0].first.meta - title = f"Classifier multiplication, {fm.num_channels} channels, {fm.num_features} features: throughput (MB/s)" - bms.plot_all_lines(title) - exit() - main() diff --git a/thirdparty/ryml/ext/c4core/cmake/bm-xp/example_mintm.py b/thirdparty/ryml/ext/c4core/cmake/bm-xp/example_mintm.py deleted file mode 100644 index 3db4175cb..000000000 --- a/thirdparty/ryml/ext/c4core/cmake/bm-xp/example_mintm.py +++ /dev/null @@ -1,1061 +0,0 @@ -import os -import sys -import argparse -import copy -import requests -import flask -import json -import re -import yaml -import shutil -import mmh3 -from itertools import islice - -from munch import Munch, munchify -from flask import render_template, redirect, url_for, send_from_directory -from markupsafe import escape - - -def log(*args, **kwargs): - print(*args, **kwargs, flush=True) - - -def myhash_combine(curr, value): - return curr ^ (value + 0x9e3779b9 + (curr<<6) + (curr>>2)) - - -def nth(iterable, n, default=None): - "Returns the nth item or a default value" - return next(islice(iterable, n, None), default) - - -def optionals(obj, *attrs): - ret = [] - for attr in attrs: - if not hasattr(obj, attr): - log("attr not present:", attr) - continue - ret.append(getattr(obj, attr)) - return ret - - -def myhash(*args): - h = 137597 - for a in args: - if isinstance(a, str): - if a == "": - continue - b = bytes(a, "utf8") - else: - b = bytes(a) - hb = mmh3.hash(b, signed=False) - h = myhash_combine(h, hb) - s = hex(h) - return s[2:min(10, len(s))] - - -def copy_file_to_dir(file, dir): - dir = os.path.abspath(dir) - src = os.path.abspath(file) - dst = f"{dir}/{os.path.basename(src)}" - if not os.path.exists(dir): - os.makedirs(dir) - if os.path.exists(dst): - os.remove(dst) - log("copy:", src, "-->", dst) - shutil.copy(src, dst) - return dst - - -def chk(f): - log(f"looking for file:", f) - assert os.path.exists(f), f - return f - - -def load_yml_file(filename): - if not os.path.exists(filename): - raise Exception(f"not found: {filename}") - with open(filename) as f: - return load_yml(f.read()) - - -def dump_yml(data, filename): - with open(filename, "w") as f: - yaml.safe_dump(data, f) - - -def load_yml(yml): - return munchify(yaml.safe_load(yml)) - - -def dump_json(data, filename): - with open(filename, "w") as f: - f.write(json.dumps(data, indent=2, sort_keys=True)) - - -def load_json(filename): - with open(filename, "r") as f: - try: - return munchify(json.load(f)) - except Exception as exc: - raise Exception(f"could not load file: {filename}: {exc}") - - -def main(): - def _common_args(parser): - parser.add_argument("-m", "--manifest", type=str, default="", help="enable debug mode") - parser.add_argument("--debug", action="store_true", help="enable debug mode") - # - parser = argparse.ArgumentParser(description="Browse benchmark results", prog="bm") - _common_args(parser) - subparsers = parser.add_subparsers() - # - sp = subparsers.add_parser("create", help="create benchmark collection") - _common_args(sp) - sp.add_argument("--debug", action="store_true", help="enable debug mode") - sp.add_argument("filename", type=str, help="the YAML file with the benchmark specs") - sp.add_argument("target", type=str, help="the directory to store the results") - # - sp = subparsers.add_parser("meta", help="get the required meta-information: cpu info, commit data") - _common_args(sp) - sp.add_argument("--debug", action="store_true", help="enable debug mode") - sp.add_argument("results", type=str, help="the directory with the results") - sp.add_argument("cmakecache", type=str, help="the path to the CMakeCache.txt file used to build the benchmark binaries") - sp.add_argument("build_type", type=str, help="the build type, eg Release Debug MinSizeRel RelWithDebInfo") - # - sp = subparsers.add_parser("add", help="add benchmark results") - _common_args(sp) - sp.add_argument("--debug", action="store_true", help="enable debug mode") - sp.add_argument("results", type=str, help="the directory with the results") - sp.add_argument("target", type=str, help="the directory to store the results") - # - sp = subparsers.add_parser("serve", help="serve benchmark results") - _common_args(sp) - sp.add_argument("--debug", action="store_true", help="enable debug mode") - sp.add_argument("bmdir", type=os.path.abspath, default=os.getcwd(), help="the directory with the results. default=.") - sp.add_argument("-H", "--host", type=str, default="localhost", help="host. default=%(default)s") - sp.add_argument("-p", "--port", type=int, default=8000, help="port. default=%(default)s") - # - sp = subparsers.add_parser("export", help="export static html") - sp.set_defaults(func=freeze) - sp.add_argument("bmdir", type=os.path.abspath, default=os.getcwd(), help="the directory with the results. default=.") - _common_args(sp) - # - sp = subparsers.add_parser("deps", help="install server dependencies") - sp.set_defaults(func=lambda _: download_deps()) - sp.add_argument("--debug", action="store_true", help="enable debug mode") - _common_args(sp) - # - args = parser.parse_args(sys.argv[1:] if len(sys.argv) > 1 else ["serve"]) - if args.debug: - log(args) - args.func(args) - - -def get_manifest(args): - bmdir = os.path.abspath(args.bmdir) - if not args.manifest: - manifest_yml = os.path.join(bmdir, "manifest.yml") - else: - if not os.path.isabs(args.manifest): - manifest_yml = os.path.join(os.getcwd(), args.manifest) - manifest_json = os.path.join(os.path.dirname(manifest.yml), "manifest.json") - manifest = load_yml_file(manifest_yml) - dump_json(manifest, manifest_json) - return manifest - - -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ - -app = flask.Flask(__name__, - template_folder='template') - - -def _setup_app(args): - def _s(prop, val): - assert not hasattr(app, prop), prop - setattr(app, prop, val) - _s('args', args) - _s('manifest', get_manifest(args)) - if args.debug: - app.config["DEBUG"] = True - - -def freeze(args): - "https://pythonhosted.org/Frozen-Flask/" - from flask_frozen import Freezer - _setup_app(args) - freezer = Freezer(app) - freezer.freeze(debug=args.debug) - - -def serve(args): - _setup_app(args) - app.run(host=args.host, port=args.port, debug=args.debug) - - -@app.route("/") -def home(): - log("requested home") - return render_template("index.html") - - -@app.route("/") -def other_(path): - path = escape(path) - d = app.args.bmdir - log("requested other path:", path, "---", os.path.join(d, path)) - return send_from_directory(d, path) - - -@app.route("/static/") -def static_(path): - path = escape(path) - d = os.path.join(app.args.bmdir, "static") - log("requested static path:", path, "---", os.path.join(d, path)) - return send_from_directory(d, path, cache_timeout=1) # timeout in seconds - - -@app.route("/bm///") -def bm_(commit, run, resultjson): - commit = escape(commit) - run = escape(run) - resultjson = escape(resultjson) - d = os.path.join(app.args.bmdir, "runs", commit, run) - log("requested result:", os.path.join(d, resultjson)) - return send_from_directory(d, resultjson, cache_timeout=1) # timeout in seconds - - -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ - -def download_deps(): - deps = [ - "https://code.jquery.com/jquery-3.3.1.js", - "https://code.jquery.com/jquery-3.3.1.js", - "https://code.jquery.com/ui/1.12.1/jquery-ui.js", - "https://cdn.datatables.net/1.10.20/js/jquery.dataTables.js", - "https://cdn.datatables.net/1.10.20/js/jquery.dataTables.min.js", - "https://cdn.datatables.net/1.10.20/css/jquery.dataTables.css", - "https://cdn.datatables.net/1.10.20/css/jquery.dataTables.min.css", - "https://www.chartjs.org/dist/2.9.1/Chart.min.js", - #("https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.3.2/styles/github.css", "highlight.github.css"), - ("https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.3.2/styles/github.min.css", "highlight.github.min.css"), - #"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.3.2/highlight.js", - "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.3.2/highlight.min.js", - ] - for src in deps: - if type(src) == str: - base = os.path.basename(src) - else: - src, base = src - dst = f"{os.getcwd()}/static/{base}" - download_url(src, dst) - - -def download_url(url, dst): - log("download url:", url, "--->", dst) - req = requests.get(url, stream=True) - if req.status_code == 200: - sz = 0 - with open(dst, 'wb') as f: - for chunk in req: - f.write(chunk) - sz += len(chunk) - log(f"........ finished: {sz}B") - else: - log(f" error:", req.status_code, url) - - -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ - -class BenchmarkCollection: - - @staticmethod - def create_new(args): - dir = args.target - filename = os.path.join(dir, "bm.yml") - manifest = os.path.join(dir, "manifest.yml") - if not os.path.exists(dir): - os.makedirs(dir) - shutil.copyfile(args.filename, filename) - dump_yml(load_yml("""{runs: {}, bm: {}}"""), manifest) - return __class__(dir) - - def __init__(self, dir): - if not os.path.exists(dir): - raise Exception(f"not found: {dir}") - self.dir = os.path.abspath(dir) - self.runs_dir = os.path.join(self.dir, "runs") - self.manifest = os.path.join(self.dir, "manifest.yml") - self.filename = os.path.join(self.dir, "bm.yml") - self.specs = munchify(load_yml_file(self.filename)) - self.manif = munchify(load_yml_file(self.manifest)) - - def add(self, results_dir): - results_dir = os.path.abspath(results_dir) - dst_dir, meta = self._read_run(results_dir) - self._add_run(results_dir, dst_dir, meta) - dump_yml(self.manif, self.manifest) - - def _read_run(self, results_dir): - log("adding run...") - id = f"{len(self.manif.runs.keys()):05d}" - log(f"adding run: id={id}") - meta = ResultMeta.load(results_dir) - dst_dir = os.path.join(self.runs_dir, meta.name) - return dst_dir, meta - - def _add_run(self, results_dir, dst_dir, meta): - cats = self._add_meta_categories(meta) - for filename in ("meta.yml", - "CMakeCCompiler.cmake", - "CMakeCXXCompiler.cmake", - "CMakeSystem.cmake", - "compile_commands.json"): - filename = os.path.join(results_dir, filename) - if os.path.exists(filename): - copy_file_to_dir(filename, dst_dir) - else: - if not filename.endswith("compile_commands.json"): - raise Exception(f"wtf???? {filename}") - for name, specs in self.specs.bm.items(): - if not hasattr(specs, 'variants'): - filename = chk(f"{results_dir}/{name}.json") - dst = copy_file_to_dir(filename, dst_dir) - self._add_bm_run(name, specs, meta) - else: - for t in specs.variants: - tname = f"{name}-{t}" - filename = chk(f"{results_dir}/{tname}.json") - dst = copy_file_to_dir(filename, dst_dir) - self._add_bm_run(tname, specs, meta) - - def _add_bm_run(self, name, specs, meta): - if name not in self.manif.bm.keys(): - self.manif.bm[name] = Munch(specs=specs, entries=[]) - entry = self.manif.bm[name] - entry.specs = specs - if meta.name not in entry.entries: - entry.entries.append(meta.name) - - def _add_meta_categories(self, meta): - run = Munch() - for catname in ('commit', 'cpu', 'system', 'build'): - meta_item = getattr(meta, catname) - self._add_item_to_category(meta.name, catname, meta_item) - run[catname] = meta_item.storage_id - # build specs are too verbose; remove them - self.manif.build[meta.build.storage_id].specs = Munch() - self.manif.runs[meta.name] = run - - def _add_item_to_category(self, run, category_name, item): - if not hasattr(self.manif, category_name): - setattr(self.manif, category_name, Munch()) - category = getattr(self.manif, category_name) - if item.storage_id not in category.keys(): - category[item.storage_id] = Munch(specs=item, entries=[]) - entry = category[item.storage_id] - entry.specs = item - if run not in entry.entries: - entry.entries.append(run) - - -# ----------------------------------------------------------------------------- -# ----------------------------------------------------------------------------- -# ----------------------------------------------------------------------------- - -class ResultMeta(Munch): - - def __init__(self, results_dir, cmakecache, build_type): - super().__init__(self) - self.date = __class__.get_date() - self.commit = __class__.get_commit(results_dir) - self.cpu = __class__.get_cpu_info() - self.system = __class__.get_sys_info() - self.build = __class__.get_build_info(cmakecache, build_type) - self.name = self._get_name() - - @staticmethod - def load(results_dir): - results_dir = os.path.join(os.path.abspath(results_dir), "meta.yml") - data = load_yml_file(results_dir) - return munchify(data) - - def save(self, results_dir): - out = os.path.join(results_dir, "meta.yml") - log("saving meta:", out) - dump_yml(self, out) - self.build.save(results_dir) - - @staticmethod - def get_date(): - import datetime - now = datetime.datetime.now() - return now.strftime("%Y%m%d-%H%M%S") - - def _get_name(self): - commit = self.commit.storage_name - cpu = self.cpu.storage_name - sys = self.system.storage_name - build = self.build.storage_name - name = f"{commit}/{cpu}-{sys}-{build}" - return name - - @staticmethod - def get_commit(results_dir): - import git - repo = git.Repo(results_dir, search_parent_directories=True) - commit = repo.head.commit - commit = {p: str(getattr(commit, p)) - for p in ('message', 'summary', 'name_rev', - 'author', - 'authored_datetime', - 'committer', - 'committed_datetime',)} - commit = Munch(commit) - commit.message = commit.message.strip() - commit.sha1 = commit.name_rev[:7] - spl = commit.authored_datetime.split(" ") - date = re.sub(r'-', '', spl[0]) - time = re.sub(r'(\d+):(\d+):(\d+).*', r'\1\2\3', spl[1]) - commit.storage_id = commit.sha1 - commit.storage_name = f"git{date}_{time}-{commit.sha1}" - return commit - - @staticmethod - def get_cpu_info(): - import cpuinfo - nfo = cpuinfo.get_cpu_info() - nfo = Munch(nfo) - for a in ('cpu_version', 'cpu_version_string', 'python_version'): - if hasattr(nfo, a): - delattr(nfo, a) - for a in ('arch_string_raw', 'brand_raw', 'hardware_raw', 'vendor_id_raw'): - if not hasattr(nfo, a): - setattr(nfo, a, '') - nfo.storage_id = myhash( - nfo.arch_string_raw, nfo.brand_raw, nfo.hardware_raw, nfo.vendor_id_raw, - nfo.arch, nfo.bits, nfo.count, nfo.family, nfo.model, nfo.stepping, - ",".join(nfo.flags), nfo.hz_advertised_friendly, - nfo.l2_cache_associativity, - nfo.l2_cache_line_size, - nfo.l2_cache_size, - nfo.l3_cache_size, - *optionals('l1_data_cache_size', 'l1_instruction_cache_size') - ) - nfo.storage_name = f"{nfo.arch.lower()}_{nfo.storage_id}" - return nfo - - @staticmethod - def get_sys_info(): - import platform - uname = platform.uname() - nfo = Munch( - sys_platform=sys.platform, - sys=platform.system(), - uname=Munch( - machine=uname.machine, - node=uname.node, - release=uname.release, - system=uname.system, - version=uname.version, - ) - ) - nfo.storage_id = myhash( - nfo.sys_platform, - nfo.uname.machine, - ) - nfo.storage_name = f"{nfo.sys_platform}_{nfo.storage_id}" - return nfo - - @staticmethod - def get_build_info(cmakecache_txt, buildtype): - nfo = CMakeCache(cmakecache_txt) - def _btflags(name): - return (getattr(nfo, name), getattr(nfo, f"{name}_{buildtype.upper()}")) - nfo.storage_id = myhash( - buildtype, - nfo.CMAKE_CXX_COMPILER_ID, - nfo.CMAKE_CXX_COMPILER_VERSION, - nfo.CMAKE_CXX_COMPILER_VERSION_INTERNAL, - nfo.CMAKE_CXX_COMPILER_ABI, - nfo.CMAKE_CXX_SIZEOF_DATA_PTR, - nfo.CMAKE_C_COMPILER_ID, - nfo.CMAKE_C_COMPILER_VERSION, - nfo.CMAKE_C_COMPILER_VERSION_INTERNAL, - nfo.CMAKE_C_COMPILER_ABI, - nfo.CMAKE_C_SIZEOF_DATA_PTR, - *_btflags("CMAKE_CXX_FLAGS"), - *_btflags("CMAKE_C_FLAGS"), - *_btflags("CMAKE_STATIC_LINKER_FLAGS"), - *_btflags("CMAKE_SHARED_LINKER_FLAGS"), - ) - # - ccname = nfo.CMAKE_CXX_COMPILER_ID.lower() - if ccname == "gnu": - ccname = "gcc" - ccname += nfo.CMAKE_CXX_COMPILER_VERSION.lower() - # - if nfo.CMAKE_C_SIZEOF_DATA_PTR == "4": - bits = "32bit" - elif nfo.CMAKE_C_SIZEOF_DATA_PTR == "8": - bits = "64bit" - else: - raise Exception("unknown architecture") - # - nfo.storage_name = f"{bits}_{buildtype}_{ccname}_{nfo.storage_id}" - return nfo - - -# ----------------------------------------------------------------------------- -# ----------------------------------------------------------------------------- -# ----------------------------------------------------------------------------- - -class CMakeCache(Munch): - - def __init__(self, cmakecache_txt): - import glob - for line in iter_cmake_lines(cmakecache_txt): - spl = line.split("=") - if len(spl) < 2: - continue - k, ty = spl[0].split(":") - v = "=".join(spl[1:]).strip() - setattr(self, k, v) - bdir = os.path.dirname(os.path.abspath(cmakecache_txt)) - self._c_compiler_file = sorted(glob.glob(f"{bdir}/CMakeFiles/*/CMakeCCompiler.cmake"))[-1] # get the last - self._cxx_compiler_file = sorted(glob.glob(f"{bdir}/CMakeFiles/*/CMakeCXXCompiler.cmake"))[-1] # get the last - self._system_file = sorted(glob.glob(f"{bdir}/CMakeFiles/*/CMakeSystem.cmake"))[-1] # get the last - self._load_cmake_file(self._c_compiler_file) - self._load_cmake_file(self._cxx_compiler_file) - ccomfile = f"{bdir}/compile_commands.json" - self._compile_commands_file = ccomfile if os.path.exists(ccomfile) else None - - def _load_cmake_file(self, filename): - for line in iter_cmake_lines(filename): - if not line.startswith("set("): - continue - k = re.sub(r"set\((.*)\ +(.*)\)", r"\1", line) - v = re.sub(r"set\((.*)\ +(.*)\)", r"\2", line) - v = v.strip('"').strip("'").strip() - setattr(self, k, v) - - def save(self, results_dir): - copy_file_to_dir(self._c_compiler_file, results_dir) - copy_file_to_dir(self._cxx_compiler_file, results_dir) - copy_file_to_dir(self._system_file, results_dir) - if self._compile_commands_file is not None: - copy_file_to_dir(self._compile_commands_file, results_dir) - - -def iter_cmake_lines(filename): - with open(filename) as f: - for line in f.readlines(): - line = line.strip() - if line.startswith("#") or line.startswith("//") or len(line) == 0: - continue - yield line - - -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ - -class BenchmarkRun(Munch): - "results of an individual run" - - def __init__(self, json_file, meta_class): - props = load_json(json_file) - setattr(self, "filename", json_file) - assert hasattr(props, "context") - assert hasattr(props, "benchmarks") - super().__init__(**props) - for e in self.benchmarks: - setattr(e, 'meta', meta_class(e.name)) - setattr(self, 'property_names', ( - 'meta', - 'shorttitle', - 'name', - 'run_name', - 'run_type', - 'repetitions', - 'repetition_index', - 'repetition_index', - 'threads', - 'iterations', - 'real_time', - 'cpu_time', - 'time_unit', - 'bytes_per_second', - 'items_per_second', - 'counters', - )) - - @property - def first(self): - return self.benchmarks[0] - - @property - def entries(self): - for entry in self.benchmarks: - yield entry - - @property - def meta(self): - for entry in self.benchmarks: - yield entry.meta - - @property - def filtered_names(self): - for entry in self.benchmarks: - yield entry.meta.shorttitle - - @property - def names(self): - for entry in self.benchmarks: - yield entry.name - - @property - def run_names(self): - for entry in self.benchmarks: - yield entry.run_name - - @property - def run_types(self): - for entry in self.benchmarks: - yield entry.run_type - - @property - def repetitions(self): - for entry in self.benchmarks: - yield entry.repetitions - - @property - def repetition_indices(self): - for entry in self.benchmarks: - yield entry.repetition_index - - @property - def threads(self): - for entry in self.benchmarks: - yield entry.threads - - @property - def iterations(self): - for entry in self.benchmarks: - yield entry.iterations - - @property - def real_time(self): - for entry in self.benchmarks: - yield entry.real_time - - @property - def cpu_time(self): - for entry in self.benchmarks: - yield entry.cpu_time - - @property - def time_unit(self): - for entry in self.benchmarks: - yield entry.time_unit - - @property - def bytes_per_second(self): - for entry in self.benchmarks: - yield entry.bytes_per_second - - @property - def items_per_second(self): - for entry in self.benchmarks: - yield entry.items_per_second - - -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ - -class BenchmarkPanel: - - def __init__(self, runs, bm_meta_cls=None): - self.runs = [BenchmarkRun(a, bm_meta_cls) for a in runs] - - def plot_bars(self, title): - plot_benchmarks_as_lines(title, *self.runs) - - - def plot_all_lines(self, title): - plot_benchmarks_as_lines(title, *self.runs, - transform=lambda r: r.meta.num_pixels, - line_title_transform=lambda r: r.meta.shortname) - - -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ - - -def plot_benchmarks_as_bars(title, *bm, transform=None): - from bokeh.models import ColumnDataSource, FactorRange - from bokeh.plotting import figure, show - from bokeh.transform import factor_cmap - pass - - - - -def plot_benchmarks_as_lines(title, *bm, transform=None, - line_title_transform=None, - logx=True, logy=True): - import bokeh - from bokeh.plotting import figure, output_file, show - from bokeh.palettes import Dark2_5 as palette - from bokeh.layouts import row, column - from bokeh.models import (Legend, LegendItem, CheckboxGroup, CustomJS, Div, - RadioGroup, Toggle, - ColumnDataSource, DataTable, TableColumn) - from bokeh.models.markers import marker_types - import itertools - # - ids = entry_ids(*bm, transform=transform) - colors = itertools.cycle(palette) - markers = itertools.cycle(marker_types) - p = figure(title=title, - x_axis_type="log" if logx else "linear", - y_axis_type="log" if logy else "linear", - #background_fill_color="#fafafa", - plot_width=1000, - x_axis_label="Number of pixels", - y_axis_label="Throughput (MB/s)", - ) - p.toolbar.autohide = True - #p.toolbar.active_inspect = [hover_tool, crosshair_tool] - p.toolbar.active_drag = "auto" - p.toolbar.active_scroll = "auto" - # - def dft(v): return v if v else (lambda n: n) - tr = dft(transform) - lttr = dft(line_title_transform) - # - for results in bm: - x = [ids[name] for name in results.names] - y = [bps/1e6 for bps in results.bytes_per_second] - c = next(colors) - marker = next(markers) - next(markers) # advance two - line_name = lttr(results.first) - #legends.append(LegendItem(name=c, label=line_name)) - p.scatter(x, y, marker=marker, size=8, color=c, legend_label=line_name) - p.line(x, y, - color=c, alpha=0.9, - #muted_color=c, muted_alpha=0.05, - legend_label=line_name) - p.legend.click_policy = "hide" - p.legend.label_text_font_size = "10px" - # - def input_title(title): - return Div(text=f"

    {title}

    ") - inputs = [] - first = bm[0].first.meta - for k, g in first.checkbox_groups().items(): - cb = CheckboxGroup(labels=[str(v) for v in g], - active=[i for i in range(len(g))], - inline=True) - inputs.append(input_title(k)) - inputs.append(cb) - # - # https://github.com/bokeh/bokeh/blob/branch-2.3/examples/app/export_csv/main.py - x_axis_values = [f"{m.num_pixels}px" for m in bm[0].meta] - table_sources = [] - for i, px in enumerate(x_axis_values): - c = ColumnDataSource(data={ - 'name': [nth(results.filtered_names, i) for results in bm], - 'bytes_per_second': [nth(results.bytes_per_second, i) for results in bm], - 'items_per_second': [nth(results.items_per_second, i) for results in bm], - 'cpu_time': [nth(results.real_time, i) for results in bm], - 'real_time': [nth(results.real_time, i) for results in bm], - 'iterations': [nth(results.iterations, i) for results in bm], - 'threads': [nth(results.threads, i) for results in bm], - }) - table_sources.append(c) - selected_x_index = 8 # FIXME (currently 2000 pixels) - table_source = copy.deepcopy(table_sources[selected_x_index]) - relvalues = Toggle(label="Table: Relative values") - px_title = input_title("Table: number of pixels") - px_radiogroup = RadioGroup(labels=x_axis_values, active=selected_x_index) - table_inputs = [relvalues, px_title, px_radiogroup] - # - table_cols = [ - TableColumn(field='name', title='Name'), - TableColumn(field='bytes_per_second', title='Bytes/second'), - TableColumn(field='items_per_second', title='Items/second'), - TableColumn(field='cpu_time', title='CPU time'), - TableColumn(field='real_time', title='Real time'), - TableColumn(field='iterations', title='Iterations'), - TableColumn(field='threads', title='Threads'), - ] - data_table = DataTable(source=table_source, columns=table_cols, width=1200) - callback = CustomJS(args=dict( - radiogroup=px_radiogroup, - source=table_source, - table=table_sources - ), code=""" - console.log(`active=${radiogroup.active}`); - /*source.data=table[radiogroup.active];*/ - var nrows = source.data['name'].length; - var ts = table[radiogroup.active].data; - var names = ["name", "bytes_per_second", "items_per_second", "cpu_time", "real_time", "iterations", "threads"]; - var ncols = names.length; - console.log(`names=${names} nrows=${nrows} ncols=${ncols}`); - for(var i = 0; i < nrows; i++) { - for(var j = 0; j < ncols; ++j) { - var name = names[j]; - /*console.log(`i=${i} j=${j} name=${name}`);*/ - source.data[name][i] = ts[name][i]; - } - } - source.change.emit(); - """) - px_radiogroup.js_on_change('active', callback) - # lambda attr, old, new: log(f"attr={attr} old={old} new={new} active={px_radiogroup.active}")) - # - layout = column( - row(column(*inputs), p), - row(column(*table_inputs), data_table)) - show(layout) - - -def chain(*iterables): - for it in iterables: - for elm in it: - yield elm - - -def entry_ids(*bm, transform=None): - ids = {} - curr = 0 - for results in bm: - log(os.path.basename(results.filename), "------------------------------") - for entry in results.entries: - log(entry.name) - if transform is not None: - ids[entry.name] = transform(entry) - else: - if ids.get(entry.name) is None: - ids[entry.name] = curr - curr += 1 - return ids - - -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ - -def add_results(args): - log("adding results:", args.results) - col = BenchmarkCollection(args.target) - col.add(args.results) - - -def add_meta(args): - log("adding bm run metadata to results dir:", args.results) - meta = ResultMeta(results_dir=args.results, - cmakecache=args.cmakecache, - build_type=args.build_type) - meta.save(args.results) - log("adding bm run metadata to results dir: success!") - - -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ -# ------------------------------------------------------------------------------ - -import typing -import enum - - -class _enum(enum.Enum): - def __str__(self): - return str(self.name) - @classmethod - def err_unknown(cls, s): - raise Exception(f"unknown {__class__.__name__}: {s}") - - -class MatrixOrder(_enum): - row_major = "row_major" - col_major = "col_major" - @property - def short(self): - return "rm" if self is MatrixOrder.row_major else "cm" - @classmethod - def make(cls, s): - try: - return {"rm": cls.row_major, "cm": cls.col_major}[s] - except: - cls.err_unknown(s) - - -class MatrixLayout(_enum): - compact = "compact" - strided = "strided" - @classmethod - def make(cls, s): - try: - return cls[s] - except: - cls.err_unknown(s) - - -class DimensionBinding(_enum): - compile_time = "compile_time" - run_time = "run_time" - @property - def short(self): - return "ct" if self is DimensionBinding.compile_time else "rt" - @classmethod - def make(cls, s): - try: - return {"ct": cls.compile_time, "rt": cls.run_time}[s] - except: - cls.err_unknown(s) - - -class MultType(_enum): - naive = "naive" - avx2 = "avx2" - avx2_unroll2 = "avx2_unroll2" - avx2_unroll4 = "avx2_unroll4" - avx2_unroll8 = "avx2_unroll8" - @classmethod - def make(cls, s): - try: - s = s.replace("dotprod_", "").replace("_naive", "") - return cls[s] - except: - cls.err_unknown(s) - - -class MatrixMult(typing.NamedTuple): - title: str - num_pixels: int - num_channels: int - num_features: int - mult_type: MultType - layout: MatrixLayout - dim_binding: DimensionBinding - ret_order: MatrixOrder - lhs_order: MatrixOrder - rhs_order: MatrixOrder - - @classmethod - def make(cls, bm_title: str): - # eg: - # mult_naive_strided_ct_rm_cmcm<250, 8, 16> - # mult_naive_compact_rt_rm_rmrm/4000/8/16 - rxline = r'mult_(.*)[") - expect(v, 'title', 'naive_strided_ct_rm_cmcm') - expect(v, 'num_pixels', 250) - expect(v, 'num_channels', 8) - expect(v, 'num_features', 16) - expect(v, 'mult_type', MultType.naive) - expect(v, 'layout', MatrixLayout.strided) - expect(v, 'dim_binding', DimensionBinding.compile_time) - expect(v, 'ret_order', MatrixOrder.row_major) - expect(v, 'lhs_order', MatrixOrder.col_major) - expect(v, 'rhs_order', MatrixOrder.col_major) - v = MatrixMult.make("mult_dotprod_avx2_compact_rt_cm_rmcm/4000/16/8") - expect(v, 'title', 'dotprod_avx2_compact_rt_cm_rmcm') - expect(v, 'num_pixels', 4000) - expect(v, 'num_channels', 16) - expect(v, 'num_features', 8) - expect(v, 'mult_type', MultType.avx2) - expect(v, 'layout', MatrixLayout.compact) - expect(v, 'dim_binding', DimensionBinding.run_time) - expect(v, 'ret_order', MatrixOrder.col_major) - expect(v, 'lhs_order', MatrixOrder.row_major) - expect(v, 'rhs_order', MatrixOrder.col_major) - -_test() - - - -def formatMBps(value): - return value / 1e6 - - - -if __name__ == '__main__': - bms = sorted(sys.argv[2:]) - log(bms) - bms = BenchmarkPanel(bms, bm_meta_cls=MatrixMult.make) - fm = bms.runs[0].first.meta - title = f"Classifier multiplication, {fm.num_channels} channels, {fm.num_features} features: throughput (MB/s)" - bms.plot_all_lines(title) - exit() - main() diff --git a/thirdparty/ryml/ext/c4core/cmake/bm-xp/requirements.txt b/thirdparty/ryml/ext/c4core/cmake/bm-xp/requirements.txt deleted file mode 100644 index 5a1b395ef..000000000 --- a/thirdparty/ryml/ext/c4core/cmake/bm-xp/requirements.txt +++ /dev/null @@ -1,14 +0,0 @@ -munch -pyyaml -py-cpuinfo -psutil -gitpython -flask -markupsafe -Frozen-Flask -requests -mmh3 -bokeh<3.0 -selenium -matplotlib -prettytable diff --git a/thirdparty/ryml/ext/c4core/cmake/bm-xp/template/index.html b/thirdparty/ryml/ext/c4core/cmake/bm-xp/template/index.html deleted file mode 100644 index fb52b8ba0..000000000 --- a/thirdparty/ryml/ext/c4core/cmake/bm-xp/template/index.html +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - -

    Title

    -
    - Available benchmarks: -
      -
      -
      -
      - - - - - - - - - - - diff --git a/thirdparty/ryml/ext/c4core/cmake/c4CatSources.cmake b/thirdparty/ryml/ext/c4core/cmake/c4CatSources.cmake deleted file mode 100644 index 1633989af..000000000 --- a/thirdparty/ryml/ext/c4core/cmake/c4CatSources.cmake +++ /dev/null @@ -1,105 +0,0 @@ -if(NOT _c4CatSourcesIncluded) -set(_c4CatSourcesIncluded ON) - - -#------------------------------------------------------------------------------ -# concatenate the source files to an output file, adding preprocessor adjustment -# for correct file/line reporting -function(c4_cat_sources files output umbrella_target) - _c4_cat_sources_create_cat(cat) - c4_to_full_path("${files}" full_files) # we must work with full paths - c4_separate_list("${full_files}" sepfiles) # and use a string instead of a list - c4_dbg("${_c4_prefix}: catting sources to ${output}") - if(NOT EXISTS "${output}") - # the cat command is executed at build time, but we need the output - # file to exist to be able to create the target. so to bootstrap, just - # run the command now - c4_dbg("${_c4_prefix}: creating ${output} for the first time") - execute_process( - COMMAND ${cat} "${sepfiles}" "${output}" - WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" - ) - else() - c4_dbg("output exists: ${output}") - endif() - # add a custom command invoking our cat script for the input files - add_custom_command(OUTPUT ${output} - COMMAND ${cat} "${sepfiles}" "${output}" - DEPENDS ${files} - WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" - COMMENT "concatenating sources to ${output}") - if(NOT TARGET ${umbrella_target}) - add_custom_target(${umbrella_target} DEPENDS ${output} ${files}) - endif() -endfunction(c4_cat_sources) - - -#------------------------------------------------------------------------------ -# get a cat script -function(_c4_cat_sources_create_cat catfile) - # create a script to concatenate the sources - if(WIN32) - set(cat ${CMAKE_BINARY_DIR}/_c4catfiles.bat) - set(cattmp ${CMAKE_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/_c4catfiles.bat) - else() - set(cat ${CMAKE_BINARY_DIR}/_c4catfiles.sh) - set(cattmp ${CMAKE_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/_c4catfiles.sh) - endif() - set(${catfile} ${cat} PARENT_SCOPE) - if(NOT EXISTS ${cat}) - if(WIN32) - file(WRITE ${cattmp} " -setlocal EnableDelayedExpansion -set \"src_files=%1\" -set \"out_file=%2\" -echo.>\"out_file%\" -for %%f in (%src_files%) do ( - echo.>>\"%out_file%\" - echo.>>\"%out_file%\" - echo \"/*BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB*/\".>>\"%out_file%\" - echo \"/*BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB*/\".>>\"%out_file%\" - echo \"/*BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB*/\".>>\"%out_file%\" - echo \"#line 1 \\\"%%f\\\" // reset __LINE__ and __FILE__ to the correct value\".>>\"%out_file%\" - type %%f>>\"%out_file%\" -) -") - else() - file(WRITE ${cattmp} "#!/bin/sh - -src_files=$1 -out_file=$2 -#echo \"src_files $src_files\" -#echo \"out_file $out_file\" - -cat > $out_file << EOF -// DO NOT EDIT. -// this is an auto-generated file, and will be overwritten -EOF -for f in $src_files ; do - cat >> $out_file <> $out_file -done - -echo \"Wrote output to $out_file\" -") - endif() - # add execute permissions - get_filename_component(catdir ${cat} DIRECTORY) - file(COPY ${cattmp} DESTINATION ${catdir} - FILE_PERMISSIONS - OWNER_READ OWNER_WRITE OWNER_EXECUTE - GROUP_READ GROUP_EXECUTE - WORLD_READ WORLD_EXECUTE - ) - endif() -endfunction() - - -endif(NOT _c4CatSourcesIncluded) diff --git a/thirdparty/ryml/ext/c4core/cmake/c4Doxygen.cmake b/thirdparty/ryml/ext/c4core/cmake/c4Doxygen.cmake deleted file mode 100644 index b5e018872..000000000 --- a/thirdparty/ryml/ext/c4core/cmake/c4Doxygen.cmake +++ /dev/null @@ -1,121 +0,0 @@ -# (C) 2019 Joao Paulo Magalhaes -if(NOT _c4_doxygen_included) -set(_c4_doxygen_included ON) - - -#------------------------------------------------------------------------------ -# TODO use customizations from https://cmake.org/cmake/help/v3.9/module/FindDoxygen.html -function(c4_setup_doxygen umbrella_option) - cmake_dependent_option(${_c4_uprefix}BUILD_DOCS "Enable targets to build documentation for ${prefix}" ON "${umbrella_option}" OFF) - if(${_c4_uprefix}BUILD_DOCS) - find_package(Doxygen QUIET) - if(DOXYGEN_FOUND) - c4_log("enabling documentation targets") - else() - c4_dbg("doxygen not found") - endif() - endif() -endfunction() - -#------------------------------------------------------------------------------ -function(c4_add_doxygen doc_name) - if(NOT ${_c4_uprefix}BUILD_DOCS) - return() - endif() - # - set(opt0 - ) - set(opt1 - DOXYFILE DOXYFILE_IN - PROJ - PROJ_BRIEF - VERSION - OUTPUT_DIR - CLANG_DATABASE_PATH - ) - set(optN - INPUT - FILE_PATTERNS - EXCLUDE - EXCLUDE_PATTERNS - EXCLUDE_SYMBOLS - STRIP_FROM_PATH - STRIP_FROM_INC_PATH - EXAMPLE_PATH - ) - cmake_parse_arguments("" "${opt0}" "${opt1}" "${optN}" ${ARGN}) - # - if(NOT _PROJ) - set(_PROJ ${_c4_ucprefix}) - endif() - if(NOT _DOXYFILE AND NOT _DOXYFILE_IN) - set(_DOXYFILE_IN ${CMAKE_CURRENT_LIST_DIR}/Doxyfile.in) - endif() - if(NOT _OUTPUT_DIR) - if("${doc_name}" MATCHES "^[Dd]oc") - set(_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/${doc_name}) - else() - set(_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/doc/${doc_name}) - endif() - endif() - # - _c4_doxy_fwd_to_cmd(_PROJ OFF) - _c4_doxy_fwd_to_cmd(_PROJ_BRIEF OFF) - _c4_doxy_fwd_to_cmd(_VERSION OFF) - _c4_doxy_fwd_to_cmd(_OUTPUT_DIR OFF) - _c4_doxy_fwd_to_cmd(_CLANG_DATABASE_PATH OFF) - _c4_doxy_fwd_to_cmd(_INPUT ON) - _c4_doxy_fwd_to_cmd(_FILE_PATTERNS ON) - _c4_doxy_fwd_to_cmd(_EXCLUDE ON) - _c4_doxy_fwd_to_cmd(_EXCLUDE_PATTERNS ON) - _c4_doxy_fwd_to_cmd(_EXCLUDE_SYMBOLS ON) - _c4_doxy_fwd_to_cmd(_STRIP_FROM_PATH ON) - _c4_doxy_fwd_to_cmd(_STRIP_FROM_INC_PATH ON) - _c4_doxy_fwd_to_cmd(_EXAMPLE_PATH ON) - # - if("${doc_name}" MATCHES "^[Dd]oc") - set(tgt ${_c4_lcprefix}-${doc_name}) - else() - set(tgt ${_c4_lcprefix}-doc-${doc_name}) - endif() - # - if(_DOXYFILE) - set(doxyfile_out ${_DOXYFILE}) - elseif(_DOXYFILE_IN) - set(doxyfile_out ${_OUTPUT_DIR}/Doxyfile) - set(config_script ${_c4_project_dir}/c4DoxygenConfig.cmake) - add_custom_command(OUTPUT ${doxyfile_out} - COMMAND ${CMAKE_COMMAND} -E remove -f ${doxyfile_out} - COMMAND ${CMAKE_COMMAND} -DDOXYFILE_IN=${_DOXYFILE_IN} -DDOXYFILE_OUT=${doxyfile_out} ${defs} '-DALLVARS=${allvars}' '-DLISTVARS=${listvars}' -P ${config_script} - DEPENDS ${_DOXYFILE_IN} ${config_script} - COMMENT "${tgt}: generating ${doxyfile_out}" - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - endif() - # - add_custom_target(${tgt} - COMMAND ${DOXYGEN_EXECUTABLE} ${doxyfile_out} - DEPENDS ${doxyfile_out} - WORKING_DIRECTORY ${_OUTPUT_DIR} - COMMENT "${tgt}: docs will be placed in ${_OUTPUT_DIR}" - VERBATIM) - _c4_set_target_folder(${tgt} doc) -endfunction() - - -macro(_c4_doxy_fwd_to_cmd varname is_list) - if(NOT ("${${varname}}" STREQUAL "")) - if("${defs}" STREQUAL "") - set(li "-D${varname}=${${varname}}") - else() - set(li ${defs}) - list(APPEND li "-D${varname}='${${varname}}'") - endif() - set(defs ${li}) - endif() - set(allvars "${allvars};${varname}") - if(${is_list}) - set(listvars "${listvars};${varname}") - endif() -endmacro() - -endif(NOT _c4_doxygen_included) diff --git a/thirdparty/ryml/ext/c4core/cmake/c4DoxygenConfig.cmake b/thirdparty/ryml/ext/c4core/cmake/c4DoxygenConfig.cmake deleted file mode 100644 index b472cab88..000000000 --- a/thirdparty/ryml/ext/c4core/cmake/c4DoxygenConfig.cmake +++ /dev/null @@ -1,24 +0,0 @@ -function(_c4_doxy_list_to_str var) - set(il) - foreach(i ${${var}}) - if("${il}" STREQUAL "") - set(il "${i}") - else() - set(il "${il} ${i}") - endif() - endforeach() - set(${var} "${il}" PARENT_SCOPE) -endfunction() - -string(REPLACE " " ";" ALLVARS ${ALLVARS}) -string(REPLACE " " ";" LISTVARS ${LISTVARS}) - -foreach(var ${LISTVARS}) - _c4_doxy_list_to_str(${var}) -endforeach() - -foreach(var ${ALLVARS}) - message(STATUS "${var}='${${var}}'") -endforeach() - -configure_file(${DOXYFILE_IN} ${DOXYFILE_OUT} @ONLY) diff --git a/thirdparty/ryml/ext/c4core/cmake/c4GetTargetPropertyRecursive.cmake b/thirdparty/ryml/ext/c4core/cmake/c4GetTargetPropertyRecursive.cmake deleted file mode 100644 index 45a74aa9e..000000000 --- a/thirdparty/ryml/ext/c4core/cmake/c4GetTargetPropertyRecursive.cmake +++ /dev/null @@ -1,186 +0,0 @@ -if(NOT _c4_GTPR_included) -set(_c4_GTPR_included ON) - -function(c4_get_target_property_recursive outputvar target property) - # - # helps for debugging - if(_stack) - set(_stack "${_stack}/${target}") - else() - set(_stack "${property}:${target}") - endif() - # - # what type of target is this? - get_target_property(_rec_target_type ${target} TYPE) - c4_dbg("${_stack} [type=${_rec_target_type}]: get property ${property}") - # - # adjust the property names for interface targets - set(_ept_prop_ll LINK_LIBRARIES) - if(_rec_target_type STREQUAL "INTERFACE_LIBRARY") - set(_ept_prop_ll INTERFACE_LINK_LIBRARIES) - if(property STREQUAL "INCLUDE_DIRECTORIES") - c4_dbg("${_stack} [type=${_rec_target_type}]: property ${property} ---> INTERFACE_INCLUDE_DIRECTORIES") - set(property INTERFACE_INCLUDE_DIRECTORIES) - elseif(property STREQUAL "LINK_LIBRARIES") - c4_dbg("${_stack} [type=${_rec_target_type}]: property ${property} ---> INTERFACE_LINK_LIBRARIES") - set(property INTERFACE_LINK_LIBRARIES) - endif() - endif() - # - get_target_property(_ept_li ${target} ${property}) - c4_dbg("${_stack} [type=${_rec_target_type}]: property ${property}=${_ept_li}") - if(NOT _ept_li) # the property may not be set (ie foo-NOTFOUND) - set(_ept_li) # so clear it in that case - endif() - # - # now descend and append the property for each of the linked libraries - get_target_property(_ept_deps ${target} ${_ept_prop_ll}) - if(_ept_deps) - foreach(_ept_ll ${_ept_deps}) - if(TARGET ${_ept_ll}) - c4_get_target_property_recursive(_ept_out ${_ept_ll} ${property}) - list(APPEND _ept_li ${_ept_out}) - endif() - endforeach() - endif() - # - foreach(le_ ${_ept_li}) - string(STRIP "${le_}" le) - if(NOT le) - elseif("${le}" STREQUAL "") - else() - list(APPEND _ept_li_f ${le}) - endif() - endforeach() - c4_dbg("${_stack} [type=${_rec_target_type}]: final=${_ept_li_f}") - set(${outputvar} ${_ept_li_f} PARENT_SCOPE) -endfunction() - - -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ - - -function(c4_set_transitive_property target prop_name prop_value) - set_target_properties(${target} PROPERTIES "${prop_name}" "${prop_value}") -endfunction() - - -function(c4_append_transitive_property target prop_name prop_value) - get_target_property(curr_value ${target} "${prop_name}") - if(curr_value) - list(APPEND curr_value "${prop_value}") - else() - set(curr_value "${prop_value}") - endif() - c4_set_transitive_property(${target} "${prop_name}" "${curr_value}") -endfunction() - - -# TODO: maybe we can use c4_get_target_property_recursive()? -function(c4_get_transitive_property target prop_name out) - if(NOT TARGET ${target}) - return() - endif() - # these will be the names of the variables we'll use to cache the result - set(_trval _C4_TRANSITIVE_${prop_name}) - set(_trmark _C4_TRANSITIVE_${prop_name}_DONE) - # - get_target_property(cached ${target} ${_trmark}) # is it cached already - if(cached) - get_target_property(p ${target} _C4_TRANSITIVE_${prop_name}) - set(${out} ${p} PARENT_SCOPE) - #c4_dbg("${target}: c4_get_transitive_property ${target} ${prop_name}: cached='${p}'") - else() - #c4_dbg("${target}: gathering transitive property: ${prop_name}...") - set(interleaved) - get_target_property(lv ${target} ${prop_name}) - if(lv) - list(APPEND interleaved ${lv}) - endif() - c4_get_transitive_libraries(${target} LINK_LIBRARIES libs) - c4_get_transitive_libraries(${target} INTERFACE_LINK_LIBRARIES ilibs) - list(APPEND libs ${ilibs}) - foreach(lib ${libs}) - #c4_dbg("${target}: considering ${lib}...") - if(NOT lib) - #c4_dbg("${target}: considering ${lib}: not found, skipping...") - continue() - endif() - if(NOT TARGET ${lib}) - #c4_dbg("${target}: considering ${lib}: not a target, skipping...") - continue() - endif() - get_target_property(lv ${lib} ${prop_name}) - if(lv) - list(APPEND interleaved ${lv}) - endif() - c4_get_transitive_property(${lib} ${prop_name} v) - if(v) - list(APPEND interleaved ${v}) - endif() - #c4_dbg("${target}: considering ${lib}---${interleaved}") - endforeach() - #c4_dbg("${target}: gathering transitive property: ${prop_name}: ${interleaved}") - set(${out} ${interleaved} PARENT_SCOPE) - get_target_property(aliased_target ${target} ALIASED_TARGET) - if(NOT aliased_target) - set_target_properties(${target} PROPERTIES - ${_trmark} ON - ${_trval} "${interleaved}") - endif() - endif() -endfunction() - - -function(c4_get_transitive_libraries target prop_name out) - if(NOT TARGET ${target}) - return() - endif() - # these will be the names of the variables we'll use to cache the result - set(_trval _C4_TRANSITIVE_${prop_name}) - set(_trmark _C4_TRANSITIVE_${prop_name}_DONE) - # - get_target_property(cached ${target} ${_trmark}) - if(cached) - get_target_property(p ${target} ${_trval}) - set(${out} ${p} PARENT_SCOPE) - #c4_dbg("${target}: c4_get_transitive_libraries ${target} ${prop_name}: cached='${p}'") - else() - #c4_dbg("${target}: gathering transitive libraries: ${prop_name}...") - get_target_property(target_type ${target} TYPE) - set(interleaved) - if(NOT ("${target_type}" STREQUAL "INTERFACE_LIBRARY") - AND ("${prop_name}" STREQUAL LINK_LIBRARIES)) - get_target_property(l ${target} ${prop_name}) - foreach(ll ${l}) - #c4_dbg("${target}: considering ${ll}...") - if(NOT ll) - #c4_dbg("${target}: considering ${ll}: not found, skipping...") - continue() - endif() - if(NOT ll) - #c4_dbg("${target}: considering ${ll}: not a target, skipping...") - continue() - endif() - list(APPEND interleaved ${ll}) - c4_get_transitive_libraries(${ll} ${prop_name} v) - if(v) - list(APPEND interleaved ${v}) - endif() - #c4_dbg("${target}: considering ${ll}---${interleaved}") - endforeach() - endif() - #c4_dbg("${target}: gathering transitive libraries: ${prop_name}: result='${interleaved}'") - set(${out} ${interleaved} PARENT_SCOPE) - get_target_property(aliased_target ${target} ALIASED_TARGET) - if(NOT aliased_target) - set_target_properties(${target} PROPERTIES - ${_trmark} ON - ${_trval} "${interleaved}") - endif() - endif() -endfunction() - -endif(NOT _c4_GTPR_included) diff --git a/thirdparty/ryml/ext/c4core/cmake/c4Project.cmake b/thirdparty/ryml/ext/c4core/cmake/c4Project.cmake deleted file mode 100644 index 60c8717fe..000000000 --- a/thirdparty/ryml/ext/c4core/cmake/c4Project.cmake +++ /dev/null @@ -1,3691 +0,0 @@ -if(NOT _c4_project_included) -set(_c4_project_included ON) -set(_c4_project_file ${CMAKE_CURRENT_LIST_FILE}) -set(_c4_project_dir ${CMAKE_CURRENT_LIST_DIR}) - - -# "I didn't have time to write a short letter, so I wrote a long one -# instead." -- Mark Twain -# -# ... Eg, hopefully this code will be cleaned up. There's a lot of -# code here that can be streamlined into a more intuitive arrangement. - - -cmake_minimum_required(VERSION 3.12 FATAL_ERROR) - -list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) -set_property(GLOBAL PROPERTY USE_FOLDERS ON) - -include(ConfigurationTypes) -include(CreateSourceGroup) -include(c4SanitizeTarget) -include(c4StaticAnalysis) -include(PrintVar) -include(c4CatSources) -include(c4Doxygen) -include(PatchUtils) - - -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ -# define c4 project settings - -set(C4_EXTERN_DIR "$ENV{C4_EXTERN_DIR}" CACHE PATH "the directory where imported projects should be looked for (or cloned in when not found)") -set(C4_DBG_ENABLED OFF CACHE BOOL "enable detailed cmake logs in c4Project code") -set(C4_LIBRARY_TYPE "" CACHE STRING "default library type: either \"\"(defer to BUILD_SHARED_LIBS),INTERFACE,STATIC,SHARED,MODULE") -set(C4_SOURCE_TRANSFORM NONE CACHE STRING "global source transform method") -set(C4_HDR_EXTS "h;hpp;hh;h++;hxx" CACHE STRING "list of header extensions for determining which files are headers") -set(C4_SRC_EXTS "c;cpp;cc;c++;cxx;cu;" CACHE STRING "list of compilation unit extensions for determining which files are sources") -set(C4_ADD_EXTS "natvis" CACHE STRING "list of additional file extensions that might be added as sources to targets") -set(C4_GEN_SRC_EXT "cpp" CACHE STRING "the extension of the output source files resulting from concatenation") -set(C4_GEN_HDR_EXT "hpp" CACHE STRING "the extension of the output header files resulting from concatenation") -set(C4_CXX_STANDARDS "20;17;14;11" CACHE STRING "list of CXX standards") -set(C4_CXX_STANDARD_DEFAULT "11" CACHE STRING "the default CXX standard for projects not specifying one") - - -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ - -macro(c4_log) - message(STATUS "${_c4_prefix}: ${ARGN}") -endmacro() - - -macro(c4_err) - message(FATAL_ERROR "${_c4_prefix}: ${ARGN}") -endmacro() - - -macro(c4_dbg) - if(C4_DBG_ENABLED) - message(STATUS "${_c4_prefix}: ${ARGN}") - endif() -endmacro() - - -macro(c4_log_var varname) - c4_log("${varname}=${${varname}} ${ARGN}") -endmacro() -macro(c4_log_vars) - set(____s____) - foreach(varname ${ARGN}) - set(____s____ "${____s____}${varname}=${${varname}} ") - endforeach() - c4_log("${____s____}") -endmacro() -macro(c4_dbg_var varname) - c4_dbg("${varname}=${${varname}} ${ARGN}") -endmacro() -macro(c4_log_var_if varname) - if(${varname}) - c4_log("${varname}=${${varname}} ${ARGN}") - endif() -endmacro() -macro(c4_dbg_var_if varname) - if(${varname}) - c4_dbg("${varname}=${${varname}} ${ARGN}") - endif() -endmacro() - - -macro(_c4_show_pfx_vars) - if(NOT ("${ARGN}" STREQUAL "")) - c4_log("prefix vars: ${ARGN}") - endif() - print_var(_c4_prefix) - print_var(_c4_ocprefix) - print_var(_c4_ucprefix) - print_var(_c4_lcprefix) - print_var(_c4_oprefix) - print_var(_c4_uprefix) - print_var(_c4_lprefix) -endmacro() - - -function(c4_zero_pad padded size str) - string(LENGTH "${str}" len) - math(EXPR numchars "${size} - ${len}") - if(numchars EQUAL 0) - set(${padded} "${str}" PARENT_SCOPE) - else() - set(out "${str}") - math(EXPR ncm1 "${numchars} - 1") - foreach(z RANGE ${ncm1}) - set(out "0${out}") - endforeach() - set(${padded} "${out}" PARENT_SCOPE) - endif() -endfunction() - - -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ - -# handy macro for dealing with arguments in one single statement. -# look for example usage cases below. -macro(_c4_handle_args) - set(opt0arg - ) - set(opt1arg - _PREFIX - ) - set(optNarg - _ARGS0 - _ARGS1 - _ARGSN - _ARGS - _DEPRECATE - ) - # parse the arguments to this macro to find out the required arguments - cmake_parse_arguments("__c4ha" "${opt0arg}" "${opt1arg}" "${optNarg}" ${ARGN}) - # now parse the required arguments - cmake_parse_arguments("${__c4ha__PREFIX}" "${__c4ha__ARGS0}" "${__c4ha__ARGS1}" "${__c4ha__ARGSN}" ${__c4ha__ARGS}) - # raise an error on deprecated arguments - foreach(a ${__c4ha__DEPRECATE}) - list(FIND __c4ha__ARGS ${a} contains) - if(NOT (${contains} EQUAL -1)) - c4err("${a} is deprecated") - endif() - endforeach() -endmacro() - -# fallback to provided default(s) if argument is not set -macro(_c4_handle_arg argname) - if("${_${argname}}" STREQUAL "") - set(_${argname} "${ARGN}") - else() - set(_${argname} "${_${argname}}") - endif() -endmacro() -macro(_c4_handle_arg_no_pfx argname) - if("${${argname}}" STREQUAL "") - set(${argname} "${ARGN}") - else() - set(${argname} "${${argname}}") - endif() -endmacro() - - -# if ${_${argname}} is non empty, return it -# otherwise, fallback to ${_c4_uprefix}${argname} -# otherwise, fallback to C4_${argname} -# otherwise, fallback to provided default through ${ARGN} -macro(_c4_handle_arg_or_fallback argname) - if(NOT ("${_${argname}}" STREQUAL "")) - c4_dbg("handle arg ${argname}: picking explicit value _${argname}=${_${argname}}") - else() - foreach(_c4haf_varname "${_c4_uprefix}${argname}" "C4_${argname}" "${argname}" "CMAKE_${argname}") - set(v ${${_c4haf_varname}}) - if("${v}" STREQUAL "") - c4_dbg("handle arg ${argname}: ${_c4haf_varname}: empty, continuing") - else() - c4_dbg("handle arg ${argname}: ${_c4haf_varname}=${v} not empty!") - c4_setg(_${argname} "${v}") - break() - endif() - endforeach() - if("${_${argname}}" STREQUAL "") - c4_dbg("handle arg ${argname}: picking default: ${ARGN}") - c4_setg(_${argname} "${ARGN}") - endif() - endif() -endmacro() - - -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ - -function(c4_get_config var name) - c4_dbg("get_config: ${var} ${name}") - c4_get_from_first_of(config ${ARGN} VARS ${_c4_uprefix}${name} C4_${name} ${name}) - c4_dbg("get_config: ${var} ${name}=${config}") - set(${var} ${config} PARENT_SCOPE) -endfunction() - - -function(c4_get_from_first_of var) - _c4_handle_args(_ARGS ${ARGN} - _ARGS0 - REQUIRED # raise an error if no set variable was found - ENV # if none of the provided vars is given, - # then search next on environment variables - # of the same name, using the same sequence - _ARGS1 - DEFAULT - _ARGSN - VARS - ) - c4_dbg("get_from_first_of(): searching ${var}") - foreach(_var ${_VARS}) - set(val ${${_var}}) - c4_dbg("${var}: searching ${_var}=${val}") - if(NOT ("${val}" STREQUAL "")) - set(${var} "${val}" PARENT_SCOPE) - return() - endif() - endforeach() - if(_ENV) - foreach(_envvar ${_VARS}) - set(val $ENV{${_envvar}}) - c4_dbg("${var}: searching environment variable ${_envvar}=${val}") - if(NOT ("${val}" STREQUAL "")) - c4_dbg("${var}: picking ${val} from ${_envvar}") - set(${var} "${val}" PARENT_SCOPE) - return() - endif() - endforeach() - endif() - if(_REQUIRED) - c4_err("could not find a value for the variable ${var}") - endif() - set(${var} ${_DEFAULT} PARENT_SCOPE) -endfunction() - - -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ - -# assumes a prior call to project() -function(c4_project) - _c4_handle_args(_ARGS ${ARGN} - _ARGS0 # zero-value macro arguments - STANDALONE # Declare that targets from this project MAY be - # compiled in standalone mode. In this mode, any - # designated libraries on which a target depends - # will be incorporated into the target instead of - # being linked with it. The effect is to "flatten" - # those libraries into the requesting library, with - # their sources now becoming part of the requesting - # library; their dependencies are transitively handled. - # Note that requesting targets must explicitly - # opt-in to this behavior via the INCORPORATE - # argument to c4_add_library() or - # c4_add_executable(). Note also that this behavior - # is only enabled if this project's option - # ${prefix}_STANDALONE or C4_STANDALONE is set to ON. - _ARGS1 # one-value macro arguments - AUTHOR # specify author(s); used in cpack - VERSION # cmake does not accept semantic versioning so we provide - # that here (see https://gitlab.kitware.com/cmake/cmake/-/issues/16716) - CXX_STANDARD # one of latest;${C4_VALID_CXX_STANDARDS} - # if this is not provided, falls back on - # ${uprefix}CXX_STANDARD, then C4_CXX_STANDARD, - # then CXX_STANDARD. if none are provided, - # defaults to 11 - _ARGSN # multi-value macro arguments - ) - # get the prefix from the call to project() - set(prefix ${PROJECT_NAME}) - string(TOUPPER "${prefix}" ucprefix) # ucprefix := upper case prefix - string(TOLOWER "${prefix}" lcprefix) # lcprefix := lower case prefix - if(NOT _c4_prefix) - c4_setg(_c4_is_root_proj ON) - c4_setg(_c4_root_proj ${prefix}) - c4_setg(_c4_root_uproj ${ucprefix}) - c4_setg(_c4_root_lproj ${lcprefix}) - c4_setg(_c4_curr_path "") - else() - c4_setg(_c4_is_root_proj OFF) - if(_c4_curr_path) - c4_setg(_c4_curr_path "${_c4_curr_path}/${prefix}") - else() - c4_setg(_c4_curr_path "${prefix}") - endif() - endif() - c4_setg(_c4_curr_subproject ${prefix}) - # get the several prefix flavors - c4_setg(_c4_ucprefix ${ucprefix}) - c4_setg(_c4_lcprefix ${lcprefix}) - c4_setg(_c4_ocprefix ${prefix}) # ocprefix := original case prefix - c4_setg(_c4_prefix ${prefix}) # prefix := original prefix - c4_setg(_c4_oprefix ${prefix}) # oprefix := original prefix - c4_setg(_c4_uprefix ${_c4_ucprefix}) # upper prefix: for variables - c4_setg(_c4_lprefix ${_c4_lcprefix}) # lower prefix: for targets - if(_c4_oprefix) - c4_setg(_c4_oprefix "${_c4_oprefix}_") - endif() - if(_c4_uprefix) - c4_setg(_c4_uprefix "${_c4_uprefix}_") - endif() - if(_c4_lprefix) - c4_setg(_c4_lprefix "${_c4_lprefix}-") - endif() - # - if(_STANDALONE) - option(${_c4_uprefix}STANDALONE - "Enable compilation of opting-in targets from ${_c4_lcprefix} in standalone mode (ie, incorporate subprojects as specified in the INCORPORATE clause to c4_add_library/c4_add_target)" - ${_c4_is_root_proj}) - c4_setg(_c4_root_proj_standalone ${_c4_uprefix}STANDALONE) - endif() - _c4_handle_arg_or_fallback(CXX_STANDARD ${C4_CXX_STANDARD_DEFAULT}) - _c4_handle_arg(VERSION 0.0.0-pre0) - _c4_handle_arg(AUTHOR "") - _c4_handle_semantic_version(${_VERSION}) - # - # make sure project-wide settings are defined -- see cmake's - # documentation for project(), which defines these and other - # variables - if("${PROJECT_DESCRIPTION}" STREQUAL "") - c4_setg(PROJECT_DESCRIPTION "${prefix}") - c4_setg(${prefix}_DESCRIPTION "${prefix}") - endif() - if("${PROJECT_HOMEPAGE_URL}" STREQUAL "") - c4_setg(PROJECT_HOMEPAGE_URL "") - c4_setg(${prefix}_HOMEPAGE_URL "") - endif() - # other specific c4_project properties - c4_setg(PROJECT_AUTHOR "${_AUTHOR}") - c4_setg(${prefix}_AUTHOR "${_AUTHOR}") - - # CXX standard - if("${_CXX_STANDARD}" STREQUAL "latest") - _c4_find_latest_supported_cxx_standard(_CXX_STANDARD) - endif() - c4_log("using C++ standard: C++${_CXX_STANDARD}") - c4_set_proj_prop(CXX_STANDARD "${_CXX_STANDARD}") - c4_setg(${_c4_uprefix}CXX_STANDARD "${_CXX_STANDARD}") - if(${_CXX_STANDARD}) - c4_set_cxx(${_CXX_STANDARD}) - endif() - - # we are opinionated with respect to directory structure - c4_setg(${_c4_uprefix}SRC_DIR ${CMAKE_CURRENT_LIST_DIR}/src) - c4_setg(${_c4_uprefix}EXT_DIR ${CMAKE_CURRENT_LIST_DIR}/ext) - c4_setg(${_c4_uprefix}API_DIR ${CMAKE_CURRENT_LIST_DIR}/api) - # opionionated also for directory test - # opionionated also for directory bm (benchmarks) - - if("${C4_DEV}" STREQUAL "") - option(C4_DEV "enable development targets for all c4 projects" OFF) - endif() - option(${_c4_uprefix}DEV "enable development targets: tests, benchmarks, sanitize, static analysis, coverage" ${C4_DEV}) - - if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/test") - cmake_dependent_option(${_c4_uprefix}BUILD_TESTS "build unit tests" ON ${_c4_uprefix}DEV OFF) - else() - c4_dbg("no tests: directory does not exist: ${CMAKE_CURRENT_LIST_DIR}/test") - endif() - if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/bm") - cmake_dependent_option(${_c4_uprefix}BUILD_BENCHMARKS "build benchmarks" ON ${_c4_uprefix}DEV OFF) - else() - c4_dbg("no benchmarks: directory does not exist: ${CMAKE_CURRENT_LIST_DIR}/bm") - endif() - if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/api") - cmake_dependent_option(${_c4_uprefix}BUILD_API "build API" OFF ${_c4_uprefix}DEV OFF) - else() - c4_dbg("no API generation: directory does not exist: ${CMAKE_CURRENT_LIST_DIR}/api") - endif() - if(_c4_is_root_proj) - c4_setup_coverage() - endif() - c4_setup_valgrind(${_c4_uprefix}DEV) - c4_setup_sanitize(${_c4_uprefix}DEV) - c4_setup_static_analysis(${_c4_uprefix}DEV) - c4_setup_doxygen(${_c4_uprefix}DEV) - - # option to use libc++ - option(${_c4_uprefix}USE_LIBCXX "use libc++ instead of the default standard library" OFF) - if(${_c4_uprefix}USE_LIBCXX) - if(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") - c4_log("using libc++") - list(APPEND CMAKE_CXX_FLAGS -stdlib=libc++) - list(APPEND CMAKE_EXE_LINKER_FLAGS -lc++) - list(APPEND CMAKE_MODULE_LINKER_FLAGS -lc++) - list(APPEND CMAKE_SHARED_LINKER_FLAGS -lc++) - list(APPEND CMAKE_STATIC_LINKER_FLAGS -lc++) - else() - c4_err("libc++ can only be used with clang") - endif() - endif() - - # default compilation flags - set(${_c4_uprefix}CXX_FLAGS "${${_c4_uprefix}CXX_FLAGS_FWD}" CACHE STRING "compilation flags for ${_c4_prefix} targets") - set(${_c4_uprefix}CXX_LINKER_FLAGS "${${_c4_uprefix}CXX_LINKER_FLAGS_FWD}" CACHE STRING "linker flags for ${_c4_prefix} targets") - c4_dbg_var_if(${_c4_uprefix}CXX_LINKER_FLAGS_FWD) - c4_dbg_var_if(${_c4_uprefix}CXX_FLAGS_FWD) - c4_dbg_var_if(${_c4_uprefix}CXX_LINKER_FLAGS) - c4_dbg_var_if(${_c4_uprefix}CXX_FLAGS) - - # Dev compilation flags, appended to the project's flags. They - # are enabled when in dev mode, but provided as a (default-disabled) - # option when not in dev mode - c4_dbg_var_if(${_c4_uprefix}CXX_FLAGS_OPT_FWD) - c4_setg(${_c4_uprefix}CXX_FLAGS_OPT "${${_c4_uprefix}CXX_FLAGS_OPT_FWD}") - c4_optional_compile_flags_dev(WERROR "Compile with warnings as errors" - GCC_CLANG -Werror -pedantic-errors - MSVC /WX - ) - c4_optional_compile_flags_dev(STRICT_ALIASING "Enable strict aliasing" - GCC_CLANG -fstrict-aliasing - MSVC # does it have this? - ) - c4_optional_compile_flags_dev(PEDANTIC "Compile in pedantic mode" - GCC ${_C4_PEDANTIC_FLAGS_GCC} - CLANG ${_C4_PEDANTIC_FLAGS_CLANG} - MSVC ${_C4_PEDANTIC_FLAGS_MSVC} - ) - c4_dbg_var_if(${_c4_uprefix}CXX_FLAGS_OPT) -endfunction(c4_project) - - -# cmake: VERSION argument in project() does not accept semantic versioning -# see: https://gitlab.kitware.com/cmake/cmake/-/issues/16716 -macro(_c4_handle_semantic_version version) - # https://stackoverflow.com/questions/18658233/split-string-to-3-variables-in-cmake - string(REPLACE "." ";" version_list ${version}) - list(GET version_list 0 _major) - list(GET version_list 1 _minor) - list(GET version_list 2 _patch) - if("${_patch}" STREQUAL "") - set(_patch 1) - set(_tweak) - else() - string(REGEX REPLACE "([0-9]+)[-_.]?(.*)" "\\2" _tweak ${_patch}) # do this first - string(REGEX REPLACE "([0-9]+)[-_.]?(.*)" "\\1" _patch ${_patch}) # ... because this replaces _patch - endif() - # because cmake handles only numeric tweak fields, make sure to skip our - # semantic tweak field if it is not numeric - if(${_tweak} MATCHES "^[0-9]+$") - set(_safe_tweak ${_tweak}) - set(_safe_version ${_major}.${_minor}.${_patch}.${_tweak}) - else() - set(_safe_tweak) - set(_safe_version ${_major}.${_minor}.${_patch}) - endif() - c4_setg(PROJECT_VERSION_FULL ${version}) - c4_setg(PROJECT_VERSION ${_safe_version}) - c4_setg(PROJECT_VERSION_MAJOR ${_major}) - c4_setg(PROJECT_VERSION_MINOR ${_minor}) - c4_setg(PROJECT_VERSION_PATCH ${_patch}) - c4_setg(PROJECT_VERSION_TWEAK "${_safe_tweak}") - c4_setg(PROJECT_VERSION_TWEAK_FULL "${_tweak}") - c4_setg(${prefix}_VERSION_FULL ${version}) - c4_setg(${prefix}_VERSION ${_safe_version}) - c4_setg(${prefix}_VERSION_MAJOR ${_major}) - c4_setg(${prefix}_VERSION_MINOR ${_minor}) - c4_setg(${prefix}_VERSION_PATCH ${_patch}) - c4_setg(${prefix}_VERSION_TWEAK "${_safe_tweak}") - c4_setg(${prefix}_VERSION_TWEAK_FULL "${_tweak}") -endmacro() - - -# Add targets for testing (dir=./test), benchmark (dir=./bm) and API (dir=./api). -# Call this macro towards the end of the project's main CMakeLists.txt. -# Experimental feature: docs. -function(c4_add_dev_targets) - if(NOT CMAKE_CURRENT_LIST_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) - c4_err("this macro needs to be called on the project's main CMakeLists.txt file") - endif() - # - if(${_c4_uprefix}BUILD_TESTS) - if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/test") - c4_dbg("adding tests: ${CMAKE_CURRENT_LIST_DIR}/test") - enable_testing() # this must be done here (and not inside the - # test dir) so that the cmake-generated test - # targets are available at the top level - add_subdirectory(test) - endif() - endif() - # - if(${_c4_uprefix}BUILD_BENCHMARKS) - if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/bm") - c4_dbg("adding benchmarks: ${CMAKE_CURRENT_LIST_DIR}/bm") - add_subdirectory(bm) - endif() - endif() - # - if(${_c4_uprefix}BUILD_API) - if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/api") - c4_dbg("adding API: ${d}") - add_subdirectory(api) - endif() - endif() - # - # FIXME - c4_add_doxygen(doc DOXYFILE_IN ${_c4_project_dir}/Doxyfile.in - PROJ c4core - INPUT ${${_c4_uprefix}SRC_DIR} - EXCLUDE ${${_c4_uprefix}EXT_DIR} ${${_c4_uprefix}SRC_DIR}/c4/ext - STRIP_FROM_PATH ${${_c4_uprefix}SRC_DIR} - STRIP_FROM_INC_PATH ${${_c4_uprefix}SRC_DIR} - CLANG_DATABASE_PATH ${CMAKE_BINARY_DIR} - ) - c4_add_doxygen(doc-full DOXYFILE_IN ${_c4_project_dir}/Doxyfile.full.in - PROJ c4core - INPUT ${${_c4_uprefix}SRC_DIR} - EXCLUDE ${${_c4_uprefix}EXT_DIR} ${${_c4_uprefix}SRC_DIR}/c4/ext - STRIP_FROM_PATH ${${_c4_uprefix}SRC_DIR} - STRIP_FROM_INC_PATH ${${_c4_uprefix}SRC_DIR} - CLANG_DATABASE_PATH ${CMAKE_BINARY_DIR} - ) -endfunction() - - -function(_c4_get_san_targets target result) - _c4_get_tgt_prop(san_targets ${target} C4_SAN_TARGETS) - if(NOT san_targets) - #c4_err("${target} must have at least itself in its sanitized target list") - set(${result} ${target} PARENT_SCOPE) - else() - set(${result} ${san_targets} PARENT_SCOPE) - endif() -endfunction() - - -# ----------------------------------------------------------------------------- -# ----------------------------------------------------------------------------- -# ----------------------------------------------------------------------------- - -# utilities for compilation flags and defines - -# flags enabled only on dev mode -macro(c4_optional_compile_flags_dev tag desc) - _c4_handle_args(_ARGS ${ARGN} - _ARGS0 - _ARGS1 - _ARGSN - MSVC # flags for Visual Studio compilers - GCC # flags for gcc compilers - CLANG # flags for clang compilers - GCC_CLANG # flags common to gcc and clang - _DEPRECATE - ) - cmake_dependent_option(${_c4_uprefix}${tag} "${desc}" ON ${_c4_uprefix}DEV OFF) - set(optname ${_c4_uprefix}${tag}) - if(${optname}) - c4_dbg("${optname} is enabled. Adding flags...") - if(MSVC) - set(flags ${_MSVC}) - elseif(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") - set(flags ${_GCC_CLANG};${_CLANG}) - elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - set(flags ${_GCC_CLANG};${_GCC}) - elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Intel") - set(flags ${_ALL};${_GCC_CLANG};${_GCC}) # FIXME - elseif(CMAKE_CXX_COMPILER_ID STREQUAL "IntelLLVM") - set(flags ${_ALL};${_GCC_CLANG};${_CLANG}) # FIXME - else() - c4_err("unknown compiler") - endif() - else() - c4_dbg("${optname} is disabled.") - endif() - if(flags) - c4_log("${tag} flags [${desc}]: ${flags}") - c4_setg(${_c4_uprefix}CXX_FLAGS_OPT "${${_c4_uprefix}CXX_FLAGS_OPT};${flags}") - endif() -endmacro() - - -function(c4_target_compile_flags target) - _c4_handle_args(_ARGS ${ARGN} - _ARGS0 - PUBLIC - PRIVATE - INTERFACE - AFTER # this is the default - BEFORE - _ARGS1 - _ARGSN - ALL # flags for all compilers - MSVC # flags for Visual Studio compilers - GCC # flags for gcc compilers - CLANG # flags for clang compilers - GCC_CLANG # flags common to gcc and clang - _DEPRECATE - ) - if(MSVC) - set(flags ${_ALL};${_MSVC}) - elseif(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") - set(flags ${_ALL};${_GCC_CLANG};${_CLANG}) - elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - set(flags ${_ALL};${_GCC_CLANG};${_GCC}) - elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Intel") - set(flags ${_ALL};${_GCC_CLANG};${_GCC}) # FIXME - elseif(CMAKE_CXX_COMPILER_ID STREQUAL "IntelLLVM") - set(flags ${_ALL};${_GCC_CLANG};${_CLANG}) # FIXME - else() - c4_err("unknown compiler") - endif() - if(NOT flags) - c4_dbg("no compile flags to be set") - return() - endif() - if(_AFTER OR (NOT _BEFORE)) - set(mode) - c4_log("${target}: adding compile flags AFTER: ${flags}") - elseif(_BEFORE) - set(mode BEFORE) - c4_log("${target}: adding compile flags BEFORE: ${flags}") - endif() - _c4_get_san_targets(${target} san_targets) - foreach(st ${san_targets}) - if(_PUBLIC) - target_compile_options(${st} ${mode} PUBLIC ${flags}) - elseif(_PRIVATE) - target_compile_options(${st} ${mode} PRIVATE ${flags}) - elseif(_INTERFACE) - target_compile_options(${st} ${mode} INTERFACE ${flags}) - else() - c4_err("${target}: must have one of PUBLIC, PRIVATE or INTERFACE") - endif() - endforeach() -endfunction() - - -function(c4_target_definitions target) - _c4_handle_args(_ARGS ${ARGN} - _ARGS0 - PUBLIC - PRIVATE - INTERFACE - _ARGS1 - _ARGSN - ALL # defines for all compilers - MSVC # defines for Visual Studio compilers - GCC # defines for gcc compilers - CLANG # defines for clang compilers - GCC_CLANG # defines common to gcc and clang - _DEPRECATE - ) - if(MSVC) - set(flags ${_ALL};${_MSVC}) - elseif(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") - set(flags ${_ALL};${_GCC_CLANG};${_CLANG}) - elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - set(flags ${_ALL};${_GCC_CLANG};${_GCC}) - else() - c4_err("unknown compiler") - endif() - if(NOT flags) - c4_dbg("no compile flags to be set") - return() - endif() - if(_AFTER OR (NOT _BEFORE)) - set(mode) - c4_log("${target}: adding definitions AFTER: ${flags}") - elseif(_BEFORE) - set(mode BEFORE) - c4_log("${target}: adding definitions BEFORE: ${flags}") - endif() - _c4_get_san_targets(${target} san_targets) - foreach(st ${san_targets}) - if(_PUBLIC) - target_compile_definitions(${st} ${mode} PUBLIC ${flags}) - elseif(_PRIVATE) - target_compile_definitions(${st} ${mode} PRIVATE ${flags}) - elseif(_INTERFACE) - target_compile_definitions(${st} ${mode} INTERFACE ${flags}) - else() - c4_err("${target}: must have one of PUBLIC, PRIVATE or INTERFACE") - endif() - endforeach() -endfunction() - - -function(c4_target_remove_compile_flags target) - _c4_handle_args(_ARGS ${ARGN} - _ARGS0 - PUBLIC # remove only from public compile options - INTERFACE # remove only from interface compile options - _ARGS1 - _ARGSN - MSVC # flags for Visual Studio compilers - GCC # flags for gcc compilers - CLANG # flags for clang compilers - GCC_CLANG # flags common to gcc and clang - _DEPRECATE - ) - if(MSVC) - set(flags ${_MSVC}) - elseif(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") - set(flags ${_GCC_CLANG};${_CLANG}) - elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - set(flags ${_GCC_CLANG};${_GCC}) - else() - c4_err("unknown compiler") - endif() - if(NOT flags) - return() - endif() - _c4_get_san_targets(${target} san_targets) - foreach(st ${san_targets}) - if(_PUBLIC OR (NOT _INTERFACE)) - get_target_property(co ${st} COMPILE_OPTIONS) - if(co) - _c4_remove_entries_from_list("${flags}" co) - set_target_properties(${st} PROPERTIES COMPILE_OPTIONS "${co}") - endif() - endif() - if(_INTERFACE OR (NOT _PUBLIC)) - get_target_property(ico ${st} INTERFACE_COMPILE_OPTIONS) - if(ico) - _c4_remove_entries_from_list("${flags}" ico) - set_target_properties(${st} PROPERTIES INTERFACE_COMPILE_OPTIONS "${ico}") - endif() - endif() - endforeach() -endfunction() - - -function(_c4_remove_entries_from_list entries_to_remove list) - set(str ${${list}}) - string(REPLACE ";" "==?==" str "${str}") - foreach(entry ${entries_to_remove}) - string(REPLACE "${entry}" "" str "${str}") - endforeach() - string(REPLACE "==?==" ";" str "${str}") - string(REPLACE ";;" ";" str "${str}") - set(${list} "${str}" PARENT_SCOPE) -endfunction() - - - -# pedantic flags... -# default pedantic flags taken from: -# https://github.com/lefticus/cpp_starter_project/blob/master/cmake/CompilerWarnings.cmake -set(_C4_PEDANTIC_FLAGS_MSVC - /W4 # Baseline reasonable warnings - /w14242 # 'identifier': conversion from 'type1' to 'type1', possible loss of data - /w14254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data - /w14263 # 'function': member function does not override any base class virtual member function - /w14265 # 'classname': class has virtual functions, but destructor is not virtual instances of this class may not - # be destructed correctly - /w14287 # 'operator': unsigned/negative constant mismatch - /we4289 # nonstandard extension used: 'variable': loop control variable declared in the for-loop is used outside - # the for-loop scope - /w14296 # 'operator': expression is always 'boolean_value' - /w14311 # 'variable': pointer truncation from 'type1' to 'type2' - /w14545 # expression before comma evaluates to a function which is missing an argument list - /w14546 # function call before comma missing argument list - /w14547 # 'operator': operator before comma has no effect; expected operator with side-effect - /w14549 # 'operator': operator before comma has no effect; did you intend 'operator'? - /w14555 # expression has no effect; expected expression with side- effect - /w14619 # pragma warning: there is no warning number 'number' - /w14640 # Enable warning on thread un-safe static member initialization - /w14826 # Conversion from 'type1' to 'type_2' is sign-extended. This may cause unexpected runtime behavior. - /w14905 # wide string literal cast to 'LPSTR' - /w14906 # string literal cast to 'LPWSTR' - /w14928 # illegal copy-initialization; more than one user-defined conversion has been implicitly applied - $<$:/permissive-> # standards conformance mode for MSVC compiler (only vs2017+) - ) - -set(_C4_PEDANTIC_FLAGS_CLANG - -Wall - -Wextra - -pedantic - -Wshadow # warn the user if a variable declaration shadows one from a parent context - -Wnon-virtual-dtor # warn the user if a class with virtual functions has a non-virtual destructor. This helps - # catch hard to track down memory errors - #-Wold-style-cast # warn for c-style casts - -Wcast-align # warn for potential performance problem casts - -Wunused # warn on anything being unused - -Woverloaded-virtual # warn if you overload (not override) a virtual function - -Wpedantic # warn if non-standard C++ is used - -Wconversion # warn on type conversions that may lose data - -Wsign-conversion # warn on sign conversions - -Wdouble-promotion # warn if float is implicit promoted to double - -Wfloat-equal # warn if comparing floats - -Wformat=2 # warn on security issues around functions that format output (ie printf) - ) - -set(_C4_PEDANTIC_FLAGS_GCC ${_C4_PEDANTIC_FLAGS_CLANG} - -Wlogical-op # where logical operations are used where bitwise were probably wanted - -Wuseless-cast # where you perform a cast to the same type - ) - -if((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") AND (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 6.0)) - list(APPEND _C4_PEDANTIC_FLAGS_GCC - -Wnull-dereference # warn if a null dereference is detected - -Wmisleading-indentation # where indentation implies blocks where blocks do not exist - -Wduplicated-cond # where if-else chain has duplicated conditions - ) -endif() - -if((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") AND (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 7.0)) - list(APPEND _C4_PEDANTIC_FLAGS_GCC - -Wduplicated-branches # where if-else branches have duplicated code - ) -endif() - - -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ - -function(c4_pack_project) - # if this is the top-level project... pack it. - if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) - c4_log("packing the project: ${ARGN}") - c4_set_default_pack_properties(${ARGN}) - include(CPack) - endif() -endfunction() - - -# [WIP] set convenient defaults for the properties used by CPack -function(c4_set_default_pack_properties) - _c4_handle_args(_ARGS ${ARGN} - _ARGS0 # zero-value macro arguments - _ARGS1 # one-value macro arguments - TYPE # one of LIBRARY, EXECUTABLE - _ARGSN # multi-value macro arguments - ) - set(pd "${PROJECT_SOURCE_DIR}") - _c4_handle_arg(TYPE EXECUTABLE) # default to EXECUTABLE - # - _c4_get_platform_tag(platform_tag) - if("${_TYPE}" STREQUAL "LIBRARY") - if(BUILD_SHARED_LIBS) - set(build_tag "-shared") - else() - set(build_tag "-static") - endif() - get_property(multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) - if(multi_config) - # doesn't work because generators are not evaluated: set(build_tag "${build_tag}-$") - # doesn't work because generators are not evaluated: set(build_tag "${build_tag}$<$:-Debug>$<$:-MinSizeRel>$<$:-Release>$<$:-RelWithDebInfo>") - # see also https://stackoverflow.com/questions/44153730/how-to-change-cpack-package-file-name-based-on-configuration - if(CMAKE_BUILD_TYPE) # in the off-chance it was explicitly set - set(build_tag "${build_tag}-${CMAKE_BUILD_TYPE}") - endif() - else() - set(build_tag "${build_tag}-${CMAKE_BUILD_TYPE}") - endif() - elseif("${_TYPE}" STREQUAL "EXECUTABLE") - set(build_tag) - elseif() - c4_err("unknown TYPE: ${_TYPE}") - endif() - # - c4_setg(CPACK_VERBATIM_VARIABLES true) - c4_setg(CPACK_PACKAGE_VENDOR "${${_c4_prefix}_HOMEPAGE_URL}") - c4_setg(CPACK_PACKAGE_CONTACT "${${_c4_prefix}_AUTHOR}") - c4_setg(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${${_c4_prefix}_DESCRIPTION}") - if(EXISTS "${pd}/README.md") - c4_setg(CPACK_PACKAGE_DESCRIPTION_FILE "${pd}/README.md") - c4_setg(CPACK_PACKAGE_DESCRIPTION_README "${pd}/README.md") - c4_setg(CPACK_PACKAGE_DESCRIPTION_WELCOME "${pd}/README.md") - elseif(EXISTS "${pd}/README.txt") - c4_setg(CPACK_PACKAGE_DESCRIPTION_FILE "${pd}/README.txt") - c4_setg(CPACK_PACKAGE_DESCRIPTION_README "${pd}/README.txt") - c4_setg(CPACK_PACKAGE_DESCRIPTION_WELCOME "${pd}/README.txt") - endif() - if(EXISTS "${pd}/LICENSE.md") - c4_setg(CPACK_RESOURCE_FILE_LICENSE "${pd}/LICENSE.md") - elseif(EXISTS "${pd}/LICENSE.txt") - c4_setg(CPACK_RESOURCE_FILE_LICENSE "${pd}/LICENSE.txt") - endif() - c4_proj_get_version("${pd}" version_tag full major minor patch tweak) - c4_setg(CPACK_PACKAGE_VERSION "${full}") - c4_setg(CPACK_PACKAGE_VERSION_MAJOR "${major}") - c4_setg(CPACK_PACKAGE_VERSION_MINOR "${minor}") - c4_setg(CPACK_PACKAGE_VERSION_PATCH "${patch}") - c4_setg(CPACK_PACKAGE_VERSION_TWEAK "${tweak}") - c4_setg(CPACK_PACKAGE_INSTALL_DIRECTORY "${_c4_prefix}-${version_tag}") - c4_setg(CPACK_PACKAGE_FILE_NAME "${_c4_prefix}-${version_tag}-${platform_tag}${build_tag}") - if(WIN32 AND NOT UNIX) - # There is a bug in NSI that does not handle full UNIX paths properly. - # Make sure there is at least one set of four backlashes. - #c4_setg(CPACK_PACKAGE_ICON "${CMake_SOURCE_DIR}/Utilities/Release\\\\InstallIcon.bmp") - #c4_setg(CPACK_NSIS_INSTALLED_ICON_NAME "bin\\\\MyExecutable.exe") - c4_setg(CPACK_NSIS_DISPLAY_NAME "${_c4_prefix} ${version_tag}") - c4_setg(CPACK_NSIS_HELP_LINK "${${_c4_prefix}_HOMEPAGE_URL}") - c4_setg(CPACK_NSIS_URL_INFO_ABOUT "${${_c4_prefix}_HOMEPAGE_URL}") - c4_setg(CPACK_NSIS_CONTACT "${${_c4_prefix}_AUTHOR}") - c4_setg(CPACK_NSIS_MODIFY_PATH ON) - else() - #c4_setg(CPACK_STRIP_FILES "bin/MyExecutable") - #c4_setg(CPACK_SOURCE_STRIP_FILES "") - c4_setg(CPACK_DEBIAN_PACKAGE_MAINTAINER "${${_c4_prefix}_AUTHOR}") - endif() - #c4_setg(CPACK_PACKAGE_EXECUTABLES "MyExecutable" "My Executable") -endfunction() - - -function(_c4_get_platform_tag tag_) - if(WIN32 AND NOT UNIX) - set(tag win) - elseif(APPLE) - set(tag apple) - elseif(UNIX) - set(tag unix) - else() - set(tag ${CMAKE_SYSTEM_NAME}) - endif() - if(CMAKE_SIZEOF_VOID_P EQUAL 8) # 64 bits - set(tag ${tag}64) - elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) # 32 bits - set(tag ${tag}32) - else() - c4_err("not implemented") - endif() - set(${tag_} ${tag} PARENT_SCOPE) -endfunction() - - -function(_c4_extract_version_tag tag_) - # git describe --tags for unannotated tags - # git describe --contains -endfunction() - - -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ - -# set project-wide property -function(c4_set_proj_prop prop value) - c4_dbg("set ${prop}=${value}") - set(C4PROJ_${_c4_prefix}_${prop} ${value}) -endfunction() - -# set project-wide property -function(c4_get_proj_prop prop var) - c4_dbg("get ${prop}=${C4PROJ_${_c4_prefix}_${prop}}") - set(${var} ${C4PROJ_${_c4_prefix}_${prop}} PARENT_SCOPE) -endfunction() - - -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ - -# set target-wide c4 property -function(c4_set_target_prop target prop value) - _c4_set_tgt_prop(${target} C4_TGT_${prop} "${value}") -endfunction() -function(c4_append_target_prop target prop value) - _c4_append_tgt_prop(${target} C4_TGT_${prop} "${value}") -endfunction() - -# get target-wide c4 property -function(c4_get_target_prop target prop var) - _c4_get_tgt_prop(val ${target} C4_TGT_${prop}) - set(${var} ${val} PARENT_SCOPE) -endfunction() - - -# get target-wide property -function(_c4_get_tgt_prop out tgt prop) - get_target_property(target_type ${target} TYPE) - if(target_type STREQUAL "INTERFACE_LIBRARY") - get_property(val GLOBAL PROPERTY C4_TGT_${tgt}_${prop}) - else() - get_target_property(val ${tgt} ${prop}) - endif() - c4_dbg("target ${tgt}: get ${prop}=${val}") - set(${out} "${val}" PARENT_SCOPE) -endfunction() - -# set target-wide property -function(_c4_set_tgt_prop tgt prop propval) - c4_dbg("target ${tgt}: set ${prop}=${propval}") - get_target_property(target_type ${target} TYPE) - if(target_type STREQUAL "INTERFACE_LIBRARY") - set_property(GLOBAL PROPERTY C4_TGT_${tgt}_${prop} "${propval}") - else() - set_target_properties(${tgt} PROPERTIES ${prop} "${propval}") - endif() -endfunction() -function(_c4_append_tgt_prop tgt prop propval) - c4_dbg("target ${tgt}: appending ${prop}=${propval}") - _c4_get_tgt_prop(curr ${tgt} ${prop}) - if(curr) - list(APPEND curr "${propval}") - else() - set(curr "${propval}") - endif() - _c4_set_tgt_prop(${tgt} ${prop} "${curr}") -endfunction() - - -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ - -function(c4_set_var_tmp var value) - c4_dbg("tmp-setting ${var} to ${value} (was ${${value}})") - set(_c4_old_val_${var} ${${var}}) - set(${var} ${value} PARENT_SCOPE) -endfunction() - -function(c4_clean_var_tmp var) - c4_dbg("cleaning ${var} to ${_c4_old_val_${var}} (tmp was ${${var}})") - set(${var} ${_c4_old_val_${var}} PARENT_SCOPE) -endfunction() - -macro(c4_override opt val) - set(${opt} ${val} CACHE BOOL "" FORCE) -endmacro() - - -macro(c4_setg var val) - set(${var} ${val}) - set(${var} ${val} PARENT_SCOPE) -endmacro() - - -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ - -function(c4_proj_get_version dir tag_o full_o major_o minor_o patch_o tweak_o) - if("${dir}" STREQUAL "") - set(dir ${CMAKE_CURRENT_LIST_DIR}) - endif() - find_program(GIT git REQUIRED) - function(_c4pgv_get_cmd outputvar) - execute_process(COMMAND ${ARGN} - WORKING_DIRECTORY ${dir} - ERROR_VARIABLE error - ERROR_STRIP_TRAILING_WHITESPACE - OUTPUT_VARIABLE output - OUTPUT_STRIP_TRAILING_WHITESPACE) - c4_dbg("output of ${ARGN}: ${outputvar}=${output} [@${dir}]") - set(${outputvar} ${output} PARENT_SCOPE) - endfunction() - # do we have any tags yet? - _c4pgv_get_cmd(head_desc ${GIT} describe HEAD) - _c4pgv_get_cmd(branch ${GIT} rev-parse --abbrev-ref HEAD) - if(NOT head_desc) - c4_dbg("the repo does not have any tags yet") - _c4pgv_get_cmd(commit_hash ${GIT} rev-parse --short HEAD) - set(otag "${commit_hash}-${branch}") - else() - c4_dbg("there are tags!") - # is the current commit tagged? - _c4pgv_get_cmd(commit_hash_full ${GIT} rev-parse HEAD) - _c4pgv_get_cmd(commit_desc ${GIT} describe --exact-match ${commit_hash_full}) - if(commit_desc) - c4_dbg("current commit is tagged") - # is the tag a version tag? - _c4_parse_version_tag(${commit_desc} is_version major minor patch tweak more) - if(is_version) - c4_dbg("current commit's tag is a version tag") - # is the tag the current version tag? - if("${is_version}" VERSION_EQUAL "${${_c4_prefix}_VERSION_FULL}") - c4_dbg("this is the official version commit") - else() - c4_dbg("this is a different version") - endif() - set(otag "${commit_desc}") - else() - c4_dbg("this is a non-version tag") - set(otag "${commit_desc}-${branch}") - endif() - else(commit_desc) - # is the latest tag in the head_desc a version tag? - string(REGEX REPLACE "(.*)-[0-9]+-[0-9a-f]+" "\\1" latest_tag "${head_desc}") - c4_dbg("current commit is NOT tagged. latest tag=${latest_tag}") - _c4_parse_version_tag(${latest_tag} latest_tag_is_a_version major minor patch tweak more) - if(latest_tag_is_a_version) - c4_dbg("latest tag is a version. stick to the head description") - set(otag "${head_desc}-${branch}") - set(full "${latest_tag_is_a_version}") - else() - c4_dbg("latest tag is NOT a version. Use the current project version from cmake + the output of git describe") - set(otag "v${full}-${head_desc}-${branch}") - set(full "${${_c4_prefix}_VERSION_FULL}") - set(major "${${_c4_prefix}_VERSION_MAJOR}") - set(minor "${${_c4_prefix}_VERSION_MINOR}") - set(patch "${${_c4_prefix}_VERSION_PATCH}") - set(tweak "${${_c4_prefix}_VERSION_TWEAK}") - endif() - endif(commit_desc) - endif(NOT head_desc) - c4_log("cpack tag: ${otag}") - set(${tag_o} "${otag}" PARENT_SCOPE) - set(${full_o} "${full}" PARENT_SCOPE) - set(${major_o} "${major}" PARENT_SCOPE) - set(${minor_o} "${minor}" PARENT_SCOPE) - set(${patch_o} "${patch}" PARENT_SCOPE) - set(${tweak_o} "${tweak}" PARENT_SCOPE) - # also: dirty index? - # https://stackoverflow.com/questions/2657935/checking-for-a-dirty-index-or-untracked-files-with-git -endfunction() - - -function(_c4_parse_version_tag tag is_version major minor patch tweak more) - # does the tag match a four-part version? - string(REGEX MATCH "v?([0-9]+)([\._][0-9]+)([\._][0-9]+)([\._][0-9]+)(.*)" match "${tag}") - function(_triml arg out) # trim the leading [\._] from the left - if("${arg}" STREQUAL "") - set(${out} "" PARENT_SCOPE) - else() - string(REGEX REPLACE "[\._](.*)" "\\1" ret "${arg}") - set("${out}" "${ret}" PARENT_SCOPE) - endif() - endfunction() - if(match) - set(${is_version} ${tag} PARENT_SCOPE) - _triml("${CMAKE_MATCH_1}" major_v) - _triml("${CMAKE_MATCH_2}" minor_v) - _triml("${CMAKE_MATCH_3}" patch_v) - _triml("${CMAKE_MATCH_4}" tweak_v) - _triml("${CMAKE_MATCH_5}" more_v) - else() - # does the tag match a three-part version? - string(REGEX MATCH "v?([0-9]+)([\._][0-9]+)([\._][0-9]+)(.*)" match "${tag}") - if(match) - set(${is_version} ${tag} PARENT_SCOPE) - _triml("${CMAKE_MATCH_1}" major_v) - _triml("${CMAKE_MATCH_2}" minor_v) - _triml("${CMAKE_MATCH_3}" patch_v) - _triml("${CMAKE_MATCH_4}" more_v) - else() - # does the tag match a two-part version? - string(REGEX MATCH "v?([0-9]+)([\._][0-9]+)(.*)" match "${tag}") - if(match) - set(${is_version} ${tag} PARENT_SCOPE) - _triml("${CMAKE_MATCH_1}" major_v) - _triml("${CMAKE_MATCH_2}" minor_v) - _triml("${CMAKE_MATCH_3}" more_v) - else() - # not a version! - set(${is_version} FALSE PARENT_SCOPE) - endif() - endif() - endif() - set(${major} "${major_v}" PARENT_SCOPE) - set(${minor} "${minor_v}" PARENT_SCOPE) - set(${patch} "${patch_v}" PARENT_SCOPE) - set(${tweak} "${tweak_v}" PARENT_SCOPE) - set(${more} "${more_v}" PARENT_SCOPE) -endfunction() - - -#function(testvtag) -# set(err FALSE) -# function(cmp value expected) -# if(NOT ("${${value}}" STREQUAL "${expected}")) -# c4_log("${tag}: error: expected ${value}=='${expected}': '${${value}}'=='${expected}'") -# set(err TRUE PARENT_SCOPE) -# else() -# c4_log("${tag}: ok: expected ${value}=='${expected}': '${${value}}'=='${expected}'") -# endif() -# endfunction() -# function(verify tag is_version_e major_e minor_e patch_e tweak_e more_e) -# _c4_parse_version_tag(${tag} is_version major minor patch tweak more) -# cmp(is_version ${is_version_e}) -# cmp(major "${major_e}") -# cmp(minor "${minor_e}") -# cmp(patch "${patch_e}") -# cmp(tweak "${tweak_e}") -# cmp(more "${more_e}") -# set(err ${err} PARENT_SCOPE) -# endfunction() -# verify(v12.34.567.89-rcfoo TRUE 12 34 567 89 -rcfoo) -# verify(v12_34_567_89-rcfoo TRUE 12 34 567 89 -rcfoo) -# verify(v12.34.567.89 TRUE 12 34 567 89 "") -# verify(v12_34_567_89 TRUE 12 34 567 89 "") -# verify(v12.34.567-rcfoo TRUE 12 34 567 "" -rcfoo) -# verify(v12_34_567-rcfoo TRUE 12 34 567 "" -rcfoo) -# verify(v12.34.567 TRUE 12 34 567 "" "") -# verify(v12_34_567 TRUE 12 34 567 "" "") -# verify(v12_34 TRUE 12 34 "" "" "") -# verify(v12.34 TRUE 12 34 "" "" "") -# if(err) -# c4_err("test failed") -# endif() -#endfunction() -#testvtag() - - -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ - - -macro(_c4_handle_cxx_standard_args) - # EXTENSIONS: - # enable compiler extensions eg, prefer gnu++11 to c++11 - if(EXTENSIONS IN_LIST ARGN) - set(_EXTENSIONS ON) - else() - c4_get_from_first_of(_EXTENSIONS - ENV - DEFAULT OFF - VARS ${_c4_uprefix}CXX_EXTENSIONS C4_CXX_EXTENSIONS CMAKE_CXX_EXTENSIONS) - endif() - # - # OPTIONAL - if(OPTIONAL IN_LIST ARGN) - set(_REQUIRED OFF) - else() - c4_get_from_first_of(_REQUIRED - ENV - DEFAULT ON - VARS ${_c4_uprefix}CXX_STANDARD_REQUIRED C4_CXX_STANDARD_REQUIRED CMAKE_CXX_STANDARD_REQUIRED) - endif() -endmacro() - - -# set the global cxx standard for the project. -# -# examples: -# c4_set_cxx(latest) # find the latest standard supported by the compiler, and use that -# c4_set_cxx(11) # required, no extensions (eg c++11) -# c4_set_cxx(14) # required, no extensions (eg c++14) -# c4_set_cxx(11 EXTENSIONS) # opt-in to extensions (eg, gnu++11) -# c4_set_cxx(14 EXTENSIONS) # opt-in to extensions (eg, gnu++14) -# c4_set_cxx(11 OPTIONAL) # not REQUIRED. no extensions -# c4_set_cxx(11 OPTIONAL EXTENSIONS) # not REQUIRED. with extensions. -macro(c4_set_cxx standard) - _c4_handle_cxx_standard_args(${ARGN}) - if(NOT DEFINED CMAKE_CXX_STANDARD) - c4_log("setting C++ standard: ${standard}") - c4_setg(CMAKE_CXX_STANDARD ${standard}) - endif() - if(NOT DEFINED CMAKE_CXX_STANDARD_REQUIRED) - c4_log("setting C++ standard required: ${_REQUIRED}") - c4_setg(CMAKE_CXX_STANDARD_REQUIRED ${_REQUIRED}) - endif() - if(NOT DEFINED CMAKE_CXX_STANDARD_REQUIRED) - c4_log("setting C++ standard extensions: ${_EXTENSIONS}") - c4_setg(CMAKE_CXX_EXTENSIONS ${_EXTENSIONS}) - endif() -endmacro() - - -# set the cxx standard for a target. -# -# examples: -# c4_target_set_cxx(target latest) # find the latest standard supported by the compiler, and use that -# c4_target_set_cxx(target 11) # required, no extensions (eg c++11) -# c4_target_set_cxx(target 14) # required, no extensions (eg c++14) -# c4_target_set_cxx(target 11 EXTENSIONS) # opt-in to extensions (eg, gnu++11) -# c4_target_set_cxx(target 14 EXTENSIONS) # opt-in to extensions (eg, gnu++14) -# c4_target_set_cxx(target 11 OPTIONAL) # not REQUIRED. no extensions -# c4_target_set_cxx(target 11 OPTIONAL EXTENSIONS) -function(c4_target_set_cxx target standard) - c4_dbg("setting C++ standard for target ${target}: ${standard}") - _c4_handle_cxx_standard_args(${ARGN}) - set_target_properties(${target} PROPERTIES - CXX_STANDARD ${standard} - CXX_STANDARD_REQUIRED ${_REQUIRED} - CXX_EXTENSIONS ${_EXTENSIONS}) - target_compile_features(${target} PUBLIC cxx_std_${standard}) -endfunction() - - -# set the cxx standard for a target based on the global project settings -function(c4_target_inherit_cxx_standard target) - c4_dbg("inheriting C++ standard for target ${target}: ${CMAKE_CXX_STANDARD}") - set_target_properties(${target} PROPERTIES - CXX_STANDARD "${CMAKE_CXX_STANDARD}" - CXX_STANDARD_REQUIRED "${CMAKE_CXX_STANDARD_REQUIRED}" - CXX_EXTENSIONS "${CMAKE_CXX_EXTENSIONS}") - target_compile_features(${target} PUBLIC cxx_std_${CMAKE_CXX_STANDARD}) -endfunction() - - -function(_c4_find_latest_supported_cxx_standard out) - if(NOT c4_latest_supported_cxx_standard) - include(CheckCXXCompilerFlag) - # make sure CMAKE_CXX_FLAGS is clean here - # see https://cmake.org/cmake/help/v3.16/module/CheckCXXCompilerFlag.html - # Note: since this is a function, we don't need to reset CMAKE_CXX_FLAGS - # back to its previous value - set(CMAKE_CXX_FLAGS) - set(standard 11) # default to C++11 if everything fails - foreach(s ${C4_CXX_STANDARDS}) - if(MSVC) - set(flag /std:c++${s}) - else() - # assume GNU-style compiler - set(flag -std=c++${s}) - endif() - c4_log("checking CXX standard: C++${s} flag=${flag}") - check_cxx_compiler_flag(${flag} has${s}) - if(has${s}) - c4_log("checking CXX standard: C++${s} is supported! flag=${flag}") - set(standard ${s}) - break() - else() - c4_log("checking CXX standard: C++${s}: no support for flag=${flag} no") - endif() - endforeach() - set(c4_latest_supported_cxx_standard ${standard} CACHE INTERNAL "") - endif() - set(${out} ${c4_latest_supported_cxx_standard} PARENT_SCOPE) -endfunction() - - -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ -# examples: -# -# # require subproject c4core, as a subdirectory. c4core will be used -# # as a separate library -# c4_require_subproject(c4core SUBDIRECTORY ${C4OPT_EXT_DIR}/c4core) -# -# # require subproject c4core, as a remote proj -# c4_require_subproject(c4core REMOTE -# GIT_REPOSITORY https://github.com/biojppm/c4core -# GIT_TAG master -# ) -function(c4_require_subproject subproj) - _c4_handle_args(_ARGS ${ARGN} - _ARGS0 - INCORPORATE - EXCLUDE_FROM_ALL - _ARGS1 - SUBDIRECTORY # the subproject is located in the given directory name and - # will be added via add_subdirectory() - _ARGSN - REMOTE # the subproject is located in a remote repo/url - # and will be added via c4_import_remote_proj(), - # forwarding all the arguments in here. - OVERRIDE # a list of variable name+value pairs - # these variables will be set with c4_override() - # before calling add_subdirectory() - SET_FOLDER_TARGETS # Set the folder of the given targets using - # c4_set_folder_remote_project_targets(). - # The first expected argument is the folder, - # and the remaining arguments are the targets - # which we want to set the folder. - _DEPRECATE - INTERFACE - ) - list(APPEND _${_c4_uprefix}_deps ${subproj}) - c4_setg(_${_c4_uprefix}_deps ${_${_c4_uprefix}_deps}) - c4_dbg("-----------------------------------------------") - c4_dbg("requires subproject ${subproj}!") - if(_INCORPORATE) - c4_dbg("requires subproject ${subproj} in INCORPORATE mode!") - c4_dbg_var(${_c4_root_uproj}_STANDALONE) - if(${_c4_root_uproj}_STANDALONE) - c4_dbg("${_c4_root_uproj} is STANDALONE: honoring INCORPORATE mode...") - else() - c4_dbg("${_c4_root_uproj} is not STANDALONE: ignoring INCORPORATE mode...") - set(_INCORPORATE OFF) - endif() - endif() - # - _c4_get_subproject_property(${subproj} AVAILABLE _available) - if(_available) - c4_dbg("required subproject ${subproj} was already imported:") - c4_dbg_subproject(${subproj}) - # TODO check version compatibility - else() #elseif(NOT _${subproj}_available) - c4_dbg("required subproject ${subproj} is unknown. Importing...") - if(_EXCLUDE_FROM_ALL) - set(excl EXCLUDE_FROM_ALL) - endif() - # forward c4 compile flags - string(TOUPPER ${subproj} usubproj) - c4_setg(${usubproj}_CXX_FLAGS_FWD "${${_c4_uprefix}CXX_FLAGS}") - c4_setg(${usubproj}_CXX_FLAGS_OPT_FWD "${${_c4_uprefix}CXX_FLAGS_OPT}") - c4_setg(${usubproj}_CXX_LINKER_FLAGS_FWD "${${_c4_uprefix}CXX_LINKER_FLAGS}") - # root dir - set(_r ${CMAKE_CURRENT_BINARY_DIR}/subprojects/${subproj}) - if(_REMOTE) - c4_log("importing subproject ${subproj} (REMOTE)... ${_REMOTE}") - _c4_mark_subproject_imported(${subproj} ${_r}/src ${_r}/build ${_INCORPORATE}) - c4_import_remote_proj(${subproj} ${_r} REMOTE ${_REMOTE} OVERRIDE ${_OVERRIDE} ${excl}) - _c4_get_subproject_property(${subproj} SRC_DIR _srcdir) - c4_dbg("finished importing subproject ${subproj} (REMOTE, SRC_DIR=${_srcdir}).") - elseif(_SUBDIRECTORY) - c4_log("importing subproject ${subproj} (SUBDIRECTORY)... ${_SUBDIRECTORY}") - _c4_mark_subproject_imported(${subproj} ${_SUBDIRECTORY} ${_r}/build ${_INCORPORATE}) - c4_add_subproj(${subproj} ${_SUBDIRECTORY} ${_r}/build OVERRIDE ${_OVERRIDE} ${excl}) - set(_srcdir ${_SUBDIRECTORY}) - c4_dbg("finished importing subproject ${subproj} (SUBDIRECTORY=${_SUBDIRECTORY}).") - else() - c4_err("subproject type must be either REMOTE or SUBDIRECTORY") - endif() - endif() - # - if(_SET_FOLDER_TARGETS) - c4_set_folder_remote_project_targets(${_SET_FOLDER_TARGETS}) - endif() -endfunction(c4_require_subproject) - - -function(c4_add_subproj proj dir bindir) - _c4_handle_args(_ARGS ${ARGN} - _ARGS0 - EXCLUDE_FROM_ALL # forward to add_subdirectory() - _ARGS1 - _ARGSN - OVERRIDE # a list of variable name+value pairs - # these variables will be set with c4_override() - # before calling add_subdirectory() - ) - # push the subproj into the current path - set(prev_subproject ${_c4_curr_subproject}) - set(prev_path ${_c4_curr_path}) - set(_c4_curr_subproject ${proj}) - string(REGEX MATCH ".*/${proj}\$" pos "${_c4_curr_path}") - if(pos EQUAL -1) - string(REGEX MATCH "^${proj}\$" pos "${_c4_curr_path}") - if(pos EQUAL -1) - set(_c4_curr_path ${_c4_curr_path}/${proj}) - endif() - endif() - # - while(_OVERRIDE) - list(POP_FRONT _OVERRIDE varname) - list(POP_FRONT _OVERRIDE varvalue) - c4_override(${varname} ${varvalue}) - endwhile() - # - if(_EXCLUDE_FROM_ALL) - set(excl EXCLUDE_FROM_ALL) - endif() - # - c4_dbg("adding subproj: ${prev_subproject}->${_c4_curr_subproject}. path=${_c4_curr_path}") - add_subdirectory(${dir} ${bindir} ${excl}) - # pop the subproj from the current path - set(_c4_curr_subproject ${prev_subproject}) - set(_c4_curr_path ${prev_path}) -endfunction() - - -function(_c4_mark_subproject_imported subproject_name subproject_src_dir subproject_bin_dir incorporate) - c4_dbg("marking subproject imported: ${subproject_name} (imported by ${_c4_prefix}). src=${subproject_src_dir}") - _c4_append_subproject_property(${_c4_prefix} DEPENDENCIES ${subproject_name}) - _c4_get_folder(folder ${_c4_prefix} ${subproject_name}) - _c4_set_subproject_property(${subproject_name} AVAILABLE ON) - _c4_set_subproject_property(${subproject_name} IMPORTER "${_c4_prefix}") - _c4_set_subproject_property(${subproject_name} SRC_DIR "${subproject_src_dir}") - _c4_set_subproject_property(${subproject_name} BIN_DIR "${subproject_bin_dir}") - _c4_set_subproject_property(${subproject_name} FOLDER "${folder}") - _c4_set_subproject_property(${subproject_name} INCORPORATE "${incorporate}") -endfunction() - - -function(_c4_get_subproject_property subproject property var) - get_property(v GLOBAL PROPERTY _c4_subproject-${subproject}-${property}) - set(${var} "${v}" PARENT_SCOPE) -endfunction() - - -function(_c4_set_subproject_property subproject property value) - c4_dbg("setting subproj prop: ${subproject}: ${property}=${value}") - set_property(GLOBAL PROPERTY _c4_subproject-${subproject}-${property} "${value}") -endfunction() -function(_c4_append_subproject_property subproject property value) - _c4_get_subproject_property(${subproject} ${property} cval) - if(cval) - list(APPEND cval ${value}) - else() - set(cval ${value}) - endif() - _c4_set_subproject_property(${subproject} ${property} ${cval}) -endfunction() - - -function(_c4_is_incorporated subproj out) - if("${subproj}" STREQUAL "${_c4_root_proj}") - c4_dbg("${subproj} is incorporated? root proj, no") - set(${out} OFF PARENT_SCOPE) - else() - _c4_get_subproject_property(${subproj} INCORPORATE inc) - c4_dbg("${subproj} is incorporated? not root proj, incorporate=${inc}") - set(${out} ${inc} PARENT_SCOPE) - endif() -endfunction() - - -function(c4_dbg_subproject subproject) - set(props AVAILABLE IMPORTER SRC_DIR BIN_DIR DEPENDENCIES FOLDER INCORPORATE) - foreach(p ${props}) - _c4_get_subproject_property(${subproject} ${p} pv) - c4_dbg("${subproject}: ${p}=${pv}") - endforeach() -endfunction() - - -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ - -# -# -function(c4_import_remote_proj name dir) - _c4_handle_args(_ARGS ${ARGN} - _ARGS0 - EXCLUDE_FROM_ALL - _ARGS1 - SUBDIR # path to the subdirectory where the CMakeLists file is to be found. - _ARGSN - OVERRIDE # a list of variable name+value pairs - # these variables will be set with c4_override() - # before calling add_subdirectory() - REMOTE # to specify url, repo, tag, or branch, - # pass the needed arguments after dir. - # These arguments will be forwarded to ExternalProject_Add() - SET_FOLDER_TARGETS # Set the folder of the given targets using - # c4_set_folder_remote_project_targets(). - # The first expected argument is the folder, - # and the remaining arguments are the targets - # which we want to set the folder. - ) - set(srcdir_in_out "${dir}") - c4_download_remote_proj(${name} srcdir_in_out ${_REMOTE}) - if(_SUBDIR) - set(srcdir_in_out "${srcdir_in_out}/${_SUBDIR}") - endif() - _c4_set_subproject_property(${name} SRC_DIR "${srcdir_in_out}") - if(_EXCLUDE_FROM_ALL) - set(excl EXCLUDE_FROM_ALL) - endif() - c4_add_subproj(${name} "${srcdir_in_out}" "${dir}/build" OVERRIDE ${_OVERRIDE} ${excl}) - # - if(_SET_FOLDER_TARGETS) - c4_set_folder_remote_project_targets(${_SET_FOLDER_TARGETS}) - endif() -endfunction() - - -# download remote projects while running cmake -# to specify url, repo, tag, or branch, -# pass the needed arguments after dir. -# These arguments will be forwarded to ExternalProject_Add() -function(c4_download_remote_proj name candidate_dir) - # https://crascit.com/2015/07/25/cmake-gtest/ - # (via https://stackoverflow.com/questions/15175318/cmake-how-to-build-external-projects-and-include-their-targets) - set(dir ${${candidate_dir}}) - if("${dir}" STREQUAL "") - set(dir "${CMAKE_BINARY_DIR}/extern/${name}") - endif() - set(cvar _${_c4_uprefix}_DOWNLOAD_${name}_LOCATION) - set(cval ${${cvar}}) - # - # was it already downloaded in this project? - if(NOT ("${cval}" STREQUAL "")) - if(EXISTS "${cval}") - c4_log("${name} was previously imported into this project - found at \"${cval}\"!") - set(${candidate_dir} "${cval}" PARENT_SCOPE) - return() - else() - c4_log("${name} was previously imported into this project - but was NOT found at \"${cval}\"!") - endif() - endif() - # - # try to find an existing version (downloaded by some other project) - set(out "${dir}") - _c4_find_cached_proj(${name} out) - if(NOT ("${out}" STREQUAL "${dir}")) - c4_log("using ${name} from \"${out}\"...") - set(${cvar} "${out}" CACHE INTERNAL "") - set(${candidate_dir} "${out}" PARENT_SCOPE) - return() - endif() - # - # no version was found; need to download. - c4_log("downloading ${name}: not in cache...") - # check for a global place to download into - set(srcdir) - _c4_get_cached_srcdir_global_extern(${name} srcdir) - if("${srcdir}" STREQUAL "") - # none found; default to the given dir - set(srcdir "${dir}/src") - endif() - # - # do it - #if((EXISTS ${dir}/dl) AND (EXISTS ${dir}/dl/CMakeLists.txt)) - # return() - #endif() - c4_log("downloading remote project: ${name} -> \"${srcdir}\" (dir=${dir})...") - # - file(WRITE ${dir}/dl/CMakeLists.txt " -cmake_minimum_required(VERSION 2.8.2) -project(${_c4_lcprefix}-download-${name} NONE) - -# this project only downloads ${name} -# (ie, no configure, build or install step) -include(ExternalProject) - -ExternalProject_Add(${name}-dl - ${ARGN} - SOURCE_DIR \"${srcdir}\" - BINARY_DIR \"${dir}/build\" - CONFIGURE_COMMAND \"\" - BUILD_COMMAND \"\" - INSTALL_COMMAND \"\" - TEST_COMMAND \"\" -) -") - execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . - WORKING_DIRECTORY ${dir}/dl) - execute_process(COMMAND ${CMAKE_COMMAND} --build . - WORKING_DIRECTORY ${dir}/dl) - # - set(${candidate_dir} "${srcdir}" PARENT_SCOPE) - set(_${_c4_uprefix}_DOWNLOAD_${name}_LOCATION "${srcdir}" CACHE INTERNAL "") -endfunction() - - -# checks if the project was already downloaded. If it was, then dir_in_out is -# changed to the directory where the project was found at. -function(_c4_find_cached_proj name dir_in_out) - c4_log("downloading ${name}: searching cached project...") - # - # 1. search in the per-import variable, eg RYML_CACHE_DOWNLOAD_GTEST - string(TOUPPER ${name} uname) - set(var ${_c4_uprefix}CACHE_DOWNLOAD_${uname}) - set(val "${${var}}") - if(NOT ("${val}" STREQUAL "")) - c4_log("downloading ${name}: searching in ${var}=${val}") - if(EXISTS "${val}") - c4_log("downloading ${name}: picked ${sav} instead of ${${dir_in_out}}") - set(${dir_in_out} ${sav} PARENT_SCOPE) - endif() - endif() - # - # 2. search in the global directory (if there is one) - _c4_get_cached_srcdir_global_extern(${name} sav) - if(NOT ("${sav}" STREQUAL "")) - c4_log("downloading ${name}: searching in C4_EXTERN_DIR: ${sav}") - if(EXISTS "${sav}") - c4_log("downloading ${name}: picked ${sav} instead of ${${dir_in_out}}") - set(${dir_in_out} ${sav} PARENT_SCOPE) - endif() - endif() -endfunction() - - -function(_c4_get_cached_srcdir_global_extern name out) - set(${out} "" PARENT_SCOPE) - if("${C4_EXTERN_DIR}" STREQUAL "") - set(C4_EXTERN_DIR "$ENV{C4_EXTERN_DIR}") - endif() - if(NOT ("${C4_EXTERN_DIR}" STREQUAL "")) - set(${out} "${C4_EXTERN_DIR}/${name}" PARENT_SCOPE) - endif() -endfunction() - - -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ - -function(_c4_get_folder output importer_subproject subproject_name) - _c4_get_subproject_property(${importer_subproject} FOLDER importer_folder) - if("${importer_folder}" STREQUAL "") - set(folder ${importer_subproject}) - else() - set(folder "${importer_folder}/deps/${subproject_name}") - endif() - set(${output} ${folder} PARENT_SCOPE) -endfunction() - - -function(_c4_set_target_folder target subfolder) - string(FIND "${subfolder}" "/" pos) - if(pos EQUAL 0) - if("${_c4_curr_path}" STREQUAL "") - string(SUBSTRING "${subfolder}" 1 -1 sf) - set_target_properties(${target} PROPERTIES - FOLDER "${sf}") - else() - set_target_properties(${target} PROPERTIES - FOLDER "${subfolder}") - endif() - elseif("${subfolder}" STREQUAL "") - set_target_properties(${target} PROPERTIES - FOLDER "${_c4_curr_path}") - else() - if("${_c4_curr_path}" STREQUAL "") - set_target_properties(${target} PROPERTIES - FOLDER "${subfolder}") - else() - set_target_properties(${target} PROPERTIES - FOLDER "${_c4_curr_path}/${subfolder}") - endif() - endif() -endfunction() - - -function(c4_set_folder_remote_project_targets subfolder) - foreach(target ${ARGN}) - if(TARGET ${target}) - _c4_set_target_folder(${target} "${subfolder}") - endif() - endforeach() -endfunction() - - -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ - -# a convenience alias to c4_add_target() -function(c4_add_executable target) - c4_add_target(${target} EXECUTABLE ${ARGN}) -endfunction(c4_add_executable) - - -# a convenience alias to c4_add_target() -function(c4_add_library target) - c4_add_target(${target} LIBRARY ${ARGN}) -endfunction(c4_add_library) - - -# example: c4_add_target(ryml LIBRARY SOURCES ${SRC}) -function(c4_add_target target) - c4_dbg("adding target: ${target}: ${ARGN}") - set(opt0arg - LIBRARY # the target is a library - EXECUTABLE # the target is an executable - WIN32 # the executable is WIN32 - SANITIZE # deprecated - ) - set(opt1arg - LIBRARY_TYPE # override global setting for C4_LIBRARY_TYPE - SHARED_MACRO # the name of the macro to turn on export/import symbols - # for compiling the library as a windows DLL. - # defaults to ${_c4_uprefix}SHARED. - SHARED_EXPORTS # the name of the macro to turn on export of symbols - # for compiling the library as a windows DLL. - # defaults to ${_c4_uprefix}EXPORTS. - SOURCE_ROOT # the directory where relative source paths - # should be resolved. when empty, - # use CMAKE_CURRENT_SOURCE_DIR - FOLDER # IDE folder to group the target in - SANITIZERS # outputs the list of sanitize targets in this var - SOURCE_TRANSFORM # WIP - ) - set(optnarg - INCORPORATE # incorporate these libraries into this target, - # subject to ${_c4_uprefix}STANDALONE and C4_STANDALONE - SOURCES PUBLIC_SOURCES INTERFACE_SOURCES PRIVATE_SOURCES - HEADERS PUBLIC_HEADERS INTERFACE_HEADERS PRIVATE_HEADERS - INC_DIRS PUBLIC_INC_DIRS INTERFACE_INC_DIRS PRIVATE_INC_DIRS - LIBS PUBLIC_LIBS INTERFACE_LIBS PRIVATE_LIBS - DEFS PUBLIC_DEFS INTERFACE_DEFS PRIVATE_DEFS # defines - CFLAGS PUBLIC_CFLAGS INTERFACE_CFLAGS PRIVATE_CFLAGS # compiler flags. TODO: linker flags - DLLS # DLLs required by this target - MORE_ARGS - ) - cmake_parse_arguments("" "${opt0arg}" "${opt1arg}" "${optnarg}" ${ARGN}) - # - if(_SANITIZE) - c4_err("SANITIZE is deprecated") - endif() - - if(${_LIBRARY}) - set(_what LIBRARY) - elseif(${_EXECUTABLE}) - set(_what EXECUTABLE) - else() - c4_err("must be either LIBRARY or EXECUTABLE") - endif() - - _c4_handle_arg(SHARED_MACRO ${_c4_uprefix}MACRO) - _c4_handle_arg(SHARED_EXPORTS ${_c4_uprefix}EXPORTS) - _c4_handle_arg_or_fallback(SOURCE_ROOT "${CMAKE_CURRENT_SOURCE_DIR}") - function(_c4_transform_to_full_path list all) - set(l) - foreach(f ${${list}}) - if(NOT IS_ABSOLUTE "${f}") - set(f "${_SOURCE_ROOT}/${f}") - endif() - list(APPEND l "${f}") - endforeach() - set(${list} "${l}" PARENT_SCOPE) - set(cp ${${all}}) - list(APPEND cp ${l}) - set(${all} ${cp} PARENT_SCOPE) - endfunction() - _c4_transform_to_full_path( _SOURCES allsrc) - _c4_transform_to_full_path( _HEADERS allsrc) - _c4_transform_to_full_path( _PUBLIC_SOURCES allsrc) - _c4_transform_to_full_path(_INTERFACE_SOURCES allsrc) - _c4_transform_to_full_path( _PRIVATE_SOURCES allsrc) - _c4_transform_to_full_path( _PUBLIC_HEADERS allsrc) - _c4_transform_to_full_path(_INTERFACE_HEADERS allsrc) - _c4_transform_to_full_path( _PRIVATE_HEADERS allsrc) - create_source_group("" "${_SOURCE_ROOT}" "${allsrc}") - # is the target name prefixed with the project prefix? - string(REGEX MATCH "${_c4_prefix}::.*" target_is_prefixed "${target}") - if(NOT ${_c4_uprefix}SANITIZE_ONLY) - if(${_EXECUTABLE}) - c4_dbg("adding executable: ${target}") - if(WIN32) - if(${_WIN32}) - list(APPEND _MORE_ARGS WIN32) - endif() - endif() - add_executable(${target} ${_MORE_ARGS}) - if(NOT target_is_prefixed) - add_executable(${_c4_prefix}::${target} ALIAS ${target}) - endif() - set(src_mode PRIVATE) - set(tgt_type PUBLIC) - set(compiled_target ON) - set_target_properties(${target} PROPERTIES VERSION ${${_c4_prefix}_VERSION}) - elseif(${_LIBRARY}) - c4_dbg("adding library: ${target}") - set(_blt ${C4_LIBRARY_TYPE}) # build library type - if(NOT "${_LIBRARY_TYPE}" STREQUAL "") - set(_blt ${_LIBRARY_TYPE}) - endif() - if("${_blt}" STREQUAL "") - endif() - # - if("${_blt}" STREQUAL "INTERFACE") - c4_dbg("adding interface library ${target}") - add_library(${target} INTERFACE) - set(src_mode INTERFACE) - set(tgt_type INTERFACE) - set(compiled_target OFF) - else() - if("${_blt}" STREQUAL "") - # obey BUILD_SHARED_LIBS (ie, either static or shared library) - c4_dbg("adding library ${target} (defer to BUILD_SHARED_LIBS=${BUILD_SHARED_LIBS}) --- ${_MORE_ARGS}") - add_library(${target} ${_MORE_ARGS}) - if(BUILD_SHARED_LIBS) - set(_blt SHARED) - else() - set(_blt STATIC) - endif() - else() - c4_dbg("adding library ${target} with type ${_blt}") - add_library(${target} ${_blt} ${_MORE_ARGS}) - endif() - # libraries - set(src_mode PRIVATE) - set(tgt_type PUBLIC) - set(compiled_target ON) - set_target_properties(${target} PROPERTIES VERSION ${${_c4_prefix}_VERSION}) - if("${_blt}" STREQUAL SHARED) - set_target_properties(${target} PROPERTIES SOVERSION ${${_c4_prefix}_VERSION}) - endif() - # exports for shared libraries - if(WIN32) - if("${_blt}" STREQUAL SHARED) - set_target_properties(${target} PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON) - target_compile_definitions(${target} PUBLIC ${_SHARED_MACRO}) - target_compile_definitions(${target} PRIVATE $) - # save the name of the macro for later use when(if) incorporating this library - c4_set_target_prop(${target} SHARED_EXPORTS ${_SHARED_EXPORTS}) - endif() # shared lib - endif() # win32 - endif() # interface or lib - if(NOT target_is_prefixed) - add_library(${_c4_prefix}::${target} ALIAS ${target}) - endif() - endif(${_EXECUTABLE}) - - if(src_mode STREQUAL "PUBLIC") - c4_add_target_sources(${target} - PUBLIC "${_SOURCES};${_HEADERS};${_PUBLIC_SOURCES};${_PUBLIC_HEADERS}" - INTERFACE "${_INTERFACE_SOURCES};${_INTERFACE_HEADERS}" - PRIVATE "${_PRIVATE_SOURCES};${_PRIVATE_HEADERS}") - elseif(src_mode STREQUAL "INTERFACE") - c4_add_target_sources(${target} - PUBLIC "${_PUBLIC_SOURCES};${_PUBLIC_HEADERS}" - INTERFACE "${_SOURCES};${_HEADERS};${_INTERFACE_SOURCES};${_INTERFACE_HEADERS}" - PRIVATE "${_PRIVATE_SOURCES};${_PRIVATE_HEADERS}") - elseif(src_mode STREQUAL "PRIVATE") - c4_add_target_sources(${target} - PUBLIC "${_PUBLIC_SOURCES};${_PUBLIC_HEADERS}" - INTERFACE "${_INTERFACE_SOURCES};${_INTERFACE_HEADERS}" - PRIVATE "${_SOURCES};${_HEADERS};${_PRIVATE_SOURCES};${_PRIVATE_HEADERS}") - elseif() - c4_err("${target}: adding sources: invalid source mode") - endif() - _c4_set_tgt_prop(${target} C4_SOURCE_ROOT "${_SOURCE_ROOT}") - - if(_INC_DIRS) - c4_dbg("${target}: adding include dirs ${_INC_DIRS} [from target: ${tgt_type}]") - target_include_directories(${target} "${tgt_type}" ${_INC_DIRS}) - endif() - if(_PUBLIC_INC_DIRS) - c4_dbg("${target}: adding PUBLIC include dirs ${_PUBLIC_INC_DIRS}") - target_include_directories(${target} PUBLIC ${_PUBLIC_INC_DIRS}) - endif() - if(_INTERFACE_INC_DIRS) - c4_dbg("${target}: adding INTERFACE include dirs ${_INTERFACE_INC_DIRS}") - target_include_directories(${target} INTERFACE ${_INTERFACE_INC_DIRS}) - endif() - if(_PRIVATE_INC_DIRS) - c4_dbg("${target}: adding PRIVATE include dirs ${_PRIVATE_INC_DIRS}") - target_include_directories(${target} PRIVATE ${_PRIVATE_INC_DIRS}) - endif() - - if(_LIBS) - _c4_link_with_libs(${target} "${tgt_type}" "${_LIBS}" "${_INCORPORATE}") - endif() - if(_PUBLIC_LIBS) - _c4_link_with_libs(${target} PUBLIC "${_PUBLIC_LIBS}" "${_INCORPORATE}") - endif() - if(_INTERFACE_LIBS) - _c4_link_with_libs(${target} INTERFACE "${_INTERFACE_LIBS}" "${_INCORPORATE}") - endif() - if(_PRIVATE_LIBS) - _c4_link_with_libs(${target} PRIVATE "${_PRIVATE_LIBS}" "${_INCORPORATE}") - endif() - - if(compiled_target) - if(_FOLDER) - _c4_set_target_folder(${target} "${_FOLDER}") - else() - _c4_set_target_folder(${target} "") - endif() - # cxx standard - c4_target_inherit_cxx_standard(${target}) - # compile flags - set(_more_flags - ${${_c4_uprefix}CXX_FLAGS} - ${${_c4_uprefix}C_FLAGS} - ${${_c4_uprefix}CXX_FLAGS_OPT}) - if(_more_flags) - get_target_property(_flags ${target} COMPILE_OPTIONS) - if(_flags) - set(_more_flags ${_flags};${_more_flags}) - endif() - c4_dbg("${target}: COMPILE_FLAGS=${_more_flags}") - target_compile_options(${target} PRIVATE "${_more_flags}") - endif() - # linker flags - set(_link_flags ${${_c4_uprefix}CXX_LINKER_FLAGS}) - if(_link_flags) - get_target_property(_flags ${target} LINK_OPTIONS) - if(_flags) - set(_link_flags ${_flags};${_more_flags}) - endif() - c4_dbg("${target}: LINKER_FLAGS=${_link_flags}") - target_link_options(${target} PUBLIC "${_link_flags}") - endif() - # static analysis - if(${_c4_uprefix}LINT) - c4_static_analysis_target(${target} "${_FOLDER}" lint_targets) - endif() - endif(compiled_target) - - if(_DEFS) - target_compile_definitions(${target} "${tgt_type}" ${_DEFS}) - endif() - if(_PUBLIC_DEFS) - target_compile_definitions(${target} PUBLIC ${_PUBLIC_DEFS}) - endif() - if(_INTERFACE_DEFS) - target_compile_definitions(${target} INTERFACE ${_INTERFACE_DEFS}) - endif() - if(_PRIVATE_DEFS) - target_compile_definitions(${target} PRIVATE ${_PRIVATE_DEFS}) - endif() - - if(_CFLAGS) - target_compile_options(${target} "${tgt_type}" ${_CFLAGS}) - endif() - if(_PUBLIC_CFLAGS) - target_compile_options(${target} PUBLIC ${_PUBLIC_CFLAGS}) - endif() - if(_INTERFACE_CFLAGS) - target_compile_options(${target} INTERFACE ${_INTERFACE_CFLAGS}) - endif() - if(_PRIVATE_CFLAGS) - target_compile_options(${target} PRIVATE ${_PRIVATE_CFLAGS}) - endif() - - if((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") AND - (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 4.8) AND - (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0)) - c4_dbg("${target}: adding compat include path") - target_include_directories(${target} PUBLIC $) - endif() - - endif(NOT ${_c4_uprefix}SANITIZE_ONLY) - - if(compiled_target) - if(${_c4_uprefix}SANITIZE) - c4_sanitize_target(${target} - ${_what} # LIBRARY or EXECUTABLE - SOURCES ${allsrc} - INC_DIRS ${_INC_DIRS} ${_PUBLIC_INC_DIRS} ${_INTERFACE_INC_DIRS} ${_PRIVATE_INC_DIRS} - LIBS ${_LIBS} ${_PUBLIC_LIBS} ${_INTERFACE_LIBS} ${_PRIVATE_LIBS} - DEFS ${_DEFS} ${_PUBLIC_DEFS} ${_INTERFACE_DEFS} ${_PRIVATE_DEFS} - CFLAGS ${_CFLAGS} ${_PUBLIC_CFLAGS} ${_INTERFACE_CFLAGS} ${_PRIVATE_CFLAGS} - OUTPUT_TARGET_NAMES san_targets - FOLDER "${_FOLDER}" - ) - endif() - - if(NOT ${_c4_uprefix}SANITIZE_ONLY) - list(INSERT san_targets 0 ${target}) - endif() - - if(_SANITIZERS) - set(${_SANITIZERS} ${san_targets} PARENT_SCOPE) - endif() - - _c4_set_tgt_prop(${target} C4_SAN_TARGETS "${san_targets}") - else() - _c4_set_tgt_prop(${target} C4_SAN_TARGETS "${target}") - endif() - - # gather dlls so that they can be automatically copied to the target directory - if(_DLLS) - c4_append_transitive_property(${target} _C4_DLLS "${_DLLS}") - endif() - - if(${_EXECUTABLE}) - if(WIN32) - c4_get_transitive_property(${target} _C4_DLLS transitive_dlls) - list(REMOVE_DUPLICATES transitive_dlls) - foreach(_dll ${transitive_dlls}) - if(_dll) - c4_dbg("enable copy of dll to target file dir: ${_dll} ---> $") - add_custom_command(TARGET ${target} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_dll}" "$" - ) - else() - message(WARNING "dll required by ${_c4_prefix}/${target} was not found, so cannot copy: ${_dll}") - endif() - endforeach() - endif() - endif() -endfunction() # add_target - - -function(_c4_link_with_libs target link_type libs incorporate) - foreach(lib ${libs}) - # add targets that are DLLs - if(WIN32) - if(TARGET ${lib}) - get_target_property(lib_type ${lib} TYPE) - if(lib_type STREQUAL SHARED_LIBRARY) - c4_append_transitive_property(${target} _C4_DLLS "$") - endif() - endif() - endif() - _c4_lib_is_incorporated(${lib} isinc) - if(isinc OR (incorporate AND ${_c4_uprefix}STANDALONE)) - c4_log("-----> target ${target} ${link_type} incorporating lib ${lib}") - _c4_incorporate_lib(${target} ${link_type} ${lib}) - else() - c4_dbg("${target} ${link_type} linking with lib ${lib}") - target_link_libraries(${target} ${link_type} ${lib}) - endif() - endforeach() -endfunction() - - -function(_c4_lib_is_incorporated lib ret) - c4_dbg("${lib}: is incorporated?") - if(NOT TARGET ${lib}) - c4_dbg("${lib}: no, not a target") - set(${ret} OFF PARENT_SCOPE) - else() - c4_get_target_prop(${lib} INCORPORATING_TARGETS inc) - if(inc) - c4_dbg("${lib}: is incorporated!") - set(${ret} ON PARENT_SCOPE) - else() - c4_dbg("${lib}: is not incorporated!") - set(${ret} OFF PARENT_SCOPE) - endif() - endif() -endfunction() - - -function(_c4_incorporate_lib target link_type lib) - c4_dbg("target ${target}: incorporating lib ${lib} [${link_type}]") - _c4_get_tgt_prop(srcroot ${lib} C4_SOURCE_ROOT) - # - c4_append_target_prop(${lib} INCORPORATING_TARGETS ${target}) - c4_append_target_prop(${target} INCORPORATED_TARGETS ${lib}) - # - _c4_get_tgt_prop(lib_src ${lib} SOURCES) - if(lib_src) - create_source_group("${lib}" "${srcroot}" "${lib_src}") - c4_add_target_sources(${target} INCORPORATED_FROM ${lib} PRIVATE ${lib_src}) - endif() - # - _c4_get_tgt_prop(lib_isrc ${lib} INTERFACE_SOURCES) - if(lib_isrc) - create_source_group("${lib}" "${srcroot}" "${lib_isrc}") - c4_add_target_sources(${target} INCORPORATED_FROM ${lib} INTERFACE ${lib_isrc}) - endif() - # - _c4_get_tgt_prop(lib_psrc ${lib} PRIVATE_SOURCES) - if(lib_psrc) - create_source_group("${lib}" "${srcroot}" "${lib_psrc}") - c4_add_target_sources(${target} INCORPORATED_FROM ${lib} INTERFACE ${lib_psrc}) - endif() - # - # - _c4_get_tgt_prop(lib_incs ${lib} INCLUDE_DIRECTORIES) - if(lib_incs) - target_include_directories(${target} PUBLIC ${lib_incs}) - endif() - # - _c4_get_tgt_prop(lib_iincs ${lib} INTERFACE_INCLUDE_DIRECTORIES) - if(lib_iincs) - target_include_directories(${target} INTERFACE ${lib_iincs}) - endif() - # - # - _c4_get_tgt_prop(lib_lib ${lib} LINK_LIBRARIES) - if(lib_lib) - target_link_libraries(${target} PUBLIC ${lib_lib}) - endif() - _c4_get_tgt_prop(lib_ilib ${lib} INTERFACE_LIBRARY) - if(lib_ilib) - target_link_libraries(${target} INTERFACE ${lib_ilib}) - endif() - # - # - c4_get_target_prop(${lib} SHARED_EXPORTS lib_exports) - if(lib_exports) - target_compile_definitions(${target} PRIVATE $) - endif() -endfunction() - - -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ -# -# -function(c4_add_target_sources target) - # https://steveire.wordpress.com/2016/08/09/opt-in-header-only-libraries-with-cmake/ - _c4_handle_args(_ARGS ${ARGN} - _ARGS1 # one-value macro arguments - INCORPORATED_FROM - TRANSFORM # Transform types: - # * NONE - do not transform the sources - # * UNITY - # * UNITY_HDR - # * SINGLE_HDR - # * SINGLE_UNIT - _ARGSN # multi-value macro arguments - PUBLIC - INTERFACE - PRIVATE - ) - if(("${_TRANSFORM}" STREQUAL "GLOBAL") OR ("${_TRANSFORM}" STREQUAL "")) - set(_TRANSFORM ${C4_SOURCE_TRANSFORM}) - endif() - if("${_TRANSFORM}" STREQUAL "") - set(_TRANSFORM NONE) - endif() - # - # is this target an interface? - set(_is_iface FALSE) - _c4_get_tgt_prop(target_type ${target} TYPE) - if("${target_type}" STREQUAL "INTERFACE_LIBRARY") - set(_is_iface TRUE) - elseif("${prop_name}" STREQUAL "LINK_LIBRARIES") - set(_is_iface FALSE) - endif() - # - set(out) - set(umbrella ${_c4_lprefix}transform-src) - # - if("${_TRANSFORM}" STREQUAL "NONE") - c4_dbg("target ${target}: source transform: NONE!") - # - # do not transform the sources - # - if(_PUBLIC) - c4_dbg("target=${target} PUBLIC sources: ${_PUBLIC}") - c4_append_target_prop(${target} PUBLIC_SRC "${_PUBLIC}") - if(_INCORPORATED_FROM) - c4_append_target_prop(${target} PUBLIC_SRC_${_INCORPORATED_FROM} "${_PUBLIC}") - else() - c4_append_target_prop(${target} PUBLIC_SRC_${target} "${_PUBLIC}") - endif() - target_sources(${target} PUBLIC "${_PUBLIC}") - endif() - if(_INTERFACE) - c4_dbg("target=${target} INTERFACE sources: ${_INTERFACE}") - c4_append_target_prop(${target} INTERFACE_SRC "${_INTERFACE}") - if(_INCORPORATED_FROM) - c4_append_target_prop(${target} INTERFACE_SRC_${_INCORPORATED_FROM} "${_INTERFACE}") - else() - c4_append_target_prop(${target} INTERFACE_SRC_${target} "${_INTERFACE}") - endif() - target_sources(${target} INTERFACE "${_INTERFACE}") - endif() - if(_PRIVATE) - c4_dbg("target=${target} PRIVATE sources: ${_PRIVATE}") - c4_append_target_prop(${target} PRIVATE_SRC "${_PRIVATE}") - if(_INCORPORATED_FROM) - c4_append_target_prop(${target} PRIVATE_SRC_${_INCORPORATED_FROM} "${_PRIVATE}") - else() - c4_append_target_prop(${target} PRIVATE_SRC_${target} "${_PRIVATE}") - endif() - target_sources(${target} PRIVATE "${_PRIVATE}") - endif() - # - elseif("${_TRANSFORM}" STREQUAL "UNITY") - c4_dbg("target ${target}: source transform: UNITY!") - c4_err("source transformation not implemented") - # - # concatenate all compilation unit files (excluding interface) - # into a single compilation unit - # - _c4cat_filter_srcs("${_PUBLIC}" cpublic) - _c4cat_filter_hdrs("${_PUBLIC}" hpublic) - _c4cat_filter_srcs("${_INTERFACE}" cinterface) - _c4cat_filter_hdrs("${_INTERFACE}" hinterface) - _c4cat_filter_srcs("${_PRIVATE}" cprivate) - _c4cat_filter_hdrs("${_PRIVATE}" hprivate) - if(cpublic OR cinterface OR cprivate) - _c4cat_get_outname(${target} "src" ${C4_GEN_SRC_EXT} out) - c4_dbg("${target}: output unit: ${out}") - c4_cat_sources("${cpublic};${cinterface};${cprivate}" "${out}" ${umbrella}) - add_dependencies(${target} ${out}) - endif() - if(_PUBLIC) - c4_append_target_prop(${target} PUBLIC_SRC - $ - $) - target_sources(${target} PUBLIC - $ - $) - endif() - if(_INTERFACE) - c4_append_target_prop(${target} INTERFACE_SRC - $ - $) - target_sources(${target} INTERFACE - $ - $) - endif() - if(_PRIVATE) - c4_append_target_prop(${target} PRIVATE_SRC - $ - $) - target_sources(${target} PRIVATE - $ - $) - endif() - elseif("${_TRANSFORM}" STREQUAL "UNITY_HDR") - c4_dbg("target ${target}: source transform: UNITY_HDR!") - c4_err("target ${target}: source transformation not implemented") - # - # like unity, but concatenate compilation units into - # a header file, leaving other header files untouched - # - _c4cat_filter_srcs("${_PUBLIC}" cpublic) - _c4cat_filter_hdrs("${_PUBLIC}" hpublic) - _c4cat_filter_srcs("${_INTERFACE}" cinterface) - _c4cat_filter_hdrs("${_INTERFACE}" hinterface) - _c4cat_filter_srcs("${_PRIVATE}" cprivate) - _c4cat_filter_hdrs("${_PRIVATE}" hprivate) - if(c) - _c4cat_get_outname(${target} "src" ${C4_GEN_HDR_EXT} out) - c4_dbg("${target}: output hdr: ${out}") - _c4cat_filter_srcs_hdrs("${_PUBLIC}" c_h) - c4_cat_sources("${c}" "${out}" ${umbrella}) - add_dependencies(${target} ${out}) - add_dependencies(${target} ${_c4_lprefix}cat) - endif() - set(${src} ${out} PARENT_SCOPE) - set(${hdr} ${h} PARENT_SCOPE) - # - elseif("${_TRANSFORM}" STREQUAL "SINGLE_HDR") - c4_dbg("target ${target}: source transform: SINGLE_HDR!") - c4_err("target ${target}: source transformation not implemented") - # - # concatenate everything into a single header file - # - _c4cat_get_outname(${target} "all" ${C4_GEN_HDR_EXT} out) - _c4cat_filter_srcs_hdrs("${_c4al_SOURCES}" ch) - c4_cat_sources("${ch}" "${out}" ${umbrella}) - # - elseif("${_TRANSFORM}" STREQUAL "SINGLE_UNIT") - c4_dbg("target ${target}: source transform: SINGLE_UNIT!") - c4_err("target ${target}: source transformation not implemented") - # - # concatenate: - # * all compilation units into a single compilation unit - # * all headers into a single header - # - _c4cat_get_outname(${target} "src" ${C4_GEN_SRC_EXT} out) - _c4cat_get_outname(${target} "hdr" ${C4_GEN_SRC_EXT} out) - _c4cat_filter_srcs_hdrs("${_c4al_SOURCES}" ch) - c4_cat_sources("${ch}" "${out}" ${umbrella}) - else() - c4_err("unknown transform type: ${transform_type}. Must be one of GLOBAL;NONE;UNITY;TO_HEADERS;SINGLE_HEADER") - endif() -endfunction() - - -# ----------------------------------------------------------------------------- -# ----------------------------------------------------------------------------- -# ----------------------------------------------------------------------------- -# WIP, under construction (still incomplete) -# see: https://github.com/pr0g/cmake-examples -# see: https://cliutils.gitlab.io/modern-cmake/ - - -function(c4_install_target target) - _c4_handle_args(_ARGS ${ARGN} - _ARGS1 # one-value macro arguments - EXPORT # the name of the export target. default: see below. - ) - _c4_handle_arg(EXPORT "${_c4_prefix}-export") - # - c4_dbg("installing target: ${target} ${ARGN}") - #_c4_is_incorporated(${_c4_prefix} inc) - #if(inc) - # c4_dbg("this project is INCORPORATEd. skipping install of targets") - # return() - #endif() - # - _c4_setup_install_vars() - install(TARGETS ${target} - EXPORT ${_EXPORT} - RUNTIME DESTINATION ${_RUNTIME_INSTALL_DIR} #COMPONENT runtime - BUNDLE DESTINATION ${_RUNTIME_INSTALL_DIR} #COMPONENT runtime - LIBRARY DESTINATION ${_LIBRARY_INSTALL_DIR} #COMPONENT runtime - ARCHIVE DESTINATION ${_ARCHIVE_INSTALL_DIR} #COMPONENT development - OBJECTS DESTINATION ${_OBJECTS_INSTALL_DIR} #COMPONENT development - INCLUDES DESTINATION ${_INCLUDE_INSTALL_DIR} #COMPONENT development - PUBLIC_HEADER DESTINATION ${_INCLUDE_INSTALL_DIR} #COMPONENT development - ) - c4_install_sources(${target} include) - # - # on windows, install also required DLLs - if(WIN32) - get_target_property(target_type ${target} TYPE) - if("${target_type}" STREQUAL "EXECUTABLE") - c4_get_transitive_property(${target} _C4_DLLS transitive_dlls) - if(transitive_dlls) - c4_dbg("${target}: installing dlls: ${transitive_dlls} to ${_RUNTIME_INSTALL_DIR}") - list(REMOVE_DUPLICATES transitive_dlls) - install(FILES ${transitive_dlls} - DESTINATION ${_RUNTIME_INSTALL_DIR} # shouldn't it be _LIBRARY_INSTALL_DIR? - #COMPONENT runtime - ) - endif() - endif() - endif() - # - set(l ${${_c4_prefix}_TARGETS}) - list(APPEND l ${target}) - set(${_c4_prefix}_TARGETS ${l} PARENT_SCOPE) - # -# # pkgconfig (WIP) -# set(pc ${CMAKE_CURRENT_BINARY_DIR}/pkgconfig/${target}.pc) -# file(WRITE ${pc} "# pkg-config: ${target} -# -#prefix=\"${CMAKE_INSTALL_PREFIX}\" -#exec_prefix=\"\${_c4_prefix}\" -#libdir=\"\${_c4_prefix}/${CMAKE_INSTALL_LIBDIR}\" -#includedir=\"\${_c4_prefix}/include\" -# -#Name: ${target} -#Description: A library for xyzzying frobnixes -#URL: https://github.com/me/mylibrary -#Version: 0.0.0 -#Requires: @PKGCONF_REQ_PUB@ -#Requires.private: @PKGCONF_REQ_PRIV@ -#Cflags: -I\"${includedir}\" -#Libs: -L\"${libdir}\" -lmylibrary -#Libs.private: -L\"${libdir}\" -lmylibrary @PKGCONF_LIBS_PRIV@ -#") -# _c4_setup_install_vars() -# install(FILES ${pc} DESTINATION "${_ARCHIVE_INSTALL_DIR}/pkgconfig/") -endfunction() - - -function(c4_install_sources target destination) - c4_dbg("target ${target}: installing sources to ${destination}") - # executables have no sources requiring install - _c4_get_tgt_prop(target_type ${target} TYPE) - if(target_type STREQUAL "EXECUTABLE") - c4_dbg("target ${target}: is executable, skipping source install") - return() - endif() - # install source from the target and incorporated targets - c4_get_target_prop(${target} INCORPORATED_TARGETS inctargets) - if(inctargets) - set(targets "${inctargets};${target}") - else() - set(targets "${target}") - endif() - foreach(t ${targets}) - _c4_get_tgt_prop(srcroot ${t} C4_SOURCE_ROOT) - # get the sources from the target - # - c4_get_target_prop(${t} PUBLIC_SRC_${t} src) - if(src) - _c4cat_filter_hdrs("${src}" srcf) - _c4cat_filter_additional_exts("${src}" add) - c4_install_files("${srcf}" "${destination}" "${srcroot}") - c4_install_files("${add}" "${destination}" "${srcroot}") - endif() - # - c4_get_target_prop(${t} PRIVATE_SRC_${t} psrc) - if(psrc) - _c4cat_filter_hdrs("${psrc}" psrcf) - _c4cat_filter_additional_exts("${psrc}" add) - c4_install_files("${psrcf}" "${destination}" "${srcroot}") - c4_install_files("${add}" "${destination}" "${srcroot}") - endif() - # - c4_get_target_prop(${t} INTERFACE_SRC_${t} isrc) - if(isrc) - _c4cat_filter_srcs_hdrs("${isrc}" isrcf) - _c4cat_filter_additional_exts("${isrc}" add) - c4_install_files("${isrcf}" "${destination}" "${srcroot}") - c4_install_files("${add}" "${destination}" "${srcroot}") - endif() - # - c4_get_target_prop(${t} ADDFILES addfiles) - if(addfiles) - foreach(af ${addfiles}) - string(REGEX REPLACE "(.*)!!(.*)!!(.*)" "\\1;\\2;\\3" li "${af}") - list(GET li 0 files) - list(GET li 1 dst) - list(GET li 2 relative_to) - string(REPLACE "%%%" ";" files "${files}") - c4_install_files("${files}" "${dst}" "${relative_to}") - endforeach() - endif() - # - c4_get_target_prop(${t} ADDDIRS adddirs) - if(adddirs) - foreach(af ${adddirs}) - string(REGEX REPLACE "(.*)!!(.*)!!(.*)" "\\1;\\2;\\3" li "${af}") - list(GET li 0 dirs) - list(GET li 1 dst) - list(GET li 2 relative_to) - string(REPLACE "%%%" ";" dirs "${files}") - c4_install_dirs("${dirs}" "${dst}" "${relative_to}") - endforeach() - endif() - endforeach() -endfunction() - - -function(c4_install_target_add_files target files destination relative_to) - c4_dbg("installing additional files for target ${target}, destination=${destination}: ${files}") - string(REPLACE ";" "%%%" rfiles "${files}") - c4_append_target_prop(${target} ADDFILES "${rfiles}!!${destination}!!${relative_to}") - # - _c4_is_incorporated(${_c4_prefix} inc) - if(inc) - c4_dbg("this project is INCORPORATEd. skipping install of targets") - return() - endif() - c4_install_files("${files}" "${destination}" "${relative_to}") -endfunction() - - -function(c4_install_target_add_dirs target dirs destination relative_to) - c4_dbg("installing additional dirs for target ${target}, destination=${destination}: ${dirs}") - string(REPLACE ";" "%%%" rdirs "${dirs}") - c4_append_target_prop(${target} ADDDIRS "${rdirs}!!${destination}!!${relative_to}") - # - _c4_is_incorporated(${_c4_prefix} inc) - if(inc) - c4_dbg("this project is INCORPORATEd. skipping install of targets") - return() - endif() - c4_install_dirs("${dirs}" "${destination}" "${relative_to}") -endfunction() - - -function(c4_install_files files destination relative_to) - c4_dbg("adding files to install list, destination ${destination}: ${files}") - foreach(f ${files}) - file(RELATIVE_PATH rf "${relative_to}" ${f}) - get_filename_component(rd "${rf}" DIRECTORY) - install(FILES ${f} DESTINATION "${destination}/${rd}" ${ARGN}) - endforeach() -endfunction() - - -function(c4_install_directories directories destination relative_to) - c4_dbg("adding directories to install list, destination ${destination}: ${directories}") - foreach(d ${directories}) - file(RELATIVE_PATH rf "${relative_to}" ${d}) - get_filename_component(rd "${rf}" DIRECTORY) - install(DIRECTORY ${d} DESTINATION "${destination}/${rd}" ${ARGN}) - endforeach() -endfunction() - - -function(c4_install_exports) - _c4_handle_args(_ARGS ${ARGN} - _ARGS1 # one-value macro arguments - PREFIX # override the c4 project-wide prefix. This will be used in the cmake - TARGET # the name of the exports target - NAMESPACE # the namespace for the targets - _ARGSN # multi-value macro arguments - DEPENDENCIES - ) - # - _c4_handle_arg(PREFIX "${_c4_prefix}") - _c4_handle_arg(TARGET "${_c4_prefix}-export") - _c4_handle_arg(NAMESPACE "${_c4_prefix}::") - # - c4_dbg("installing exports: ${ARGN}") - #_c4_is_incorporated(${_c4_prefix} inc) - #if(inc) - # c4_dbg("this project is INCORPORATEd. skipping install of exports") - # return() - #endif() - # - _c4_setup_install_vars() - # - list(GET ${_c4_prefix}_TARGETS 0 target) - set(exported_target "${_NAMESPACE}${target}") - set(targets_file "${_PREFIX}Targets.cmake") - # - set(deps) - if(_DEPENDENCIES) - set(deps "#----------------------------- -include(CMakeFindDependencyMacro) -") - foreach(d ${_DEPENDENCIES}) - _c4_is_incorporated(${d} inc) - if(inc) - c4_dbg("install: dependency ${d} is INCORPORATEd, skipping check") - continue() - endif() - c4_dbg("install: adding dependency check for ${d}") - set(deps "${deps}find_dependency(${d} REQUIRED) -") - endforeach() - set(deps "${deps}#-----------------------------") - endif() - # - # cfg_dst is the path relative to install root where the export - # should be installed; cfg_dst_rel is the path from there to - # the install root - macro(__c4_install_exports cfg_dst cfg_dst_rel) - # make sure that different exports are staged in different directories - set(case ${CMAKE_CURRENT_BINARY_DIR}/export_cases/${cfg_dst}) - file(MAKE_DIRECTORY ${case}) - # - install(EXPORT "${_TARGET}" - FILE "${targets_file}" - NAMESPACE "${_NAMESPACE}" - DESTINATION "${cfg_dst}") - export(EXPORT ${_TARGET} - FILE "${targets_file}" - NAMESPACE "${_NAMESPACE}") - # - # Config files - # the module below has nice docs in it; do read them - # to understand the macro calls below - include(CMakePackageConfigHelpers) - set(cfg ${case}/${_PREFIX}Config.cmake) - set(cfg_ver ${case}/${_PREFIX}ConfigVersion.cmake) - # - file(WRITE ${cfg}.in "${deps} -set(${_c4_uprefix}VERSION ${${_c4_uprefix}VERSION}) - -@PACKAGE_INIT@ - -if(NOT TARGET ${exported_target}) - include(\${PACKAGE_PREFIX_DIR}/${targets_file}) -endif() - -# HACK: PACKAGE_PREFIX_DIR is obtained from the PACKAGE_INIT macro above; -# When used below in the calls to set_and_check(), -# it points at the location of this file. So point it instead -# to the CMAKE_INSTALL_PREFIX, in relative terms -get_filename_component(PACKAGE_PREFIX_DIR - \"\${PACKAGE_PREFIX_DIR}/${cfg_dst_rel}\" ABSOLUTE) - -set_and_check(${_c4_uprefix}INCLUDE_DIR \"@PACKAGE__INCLUDE_INSTALL_DIR@\") -set_and_check(${_c4_uprefix}LIB_DIR \"@PACKAGE__LIBRARY_INSTALL_DIR@\") -#set_and_check(${_c4_uprefix}SYSCONFIG_DIR \"@PACKAGE__SYSCONFIG_INSTALL_DIR@\") - -check_required_components(${_c4_lcprefix}) -") - configure_package_config_file(${cfg}.in ${cfg} - INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}" # defaults to CMAKE_INSTALL_PREFIX - INSTALL_DESTINATION "${CMAKE_INSTALL_PREFIX}" - PATH_VARS - _INCLUDE_INSTALL_DIR - _LIBRARY_INSTALL_DIR - _SYSCONFIG_INSTALL_DIR - #NO_SET_AND_CHECK_MACRO - #NO_CHECK_REQUIRED_COMPONENTS_MACRO - ) - write_basic_package_version_file( - ${cfg_ver} - VERSION ${${_c4_uprefix}VERSION} - COMPATIBILITY AnyNewerVersion - ) - install(FILES ${cfg} ${cfg_ver} DESTINATION ${cfg_dst}) - endmacro(__c4_install_exports) - # - # To install the exports: - # - # Windows: - # / - # /(cmake|CMake)/ - # /*/ - # /*/(cmake|CMake)/ - # - # Unix: - # /(lib/|lib|share)/cmake/*/ - # /(lib/|lib|share)/*/ - # /(lib/|lib|share)/*/(cmake|CMake)/ - # - # Apple: - # /.framework/Resources/ - # /.framework/Resources/CMake/ - # /.framework/Versions/*/Resources/ - # /.framework/Versions/*/Resources/CMake/ - # /.app/Contents/Resources/ - # /.app/Contents/Resources/CMake/ - # - # (This was taken from the find_package() documentation) - if(WIN32) - __c4_install_exports(cmake/ "..") - elseif(APPLE) - __c4_install_exports(${_ARCHIVE_INSTALL_DIR}/cmake/${_c4_prefix} "../../..") - #__c4_install_exports(${_ARCHIVE_INSTALL_DIR}/${_c4_prefix}.framework/Resources/ "../../..") - elseif(UNIX OR (CMAKE_SYSTEM_NAME STREQUAL UNIX) OR (CMAKE_SYSTEM_NAME STREQUAL Linux) OR (CMAKE_SYSTEM_NAME STREQUAL Generic)) - __c4_install_exports(${_ARCHIVE_INSTALL_DIR}/cmake/${_c4_prefix} "../../..") - else() - c4_err("unknown platform. CMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME} CMAKE_SYSTEM_PROCESSOR=${CMAKE_SYSTEM_PROCESSOR}") - endif() -endfunction() - - -macro(_c4_setup_install_vars) - set(_RUNTIME_INSTALL_DIR bin/) - set(_ARCHIVE_INSTALL_DIR lib/) - set(_LIBRARY_INSTALL_DIR lib/) # TODO on Windows, ARCHIVE and LIBRARY dirs must be different to prevent name clashes - set(_INCLUDE_INSTALL_DIR include/) - set(_OBJECTS_INSTALL_DIR obj/) - set(_SYSCONFIG_INSTALL_DIR etc/${_c4_lcprefix}/) -endmacro() - - -function(c4_get_target_installed_headers target out) - c4_get_target_prop(${target} INCORPORATED_TARGETS inctargets) - if(inctargets) - set(targets "${inctargets};${target}") - else() - set(targets "${target}") - endif() - set(hdrs) - foreach(t ${targets}) - _c4_get_tgt_prop(srcroot ${t} C4_SOURCE_ROOT) - # - c4_get_target_prop(${t} PUBLIC_SRC_${t} src) - if(src) - _c4cat_filter_hdrs("${src}" srcf) - if(thdrs) - set(thdrs "${thdrs};${srcf}") - else() - set(thdrs "${srcf}") - endif() - endif() - # - c4_get_target_prop(${t} PRIVATE_SRC_${t} psrc) - if(src) - _c4cat_filter_hdrs("${psrc}" psrcf) - if(thdrs) - set(thdrs "${thdrs};${psrcf}") - else() - set(thdrs "${psrcf}") - endif() - endif() - # - c4_get_target_prop(${t} INTERFACE_SRC_${t} isrc) - if(src) - _c4cat_filter_hdrs("${isrc}" isrcf) - if(thdrs) - set(thdrs "${thdrs};${isrcf}") - else() - set(thdrs "${isrcf}") - endif() - endif() - # - foreach(h ${thdrs}) - file(RELATIVE_PATH rf "${srcroot}" "${h}") - list(APPEND hdrs "${rf}") - endforeach() - endforeach() - set(${out} ${hdrs} PARENT_SCOPE) -endfunction() - - -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ -function(c4_setup_testing) - _c4_handle_args(_ARGS ${ARGN} - _ARGS0 - GTEST # download and import googletest - DOCTEST # download and import doctest - _ARGS1 - _ARGSN - ) - #include(GoogleTest) # this module requires at least cmake 3.9 - c4_dbg("enabling tests") - # umbrella target for building test binaries - add_custom_target(${_c4_lprefix}test-build) - _c4_set_target_folder(${_c4_lprefix}test-build test) - # umbrella targets for running tests - if(NOT TARGET test-build) - add_custom_target(test-build) - add_custom_target(test-verbose) - _c4_set_target_folder(test-build "/test") - _c4_set_target_folder(test-verbose "/test") - endif() - if(NOT TARGET test) - # add a test target. To prevent a warning, we need to set up a policy, - # and also suppress the resulting warning from suppressing the warning. - set(_depr_old_val ${CMAKE_WARN_DEPRECATED}) - set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "" FORCE) # https://stackoverflow.com/questions/67432538/cannot-set-cmake-warn-deprecated-inside-the-cmakelists-txt - cmake_policy(PUSH) - cmake_policy(SET CMP0037 OLD) # target name "test" is reserved for CTesting - add_custom_target(test) - _c4_set_target_folder(test "/test") - cmake_policy(POP) - set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "${_depr_old_val}" FORCE) - unset(_depr_old_val) - endif() - function(_def_runner runner) - set(echo " -CWD=${CMAKE_CURRENT_BINARY_DIR} ----------------------------------- -${ARGN} ----------------------------------- -") - add_custom_target(${runner} - #${CMAKE_COMMAND} -E echo "${echo}" - COMMAND ${ARGN} - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS ${_c4_lprefix}test-build - ) - _c4_set_target_folder(${runner} test) - endfunction() - _def_runner(${_c4_lprefix}test-run ${CMAKE_CTEST_COMMAND} --output-on-failure ${${_c4_uprefix}CTEST_OPTIONS} -C $) - _def_runner(${_c4_lprefix}test-run-verbose ${CMAKE_CTEST_COMMAND} -VV ${${_c4_uprefix}CTEST_OPTIONS} -C $) - add_dependencies(test ${_c4_lprefix}test-run) - add_dependencies(test-verbose ${_c4_lprefix}test-run-verbose) - add_dependencies(test-build ${_c4_lprefix}test-build) - # - # import required libraries - if(_GTEST) - c4_log("testing requires googletest") - if(NOT TARGET gtest) - c4_import_remote_proj(gtest ${CMAKE_CURRENT_BINARY_DIR}/ext/gtest - REMOTE - GIT_REPOSITORY https://github.com/google/googletest.git - GIT_TAG release-1.11.0 #GIT_SHALLOW ON - OVERRIDE - BUILD_GTEST ON - BUILD_GMOCK OFF - gtest_force_shared_crt ON - gtest_build_samples OFF - gtest_build_tests OFF - SET_FOLDER_TARGETS ext gtest gtest_main - EXCLUDE_FROM_ALL - ) - # old gcc-4.8 support - if((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") AND - (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 4.8) AND - (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0)) - _c4_get_subproject_property(gtest SRC_DIR _gtest_patch_src_dir) - apply_patch("${_c4_project_dir}/compat/gtest_gcc-4.8.patch" - "${_gtest_patch_src_dir}" - "${_gtest_patch_src_dir}/.gtest_gcc-4.8.patch") - unset(_gtest_patch_src_dir) - target_compile_options(gtest PUBLIC -include ${_c4_project_dir}/compat/c4/gcc-4.8.hpp) - endif() - endif() - endif() - if(_DOCTEST) - c4_log("testing requires doctest") - if(NOT TARGET doctest) - c4_import_remote_proj(doctest ${CMAKE_CURRENT_BINARY_DIR}/ext/doctest - REMOTE - GIT_REPOSITORY https://github.com/onqtam/doctest.git - GIT_TAG 2.4.6 #GIT_SHALLOW ON - OVERRIDE - DOCTEST_WITH_TESTS OFF - DOCTEST_WITH_MAIN_IN_STATIC_LIB ON - SET_FOLDER_TARGETS ext doctest_with_main - EXCLUDE_FROM_ALL - ) - endif() - endif() -endfunction(c4_setup_testing) - - -function(c4_add_test target) - _c4_handle_args(_ARGS ${ARGN} - _ARGS0 # zero-value macro arguments - _ARGS1 # one-value macro arguments - WORKING_DIRECTORY - _ARGSN # multi-value macro arguments - ARGS - ) - # - if(_WORKING_DIRECTORY) - set(_WORKING_DIRECTORY WORKING_DIRECTORY ${_WORKING_DIRECTORY}) - endif() - set(cmd_pfx) - if(CMAKE_CROSSCOMPILING) - set(cmd_pfx ${CMAKE_CROSSCOMPILING_EMULATOR}) - endif() - if(NOT ${uprefix}SANITIZE_ONLY) - if(${CMAKE_VERSION} VERSION_LESS "3.16.0") - add_test(NAME ${target} - COMMAND ${cmd_pfx} "$" ${_ARGS} - ${_WORKING_DIRECTORY}) - else() - add_test(NAME ${target} - COMMAND ${cmd_pfx} "$" ${_ARGS} - ${_WORKING_DIRECTORY} - COMMAND_EXPAND_LISTS) - endif() - endif() - # - if("${CMAKE_BUILD_TYPE}" STREQUAL "Coverage") - add_dependencies(${_c4_lprefix}test-build ${target}) - return() - endif() - # - set(sanitized_targets) - foreach(s asan msan tsan ubsan) - set(t ${target}-${s}) - if(TARGET ${t}) - list(APPEND sanitized_targets ${s}) - endif() - endforeach() - if(sanitized_targets) - add_custom_target(${target}-all) - add_dependencies(${target}-all ${target}) - add_dependencies(${_c4_lprefix}test-build ${target}-all) - _c4_set_target_folder(${target}-all test/${target}) - else() - add_dependencies(${_c4_lprefix}test-build ${target}) - endif() - if(sanitized_targets) - foreach(s asan msan tsan ubsan) - set(t ${target}-${s}) - if(TARGET ${t}) - add_dependencies(${target}-all ${t}) - c4_sanitize_get_target_command("${cmd_pfx};$" ${s} cmd) - #c4_log("adding test: ${t}") - add_test(NAME ${t} - COMMAND ${cmd} ${_ARGS} - ${_WORKING_DIRECTORY} - COMMAND_EXPAND_LISTS) - endif() - endforeach() - endif() - if(NOT CMAKE_CROSSCOMPILING) - if(NOT ${_c4_uprefix}SANITIZE_ONLY) - c4_add_valgrind(${target} ${ARGN}) - endif() - endif() - if(${_c4_uprefix}LINT) - c4_static_analysis_add_tests(${target}) # this will not actually run the executable - endif() -endfunction(c4_add_test) - - -# every excess argument is passed on to set_target_properties() -function(c4_add_test_fail_build name srccontent_or_srcfilename) - # - set(sdir ${CMAKE_CURRENT_BINARY_DIR}/test_fail_build) - set(src ${srccontent_or_srcfilename}) - if("${src}" STREQUAL "") - c4_err("must be given an existing source file name or a non-empty string") - endif() - # - if(EXISTS ${src}) - set(fn ${src}) - else() - if(NOT EXISTS ${sdir}) - file(MAKE_DIRECTORY ${sdir}) - endif() - set(fn ${sdir}/${name}.cpp) - file(WRITE ${fn} "${src}") - endif() - # - # https://stackoverflow.com/questions/30155619/expected-build-failure-tests-in-cmake - add_executable(${name} ${fn}) - # don't build this target - set_target_properties(${name} PROPERTIES - EXCLUDE_FROM_ALL TRUE - EXCLUDE_FROM_DEFAULT_BUILD TRUE - # and pass on further properties given by the caller - ${ARGN}) - add_test(NAME ${name} - COMMAND ${CMAKE_COMMAND} --build . --target ${name} --config $ - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - set_tests_properties(${name} PROPERTIES WILL_FAIL TRUE) -endfunction() - - -# add a test ensuring that a target linking and using code from a library -# successfully compiles and runs against the installed library -function(c4_add_install_link_test library namespace exe_source_code) - if(CMAKE_CROSSCOMPILING) - c4_log("cross-compiling: skip install link test") - return() - endif() - if("${library}" STREQUAL "${_c4_prefix}") - set(testname ${_c4_lprefix}test-install-link) - else() - set(testname ${_c4_lprefix}test-install-link-${library}) - endif() - _c4_add_library_client_test(${library} "${namespace}" "${testname}" "${exe_source_code}") -endfunction() - - -# add a test ensuring that a target consuming every header in a library -# successfully compiles and runs against the installed library -function(c4_add_install_include_test library namespace) - if(CMAKE_CROSSCOMPILING) - c4_log("cross-compiling: skip install include test") - return() - endif() - c4_get_target_installed_headers(${library} incfiles) - set(incblock) - foreach(i ${incfiles}) - set(incblock "${incblock} -#include <${i}>") - endforeach() - set(src "${incblock} - -int main() -{ - return 0; -} -") - if("${library}" STREQUAL "${_c4_prefix}") - set(testname ${_c4_lprefix}test-install-include) - else() - set(testname ${_c4_lprefix}test-install-include-${library}) - endif() - _c4_add_library_client_test(${library} "${namespace}" "${testname}" "${src}") -endfunction() - - -function(_c4_add_library_client_test library namespace pname source_code) - if("${CMAKE_BUILD_TYPE}" STREQUAL Coverage) - add_test(NAME ${pname} - COMMAND ${CMAKE_COMMAND} -E echo "skipping this test in coverage builds" - ) - return() - endif() - set(pdir "${CMAKE_CURRENT_BINARY_DIR}/${pname}") - set(bdir "${pdir}/build") - if(NOT EXISTS "${pdir}") - file(MAKE_DIRECTORY "${pdir}") - endif() - if(NOT EXISTS "${bdir}/build") - file(MAKE_DIRECTORY "${bdir}/build") - endif() - set(psrc "${pdir}/${pname}.cpp") - set(tsrc "${pdir}/${pname}-run.cmake") - set(tout "${pdir}/${pname}-run-out") - # generate the source file - file(WRITE "${psrc}" "${source_code}") - # generate the cmake project consuming this library - file(WRITE "${pdir}/CMakeLists.txt" " -cmake_minimum_required(VERSION 3.12) -project(${pname} LANGUAGES CXX) - -find_package(${library} REQUIRED) - -message(STATUS \" -found ${library}: - ${_c4_uprefix}INCLUDE_DIR=\${${_c4_uprefix}INCLUDE_DIR} - ${_c4_uprefix}LIB_DIR=\${${_c4_uprefix}LIB_DIR} -\") - -add_executable(${pname} ${pname}.cpp) -# this must be the only required setup to link with ${library} -target_link_libraries(${pname} PUBLIC ${namespace}${library}) - -get_target_property(lib_type ${namespace}${library} TYPE) -if(WIN32 AND (lib_type STREQUAL SHARED_LIBRARY)) - # add the directory containing the DLL to the path - get_target_property(imported_configs ${namespace}${library} IMPORTED_CONFIGURATIONS) - message(STATUS \"${namespace}${library}: it's a shared library. imported configs: \${imported_configs}\") - foreach(cfg \${imported_configs}) - get_target_property(implib ${namespace}${library} IMPORTED_IMPLIB_\${cfg}) - get_target_property(location ${namespace}${library} IMPORTED_LOCATION_\${cfg}) - message(STATUS \"${namespace}${library}: implib_\${cfg}=\${implib}\") - message(STATUS \"${namespace}${library}: location_\${cfg}=\${location}\") - break() - endforeach() - get_filename_component(dlldir \"\${location}\" DIRECTORY) - message(STATUS \"${namespace}${library}: dlldir=\${dlldir}\") - add_custom_target(${pname}-run - COMMAND \${CMAKE_COMMAND} -E echo \"cd \${dlldir} && \$\" - COMMAND \$ - DEPENDS ${pname} - WORKING_DIRECTORY \${dlldir}) -else() - add_custom_target(${pname}-run - COMMAND \$ - DEPENDS ${pname}) -endif() -") - # The test consists in running the script generated below. - # We force evaluation of the configuration generator expression - # by receiving its result via the command line. - add_test(NAME ${pname} - COMMAND ${CMAKE_COMMAND} -DCFG_IN=$ -P "${tsrc}" - ) - # NOTE: in the cmake configure command, be sure to NOT use quotes - # in -DCMAKE_PREFIX_PATH=\"${CMAKE_INSTALL_PREFIX}\". Use - # -DCMAKE_PREFIX_PATH=${CMAKE_INSTALL_PREFIX} instead. - # So here we add a check to make sure the install path has no spaces - string(FIND "${CMAKE_INSTALL_PREFIX}" " " has_spaces) - if(NOT (has_spaces EQUAL -1)) - c4_err("install tests will fail if the install path has spaces: '${CMAKE_INSTALL_PREFIX}' : ... ${has_spaces}") - endif() - # make sure the test project uses the same architecture - # CMAKE_VS_PLATFORM_NAME is available only since cmake 3.9 - # see https://cmake.org/cmake/help/v3.9/variable/CMAKE_GENERATOR_PLATFORM.html - if(WIN32) - set(cfg_opt "--config \${cfg}") - if(CMAKE_GENERATOR_PLATFORM OR CMAKE_VS_PLATFORM_NAME) - set(arch "-DCMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}" "-DCMAKE_VS_PLATFORM_NAME=${CMAKE_VS_PLATFORM_NAME}") - else() - if(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(arch -A x64) - elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) - set(arch -A Win32) - else() - c4_err("not implemented") - endif() - endif() - elseif(ANDROID OR IOS OR WINCE OR WINDOWS_PHONE) - c4_err("not implemented") - elseif(IOS) - c4_err("not implemented") - elseif(UNIX) - if(CMAKE_GENERATOR_PLATFORM OR CMAKE_VS_PLATFORM_NAME) - set(arch "-DCMAKE_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}" "-DCMAKE_VS_PLATFORM_NAME=${CMAKE_VS_PLATFORM_NAME}") - else() - if(CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64) - else() - if(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(arch "-DCMAKE_CXX_FLAGS=-m64") - elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) - set(arch "-DCMAKE_CXX_FLAGS=-m32") - else() - c4_err("not implemented") - endif() - endif() - endif() - endif() - # generate the cmake script with the test content - file(WRITE "${tsrc}" " -# run a command and check its return status -function(runcmd id) - set(cmdout \"${tout}-\${id}.log\") - message(STATUS \"Running command: \${ARGN}\") - message(STATUS \"Running command: output goes to \${cmdout}\") - execute_process( - COMMAND \${ARGN} - RESULT_VARIABLE retval - OUTPUT_FILE \"\${cmdout}\" - ERROR_FILE \"\${cmdout}\" - # COMMAND_ECHO STDOUT # only available from cmake-3.15 - ) - message(STATUS \"Running command: exit status was \${retval}\") - file(READ \"\${cmdout}\" output) - if(\"\${cmdout}\" STREQUAL \"\") - message(STATUS \"Running command: no output\") - else() - message(STATUS \"Running command: output: --------------------- -\${output}--------------------\") - endif() - if(NOT (\${retval} EQUAL 0)) - message(FATAL_ERROR \"Command failed with exit status \${retval}: \${ARGN}\") - endif() -endfunction() - -set(cmk \"${CMAKE_COMMAND}\") -set(pfx \"${CMAKE_INSTALL_PREFIX}\") -set(idir \"${CMAKE_BINARY_DIR}\") -set(pdir \"${pdir}\") -set(bdir \"${bdir}\") - -# force evaluation of the configuration generator expression -# by receiving its result via the command line -set(cfg \${CFG_IN}) - -# remove any existing library install -if(EXISTS \"\${pfx}\") - runcmd(0_rmdir \"\${cmk}\" -E remove_directory \"\${pfx}\") -else() - message(STATUS \"does not exist: \${pfx}\") -endif() - -# install the library -#runcmd(1_install_lib \"\${cmk}\" --install \"\${idir}\" ${cfg_opt}) # requires cmake>3.13 (at least) -runcmd(1_install_lib \"\${cmk}\" --build \"\${idir}\" ${cfg_opt} --target install) - -# configure the client project -runcmd(2_config \"\${cmk}\" -S \"\${pdir}\" -B \"\${bdir}\" \"-DCMAKE_PREFIX_PATH=\${pfx}\" \"-DCMAKE_GENERATOR=${CMAKE_GENERATOR}\" ${arch} \"-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}\" \"-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}\") - -# build the client project -runcmd(3_build \"\${cmk}\" --build \"\${bdir}\" ${cfg_opt}) - -# run the client executable -runcmd(4_install \"\${cmk}\" --build \"\${bdir}\" --target \"${pname}-run\" ${cfg_opt}) -") -endfunction() - - -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ -function(c4_setup_valgrind umbrella_option) - if(UNIX AND (NOT "${CMAKE_BUILD_TYPE}" STREQUAL "Coverage")) - if("${C4_VALGRIND}" STREQUAL "") - option(C4_VALGRIND "enable valgrind tests (all subprojects)" ON) - endif() - if("${C4_VALGRIND_SGCHECK}" STREQUAL "") - option(C4_VALGRIND_SGCHECK "enable valgrind tests with the exp-sgcheck tool (all subprojects)" OFF) - endif() - cmake_dependent_option(${_c4_uprefix}VALGRIND "enable valgrind tests" ${C4_VALGRIND} ${umbrella_option} OFF) - cmake_dependent_option(${_c4_uprefix}VALGRIND_SGCHECK "enable valgrind tests with the exp-sgcheck tool" ${C4_VALGRIND_SGCHECK} ${umbrella_option} OFF) - set(${_c4_uprefix}VALGRIND_OPTIONS "--gen-suppressions=all --error-exitcode=10101" CACHE STRING "options for valgrind tests") - endif() -endfunction(c4_setup_valgrind) - - -function(c4_add_valgrind target_name) - _c4_handle_args(_ARGS ${ARGN} - _ARGS0 # zero-value macro arguments - _ARGS1 # one-value macro arguments - WORKING_DIRECTORY - _ARGSN # multi-value macro arguments - ARGS - ) - # - if(_WORKING_DIRECTORY) - set(_WORKING_DIRECTORY WORKING_DIRECTORY ${_WORKING_DIRECTORY}) - endif() - # @todo: consider doing this for valgrind: - # http://stackoverflow.com/questions/40325957/how-do-i-add-valgrind-tests-to-my-cmake-test-target - # for now we explicitly run it: - if(${_c4_uprefix}VALGRIND) - separate_arguments(_vg_opts UNIX_COMMAND "${${_c4_uprefix}VALGRIND_OPTIONS}") - add_test(NAME ${target_name}-valgrind - COMMAND valgrind ${_vg_opts} $ ${_ARGS} - ${_WORKING_DIRECTORY} - COMMAND_EXPAND_LISTS) - endif() - if(${_c4_uprefix}VALGRIND_SGCHECK) - # stack and global array overrun detector - # http://valgrind.org/docs/manual/sg-manual.html - separate_arguments(_sg_opts UNIX_COMMAND "--tool=exp-sgcheck ${${_c4_uprefix}VALGRIND_OPTIONS}") - add_test(NAME ${target_name}-sgcheck - COMMAND valgrind ${_sg_opts} $ ${_ARGS} - ${_WORKING_DIRECTORY} - COMMAND_EXPAND_LISTS) - endif() -endfunction(c4_add_valgrind) - - -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ - -function(c4_setup_coverage) - if(NOT ("${CMAKE_BUILD_TYPE}" STREQUAL "Coverage")) - return() - endif() - # - _c4_handle_args(_ARGS ${ARGN} - _ARGS0 # zero-value macro arguments - _ARGS1 # one-value macro arguments - _ARGSN # multi-value macro arguments - COVFLAGS # coverage compilation flags - INCLUDE # patterns to include in the coverage, relative to CMAKE_SOURCE_DIR - EXCLUDE # patterns to exclude in the coverage, relative to CMAKE_SOURCE_DIR - EXCLUDE_ABS # absolute paths to exclude in the coverage - GENHTML_ARGS # options to pass to genhtml - ) - # defaults for the macro arguments - set(_genhtml_args "--title ${_c4_lcprefix} --demangle-cpp --sort --function-coverage --branch-coverage --prefix '${CMAKE_SOURCE_DIR}' --prefix '${CMAKE_BINARY_DIR}'") - set(covflags "-g -O0 --coverage") #set(covflags "-g -O0 -fprofile-arcs -ftest-coverage") - if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") - set(covflags "${covflags} -fprofile-arcs -ftest-coverage -fno-inline -fno-inline-small-functions -fno-default-inline") - endif() - set(${_c4_uprefix}COVERAGE_FLAGS "${covflags}" CACHE STRING "coverage compilation flags") - set(${_c4_uprefix}COVERAGE_GENHTML_ARGS "${_genhtml_args}" CACHE STRING "arguments to pass to genhtml") - set(${_c4_uprefix}COVERAGE_INCLUDE src CACHE STRING "relative paths to include in the coverage, relative to CMAKE_SOURCE_DIR") - set(${_c4_uprefix}COVERAGE_EXCLUDE bm;build;extern;ext;src/c4/ext;test CACHE STRING "relative paths to exclude from the coverage, relative to CMAKE_SOURCE_DIR") - set(${_c4_uprefix}COVERAGE_EXCLUDE_ABS /usr CACHE STRING "absolute paths to exclude from the coverage") - _c4_handle_arg(COVFLAGS ${${_c4_uprefix}COVERAGE_FLAGS}) - _c4_handle_arg(INCLUDE ${${_c4_uprefix}COVERAGE_INCLUDE}) - _c4_handle_arg(EXCLUDE ${${_c4_uprefix}COVERAGE_EXCLUDE}) - _c4_handle_arg(EXCLUDE_ABS ${${_c4_uprefix}COVERAGE_EXCLUDE_ABS} "${CMAKE_BINARY_DIR}") - _c4_handle_arg(GENHTML_ARGS ${${_c4_uprefix}COVERAGE_GENHTML_ARGS}) - # - function(_c4cov_transform_filters var reldir) - set(_filters) - foreach(pat ${${var}}) - list(APPEND _filters "'${reldir}${pat}/*'") - endforeach() - set(${var} ${_filters} PARENT_SCOPE) - endfunction() - _c4cov_transform_filters(_INCLUDE "${CMAKE_SOURCE_DIR}/") - _c4cov_transform_filters(_EXCLUDE "${CMAKE_SOURCE_DIR}/") - _c4cov_transform_filters(_EXCLUDE_ABS "") - # - if("${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang") - if("${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS 3) - c4_err("coverage: clang version must be 3.0.0 or greater") - endif() - elseif(NOT CMAKE_COMPILER_IS_GNUCXX) - c4_err("coverage: compiler is not GNUCXX") - endif() - # - find_program(GCOV gcov) - find_program(LCOV lcov) - find_program(GENHTML genhtml) - find_program(CTEST ctest) - if(NOT (GCOV AND LCOV AND GENHTML AND CTEST)) - c4_err("Coverage tools not available: - gcov: ${GCOV} - lcov: ${LCOV} - genhtml: ${GENHTML} - ctest: ${CTEST} - --coverage flags: ${_COVFLAGS}") - endif() - # - add_configuration_type(Coverage - DEFAULT_FROM DEBUG - C_FLAGS ${_COVFLAGS} - CXX_FLAGS ${_COVFLAGS} - ) - # - option(${_c4_uprefix}COVERAGE_CODECOV "enable target to submit coverage to codecov.io" OFF) - option(${_c4_uprefix}COVERAGE_COVERALLS "enable target to submit coverage to coveralls.io" OFF) - # - c4_dbg("adding coverage targets") - # - set(sd "${CMAKE_SOURCE_DIR}") - set(bd "${CMAKE_BINARY_DIR}") - set(coverage_result ${bd}/lcov/index.html) - set(lcov_result ${bd}/coverage3-final_filtered.lcov) - separate_arguments(_GENHTML_ARGS NATIVE_COMMAND ${_GENHTML_ARGS}) - add_custom_command(OUTPUT ${coverage_result} ${lcov_result} - COMMAND echo "cd ${CMAKE_BINARY_DIR}" - COMMAND ${LCOV} -q --zerocounters --directory . - COMMAND ${LCOV} -q --no-external --capture --base-directory "${sd}" --directory . --output-file ${bd}/coverage0-before.lcov --initial - COMMAND ${CMAKE_COMMAND} --build . --target ${_c4_lprefix}test-run || echo "Failed running the tests. Proceeding with coverage, but results may be affected or even empty." - COMMAND ${LCOV} -q --no-external --capture --base-directory "${sd}" --directory . --output-file ${bd}/coverage1-after.lcov - COMMAND ${LCOV} -q --add-tracefile ${bd}/coverage0-before.lcov --add-tracefile ${bd}/coverage1-after.lcov --output-file ${bd}/coverage2-final.lcov - COMMAND ${LCOV} -q --remove ${bd}/coverage2-final.lcov ${_EXCLUDE} ${EXCLUDE_ABS} --output-file ${bd}/coverage3-final_filtered.lcov - COMMAND ${GENHTML} ${bd}/coverage3-final_filtered.lcov -o ${bd}/lcov ${_GENHTML_ARGS} - COMMAND echo "Coverage report: ${coverage_result}" - DEPENDS ${_c4_lprefix}test-build - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - COMMENT "${_c4_prefix} coverage: LCOV report at ${coverage_result}" - #VERBATIM - ) - add_custom_target(${_c4_lprefix}coverage SOURCES ${coverage_result} ${lcov_result}) - # - if(${_c4_uprefix}COVERAGE_CODECOV) - set(_subm ${_c4_lprefix}coverage-submit-codecov) - _c4cov_get_service_token(codecov _token) - if(NOT ("${_token}" STREQUAL "")) - set(_token -t "${_token}") - endif() - set(_silent_codecov) - if(${_c4_uprefix}COVERAGE_CODECOV_SILENT) - set(_silent_codecov >${CMAKE_BINARY_DIR}/codecov.log 2>&1) - endif() - # - c4_log("coverage: enabling submission of results to https://codecov.io: ${_subm}") - set(submitcc "${CMAKE_BINARY_DIR}/submit_codecov.sh") - c4_download_file("https://codecov.io/bash" "${submitcc}") - set(submit_cmd bash ${submitcc} -Z ${_token} -X gcov -X gcovout -p ${CMAKE_SOURCE_DIR} -f ${lcov_result} ${_silent_codecov}) - string(REPLACE ";" " " submit_cmd_str "${submit_cmd}") - add_custom_target(${_subm} - SOURCES ${lcov_result} - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - COMMAND echo "cd ${CMAKE_BINARY_DIR} && ${submit_cmd_str}" - COMMAND ${submit_cmd} - VERBATIM - COMMENT "${_c4_lcprefix} coverage: submit to codecov" - ) - c4_add_umbrella_target(coverage-submit-codecov coverage-submit) # uses the current prefix - endif() - # - if(${_c4_uprefix}COVERAGE_COVERALLS) - set(_subm ${_c4_lprefix}coverage-submit-coveralls) - _c4cov_get_service_token(coveralls _token) - if(NOT ("${_token}" STREQUAL "")) - set(_token --repo-token "${_token}") - endif() - set(_silent_coveralls) - if(${_c4_uprefix}COVERAGE_COVERALLS_SILENT) - set(_silent_coveralls >${CMAKE_BINARY_DIR}/coveralls.log 2>&1) - endif() - # - c4_log("coverage: enabling submission of results to https://coveralls.io: ${_subm}") - set(submit_cmd coveralls ${_token} --build-root ${CMAKE_BINARY_DIR} --root ${CMAKE_SOURCE_DIR} --no-gcov --lcov-file ${lcov_result} ${_silent_coveralls}) - string(REPLACE ";" " " submit_cmd_str "${submit_cmd}") - add_custom_target(${_subm} - SOURCES ${lcov_result} - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - COMMAND echo "cd ${CMAKE_BINARY_DIR} && ${submit_cmd_str}" - COMMAND ${submit_cmd} - VERBATIM - COMMENT "${_c4_lcprefix} coverage: submit to coveralls" - ) - c4_add_umbrella_target(coverage-submit-coveralls coverage-submit) # uses the current prefix - endif() -endfunction(c4_setup_coverage) - - -# 1. try cmake or environment variables -# 2. try local file -function(_c4cov_get_service_token service out) - # try cmake var - string(TOUPPER ${service} uservice) - c4_get_from_first_of(token COVERAGE_${uservice}_TOKEN ENV) - if(NOT ("${token}" STREQUAL "")) - c4_dbg("${service}: found token from variable: ${token}") - else() - # try local file - set(service_token_file ${CMAKE_SOURCE_DIR}/.ci/${service}.token) - if(EXISTS ${service_token_file}) - file(READ ${service_token_file} token) - c4_dbg("found token file for ${service} coverage report: ${service_token_file}") - else() - c4_dbg("could not find token for ${service} coverage report") - endif() - endif() - set(${out} ${token} PARENT_SCOPE) -endfunction() - - -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ - -function(c4_add_umbrella_target target umbrella_target) - _c4_handle_args(_ARGS ${ARGN} - # zero-value macro arguments - _ARGS0 - ALWAYS # Add the umbrella target even if this is the only one under it. - # The default behavior is to add the umbrella target only if - # there is more than one target under it. - # one-value macro arguments - _ARGS1 - PREFIX # The project prefix. Defaults to ${_c4_lprefix} - # multi-value macro arguments - _ARGSN - ARGS # more args to add_custom_target() - ) - if(NOT _PREFIX) - set(_PREFIX "${_c4_lprefix}") - endif() - set(t ${_PREFIX}${target}) - set(ut ${_PREFIX}${umbrella_target}) - # if the umbrella target already exists, just add the dependency - if(TARGET ${ut}) - add_dependencies(${ut} ${t}) - else() - if(_ALWAYS) - add_custom_target(${ut} ${_ARGS}) - add_dependencies(${ut} ${t}) - else() - # check if there is more than one under the same umbrella - c4_get_proj_prop(${ut}_subtargets sub) - if(sub) - add_custom_target(${ut} ${_ARGS}) - add_dependencies(${ut} ${sub}) - add_dependencies(${ut} ${t}) - else() - c4_set_proj_prop(${ut}_subtargets ${t}) - endif() - endif() - endif() -endfunction() - - - -function(c4_download_file url dstpath) - c4_dbg("downloading file: ${url} ---> ${dstpath}") - get_filename_component(abspath ${dstpath} ABSOLUTE) - if(NOT EXISTS ${abspath}) - c4_dbg("downloading file: does not exist: ${dstpath}") - file(DOWNLOAD ${url} ${abspath} LOG dl_log STATUS status ${ARGN}) - if((NOT (status EQUAL 0)) OR (NOT EXISTS ${abspath})) - c4_err("error downloading file: ${url} -> ${abspath}:\n${dl_log}") - endif() - endif() -endfunction() - - -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ -function(c4_setup_benchmarking) - c4_log("enabling benchmarks: to build, ${_c4_lprefix}bm-build") - c4_log("enabling benchmarks: to run, ${_c4_lprefix}bm-run") - # umbrella target for building test binaries - add_custom_target(${_c4_lprefix}bm-build) - # umbrella target for running benchmarks - add_custom_target(${_c4_lprefix}bm-run - ${CMAKE_COMMAND} -E echo CWD=${CMAKE_CURRENT_BINARY_DIR} - DEPENDS ${_c4_lprefix}bm-build - ) - if(NOT TARGET bm-run) - add_custom_target(bm-run) - add_custom_target(bm-build) - endif() - add_dependencies(bm-run ${_c4_lprefix}bm-run) - add_dependencies(bm-build ${_c4_lprefix}bm-build) - _c4_set_target_folder(${_c4_lprefix}bm-run bm) - _c4_set_target_folder(${_c4_lprefix}bm-build bm) - _c4_set_target_folder(bm-build "/bm") - _c4_set_target_folder(bm-run "/bm") - # download google benchmark - if(NOT TARGET benchmark) - c4_import_remote_proj(googlebenchmark ${CMAKE_CURRENT_BINARY_DIR}/ext/googlebenchmark - REMOTE - GIT_REPOSITORY https://github.com/google/benchmark.git - GIT_TAG main GIT_SHALLOW ON - OVERRIDE - BENCHMARK_ENABLE_TESTING OFF - BENCHMARK_ENABLE_EXCEPTIONS OFF - BENCHMARK_ENABLE_LTO OFF - SET_FOLDER_TARGETS ext benchmark benchmark_main - EXCLUDE_FROM_ALL - ) - # - if((CMAKE_CXX_COMPILER_ID STREQUAL GNU) OR (CMAKE_COMPILER_IS_GNUCC)) - target_compile_options(benchmark PRIVATE -Wno-deprecated-declarations) - target_compile_options(benchmark PRIVATE -Wno-restrict) - endif() - # - if(NOT WIN32) - option(${_c4_uprefix}BENCHMARK_CPUPOWER - "set the cpu mode to performance before / powersave after the benchmark" OFF) - if(${_c4_uprefix}BENCHMARK_CPUPOWER) - find_program(C4_SUDO sudo) - find_program(C4_CPUPOWER cpupower) - endif() - endif() - endif() -endfunction() - - -function(c4_add_benchmark_cmd casename) - add_custom_target(${casename} - COMMAND ${ARGN} - VERBATIM - COMMENT "${_c4_prefix}: running benchmark ${casename}: ${ARGN}") - add_dependencies(${_c4_lprefix}bm-build ${casename}) - _c4_set_target_folder(${casename} bm) -endfunction() - - -# assumes this is a googlebenchmark target, and that multiple -# benchmarks are defined from it -function(c4_add_target_benchmark target casename) - set(opt0arg - ) - set(opt1arg - WORKDIR # working directory - FILTER # benchmark patterns to filter - UMBRELLA_TARGET - RESULTS_FILE - ) - set(optnarg - ARGS - ) - cmake_parse_arguments("" "${opt0arg}" "${opt1arg}" "${optnarg}" ${ARGN}) - # - set(name "${target}-${casename}") - set(rdir "${CMAKE_CURRENT_BINARY_DIR}/bm-results") - set(rfile "${rdir}/${name}.json") - if(_RESULTS_FILE) - set(${_RESULTS_FILE} "${rfile}" PARENT_SCOPE) - endif() - if(NOT EXISTS "${rdir}") - file(MAKE_DIRECTORY "${rdir}") - endif() - set(filter) - if(NOT ("${_FILTER}" STREQUAL "")) - set(filter "--benchmark_filter=${_FILTER}") - endif() - set(args_fwd ${filter} --benchmark_out_format=json --benchmark_out=${rfile} ${_ARGS}) - c4_add_benchmark(${target} - "${name}" - "${_WORKDIR}" - "saving results in ${rfile}" - ${args_fwd} - OUTPUT_FILE ${rfile}) - if(_UMBRELLA_TARGET) - add_dependencies(${_UMBRELLA_TARGET} "${name}") - endif() -endfunction() - - -function(c4_add_benchmark target casename work_dir comment) - set(opt0arg - ) - set(opt1arg - OUTPUT_FILE - ) - set(optnarg - ) - cmake_parse_arguments("" "${opt0arg}" "${opt1arg}" "${optnarg}" ${ARGN}) - if(NOT TARGET ${target}) - c4_err("target ${target} does not exist...") - endif() - if(NOT ("${work_dir}" STREQUAL "")) - if(NOT EXISTS "${work_dir}") - file(MAKE_DIRECTORY "${work_dir}") - endif() - endif() - set(exe $) - if(${_c4_uprefix}BENCHMARK_CPUPOWER) - if(C4_BM_SUDO AND C4_BM_CPUPOWER) - set(c ${C4_SUDO} ${C4_CPUPOWER} frequency-set --governor performance) - set(cpupow_before - COMMAND echo ${c} - COMMAND ${c}) - set(c ${C4_SUDO} ${C4_CPUPOWER} frequency-set --governor powersave) - set(cpupow_after - COMMAND echo ${c} - COMMAND ${c}) - endif() - endif() - if(_OUTPUT_FILE) - set(_OUTPUT_FILE BYPRODUCTS ${_OUTPUT_FILE}) - set(_OUTPUT_FILE) # otherwise the benchmarks run everytime when building depending targets - endif() - add_custom_target(${casename} - ${cpupow_before} - # this is useful to show the target file (you cannot echo generator variables) - #COMMAND ${CMAKE_COMMAND} -E echo "target file = $" - COMMAND ${CMAKE_COMMAND} -E echo "${exe} ${ARGN}" - COMMAND "${exe}" ${ARGN} - ${cpupow_after} - VERBATIM - ${_OUTPUT_FILE} - WORKING_DIRECTORY "${work_dir}" - DEPENDS ${target} - COMMENT "${_c4_lcprefix}: running benchmark ${target}, case ${casename}: ${comment}" - ) - add_dependencies(${_c4_lprefix}bm-build ${target}) - add_dependencies(${_c4_lprefix}bm-run ${casename}) - _c4_set_target_folder(${casename} bm/run) -endfunction() - - -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ - -function(_c4cat_get_outname target id ext out) - if("${_c4_lcprefix}" STREQUAL "${target}") - set(p "${target}") - else() - set(p "${_c4_lcprefix}.${target}") - endif() - set(${out} "${CMAKE_CURRENT_BINARY_DIR}/${p}.${id}.${ext}" PARENT_SCOPE) -endfunction() - -function(_c4cat_filter_srcs in out) - _c4cat_filter_extensions("${in}" "${C4_SRC_EXTS}" l) - set(${out} ${l} PARENT_SCOPE) -endfunction() - -function(_c4cat_filter_hdrs in out) - _c4cat_filter_extensions("${in}" "${C4_HDR_EXTS}" l) - set(${out} ${l} PARENT_SCOPE) -endfunction() - -function(_c4cat_filter_srcs_hdrs in out) - _c4cat_filter_extensions("${in}" "${C4_HDR_EXTS};${C4_SRC_EXTS}" l) - set(${out} ${l} PARENT_SCOPE) -endfunction() - -function(_c4cat_filter_additional_exts in out) - _c4cat_filter_extensions("${in}" "${C4_ADD_EXTS}" l) - set(${out} ${l} PARENT_SCOPE) -endfunction() - -function(_c4cat_filter_extensions in filter out) - set(l) - foreach(fn ${in}) # don't quote the list here - _c4cat_get_file_ext("${fn}" ext) - _c4cat_one_of("${ext}" "${filter}" yes) - if(${yes}) - list(APPEND l "${fn}") - endif() - endforeach() - set(${out} "${l}" PARENT_SCOPE) -endfunction() - -function(_c4cat_get_file_ext in out) - # https://stackoverflow.com/questions/30049180/strip-filename-shortest-extension-by-cmake-get-filename-removing-the-last-ext - string(REGEX MATCH "^.*\\.([^.]*)$" dummy ${in}) - set(${out} ${CMAKE_MATCH_1} PARENT_SCOPE) -endfunction() - -function(_c4cat_one_of ext candidates out) - foreach(e ${candidates}) - if("${ext}" STREQUAL "${e}") - set(${out} TRUE PARENT_SCOPE) - return() - endif() - endforeach() - set(${out} FALSE PARENT_SCOPE) -endfunction() - - -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ - -# given a list of source files, return a list with full paths -function(c4_to_full_path source_list source_list_with_full_paths) - set(l) - foreach(f ${source_list}) - if(IS_ABSOLUTE "${f}") - list(APPEND l "${f}") - else() - list(APPEND l "${CMAKE_CURRENT_SOURCE_DIR}/${f}") - endif() - endforeach() - set(${source_list_with_full_paths} ${l} PARENT_SCOPE) -endfunction() - - -# convert a list to a string separated with spaces -function(c4_separate_list input_list output_string) - set(s) - foreach(e ${input_list}) - set(s "${s} ${e}") - endforeach() - set(${output_string} ${s} PARENT_SCOPE) -endfunction() - - - -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ -#------------------------------------------------------------------------------ -endif(NOT _c4_project_included) diff --git a/thirdparty/ryml/ext/c4core/cmake/c4SanitizeTarget.cmake b/thirdparty/ryml/ext/c4core/cmake/c4SanitizeTarget.cmake deleted file mode 100644 index a064f91ee..000000000 --- a/thirdparty/ryml/ext/c4core/cmake/c4SanitizeTarget.cmake +++ /dev/null @@ -1,292 +0,0 @@ -# (C) 2017 Joao Paulo Magalhaes -if(NOT _c4_sanitize_target_included) -set(_c4_sanitize_target_included ON) - -include(CMakeDependentOption) -include(PrintVar) - -function(_c4_default_if_not_set var dft) - if("${${var}}" STREQUAL "") - option(${var} "" ${dft}) - endif() -endfunction() - - -#------------------------------------------------------------------------------ -function(c4_setup_sanitize umbrella_option) - if("${CMAKE_BUILD_TYPE}" STREQUAL "Coverage") - return() - endif() - if(NOT ((CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") OR (CMAKE_CXX_COMPILER_ID STREQUAL "GNU"))) - return() - endif() - - _c4_default_if_not_set(C4_SANITIZE ON) - _c4_default_if_not_set(C4_SANITIZE_ONLY OFF) - _c4_default_if_not_set(C4_ASAN ON) - _c4_default_if_not_set(C4_TSAN ON) - _c4_default_if_not_set(C4_MSAN ON) - _c4_default_if_not_set(C4_UBSAN ON) - - cmake_dependent_option(${_c4_uprefix}SANITIZE "turn on clang sanitizer targets" ${C4_SANITIZE} ${umbrella_option} OFF) - cmake_dependent_option(${_c4_uprefix}SANITIZE_ONLY "compile only sanitize targets (not the regular unsanitized targets)" ${C4_SANITIZE_ONLY} ${umbrella_option} OFF) - - # options for individual sanitizers - contingent on sanitize on/off - cmake_dependent_option(${_c4_uprefix}ASAN "" ${C4_ASAN} "${_c4_uprefix}SANITIZE" OFF) - cmake_dependent_option(${_c4_uprefix}TSAN "" ${C4_TSAN} "${_c4_uprefix}SANITIZE" OFF) - cmake_dependent_option(${_c4_uprefix}MSAN "" ${C4_MSAN} "${_c4_uprefix}SANITIZE" OFF) - cmake_dependent_option(${_c4_uprefix}UBSAN "" ${C4_UBSAN} "${_c4_uprefix}SANITIZE" OFF) - - if(${_c4_uprefix}SANITIZE) - string(REGEX REPLACE "([0-9]+\\.[0-9]+).*" "\\1" LLVM_VERSION "${CMAKE_CXX_COMPILER_VERSION}") - find_program(LLVM_SYMBOLIZER llvm-symbolizer - NAMES llvm-symbolizer-${LLVM_VERSION} llvm-symbolizer - DOC "symbolizer to use in sanitize tools") - if(NOT LLVM_SYMBOLIZER) - string(REGEX REPLACE "([0-9]+)\\.[0-9]+.*" "\\1" LLVM_VERSION "${CMAKE_CXX_COMPILER_VERSION}") - find_program(LLVM_SYMBOLIZER llvm-symbolizer - NAMES llvm-symbolizer-${LLVM_VERSION} llvm-symbolizer - DOC "symbolizer to use in sanitize tools") - if(NOT LLVM_SYMBOLIZER) - message(FATAL_ERROR "could not find symbolizer. LLVM_VERSION=${LLVM_VERSION}") - endif() - endif() - - set(ss) # string to report enabled sanitizers - - if(${_c4_uprefix}ASAN) - set(ss "asan") - set(${_c4_uprefix}ASAN_CFLAGS "-O1 -g -fsanitize=address -fno-omit-frame-pointer -fno-optimize-sibling-calls" CACHE STRING "compile flags for clang address sanitizer: https://clang.llvm.org/docs/AddressSanitizer.html") - set(${_c4_uprefix}ASAN_LFLAGS "-g -fsanitize=address" CACHE STRING "linker flags for clang address sanitizer: https://clang.llvm.org/docs/AddressSanitizer.html") - set(${_c4_uprefix}ASAN_RENV "env ASAN_SYMBOLIZER_PATH=${LLVM_SYMBOLIZER} ASAN_OPTIONS=symbolize=1" CACHE STRING "run environment for clang address sanitizer: https://clang.llvm.org/docs/AddressSanitizer.html") - # the flags are strings; we need to separate them into a list - # to prevent cmake from quoting them when passing to the targets - separate_arguments(${_c4_uprefix}ASAN_CFLAGS_SEP UNIX_COMMAND ${${_c4_uprefix}ASAN_CFLAGS}) - separate_arguments(${_c4_uprefix}ASAN_LFLAGS_SEP UNIX_COMMAND ${${_c4_uprefix}ASAN_LFLAGS}) - endif() - - if(${_c4_uprefix}TSAN) - set(ss "${ss} tsan") - set(${_c4_uprefix}TSAN_CFLAGS "-O1 -g -fsanitize=thread -fno-omit-frame-pointer" CACHE STRING "compile flags for clang thread sanitizer: https://clang.llvm.org/docs/ThreadSanitizer.html") - set(${_c4_uprefix}TSAN_LFLAGS "-g -fsanitize=thread" CACHE STRING "linker flags for clang thread sanitizer: https://clang.llvm.org/docs/ThreadSanitizer.html") - set(${_c4_uprefix}TSAN_RENV "env TSAN_SYMBOLIZER_PATH=${LLVM_SYMBOLIZER} TSAN_OPTIONS=symbolize=1" CACHE STRING "run environment for clang thread sanitizer: https://clang.llvm.org/docs/ThreadSanitizer.html") - separate_arguments(${_c4_uprefix}TSAN_CFLAGS_SEP UNIX_COMMAND ${${_c4_uprefix}TSAN_CFLAGS}) - separate_arguments(${_c4_uprefix}TSAN_LFLAGS_SEP UNIX_COMMAND ${${_c4_uprefix}TSAN_LFLAGS}) - endif() - - if(${_c4_uprefix}MSAN) - set(ss "${ss} msan") - set(${_c4_uprefix}MSAN_CFLAGS "-O1 -g -fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer -fno-optimize-sibling-calls" CACHE STRING "compile flags for clang memory sanitizer: https://clang.llvm.org/docs/MemorySanitizer.html") - set(${_c4_uprefix}MSAN_LFLAGS "-g -fsanitize=memory" CACHE STRING "linker flags for clang memory sanitizer: https://clang.llvm.org/docs/MemorySanitizer.html") - set(${_c4_uprefix}MSAN_RENV "env MSAN_SYMBOLIZER_PATH=${LLVM_SYMBOLIZER} MSAN_OPTIONS=symbolize=1" CACHE STRING "run environment for clang memory sanitizer: https://clang.llvm.org/docs/MemorySanitizer.html") - separate_arguments(${_c4_uprefix}MSAN_CFLAGS_SEP UNIX_COMMAND ${${_c4_uprefix}MSAN_CFLAGS}) - separate_arguments(${_c4_uprefix}MSAN_LFLAGS_SEP UNIX_COMMAND ${${_c4_uprefix}MSAN_LFLAGS}) - endif() - - if(${_c4_uprefix}UBSAN) - set(ss "${ss} ubsan") - set(${_c4_uprefix}UBSAN_CFLAGS "-g -fsanitize=undefined" CACHE STRING "compile flags for clang undefined behaviour sanitizer: https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html") - set(${_c4_uprefix}UBSAN_LFLAGS "-g -fsanitize=undefined" CACHE STRING "linker flags for clang undefined behaviour sanitizer: https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html") - set(${_c4_uprefix}UBSAN_RENV "env UBSAN_SYMBOLIZER_PATH=${LLVM_SYMBOLIZER} UBSAN_OPTIONS='symbolize=1 print_stacktrace=1'" CACHE STRING "run environment for clang undefined behaviour sanitizer: https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html") - separate_arguments(${_c4_uprefix}UBSAN_CFLAGS_SEP UNIX_COMMAND ${${_c4_uprefix}UBSAN_CFLAGS}) - separate_arguments(${_c4_uprefix}UBSAN_LFLAGS_SEP UNIX_COMMAND ${${_c4_uprefix}UBSAN_LFLAGS}) - endif() - - c4_dbg("enabled clang sanitizers: ${ss}") - endif() # ${_c4_uprefix}SANITIZE - -endfunction() - - -#------------------------------------------------------------------------------ -function(c4_sanitize_get_target_command name which_sanitizer_ output) - string(TOUPPER ${which_sanitizer_} which_sanitizer) - if("${which_sanitizer}" STREQUAL ASAN) - elseif("${which_sanitizer}" STREQUAL TSAN) - elseif("${which_sanitizer}" STREQUAL MSAN) - elseif("${which_sanitizer}" STREQUAL UBSAN) - else() - message(FATAL_ERROR "the sanitizer must be one of: ASAN, TSAN, MSAN, UBSAN") - endif() - separate_arguments(cmd UNIX_COMMAND "${${_c4_uprefix}${which_sanitizer}_RENV} ${name}") - set(${output} ${cmd} PARENT_SCOPE) -endfunction() - -function(_sanitize_set_target_folder tgt folder) - if(folder) - set_target_properties(${tgt} PROPERTIES FOLDER "${folder}") - endif() -endfunction() - - -#------------------------------------------------------------------------------ -function(c4_sanitize_target name) - set(opt0arg - LIBRARY - EXECUTABLE - ) - set(opt1arg - OUTPUT_TARGET_NAMES - FOLDER - ) - set(optnarg - SOURCES - INC_DIRS # TODO public, interface, private - LIBS # TODO public, interface, private - LIB_DIRS # TODO public, interface, private - DEFS # TODO public, interface, private - CFLAGS # TODO public, interface, private - ) - cmake_parse_arguments("" "${opt0arg}" "${opt1arg}" "${optnarg}" ${ARGN}) - - if((NOT _LIBRARY) AND (NOT _EXECUTABLE)) - c4_err("either LIBRARY or EXECUTABLE must be specified") - endif() - - if(${_c4_uprefix}SANITIZE AND NOT TARGET ${_c4_lprefix}sanitize) - add_custom_target(${_c4_lprefix}sanitize) - _sanitize_set_target_folder(${_c4_lprefix}sanitize "${_FOLDER}") - endif() - if(${_c4_uprefix}ASAN AND NOT TARGET ${_c4_lprefix}asan-all) - add_custom_target(${_c4_lprefix}asan-all) - add_dependencies(${_c4_lprefix}sanitize ${_c4_lprefix}asan-all) - _sanitize_set_target_folder(${_c4_lprefix}asan-all "${_FOLDER}") - endif() - if(${_c4_uprefix}MSAN AND NOT TARGET ${_c4_lprefix}msan-all) - add_custom_target(${_c4_lprefix}msan-all) - add_dependencies(${_c4_lprefix}sanitize ${_c4_lprefix}msan-all) - _sanitize_set_target_folder(${_c4_lprefix}msan-all "${_FOLDER}") - endif() - if(${_c4_uprefix}TSAN AND NOT TARGET ${_c4_lprefix}tsan-all) - add_custom_target(${_c4_lprefix}tsan-all) - add_dependencies(${_c4_lprefix}sanitize ${_c4_lprefix}tsan-all) - _sanitize_set_target_folder(${_c4_lprefix}tsan-all "${_FOLDER}") - endif() - if(${_c4_uprefix}UBSAN AND NOT TARGET ${_c4_lprefix}ubsan-all) - add_custom_target(${_c4_lprefix}ubsan-all) - add_dependencies(${_c4_lprefix}sanitize ${_c4_lprefix}ubsan-all) - _sanitize_set_target_folder(${_c4_lprefix}ubsan-all "${_FOLDER}") - endif() - - if(${_c4_uprefix}ASAN OR ${_c4_uprefix}MSAN OR ${_c4_uprefix}TSAN OR ${_c4_uprefix}UBSAN) - add_custom_target(${name}-sanitize-all) - _sanitize_set_target_folder(${name}-sanitize-all "${_FOLDER}") - endif() - - set(targets) - - # https://clang.llvm.org/docs/AddressSanitizer.html - if(${_c4_uprefix}ASAN) - if(${_LIBRARY}) - add_library(${name}-asan EXCLUDE_FROM_ALL ${_SOURCES}) - elseif(${_EXECUTABLE}) - add_executable(${name}-asan EXCLUDE_FROM_ALL ${_SOURCES}) - endif() - _sanitize_set_target_folder(${name}-asan "${_FOLDER}") - list(APPEND targets ${name}-asan) - target_include_directories(${name}-asan PUBLIC ${_INC_DIRS}) - set(_real_libs) - foreach(_l ${_LIBS}) - if(TARGET ${_l}-asan) - list(APPEND _real_libs ${_l}-asan) - else() - list(APPEND _real_libs ${_l}) - endif() - endforeach() - target_link_libraries(${name}-asan PUBLIC ${_real_libs}) - target_compile_definitions(${name}-asan PUBLIC ${_DEFS}) - target_compile_options(${name}-asan PUBLIC ${_CFLAGS} ${${_c4_uprefix}ASAN_CFLAGS_SEP}) - # http://stackoverflow.com/questions/25043458/does-cmake-have-something-like-target-link-options - target_link_libraries(${name}-asan PUBLIC ${${_c4_uprefix}ASAN_LFLAGS_SEP}) - add_dependencies(${_c4_lprefix}asan-all ${name}-asan) - add_dependencies(${name}-sanitize-all ${name}-asan) - endif() - - # https://clang.llvm.org/docs/ThreadSanitizer.html - if(${_c4_uprefix}TSAN) - if(${_LIBRARY}) - add_library(${name}-tsan EXCLUDE_FROM_ALL ${_SOURCES}) - elseif(${_EXECUTABLE}) - add_executable(${name}-tsan EXCLUDE_FROM_ALL ${_SOURCES}) - endif() - _sanitize_set_target_folder(${name}-tsan "${_FOLDER}") - list(APPEND targets ${name}-tsan) - target_include_directories(${name}-tsan PUBLIC ${_INC_DIRS}) - set(_real_libs) - foreach(_l ${_LIBS}) - if(TARGET ${_l}-tsan) - list(APPEND _real_libs ${_l}-tsan) - else() - list(APPEND _real_libs ${_l}) - endif() - endforeach() - target_link_libraries(${name}-tsan PUBLIC ${_real_libs}) - target_compile_definitions(${name}-tsan PUBLIC ${_DEFS}) - target_compile_options(${name}-tsan PUBLIC ${_CFLAGS} ${${_c4_uprefix}TSAN_CFLAGS_SEP}) - # http://stackoverflow.com/questions/25043458/does-cmake-have-something-like-target-link-options - target_link_libraries(${name}-tsan PUBLIC ${${_c4_uprefix}TSAN_LFLAGS_SEP}) - add_dependencies(${_c4_lprefix}tsan-all ${name}-tsan) - add_dependencies(${name}-sanitize-all ${name}-tsan) - endif() - - # https://clang.llvm.org/docs/MemorySanitizer.html - if(${_c4_uprefix}MSAN) - if(${_LIBRARY}) - add_library(${name}-msan EXCLUDE_FROM_ALL ${_SOURCES}) - elseif(${_EXECUTABLE}) - add_executable(${name}-msan EXCLUDE_FROM_ALL ${_SOURCES}) - endif() - _sanitize_set_target_folder(${name}-msan "${_FOLDER}") - list(APPEND targets ${name}-msan) - target_include_directories(${name}-msan PUBLIC ${_INC_DIRS}) - set(_real_libs) - foreach(_l ${_LIBS}) - if(TARGET ${_l}-msan) - list(APPEND _real_libs ${_l}-msan) - else() - list(APPEND _real_libs ${_l}) - endif() - endforeach() - target_link_libraries(${name}-msan PUBLIC ${_real_libs}) - target_compile_definitions(${name}-msan PUBLIC ${_DEFS}) - target_compile_options(${name}-msan PUBLIC ${_CFLAGS} ${${_c4_uprefix}MSAN_CFLAGS_SEP}) - # http://stackoverflow.com/questions/25043458/does-cmake-have-something-like-target-link-options - target_link_libraries(${name}-msan PUBLIC ${${_c4_uprefix}MSAN_LFLAGS_SEP}) - add_dependencies(${_c4_lprefix}msan-all ${name}-msan) - add_dependencies(${name}-sanitize-all ${name}-msan) - endif() - - # https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html - if(${_c4_uprefix}UBSAN) - if(${_LIBRARY}) - add_library(${name}-ubsan EXCLUDE_FROM_ALL ${_SOURCES}) - elseif(${_EXECUTABLE}) - add_executable(${name}-ubsan EXCLUDE_FROM_ALL ${_SOURCES}) - endif() - _sanitize_set_target_folder(${name}-ubsan "${_FOLDER}") - list(APPEND targets ${name}-ubsan) - target_include_directories(${name}-ubsan PUBLIC ${_INC_DIRS}) - set(_real_libs) - foreach(_l ${_LIBS}) - if(TARGET ${_l}-ubsan) - list(APPEND _real_libs ${_l}-ubsan) - else() - list(APPEND _real_libs ${_l}) - endif() - endforeach() - target_link_libraries(${name}-ubsan PUBLIC ${_real_libs}) - target_compile_definitions(${name}-ubsan PUBLIC ${_DEFS}) - target_compile_options(${name}-ubsan PUBLIC ${_CFLAGS} ${${_c4_uprefix}UBSAN_CFLAGS_SEP}) - # http://stackoverflow.com/questions/25043458/does-cmake-have-something-like-target-link-options - target_link_libraries(${name}-ubsan PUBLIC ${${_c4_uprefix}UBSAN_LFLAGS_SEP}) - add_dependencies(${_c4_lprefix}ubsan-all ${name}-ubsan) - add_dependencies(${name}-sanitize-all ${name}-ubsan) - endif() - - if(_OUTPUT_TARGET_NAMES) - set(${_OUTPUT_TARGET_NAMES} ${targets} PARENT_SCOPE) - endif() -endfunction() - - -endif(NOT _c4_sanitize_target_included) diff --git a/thirdparty/ryml/ext/c4core/cmake/c4StaticAnalysis.cmake b/thirdparty/ryml/ext/c4core/cmake/c4StaticAnalysis.cmake deleted file mode 100644 index 06de5ca2f..000000000 --- a/thirdparty/ryml/ext/c4core/cmake/c4StaticAnalysis.cmake +++ /dev/null @@ -1,154 +0,0 @@ -include(PVS-Studio) -include(GetFlags) -include(c4GetTargetPropertyRecursive) - - -function(_c4sta_default_if_not_set var dft) - if("${${var}}" STREQUAL "") - set(${var} "${dft}" PARENT_SCOPE) - endif() -endfunction() - - -function(c4_setup_static_analysis umbrella_option) - if(WIN32) - c4_dbg("no static analyzer available in WIN32") - return() - endif() - if("${CMAKE_BUILD_TYPE}" STREQUAL "Coverage") - c4_dbg("Coverage build: disabling static analyzers") - return() - endif() - _c4sta_default_if_not_set(C4_LINT ${umbrella_option}) - _c4sta_default_if_not_set(C4_LINT_TESTS ${umbrella_option}) - _c4sta_default_if_not_set(C4_LINT_CLANG_TIDY ${umbrella_option}) - _c4sta_default_if_not_set(C4_LINT_PVS_STUDIO OFF) - # option to turn lints on/off - cmake_dependent_option(${_c4_uprefix}LINT "add static analyzer targets" ${C4_LINT} ${umbrella_option} OFF) - cmake_dependent_option(${_c4_uprefix}LINT_TESTS "add tests to run static analyzer targets" ${C4_LINT_TESTS} ${umbrella_option} OFF) - # options for individual lints - contingent on linting on/off - cmake_dependent_option(${_c4_uprefix}LINT_CLANG_TIDY "use the clang-tidy static analyzer" ${C4_LINT_CLANG_TIDY} "${_c4_uprefix}LINT" ON) - cmake_dependent_option(${_c4_uprefix}LINT_PVS_STUDIO "use the PVS-Studio static analyzer https://www.viva64.com/en/b/0457/" ${C4_LINT_PVS_STUDIO} "${_c4_uprefix}LINT" OFF) - if(${_c4_uprefix}LINT_CLANG_TIDY) - find_program(CLANG_TIDY clang-tidy) - endif() - if(${_c4_uprefix}LINT_PVS_STUDIO) - set(${_c4_uprefix}LINT_PVS_STUDIO_FORMAT "errorfile" CACHE STRING "PVS-Studio output format. Choices: xml,csv,errorfile(like gcc/clang),tasklist(qtcreator)") - endif() - # - set(sa) - if(${_c4_uprefix}LINT_CLANG_TIDY) - set(sa "clang_tidy") - endif() - if(${_c4_uprefix}LINT_PVS_STUDIO) - set(sa "${sa} PVS-Studio") - endif() - if(sa) - c4_dbg("enabled static analyzers: ${sa}") - endif() -endfunction() - - -function(c4_static_analysis_target target_name folder generated_targets) - set(any_linter OFF) - if(${_c4_uprefix}LINT_CLANG_TIDY OR ${_c4_uprefix}LINT_PVS_STUDIO) - set(any_linter ON) - endif() - if(${_c4_uprefix}LINT AND any_linter) - # umbrella target for running all linters for this particular target - if(any_linter AND NOT TARGET ${_c4_lprefix}lint-all) - add_custom_target(${_c4_lprefix}lint-all) - if(folder) - #message(STATUS "${target_name}: folder=${folder}") - set_target_properties(${_c4_lprefix}lint-all PROPERTIES FOLDER "${folder}") - endif() - endif() - if(${_c4_uprefix}LINT_CLANG_TIDY) - c4_static_analysis_clang_tidy(${target_name} - ${target_name}-lint-clang_tidy - ${_c4_lprefix}lint-all-clang_tidy - "${folder}") - list(APPEND ${generated_targets} ${_c4_lprefix}lint-clang_tidy) - add_dependencies(${_c4_lprefix}lint-all ${_c4_lprefix}lint-all-clang_tidy) - endif() - if(${_c4_uprefix}LINT_PVS_STUDIO) - c4_static_analysis_pvs_studio(${target_name} - ${target_name}-lint-pvs_studio - ${_c4_lprefix}lint-all-pvs_studio - "${folder}") - list(APPEND ${generated_targets} ${_c4_lprefix}lint-pvs_studio) - add_dependencies(${_c4_lprefix}lint-all ${_c4_lprefix}lint-all-pvs_studio) - endif() - endif() -endfunction() - - -function(c4_static_analysis_add_tests target_name) - if(${_c4_uprefix}LINT_CLANG_TIDY AND ${_c4_uprefix}LINT_TESTS) - add_test(NAME ${target_name}-lint-clang_tidy-run - COMMAND - ${CMAKE_COMMAND} --build ${CMAKE_CURRENT_BINARY_DIR} --target ${target_name}-lint-clang_tidy) - endif() - if(${_c4_uprefix}LINT_PVS_STUDIO AND ${_c4_uprefix}LINT_TESTS) - add_test(NAME ${target_name}-lint-pvs_studio-run - COMMAND - ${CMAKE_COMMAND} --build ${CMAKE_CURRENT_BINARY_DIR} --target ${target_name}-lint-pvs_studio) - endif() -endfunction() - - -#------------------------------------------------------------------------------ -function(c4_static_analysis_clang_tidy subj_target lint_target umbrella_target folder) - c4_static_analysis_clang_tidy_get_cmd(${subj_target} ${lint_target} cmd) - string(REPLACE ";" " " cmd_str "${cmd}") - add_custom_target(${lint_target} - COMMAND ${CMAKE_COMMAND} -E echo "cd ${CMAKE_CURRENT_SOURCE_DIR} ; ${cmd_str}" - COMMAND ${cmd} - VERBATIM - COMMENT "clang-tidy: analyzing sources of ${subj_target}" - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) - if(folder) - set_target_properties(${lint_target} PROPERTIES FOLDER "${folder}") - endif() - if(NOT TARGET ${umbrella_target}) - add_custom_target(${umbrella_target}) - endif() - add_dependencies(${umbrella_target} ${lint_target}) -endfunction() - -function(c4_static_analysis_clang_tidy_get_cmd subj_target lint_target cmd) - get_target_property(_clt_all_srcs ${subj_target} SOURCES) - _c4cat_filter_srcs_hdrs("${_clt_all_srcs}" _clt_srcs) - set(result "${CLANG_TIDY}" -p ${CMAKE_BINARY_DIR} --header-filter=.* ${_clt_srcs}) - set(${cmd} ${result} PARENT_SCOPE) -endfunction() - - -#------------------------------------------------------------------------------ -function(c4_static_analysis_pvs_studio subj_target lint_target umbrella_target folder) - c4_get_target_property_recursive(_c4al_pvs_incs ${subj_target} INCLUDE_DIRECTORIES) - c4_get_include_flags(_c4al_pvs_incs ${_c4al_pvs_incs}) - separate_arguments(_c4al_cxx_flags_sep UNIX_COMMAND "${CMAKE_CXX_FLAGS} ${_c4al_pvs_incs}") - separate_arguments(_c4al_c_flags_sep UNIX_COMMAND "${CMAKE_C_FLAGS} ${_c4al_pvs_incs}") - pvs_studio_add_target(TARGET ${lint_target} - ALL # indicates that the analysis starts when you build the project - #PREPROCESSOR ${_c4al_preproc} - FORMAT tasklist - LOG "${CMAKE_CURRENT_BINARY_DIR}/${subj_target}.pvs-analysis.tasks" - ANALYZE ${name} #main_target subtarget:path/to/subtarget - CXX_FLAGS ${_c4al_cxx_flags_sep} - C_FLAGS ${_c4al_c_flags_sep} - #CONFIG "/path/to/PVS-Studio.cfg" - ) - if(folder) - set_target_properties(${lint_target} PROPERTIES FOLDER "${folder}") - endif() - if(NOT TARGET ${umbrella_target}) - add_custom_target(${umbrella_target}) - endif() - add_dependencies(${umbrella_target} ${lint_target}) -endfunction() - -function(c4_static_analysis_pvs_studio_get_cmd subj_target lint_target cmd) - set(${cmd} $ PARENT_SCOPE) -endfunction() diff --git a/thirdparty/ryml/ext/c4core/cmake/c4stlAddTarget.cmake b/thirdparty/ryml/ext/c4core/cmake/c4stlAddTarget.cmake deleted file mode 100644 index 07835977b..000000000 --- a/thirdparty/ryml/ext/c4core/cmake/c4stlAddTarget.cmake +++ /dev/null @@ -1,5 +0,0 @@ -include(c4project) - -function(c4stl_add_target name) - c4_add_target(c4stl ${name} ${ARGN}) -endfunction() # c4stl_add_target diff --git a/thirdparty/ryml/ext/c4core/cmake/compat/c4/gcc-4.8.hpp b/thirdparty/ryml/ext/c4core/cmake/compat/c4/gcc-4.8.hpp deleted file mode 100644 index 83cad6256..000000000 --- a/thirdparty/ryml/ext/c4core/cmake/compat/c4/gcc-4.8.hpp +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef _C4_COMPAT_GCC_4_8_HPP_ -#define _C4_COMPAT_GCC_4_8_HPP_ - -#if __GNUC__ == 4 && __GNUC_MINOR__ >= 8 -/* STL polyfills for old GNU compilers */ - -_Pragma("GCC diagnostic ignored \"-Wshadow\"") -_Pragma("GCC diagnostic ignored \"-Wmissing-field-initializers\"") - -#if __cplusplus -#include -#include - -namespace std { - -template -struct is_trivially_copyable : public integral_constant::value && __has_trivial_destructor(_Tp) && - (__has_trivial_constructor(_Tp) || __has_trivial_copy(_Tp) || __has_trivial_assign(_Tp))> -{ }; - -template -using is_trivially_copy_constructible = has_trivial_copy_constructor<_Tp>; - -template -using is_trivially_default_constructible = has_trivial_default_constructor<_Tp>; - -template -using is_trivially_copy_assignable = has_trivial_copy_assign<_Tp>; - -/* not supported */ -template -struct is_trivially_move_constructible : false_type -{ }; - -/* not supported */ -template -struct is_trivially_move_assignable : false_type -{ }; - -inline void *align(size_t __align, size_t __size, void*& __ptr, size_t& __space) noexcept -{ - if (__space < __size) - return nullptr; - const auto __intptr = reinterpret_cast(__ptr); - const auto __aligned = (__intptr - 1u + __align) & -__align; - const auto __diff = __aligned - __intptr; - if (__diff > (__space - __size)) - return nullptr; - else - { - __space -= __diff; - return __ptr = reinterpret_cast(__aligned); - } -} -typedef long double max_align_t ; - -} -#else // __cplusplus - -#include -// see https://sourceware.org/bugzilla/show_bug.cgi?id=25399 (ubuntu gcc-4.8) -#define memset(s, c, count) __builtin_memset(s, c, count) - -#endif // __cplusplus - -#endif // __GNUC__ == 4 && __GNUC_MINOR__ >= 8 - -#endif // _C4_COMPAT_GCC_4_8_HPP_ diff --git a/thirdparty/ryml/ext/c4core/cmake/compat/gtest_gcc-4.8.patch b/thirdparty/ryml/ext/c4core/cmake/compat/gtest_gcc-4.8.patch deleted file mode 100644 index 07f0ca577..000000000 --- a/thirdparty/ryml/ext/c4core/cmake/compat/gtest_gcc-4.8.patch +++ /dev/null @@ -1,97 +0,0 @@ -Multi-line macros support is not guaranteed with gcc-4.8. - -This uses temporary objects to work-arround this limitation, main drawback is -that compared code is not displayed in message anymore (only "val" placeholders). - ---- googletest/include/gtest/gtest.h -+++ googletest/include/gtest/gtest.h -@@ -2040,6 +2040,80 @@ class TestWithParam : public Test, publi - // ASSERT_LT(i, array_size); - // ASSERT_GT(records.size(), 0) << "There is no record left."; - -+#if __GNUC__ == 4 && __GNUC_MINOR__ >= 8 -+/* -+ * multi-line macros support is not guaranteed with gcc-4.8. -+ * This uses temporary objects to work-arround this limitation, main drawback is -+ * that compared code is not displayed in message anymore (only "val" placeholders) -+ */ -+ -+enum class CompatExpectSelector { EQ, NE, LE, LT, GE, GT }; -+ -+template -+struct CompatExpect -+{ -+ const char *file; -+ int line; -+ ::testing::AssertionResult gtest_ar = AssertionSuccess(); -+ ::testing::Message msg; -+ -+ CompatExpect(const char *file, int line) : file(file), line(line) {} -+ ~CompatExpect() { -+ if (!gtest_ar) -+ GTEST_MESSAGE_AT_(file, line, gtest_ar.failure_message(), ::testing::TestPartResult::kNonFatalFailure) << msg; -+ } -+ -+ template ::type = 0> -+ CompatExpect &operator ()(const T1 &val1, const T2 &val2) { -+ gtest_ar = ::testing::internal::EqHelper::Compare("val1", "val2", val1, val2); -+ return *this; -+ } -+ -+ template ::type = 0> -+ CompatExpect &operator ()(const T1 &val1, const T2 &val2) { -+ gtest_ar = ::testing::internal::CmpHelperNE("val1", "val2", val1, val2); -+ return *this; -+ } -+ -+ template ::type = 0> -+ CompatExpect &operator ()(const T1 &val1, const T2 &val2) { -+ gtest_ar = ::testing::internal::CmpHelperLE("val1", "val2", val1, val2); -+ return *this; -+ } -+ -+ template ::type = 0> -+ CompatExpect &operator ()(const T1 &val1, const T2 &val2) { -+ gtest_ar = ::testing::internal::CmpHelperLT("val1", "val2", val1, val2); -+ return *this; -+ } -+ -+ template ::type = 0> -+ CompatExpect &operator ()(const T1 &val1, const T2 &val2) { -+ gtest_ar = ::testing::internal::CmpHelperGE("val1", "val2", val1, val2); -+ return *this; -+ } -+ -+ template ::type = 0> -+ CompatExpect &operator ()(const T1 &val1, const T2 &val2) { -+ gtest_ar = ::testing::internal::CmpHelperGT("val1", "val2", val1, val2); -+ return *this; -+ } -+ -+ template -+ CompatExpect &operator << (const T1 &t) { -+ msg << t; -+ return *this; -+ } -+}; -+#define EXPECT_EQ ::testing::CompatExpect<::testing::CompatExpectSelector::EQ>{__FILE__,__LINE__} -+#define EXPECT_NE ::testing::CompatExpect<::testing::CompatExpectSelector::NE>{__FILE__,__LINE__} -+#define EXPECT_LE ::testing::CompatExpect<::testing::CompatExpectSelector::LE>{__FILE__,__LINE__} -+#define EXPECT_LT ::testing::CompatExpect<::testing::CompatExpectSelector::LT>{__FILE__,__LINE__} -+#define EXPECT_GE ::testing::CompatExpect<::testing::CompatExpectSelector::GE>{__FILE__,__LINE__} -+#define EXPECT_GT ::testing::CompatExpect<::testing::CompatExpectSelector::GT>{__FILE__,__LINE__} -+ -+#else -+ - #define EXPECT_EQ(val1, val2) \ - EXPECT_PRED_FORMAT2(::testing::internal::EqHelper::Compare, val1, val2) - #define EXPECT_NE(val1, val2) \ -@@ -2053,6 +2127,8 @@ class TestWithParam : public Test, publi - #define EXPECT_GT(val1, val2) \ - EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2) - -+#endif -+ - #define GTEST_ASSERT_EQ(val1, val2) \ - ASSERT_PRED_FORMAT2(::testing::internal::EqHelper::Compare, val1, val2) - #define GTEST_ASSERT_NE(val1, val2) \ diff --git a/thirdparty/ryml/ext/c4core/cmake/requirements_doc.txt b/thirdparty/ryml/ext/c4core/cmake/requirements_doc.txt deleted file mode 100644 index baeb2ce4f..000000000 --- a/thirdparty/ryml/ext/c4core/cmake/requirements_doc.txt +++ /dev/null @@ -1,3 +0,0 @@ -sphinx -sphinx_rtd_theme -breathe diff --git a/thirdparty/ryml/ext/c4core/compat.cmake b/thirdparty/ryml/ext/c4core/compat.cmake deleted file mode 100644 index 186b84e0b..000000000 --- a/thirdparty/ryml/ext/c4core/compat.cmake +++ /dev/null @@ -1,16 +0,0 @@ - -# old gcc-4.8 support -if((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") AND - (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 4.8) AND - (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0)) - - c4_install_files( - "${CMAKE_CURRENT_LIST_DIR}/cmake/compat/c4/gcc-4.8.hpp" - "include" - "${CMAKE_CURRENT_LIST_DIR}/cmake/compat") - - # c++17 compiler required - set(C4CORE_BUILD_BENCHMARKS OFF CACHE BOOL "" FORCE) - # LLVM required - set(C4CORE_SANITIZE OFF CACHE BOOL "" FORCE) -endif() diff --git a/thirdparty/ryml/ext/c4core/src/c4/allocator.hpp b/thirdparty/ryml/ext/c4core/src/c4/allocator.hpp deleted file mode 100644 index d221341c5..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/allocator.hpp +++ /dev/null @@ -1,405 +0,0 @@ -#ifndef _C4_ALLOCATOR_HPP_ -#define _C4_ALLOCATOR_HPP_ - -#include "c4/memory_resource.hpp" -#include "c4/ctor_dtor.hpp" - -#include // std::allocator_traits -#include - -/** @file allocator.hpp Contains classes to make typeful allocations (note - * that memory resources are typeless) */ - -/** @defgroup mem_res_providers Memory resource providers - * @brief Policy classes which provide a memory resource for - * use in an allocator. - * @ingroup memory - */ - -/** @defgroup allocators Allocators - * @brief Lightweight classes that act as handles to specific memory - * resources and provide typeful memory. - * @ingroup memory - */ - -namespace c4 { - -namespace detail { -template inline size_t size_for (size_t num_objs) noexcept { return num_objs * sizeof(T); } -template< > inline size_t size_for(size_t num_objs) noexcept { return num_objs; } -} // namespace detail - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -/** provides a per-allocator memory resource - * @ingroup mem_res_providers */ -class MemRes -{ -public: - - MemRes() : m_resource(get_memory_resource()) {} - MemRes(MemoryResource* r) noexcept : m_resource(r ? r : get_memory_resource()) {} - - inline MemoryResource* resource() const { return m_resource; } - -private: - - MemoryResource* m_resource; - -}; - - -/** the allocators using this will default to the global memory resource - * @ingroup mem_res_providers */ -class MemResGlobal -{ -public: - - MemResGlobal() {} - MemResGlobal(MemoryResource* r) noexcept { C4_UNUSED(r); C4_ASSERT(r == get_memory_resource()); } - - inline MemoryResource* resource() const { return get_memory_resource(); } -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -namespace detail { -template -struct _AllocatorUtil; - -template -struct has_no_alloc - : public std::integral_constant::value) - && std::is_constructible::value> {}; - -// std::uses_allocator_v && std::is_constructible -// ie can construct(std::allocator_arg_t, MemoryResource*, Args...) -template -struct has_alloc_arg - : public std::integral_constant::value - && std::is_constructible::value> {}; -// std::uses_allocator && std::is_constructible -// ie, can construct(Args..., MemoryResource*) -template -struct has_alloc - : public std::integral_constant::value - && std::is_constructible::value> {}; - -} // namespace detail - - -template -struct detail::_AllocatorUtil : public MemRes -{ - using MemRes::MemRes; - - /** for construct: - * @see http://en.cppreference.com/w/cpp/experimental/polymorphic_allocator/construct */ - - // 1. types with no allocators - template - C4_ALWAYS_INLINE typename std::enable_if::value, void>::type - construct(U *ptr, Args &&...args) - { - c4::construct(ptr, std::forward(args)...); - } - template - C4_ALWAYS_INLINE typename std::enable_if::value, void>::type - construct_n(U* ptr, I n, Args&&... args) - { - c4::construct_n(ptr, n, std::forward(args)...); - } - - // 2. types using allocators (ie, containers) - - // 2.1. can construct(std::allocator_arg_t, MemoryResource*, Args...) - template - C4_ALWAYS_INLINE typename std::enable_if::value, void>::type - construct(U* ptr, Args&&... args) - { - c4::construct(ptr, std::allocator_arg, this->resource(), std::forward(args)...); - } - template - C4_ALWAYS_INLINE typename std::enable_if::value, void>::type - construct_n(U* ptr, I n, Args&&... args) - { - c4::construct_n(ptr, n, std::allocator_arg, this->resource(), std::forward(args)...); - } - - // 2.2. can construct(Args..., MemoryResource*) - template - C4_ALWAYS_INLINE typename std::enable_if::value, void>::type - construct(U* ptr, Args&&... args) - { - c4::construct(ptr, std::forward(args)..., this->resource()); - } - template - C4_ALWAYS_INLINE typename std::enable_if::value, void>::type - construct_n(U* ptr, I n, Args&&... args) - { - c4::construct_n(ptr, n, std::forward(args)..., this->resource()); - } - - template - static C4_ALWAYS_INLINE void destroy(U* ptr) - { - c4::destroy(ptr); - } - template - static C4_ALWAYS_INLINE void destroy_n(U* ptr, I n) - { - c4::destroy_n(ptr, n); - } -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -/** An allocator is simply a proxy to a memory resource. - * @param T - * @param MemResProvider - * @ingroup allocators */ -template -class Allocator : public detail::_AllocatorUtil -{ -public: - - using impl_type = detail::_AllocatorUtil; - - using value_type = T; - using pointer = T*; - using const_pointer = T const*; - using reference = T&; - using const_reference = T const&; - using size_type = size_t; - using difference_type = std::ptrdiff_t; - using propagate_on_container_move_assigment = std::true_type; - -public: - - template - bool operator== (Allocator const& that) const - { - return this->resource() == that.resource(); - } - template - bool operator!= (Allocator const& that) const - { - return this->resource() != that.resource(); - } - -public: - - template friend class Allocator; - template - struct rebind - { - using other = Allocator; - }; - template - typename rebind::other rebound() - { - return typename rebind::other(*this); - } - -public: - - using impl_type::impl_type; - Allocator() : impl_type() {} // VS demands this - - template Allocator(Allocator const& that) : impl_type(that.resource()) {} - - Allocator(Allocator const&) = default; - Allocator(Allocator &&) = default; - - Allocator& operator= (Allocator const&) = default; // WTF? why? @see http://en.cppreference.com/w/cpp/memory/polymorphic_allocator - Allocator& operator= (Allocator &&) = default; - - /** returns a default-constructed polymorphic allocator object - * @see http://en.cppreference.com/w/cpp/memory/polymorphic_allocator/select_on_container_copy_construction */ - Allocator select_on_container_copy_construct() const { return Allocator(*this); } - - T* allocate(size_t num_objs, size_t alignment=alignof(T)) - { - C4_ASSERT(this->resource() != nullptr); - C4_ASSERT(alignment >= alignof(T)); - void* vmem = this->resource()->allocate(detail::size_for(num_objs), alignment); - T* mem = static_cast(vmem); - return mem; - } - - void deallocate(T * ptr, size_t num_objs, size_t alignment=alignof(T)) - { - C4_ASSERT(this->resource() != nullptr); - C4_ASSERT(alignment>= alignof(T)); - this->resource()->deallocate(ptr, detail::size_for(num_objs), alignment); - } - - T* reallocate(T* ptr, size_t oldnum, size_t newnum, size_t alignment=alignof(T)) - { - C4_ASSERT(this->resource() != nullptr); - C4_ASSERT(alignment >= alignof(T)); - void* vmem = this->resource()->reallocate(ptr, detail::size_for(oldnum), detail::size_for(newnum), alignment); - T* mem = static_cast(vmem); - return mem; - } - -}; - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -/** @ingroup allocators */ -template -class SmallAllocator : public detail::_AllocatorUtil -{ - static_assert(Alignment >= alignof(T), "invalid alignment"); - - using impl_type = detail::_AllocatorUtil; - - alignas(Alignment) char m_arr[N * sizeof(T)]; - size_t m_num{0}; - -public: - - using value_type = T; - using pointer = T*; - using const_pointer = T const*; - using reference = T&; - using const_reference = T const&; - using size_type = size_t; - using difference_type = std::ptrdiff_t; - using propagate_on_container_move_assigment = std::true_type; - - template - bool operator== (SmallAllocator const&) const - { - return false; - } - template - bool operator!= (SmallAllocator const&) const - { - return true; - } - -public: - - template friend class SmallAllocator; - template - struct rebind - { - using other = SmallAllocator; - }; - template - typename rebind::other rebound() - { - return typename rebind::other(*this); - } - -public: - - using impl_type::impl_type; - SmallAllocator() : impl_type() {} // VS demands this - - template - SmallAllocator(SmallAllocator const& that) : impl_type(that.resource()) - { - C4_ASSERT(that.m_num == 0); - } - - SmallAllocator(SmallAllocator const&) = default; - SmallAllocator(SmallAllocator &&) = default; - - SmallAllocator& operator= (SmallAllocator const&) = default; // WTF? why? @see http://en.cppreference.com/w/cpp/memory/polymorphic_allocator - SmallAllocator& operator= (SmallAllocator &&) = default; - - /** returns a default-constructed polymorphic allocator object - * @see http://en.cppreference.com/w/cpp/memory/polymorphic_allocator/select_on_container_copy_construction */ - SmallAllocator select_on_container_copy_construct() const { return SmallAllocator(*this); } - - T* allocate(size_t num_objs, size_t alignment=Alignment) - { - C4_ASSERT(this->resource() != nullptr); - C4_ASSERT(alignment >= alignof(T)); - void *vmem; - if(m_num + num_objs <= N) - { - vmem = (m_arr + m_num * sizeof(T)); - } - else - { - vmem = this->resource()->allocate(num_objs * sizeof(T), alignment); - } - m_num += num_objs; - T *mem = static_cast(vmem); - return mem; - } - - void deallocate(T * ptr, size_t num_objs, size_t alignment=Alignment) - { - C4_ASSERT(m_num >= num_objs); - m_num -= num_objs; - if((char*)ptr >= m_arr && (char*)ptr < m_arr + (N * sizeof(T))) - { - return; - } - C4_ASSERT(this->resource() != nullptr); - C4_ASSERT(alignment >= alignof(T)); - this->resource()->deallocate(ptr, num_objs * sizeof(T), alignment); - } - - T* reallocate(T * ptr, size_t oldnum, size_t newnum, size_t alignment=Alignment) - { - C4_ASSERT(this->resource() != nullptr); - C4_ASSERT(alignment >= alignof(T)); - if(oldnum <= N && newnum <= N) - { - return m_arr; - } - else if(oldnum <= N && newnum > N) - { - return allocate(newnum, alignment); - } - else if(oldnum > N && newnum <= N) - { - deallocate(ptr, oldnum, alignment); - return m_arr; - } - void* vmem = this->resource()->reallocate(ptr, oldnum * sizeof(T), newnum * sizeof(T), alignment); - T* mem = static_cast(vmem); - return mem; - } - -}; - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -/** An allocator making use of the global memory resource. - * @ingroup allocators */ -template using allocator = Allocator; -/** An allocator with a per-instance memory resource - * @ingroup allocators */ -template using allocator_mr = Allocator; - -/** @ingroup allocators */ -template using small_allocator = SmallAllocator; -/** @ingroup allocators */ -template using small_allocator_mr = SmallAllocator; - -} // namespace c4 - -#endif /* _C4_ALLOCATOR_HPP_ */ diff --git a/thirdparty/ryml/ext/c4core/src/c4/base64.cpp b/thirdparty/ryml/ext/c4core/src/c4/base64.cpp deleted file mode 100644 index bc75d3e0e..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/base64.cpp +++ /dev/null @@ -1,220 +0,0 @@ -#include "c4/base64.hpp" - -#ifdef __clang__ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wchar-subscripts" // array subscript is of type 'char' -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wchar-subscripts" -# pragma GCC diagnostic ignored "-Wtype-limits" -#endif - -namespace c4 { - -namespace detail { - -constexpr static const char base64_sextet_to_char_[64] = { - /* 0/ 65*/ 'A', /* 1/ 66*/ 'B', /* 2/ 67*/ 'C', /* 3/ 68*/ 'D', - /* 4/ 69*/ 'E', /* 5/ 70*/ 'F', /* 6/ 71*/ 'G', /* 7/ 72*/ 'H', - /* 8/ 73*/ 'I', /* 9/ 74*/ 'J', /*10/ 75*/ 'K', /*11/ 74*/ 'L', - /*12/ 77*/ 'M', /*13/ 78*/ 'N', /*14/ 79*/ 'O', /*15/ 78*/ 'P', - /*16/ 81*/ 'Q', /*17/ 82*/ 'R', /*18/ 83*/ 'S', /*19/ 82*/ 'T', - /*20/ 85*/ 'U', /*21/ 86*/ 'V', /*22/ 87*/ 'W', /*23/ 88*/ 'X', - /*24/ 89*/ 'Y', /*25/ 90*/ 'Z', /*26/ 97*/ 'a', /*27/ 98*/ 'b', - /*28/ 99*/ 'c', /*29/100*/ 'd', /*30/101*/ 'e', /*31/102*/ 'f', - /*32/103*/ 'g', /*33/104*/ 'h', /*34/105*/ 'i', /*35/106*/ 'j', - /*36/107*/ 'k', /*37/108*/ 'l', /*38/109*/ 'm', /*39/110*/ 'n', - /*40/111*/ 'o', /*41/112*/ 'p', /*42/113*/ 'q', /*43/114*/ 'r', - /*44/115*/ 's', /*45/116*/ 't', /*46/117*/ 'u', /*47/118*/ 'v', - /*48/119*/ 'w', /*49/120*/ 'x', /*50/121*/ 'y', /*51/122*/ 'z', - /*52/ 48*/ '0', /*53/ 49*/ '1', /*54/ 50*/ '2', /*55/ 51*/ '3', - /*56/ 52*/ '4', /*57/ 53*/ '5', /*58/ 54*/ '6', /*59/ 55*/ '7', - /*60/ 56*/ '8', /*61/ 57*/ '9', /*62/ 43*/ '+', /*63/ 47*/ '/', -}; - -// https://www.cs.cmu.edu/~pattis/15-1XX/common/handouts/ascii.html -constexpr static const char base64_char_to_sextet_[128] = { - #define __ char(-1) // undefined below - /* 0 NUL*/ __, /* 1 SOH*/ __, /* 2 STX*/ __, /* 3 ETX*/ __, - /* 4 EOT*/ __, /* 5 ENQ*/ __, /* 6 ACK*/ __, /* 7 BEL*/ __, - /* 8 BS */ __, /* 9 TAB*/ __, /* 10 LF */ __, /* 11 VT */ __, - /* 12 FF */ __, /* 13 CR */ __, /* 14 SO */ __, /* 15 SI */ __, - /* 16 DLE*/ __, /* 17 DC1*/ __, /* 18 DC2*/ __, /* 19 DC3*/ __, - /* 20 DC4*/ __, /* 21 NAK*/ __, /* 22 SYN*/ __, /* 23 ETB*/ __, - /* 24 CAN*/ __, /* 25 EM */ __, /* 26 SUB*/ __, /* 27 ESC*/ __, - /* 28 FS */ __, /* 29 GS */ __, /* 30 RS */ __, /* 31 US */ __, - /* 32 SPC*/ __, /* 33 ! */ __, /* 34 " */ __, /* 35 # */ __, - /* 36 $ */ __, /* 37 % */ __, /* 38 & */ __, /* 39 ' */ __, - /* 40 ( */ __, /* 41 ) */ __, /* 42 * */ __, /* 43 + */ 62, - /* 44 , */ __, /* 45 - */ __, /* 46 . */ __, /* 47 / */ 63, - /* 48 0 */ 52, /* 49 1 */ 53, /* 50 2 */ 54, /* 51 3 */ 55, - /* 52 4 */ 56, /* 53 5 */ 57, /* 54 6 */ 58, /* 55 7 */ 59, - /* 56 8 */ 60, /* 57 9 */ 61, /* 58 : */ __, /* 59 ; */ __, - /* 60 < */ __, /* 61 = */ __, /* 62 > */ __, /* 63 ? */ __, - /* 64 @ */ __, /* 65 A */ 0, /* 66 B */ 1, /* 67 C */ 2, - /* 68 D */ 3, /* 69 E */ 4, /* 70 F */ 5, /* 71 G */ 6, - /* 72 H */ 7, /* 73 I */ 8, /* 74 J */ 9, /* 75 K */ 10, - /* 76 L */ 11, /* 77 M */ 12, /* 78 N */ 13, /* 79 O */ 14, - /* 80 P */ 15, /* 81 Q */ 16, /* 82 R */ 17, /* 83 S */ 18, - /* 84 T */ 19, /* 85 U */ 20, /* 86 V */ 21, /* 87 W */ 22, - /* 88 X */ 23, /* 89 Y */ 24, /* 90 Z */ 25, /* 91 [ */ __, - /* 92 \ */ __, /* 93 ] */ __, /* 94 ^ */ __, /* 95 _ */ __, - /* 96 ` */ __, /* 97 a */ 26, /* 98 b */ 27, /* 99 c */ 28, - /*100 d */ 29, /*101 e */ 30, /*102 f */ 31, /*103 g */ 32, - /*104 h */ 33, /*105 i */ 34, /*106 j */ 35, /*107 k */ 36, - /*108 l */ 37, /*109 m */ 38, /*110 n */ 39, /*111 o */ 40, - /*112 p */ 41, /*113 q */ 42, /*114 r */ 43, /*115 s */ 44, - /*116 t */ 45, /*117 u */ 46, /*118 v */ 47, /*119 w */ 48, - /*120 x */ 49, /*121 y */ 50, /*122 z */ 51, /*123 { */ __, - /*124 | */ __, /*125 } */ __, /*126 ~ */ __, /*127 DEL*/ __, - #undef __ -}; - -#ifndef NDEBUG -void base64_test_tables() -{ - for(size_t i = 0; i < C4_COUNTOF(detail::base64_sextet_to_char_); ++i) - { - char s2c = base64_sextet_to_char_[i]; - char c2s = base64_char_to_sextet_[(int)s2c]; - C4_CHECK((size_t)c2s == i); - } - for(size_t i = 0; i < C4_COUNTOF(detail::base64_char_to_sextet_); ++i) - { - char c2s = base64_char_to_sextet_[i]; - if(c2s == char(-1)) - continue; - char s2c = base64_sextet_to_char_[(int)c2s]; - C4_CHECK((size_t)s2c == i); - } -} -#endif -} // namespace detail - - -bool base64_valid(csubstr encoded) -{ - if(encoded.len % 4) return false; - for(const char c : encoded) - { - if(c < 0/* || c >= 128*/) - return false; - if(c == '=') - continue; - if(detail::base64_char_to_sextet_[c] == char(-1)) - return false; - } - return true; -} - - -size_t base64_encode(substr buf, cblob data) -{ - #define c4append_(c) { if(pos < buf.len) { buf.str[pos] = (c); } ++pos; } - #define c4append_idx_(char_idx) \ - {\ - C4_XASSERT((char_idx) < sizeof(detail::base64_sextet_to_char_));\ - c4append_(detail::base64_sextet_to_char_[(char_idx)]);\ - } - - size_t rem, pos = 0; - constexpr const uint32_t sextet_mask = uint32_t(1 << 6) - 1; - const unsigned char *C4_RESTRICT d = (unsigned char *) data.buf; // cast to unsigned to avoid wrapping high-bits - for(rem = data.len; rem >= 3; rem -= 3, d += 3) - { - const uint32_t val = ((uint32_t(d[0]) << 16) | (uint32_t(d[1]) << 8) | (uint32_t(d[2]))); - c4append_idx_((val >> 18) & sextet_mask); - c4append_idx_((val >> 12) & sextet_mask); - c4append_idx_((val >> 6) & sextet_mask); - c4append_idx_((val ) & sextet_mask); - } - C4_ASSERT(rem < 3); - if(rem == 2) - { - const uint32_t val = ((uint32_t(d[0]) << 16) | (uint32_t(d[1]) << 8)); - c4append_idx_((val >> 18) & sextet_mask); - c4append_idx_((val >> 12) & sextet_mask); - c4append_idx_((val >> 6) & sextet_mask); - c4append_('='); - } - else if(rem == 1) - { - const uint32_t val = ((uint32_t(d[0]) << 16)); - c4append_idx_((val >> 18) & sextet_mask); - c4append_idx_((val >> 12) & sextet_mask); - c4append_('='); - c4append_('='); - } - return pos; - - #undef c4append_ - #undef c4append_idx_ -} - - -size_t base64_decode(csubstr encoded, blob data) -{ - #define c4append_(c) { if(wpos < data.len) { data.buf[wpos] = static_cast(c); } ++wpos; } - #define c4appendval_(c, shift)\ - {\ - C4_XASSERT(c >= 0);\ - C4_XASSERT(size_t(c) < sizeof(detail::base64_char_to_sextet_));\ - val |= static_cast(detail::base64_char_to_sextet_[(c)]) << ((shift) * 6);\ - } - - C4_ASSERT(base64_valid(encoded)); - C4_CHECK(encoded.len % 4 == 0); - size_t wpos = 0; // the write position - const char *C4_RESTRICT d = encoded.str; - constexpr const uint32_t full_byte = 0xff; - // process every quartet of input 6 bits --> triplet of output bytes - for(size_t rpos = 0; rpos < encoded.len; rpos += 4, d += 4) - { - if(d[2] == '=' || d[3] == '=') // skip the last quartet if it is padded - { - C4_ASSERT(d + 4 == encoded.str + encoded.len); - break; - } - uint32_t val = 0; - c4appendval_(d[3], 0); - c4appendval_(d[2], 1); - c4appendval_(d[1], 2); - c4appendval_(d[0], 3); - c4append_((val >> (2 * 8)) & full_byte); - c4append_((val >> (1 * 8)) & full_byte); - c4append_((val ) & full_byte); - } - // deal with the last quartet when it is padded - if(d == encoded.str + encoded.len) - return wpos; - if(d[2] == '=') // 2 padding chars - { - C4_ASSERT(d + 4 == encoded.str + encoded.len); - C4_ASSERT(d[3] == '='); - uint32_t val = 0; - c4appendval_(d[1], 2); - c4appendval_(d[0], 3); - c4append_((val >> (2 * 8)) & full_byte); - } - else if(d[3] == '=') // 1 padding char - { - C4_ASSERT(d + 4 == encoded.str + encoded.len); - uint32_t val = 0; - c4appendval_(d[2], 1); - c4appendval_(d[1], 2); - c4appendval_(d[0], 3); - c4append_((val >> (2 * 8)) & full_byte); - c4append_((val >> (1 * 8)) & full_byte); - } - return wpos; - #undef c4append_ - #undef c4appendval_ -} - -} // namespace c4 - -#ifdef __clang__ -# pragma clang diagnostic pop -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#endif diff --git a/thirdparty/ryml/ext/c4core/src/c4/base64.hpp b/thirdparty/ryml/ext/c4core/src/c4/base64.hpp deleted file mode 100644 index 673f4d77e..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/base64.hpp +++ /dev/null @@ -1,98 +0,0 @@ -#ifndef _C4_BASE64_HPP_ -#define _C4_BASE64_HPP_ - -/** @file base64.hpp encoding/decoding for base64. - * @see https://en.wikipedia.org/wiki/Base64 - * @see https://www.base64encode.org/ - * */ - -#include "c4/charconv.hpp" -#include "c4/blob.hpp" - -namespace c4 { - -/** check that the given buffer is a valid base64 encoding - * @see https://en.wikipedia.org/wiki/Base64 */ -bool base64_valid(csubstr encoded); - -/** base64-encode binary data. - * @param encoded [out] output buffer for encoded data - * @param data [in] the input buffer with the binary data - * @return the number of bytes needed to return the output. No writes occur beyond the end of the output buffer. - * @see https://en.wikipedia.org/wiki/Base64 */ -size_t base64_encode(substr encoded, cblob data); - -/** decode the base64 encoding in the given buffer - * @param encoded [in] the encoded base64 - * @param data [out] the output buffer - * @return the number of bytes needed to return the output.. No writes occur beyond the end of the output buffer. - * @see https://en.wikipedia.org/wiki/Base64 */ -size_t base64_decode(csubstr encoded, blob data); - - -namespace fmt { - -template -struct base64_wrapper_ -{ - blob_ data; - base64_wrapper_() : data() {} - base64_wrapper_(blob_ blob) : data(blob) {} -}; -using const_base64_wrapper = base64_wrapper_; -using base64_wrapper = base64_wrapper_; - - -/** mark a variable to be written in base64 format */ -template -C4_ALWAYS_INLINE const_base64_wrapper cbase64(Args const& C4_RESTRICT ...args) -{ - return const_base64_wrapper(cblob(args...)); -} -/** mark a csubstr to be written in base64 format */ -C4_ALWAYS_INLINE const_base64_wrapper cbase64(csubstr s) -{ - return const_base64_wrapper(cblob(s.str, s.len)); -} -/** mark a variable to be written in base64 format */ -template -C4_ALWAYS_INLINE const_base64_wrapper base64(Args const& C4_RESTRICT ...args) -{ - return const_base64_wrapper(cblob(args...)); -} -/** mark a csubstr to be written in base64 format */ -C4_ALWAYS_INLINE const_base64_wrapper base64(csubstr s) -{ - return const_base64_wrapper(cblob(s.str, s.len)); -} - -/** mark a variable to be read in base64 format */ -template -C4_ALWAYS_INLINE base64_wrapper base64(Args &... args) -{ - return base64_wrapper(blob(args...)); -} -/** mark a variable to be read in base64 format */ -C4_ALWAYS_INLINE base64_wrapper base64(substr s) -{ - return base64_wrapper(blob(s.str, s.len)); -} - -} // namespace fmt - - -/** write a variable in base64 format */ -inline size_t to_chars(substr buf, fmt::const_base64_wrapper b) -{ - return base64_encode(buf, b.data); -} - -/** read a variable in base64 format */ -inline size_t from_chars(csubstr buf, fmt::base64_wrapper *b) -{ - return base64_decode(buf, b->data); -} - -} // namespace c4 - -#endif /* _C4_BASE64_HPP_ */ diff --git a/thirdparty/ryml/ext/c4core/src/c4/bitmask.hpp b/thirdparty/ryml/ext/c4core/src/c4/bitmask.hpp deleted file mode 100644 index 8c239da30..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/bitmask.hpp +++ /dev/null @@ -1,330 +0,0 @@ -#ifndef _C4_BITMASK_HPP_ -#define _C4_BITMASK_HPP_ - -/** @file bitmask.hpp bitmask utilities */ - -#include -#include - -#include "c4/enum.hpp" -#include "c4/format.hpp" - -#ifdef _MSC_VER -# pragma warning(push) -# pragma warning(disable : 4996) // 'strncpy', fopen, etc: This function or variable may be unsafe -#elif defined(__clang__) -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# if __GNUC__ >= 8 -# pragma GCC diagnostic ignored "-Wstringop-truncation" -# pragma GCC diagnostic ignored "-Wstringop-overflow" -# endif -#endif - -namespace c4 { - -//----------------------------------------------------------------------------- -/** write a bitmask to a stream, formatted as a string */ - -template -Stream& bm2stream(Stream &s, typename std::underlying_type::type bits, EnumOffsetType offst=EOFFS_PFX) -{ - using I = typename std::underlying_type::type; - bool written = false; - - auto const& pairs = esyms(); - - // write non null value - if(bits) - { - // do reverse iteration to give preference to composite enum symbols, - // which are likely to appear at the end of the enum sequence - for(size_t i = pairs.size() - 1; i != size_t(-1); --i) - { - auto p = pairs[i]; - I b(static_cast(p.value)); - if(b && (bits & b) == b) - { - if(written) s << '|'; // append bit-or character - written = true; - s << p.name_offs(offst); // append bit string - bits &= ~b; - } - } - return s; - } - else - { - // write a null value - for(size_t i = pairs.size() - 1; i != size_t(-1); --i) - { - auto p = pairs[i]; - I b(static_cast(p.value)); - if(b == 0) - { - s << p.name_offs(offst); - written = true; - break; - } - } - } - if(!written) - { - s << '0'; - } - return s; -} - -template -typename std::enable_if::value, Stream&>::type -bm2stream(Stream &s, Enum value, EnumOffsetType offst=EOFFS_PFX) -{ - using I = typename std::underlying_type::type; - return bm2stream(s, static_cast(value), offst); -} - - -//----------------------------------------------------------------------------- - -// some utility macros, undefed below - -/// @cond dev - -/* Execute `code` if the `num` of characters is available in the str - * buffer. This macro simplifies the code for bm2str(). - * @todo improve performance by writing from the end and moving only once. */ -#define _c4prependchars(code, num) \ - if(str && (pos + num <= sz)) \ - { \ - /* move the current string to the right */ \ - memmove(str + num, str, pos); \ - /* now write in the beginning of the string */ \ - code; \ - } \ - else if(str && sz) \ - { \ - C4_ERROR("cannot write to string pos=%d num=%d sz=%d", \ - (int)pos, (int)num, (int)sz); \ - } \ - pos += num - -/* Execute `code` if the `num` of characters is available in the str - * buffer. This macro simplifies the code for bm2str(). */ -#define _c4appendchars(code, num) \ - if(str && (pos + num <= sz)) \ - { \ - code; \ - } \ - else if(str && sz) \ - { \ - C4_ERROR("cannot write to string pos=%d num=%d sz=%d", \ - (int)pos, (int)num, (int)sz); \ - } \ - pos += num - -/// @endcond - - -/** convert a bitmask to string. - * return the number of characters written. To find the needed size, - * call first with str=nullptr and sz=0 */ -template -size_t bm2str -( - typename std::underlying_type::type bits, - char *str=nullptr, - size_t sz=0, - EnumOffsetType offst=EOFFS_PFX -) -{ - using I = typename std::underlying_type::type; - C4_ASSERT((str == nullptr) == (sz == 0)); - - auto syms = esyms(); - size_t pos = 0; - typename EnumSymbols::Sym const* C4_RESTRICT zero = nullptr; - - // do reverse iteration to give preference to composite enum symbols, - // which are likely to appear later in the enum sequence - for(size_t i = syms.size()-1; i != size_t(-1); --i) - { - auto const &C4_RESTRICT p = syms[i]; // do not copy, we are assigning to `zero` - I b = static_cast(p.value); - if(b == 0) - { - zero = &p; // save this symbol for later - } - else if((bits & b) == b) - { - bits &= ~b; - // append bit-or character - if(pos > 0) - { - _c4prependchars(*str = '|', 1); - } - // append bit string - const char *pname = p.name_offs(offst); - size_t len = strlen(pname); - _c4prependchars(strncpy(str, pname, len), len); - } - } - - C4_CHECK_MSG(bits == 0, "could not find all bits"); - if(pos == 0) // make sure at least something is written - { - if(zero) // if we have a zero symbol, use that - { - const char *pname = zero->name_offs(offst); - size_t len = strlen(pname); - _c4prependchars(strncpy(str, pname, len), len); - } - else // otherwise just write an integer zero - { - _c4prependchars(*str = '0', 1); - } - } - _c4appendchars(str[pos] = '\0', 1); - - return pos; -} - - -// cleanup! -#undef _c4appendchars -#undef _c4prependchars - - -/** scoped enums do not convert automatically to their underlying type, - * so this SFINAE overload will accept scoped enum symbols and cast them - * to the underlying type */ -template -typename std::enable_if::value, size_t>::type -bm2str -( - Enum bits, - char *str=nullptr, - size_t sz=0, - EnumOffsetType offst=EOFFS_PFX -) -{ - using I = typename std::underlying_type::type; - return bm2str(static_cast(bits), str, sz, offst); -} - - -//----------------------------------------------------------------------------- - -namespace detail { - -#ifdef __clang__ -# pragma clang diagnostic push -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# if __GNUC__ >= 6 -# pragma GCC diagnostic ignored "-Wnull-dereference" -# endif -#endif - -template -typename std::underlying_type::type str2bm_read_one(const char *str, size_t sz, bool alnum) -{ - using I = typename std::underlying_type::type; - auto pairs = esyms(); - if(alnum) - { - auto *p = pairs.find(str, sz); - C4_CHECK_MSG(p != nullptr, "no valid enum pair name for '%.*s'", (int)sz, str); - return static_cast(p->value); - } - I tmp; - size_t len = uncat(csubstr(str, sz), tmp); - C4_CHECK_MSG(len != csubstr::npos, "could not read string as an integral type: '%.*s'", (int)sz, str); - return tmp; -} - -#ifdef __clang__ -# pragma clang diagnostic pop -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#endif -} // namespace detail - -/** convert a string to a bitmask */ -template -typename std::underlying_type::type str2bm(const char *str, size_t sz) -{ - using I = typename std::underlying_type::type; - - I val = 0; - bool started = false; - bool alnum = false, num = false; - const char *f = nullptr, *pc = str; - for( ; pc < str+sz; ++pc) - { - const char c = *pc; - if((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_') - { - C4_CHECK(( ! num) || ((pc - f) == 1 && (c == 'x' || c == 'X'))); // accept hexadecimal numbers - if( ! started) - { - f = pc; - alnum = started = true; - } - } - else if(c >= '0' && c <= '9') - { - C4_CHECK( ! alnum); - if(!started) - { - f = pc; - num = started = true; - } - } - else if(c == ':' || c == ' ') - { - // skip this char - } - else if(c == '|' || c == '\0') - { - C4_ASSERT(num != alnum); - C4_ASSERT(pc >= f); - val |= detail::str2bm_read_one(f, static_cast(pc-f), alnum); - started = num = alnum = false; - if(c == '\0') - { - return val; - } - } - else - { - C4_ERROR("bad character '%c' in bitmask string", c); - } - } - - if(f) - { - C4_ASSERT(num != alnum); - C4_ASSERT(pc >= f); - val |= detail::str2bm_read_one(f, static_cast(pc-f), alnum); - } - - return val; -} - -/** convert a string to a bitmask */ -template -typename std::underlying_type::type str2bm(const char *str) -{ - return str2bm(str, strlen(str)); -} - -} // namespace c4 - -#ifdef _MSC_VER -# pragma warning(pop) -#elif defined(__clang__) -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#endif - -#endif // _C4_BITMASK_HPP_ diff --git a/thirdparty/ryml/ext/c4core/src/c4/blob.hpp b/thirdparty/ryml/ext/c4core/src/c4/blob.hpp deleted file mode 100644 index 9c233d9f3..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/blob.hpp +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef _C4_BLOB_HPP_ -#define _C4_BLOB_HPP_ - -#include "c4/types.hpp" -#include "c4/error.hpp" - -/** @file blob.hpp Mutable and immutable binary data blobs. -*/ - -namespace c4 { - -template -struct blob_ -{ - T * buf; - size_t len; - - C4_ALWAYS_INLINE blob_() noexcept : buf(), len() {} - - C4_ALWAYS_INLINE blob_(blob_ const& that) noexcept = default; - C4_ALWAYS_INLINE blob_(blob_ && that) noexcept = default; - C4_ALWAYS_INLINE blob_& operator=(blob_ && that) noexcept = default; - C4_ALWAYS_INLINE blob_& operator=(blob_ const& that) noexcept = default; - - // need to sfinae out copy constructors! (why? isn't the above sufficient?) - #define _C4_REQUIRE_NOT_SAME class=typename std::enable_if<( ! std::is_same::value) && ( ! std::is_pointer::value), T>::type - template C4_ALWAYS_INLINE blob_(U &var) noexcept : buf(reinterpret_cast(&var)), len(sizeof(U)) {} - template C4_ALWAYS_INLINE blob_& operator= (U &var) noexcept { buf = reinterpret_cast(&var); len = sizeof(U); return *this; } - #undef _C4_REQUIRE_NOT_SAME - - template C4_ALWAYS_INLINE blob_(U (&arr)[N]) noexcept : buf(reinterpret_cast(arr)), len(sizeof(U) * N) {} - template C4_ALWAYS_INLINE blob_& operator= (U (&arr)[N]) noexcept { buf = reinterpret_cast(arr); len = sizeof(U) * N; return *this; } - - template - C4_ALWAYS_INLINE blob_(U *ptr, size_t n) noexcept : buf(reinterpret_cast(ptr)), len(sizeof(U) * n) { C4_ASSERT(is_aligned(ptr)); } - C4_ALWAYS_INLINE blob_(void *ptr, size_t n) noexcept : buf(reinterpret_cast(ptr)), len(n) {} - C4_ALWAYS_INLINE blob_(void const *ptr, size_t n) noexcept : buf(reinterpret_cast(ptr)), len(n) {} -}; - -/** an immutable binary blob */ -using cblob = blob_; -/** a mutable binary blob */ -using blob = blob_< byte>; - -C4_MUST_BE_TRIVIAL_COPY(blob); -C4_MUST_BE_TRIVIAL_COPY(cblob); - -} // namespace c4 - -#endif // _C4_BLOB_HPP_ diff --git a/thirdparty/ryml/ext/c4core/src/c4/c4_pop.hpp b/thirdparty/ryml/ext/c4core/src/c4/c4_pop.hpp deleted file mode 100644 index 3aa213352..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/c4_pop.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#ifdef _C4_PUSH_HPP_ // this must match the include guard from c4_push - -/** @file c4_pop.hpp disables the macros and control directives - * enabled in c4_push.hpp. - * @see c4_push.hpp */ - -#include "c4/unrestrict.hpp" - -#ifdef C4_WIN -# include "c4/windows_pop.hpp" -#endif - -#ifdef _MSC_VER -# pragma warning(pop) -#endif - -#undef _C4_PUSH_HPP_ - -#endif /* _C4_PUSH_HPP_ */ diff --git a/thirdparty/ryml/ext/c4core/src/c4/c4_push.hpp b/thirdparty/ryml/ext/c4core/src/c4/c4_push.hpp deleted file mode 100644 index 5498bdb28..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/c4_push.hpp +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef _C4_PUSH_HPP_ -#define _C4_PUSH_HPP_ - - -/** @file c4_push.hpp enables macros and warning control directives - * needed by c4core. This is implemented in a push/pop way. - * @see c4_pop.hpp */ - - -#ifndef _C4_CONFIG_HPP_ -#include "c4/config.hpp" -#endif - -#include "c4/restrict.hpp" - -#ifdef C4_WIN -# include "c4/windows_push.hpp" -#endif - -#ifdef _MSC_VER -# pragma warning(push) -# pragma warning(disable : 4068) // unknown pragma -# pragma warning(disable : 4100) // unreferenced formal parameter -# pragma warning(disable : 4127) // conditional expression is constant -- eg do {} while(1); -# pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union -//# pragma warning(disable : 4238) // nonstandard extension used: class rvalue used as lvalue -# pragma warning(disable : 4244) -# pragma warning(disable : 4503) // decorated name length exceeded, name was truncated -# pragma warning(disable : 4702) // unreachable code -# pragma warning(disable : 4714) // function marked as __forceinline not inlined -# pragma warning(disable : 4996) // 'strncpy', fopen, etc: This function or variable may be unsafe -# if C4_MSVC_VERSION != C4_MSVC_VERSION_2017 -# pragma warning(disable : 4800) // forcing value to bool 'true' or 'false' (performance warning) -# endif -#endif - -#endif /* _C4_PUSH_HPP_ */ diff --git a/thirdparty/ryml/ext/c4core/src/c4/c4core.natvis b/thirdparty/ryml/ext/c4core/src/c4/c4core.natvis deleted file mode 100644 index 7cd138fe6..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/c4core.natvis +++ /dev/null @@ -1,168 +0,0 @@ - - - - - - - - {str,[len]} (sz={len}) - str,[len] - - len - - len - str - - - - - - {m_ptr,[m_size]} (sz={m_size}) - - m_size - - m_size - m_ptr - - - - - {m_ptr,[m_size]} (sz={m_size}, cap={m_capacity}) - - m_size - m_capacity - - m_size - m_ptr - - - - - - {m_ptr,[m_size]} (sz={m_size}) - m_ptr,[m_size] - - m_size - - m_size - m_ptr - - - - - {m_ptr,[m_size]} (sz={m_size}) - m_ptr,[m_size] - - m_size - - m_size - m_ptr - - - - - - {m_ptr,[m_size]} (sz={m_size}, cap={m_capacity}) - m_ptr,[m_size] - - m_size - m_capacity - - m_size - m_ptr - - - - - {m_ptr,[m_size]} (sz={m_size}, cap={m_capacity}) - m_ptr,[m_size] - - m_size - m_capacity - - m_size - m_ptr - - - - - - - {(($T3*)this)->m_str,[(($T3*)this)->m_size]} (sz={(($T3*)this)->m_size}) - (($T3*)this)->m_str,[(($T3*)this)->m_size] - - - {(($T3*)this)->m_str,[(($T3*)this)->m_size]} - (($T3*)this)->m_str,[(($T3*)this)->m_size] - - - {(($T3*)this)->m_size} - - - - - {m_str,[m_size]} (sz={m_size}) - m_str,[m_size] - - - {m_size} - - - - - {m_str,[m_size]} (sz={m_size},cap={m_capacity}) - m_str,[m_size] - - - {m_size} - - - {m_capacity} - - - {m_str,[m_capacity]} - m_str,[m_capacity] - - - - - {m_str,[m_size]} (sz={m_size},cap={m_capacity}) - m_str,[m_size] - - - {m_size} - - - {m_str,[m_capacity]} - m_str,[m_capacity] - - - - - - - {value} - {name} - - value - name - - - - {m_symbols,[m_num]} (sz={m_num}) - - m_num - - m_num - m_symbols - - - - - diff --git a/thirdparty/ryml/ext/c4core/src/c4/char_traits.cpp b/thirdparty/ryml/ext/c4core/src/c4/char_traits.cpp deleted file mode 100644 index 053a7c3b1..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/char_traits.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "c4/char_traits.hpp" - -namespace c4 { - -constexpr const char char_traits< char >::whitespace_chars[]; -constexpr const size_t char_traits< char >::num_whitespace_chars; -constexpr const wchar_t char_traits< wchar_t >::whitespace_chars[]; -constexpr const size_t char_traits< wchar_t >::num_whitespace_chars; - -} // namespace c4 diff --git a/thirdparty/ryml/ext/c4core/src/c4/char_traits.hpp b/thirdparty/ryml/ext/c4core/src/c4/char_traits.hpp deleted file mode 100644 index b080659fb..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/char_traits.hpp +++ /dev/null @@ -1,98 +0,0 @@ -#ifndef _C4_CHAR_TRAITS_HPP_ -#define _C4_CHAR_TRAITS_HPP_ - -#include "c4/config.hpp" - -#include // needed because of std::char_traits -#include -#include - -namespace c4 { - -C4_ALWAYS_INLINE bool isspace(char c) { return std::isspace(c) != 0; } -C4_ALWAYS_INLINE bool isspace(wchar_t c) { return std::iswspace(static_cast(c)) != 0; } - -//----------------------------------------------------------------------------- -template -struct char_traits; - -template<> -struct char_traits : public std::char_traits -{ - constexpr static const char whitespace_chars[] = " \f\n\r\t\v"; - constexpr static const size_t num_whitespace_chars = sizeof(whitespace_chars) - 1; -}; - -template<> -struct char_traits : public std::char_traits -{ - constexpr static const wchar_t whitespace_chars[] = L" \f\n\r\t\v"; - constexpr static const size_t num_whitespace_chars = sizeof(whitespace_chars) - 1; -}; - - -//----------------------------------------------------------------------------- -namespace detail { -template -struct needed_chars; -template<> -struct needed_chars -{ - template - C4_ALWAYS_INLINE constexpr static SizeType for_bytes(SizeType num_bytes) - { - return num_bytes; - } -}; -template<> -struct needed_chars -{ - template - C4_ALWAYS_INLINE constexpr static SizeType for_bytes(SizeType num_bytes) - { - // wchar_t is not necessarily 2 bytes. - return (num_bytes / static_cast(sizeof(wchar_t))) + ((num_bytes & static_cast(SizeType(sizeof(wchar_t)) - SizeType(1))) != 0); - } -}; -} // namespace detail - -/** get the number of C characters needed to store a number of bytes */ -template -C4_ALWAYS_INLINE constexpr SizeType num_needed_chars(SizeType num_bytes) -{ - return detail::needed_chars::for_bytes(num_bytes); -} - - -//----------------------------------------------------------------------------- - -/** get the given text string as either char or wchar_t according to the given type */ -#define C4_TXTTY(txt, type) \ - /* is there a smarter way to do this? */\ - c4::detail::literal_as::get(txt, C4_WIDEN(txt)) - -namespace detail { -template -struct literal_as; - -template<> -struct literal_as -{ - C4_ALWAYS_INLINE static constexpr const char* get(const char* str, const wchar_t *) - { - return str; - } -}; -template<> -struct literal_as -{ - C4_ALWAYS_INLINE static constexpr const wchar_t* get(const char*, const wchar_t *wstr) - { - return wstr; - } -}; -} // namespace detail - -} // namespace c4 - -#endif /* _C4_CHAR_TRAITS_HPP_ */ diff --git a/thirdparty/ryml/ext/c4core/src/c4/charconv.hpp b/thirdparty/ryml/ext/c4core/src/c4/charconv.hpp deleted file mode 100644 index af44f136c..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/charconv.hpp +++ /dev/null @@ -1,2407 +0,0 @@ -#ifndef _C4_CHARCONV_HPP_ -#define _C4_CHARCONV_HPP_ - -/** @file charconv.hpp Lightweight generic type-safe wrappers for - * converting individual values to/from strings. - * - * These are the main functions: - * - * @code{.cpp} - * // Convert the given value, writing into the string. - * // The resulting string will NOT be null-terminated. - * // Return the number of characters needed. - * // This function is safe to call when the string is too small - - * // no writes will occur beyond the string's last character. - * template size_t c4::to_chars(substr buf, T const& C4_RESTRICT val); - * - * - * // Convert the given value to a string using to_chars(), and - * // return the resulting string, up to and including the last - * // written character. - * template substr c4::to_chars_sub(substr buf, T const& C4_RESTRICT val); - * - * - * // Read a value from the string, which must be - * // trimmed to the value (ie, no leading/trailing whitespace). - * // return true if the conversion succeeded. - * // There is no check for overflow; the value wraps around in a way similar - * // to the standard C/C++ overflow behavior. For example, - * // from_chars("128", &val) returns true and val will be - * // set tot 0. - * template bool c4::from_chars(csubstr buf, T * C4_RESTRICT val); - * - * - * // Read the first valid sequence of characters from the string, - * // skipping leading whitespace, and convert it using from_chars(). - * // Return the number of characters read for converting. - * template size_t c4::from_chars_first(csubstr buf, T * C4_RESTRICT val); - * @endcode - */ - -#include "c4/language.hpp" -#include -#include -#include -#include -#include - -#include "c4/config.hpp" -#include "c4/substr.hpp" -#include "c4/std/std_fwd.hpp" -#include "c4/memory_util.hpp" -#include "c4/szconv.hpp" - -#ifndef C4CORE_NO_FAST_FLOAT -# if (C4_CPP >= 17) -# if defined(_MSC_VER) -# if (C4_MSVC_VERSION >= C4_MSVC_VERSION_2019) // VS2017 and lower do not have these macros -# include -# define C4CORE_HAVE_STD_TOCHARS 1 -# define C4CORE_HAVE_STD_FROMCHARS 0 // prefer fast_float with MSVC -# define C4CORE_HAVE_FAST_FLOAT 1 -# else -# define C4CORE_HAVE_STD_TOCHARS 0 -# define C4CORE_HAVE_STD_FROMCHARS 0 -# define C4CORE_HAVE_FAST_FLOAT 1 -# endif -# else -# if __has_include() -# include -# if defined(__cpp_lib_to_chars) -# define C4CORE_HAVE_STD_TOCHARS 1 -# define C4CORE_HAVE_STD_FROMCHARS 0 // glibc uses fast_float internally -# define C4CORE_HAVE_FAST_FLOAT 1 -# else -# define C4CORE_HAVE_STD_TOCHARS 0 -# define C4CORE_HAVE_STD_FROMCHARS 0 -# define C4CORE_HAVE_FAST_FLOAT 1 -# endif -# else -# define C4CORE_HAVE_STD_TOCHARS 0 -# define C4CORE_HAVE_STD_FROMCHARS 0 -# define C4CORE_HAVE_FAST_FLOAT 1 -# endif -# endif -# else -# define C4CORE_HAVE_STD_TOCHARS 0 -# define C4CORE_HAVE_STD_FROMCHARS 0 -# define C4CORE_HAVE_FAST_FLOAT 1 -# endif -# if C4CORE_HAVE_FAST_FLOAT - C4_SUPPRESS_WARNING_GCC_WITH_PUSH("-Wsign-conversion") - C4_SUPPRESS_WARNING_GCC("-Warray-bounds") -# if __GNUC__ >= 5 - C4_SUPPRESS_WARNING_GCC("-Wshift-count-overflow") -# endif -# include "c4/ext/fast_float.hpp" - C4_SUPPRESS_WARNING_GCC_POP -# endif -#elif (C4_CPP >= 17) -# define C4CORE_HAVE_FAST_FLOAT 0 -# if defined(_MSC_VER) -# if (C4_MSVC_VERSION >= C4_MSVC_VERSION_2019) // VS2017 and lower do not have these macros -# include -# define C4CORE_HAVE_STD_TOCHARS 1 -# define C4CORE_HAVE_STD_FROMCHARS 1 -# else -# define C4CORE_HAVE_STD_TOCHARS 0 -# define C4CORE_HAVE_STD_FROMCHARS 0 -# endif -# else -# if __has_include() -# include -# if defined(__cpp_lib_to_chars) -# define C4CORE_HAVE_STD_TOCHARS 1 -# define C4CORE_HAVE_STD_FROMCHARS 1 // glibc uses fast_float internally -# else -# define C4CORE_HAVE_STD_TOCHARS 0 -# define C4CORE_HAVE_STD_FROMCHARS 0 -# endif -# else -# define C4CORE_HAVE_STD_TOCHARS 0 -# define C4CORE_HAVE_STD_FROMCHARS 0 -# endif -# endif -#else -# define C4CORE_HAVE_STD_TOCHARS 0 -# define C4CORE_HAVE_STD_FROMCHARS 0 -# define C4CORE_HAVE_FAST_FLOAT 0 -#endif - - -#if !C4CORE_HAVE_STD_FROMCHARS -#include -#endif - - -#ifdef _MSC_VER -# pragma warning(push) -# if C4_MSVC_VERSION != C4_MSVC_VERSION_2017 -# pragma warning(disable: 4800) //'int': forcing value to bool 'true' or 'false' (performance warning) -# endif -# pragma warning(disable: 4996) // snprintf/scanf: this function or variable may be unsafe -#elif defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wtautological-constant-out-of-range-compare" -# pragma clang diagnostic ignored "-Wformat-nonliteral" -# pragma clang diagnostic ignored "-Wdouble-promotion" // implicit conversion increases floating-point precision -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wformat-nonliteral" -# pragma GCC diagnostic ignored "-Wdouble-promotion" // implicit conversion increases floating-point precision -# pragma GCC diagnostic ignored "-Wuseless-cast" -#endif - - -namespace c4 { - -#if C4CORE_HAVE_STD_TOCHARS -/** @warning Use only the symbol. Do not rely on the type or naked value of this enum. */ -typedef enum : std::underlying_type::type { - /** print the real number in floating point format (like %f) */ - FTOA_FLOAT = static_cast::type>(std::chars_format::fixed), - /** print the real number in scientific format (like %e) */ - FTOA_SCIENT = static_cast::type>(std::chars_format::scientific), - /** print the real number in flexible format (like %g) */ - FTOA_FLEX = static_cast::type>(std::chars_format::general), - /** print the real number in hexadecimal format (like %a) */ - FTOA_HEXA = static_cast::type>(std::chars_format::hex), -} RealFormat_e; -#else -/** @warning Use only the symbol. Do not rely on the type or naked value of this enum. */ -typedef enum : char { - /** print the real number in floating point format (like %f) */ - FTOA_FLOAT = 'f', - /** print the real number in scientific format (like %e) */ - FTOA_SCIENT = 'e', - /** print the real number in flexible format (like %g) */ - FTOA_FLEX = 'g', - /** print the real number in hexadecimal format (like %a) */ - FTOA_HEXA = 'a', -} RealFormat_e; -#endif - - -/** in some platforms, int,unsigned int - * are not any of int8_t...int64_t and - * long,unsigned long are not any of uint8_t...uint64_t */ -template -struct is_fixed_length -{ - enum : bool { - /** true if T is one of the fixed length signed types */ - value_i = (std::is_integral::value - && (std::is_same::value - || std::is_same::value - || std::is_same::value - || std::is_same::value)), - /** true if T is one of the fixed length unsigned types */ - value_u = (std::is_integral::value - && (std::is_same::value - || std::is_same::value - || std::is_same::value - || std::is_same::value)), - /** true if T is one of the fixed length signed or unsigned types */ - value = value_i || value_u - }; -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -#ifdef _MSC_VER -# pragma warning(push) -#elif defined(__clang__) -# pragma clang diagnostic push -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wconversion" -# if __GNUC__ >= 6 -# pragma GCC diagnostic ignored "-Wnull-dereference" -# endif -#endif - -namespace detail { - -/* python command to get the values below: -def dec(v): - return str(v) -for bits in (8, 16, 32, 64): - imin, imax, umax = (-(1 << (bits - 1))), (1 << (bits - 1)) - 1, (1 << bits) - 1 - for vname, v in (("imin", imin), ("imax", imax), ("umax", umax)): - for f in (bin, oct, dec, hex): - print(f"{bits}b: {vname}={v} {f.__name__}: len={len(f(v)):2d}: {v} {f(v)}") -*/ - -// do not use the type as the template argument because in some -// platforms long!=int32 and long!=int64. Just use the numbytes -// which is more generic and spares lengthy SFINAE code. -template struct charconv_digits_; -template using charconv_digits = charconv_digits_::value>; - -template<> struct charconv_digits_<1u, true> // int8_t -{ - enum : size_t { - maxdigits_bin = 1 + 2 + 8, // -128==-0b10000000 - maxdigits_oct = 1 + 2 + 3, // -128==-0o200 - maxdigits_dec = 1 + 3, // -128 - maxdigits_hex = 1 + 2 + 2, // -128==-0x80 - maxdigits_bin_nopfx = 8, // -128==-0b10000000 - maxdigits_oct_nopfx = 3, // -128==-0o200 - maxdigits_dec_nopfx = 3, // -128 - maxdigits_hex_nopfx = 2, // -128==-0x80 - }; - // min values without sign! - static constexpr csubstr min_value_dec() noexcept { return csubstr("128"); } - static constexpr csubstr min_value_hex() noexcept { return csubstr("80"); } - static constexpr csubstr min_value_oct() noexcept { return csubstr("200"); } - static constexpr csubstr min_value_bin() noexcept { return csubstr("10000000"); } - static constexpr csubstr max_value_dec() noexcept { return csubstr("127"); } - static constexpr bool is_oct_overflow(csubstr str) noexcept { return !((str.len < 3) || (str.len == 3 && str[0] <= '1')); } -}; -template<> struct charconv_digits_<1u, false> // uint8_t -{ - enum : size_t { - maxdigits_bin = 2 + 8, // 255 0b11111111 - maxdigits_oct = 2 + 3, // 255 0o377 - maxdigits_dec = 3, // 255 - maxdigits_hex = 2 + 2, // 255 0xff - maxdigits_bin_nopfx = 8, // 255 0b11111111 - maxdigits_oct_nopfx = 3, // 255 0o377 - maxdigits_dec_nopfx = 3, // 255 - maxdigits_hex_nopfx = 2, // 255 0xff - }; - static constexpr csubstr max_value_dec() noexcept { return csubstr("255"); } - static constexpr bool is_oct_overflow(csubstr str) noexcept { return !((str.len < 3) || (str.len == 3 && str[0] <= '3')); } -}; -template<> struct charconv_digits_<2u, true> // int16_t -{ - enum : size_t { - maxdigits_bin = 1 + 2 + 16, // -32768 -0b1000000000000000 - maxdigits_oct = 1 + 2 + 6, // -32768 -0o100000 - maxdigits_dec = 1 + 5, // -32768 -32768 - maxdigits_hex = 1 + 2 + 4, // -32768 -0x8000 - maxdigits_bin_nopfx = 16, // -32768 -0b1000000000000000 - maxdigits_oct_nopfx = 6, // -32768 -0o100000 - maxdigits_dec_nopfx = 5, // -32768 -32768 - maxdigits_hex_nopfx = 4, // -32768 -0x8000 - }; - // min values without sign! - static constexpr csubstr min_value_dec() noexcept { return csubstr("32768"); } - static constexpr csubstr min_value_hex() noexcept { return csubstr("8000"); } - static constexpr csubstr min_value_oct() noexcept { return csubstr("100000"); } - static constexpr csubstr min_value_bin() noexcept { return csubstr("1000000000000000"); } - static constexpr csubstr max_value_dec() noexcept { return csubstr("32767"); } - static constexpr bool is_oct_overflow(csubstr str) noexcept { return !((str.len < 6)); } -}; -template<> struct charconv_digits_<2u, false> // uint16_t -{ - enum : size_t { - maxdigits_bin = 2 + 16, // 65535 0b1111111111111111 - maxdigits_oct = 2 + 6, // 65535 0o177777 - maxdigits_dec = 6, // 65535 65535 - maxdigits_hex = 2 + 4, // 65535 0xffff - maxdigits_bin_nopfx = 16, // 65535 0b1111111111111111 - maxdigits_oct_nopfx = 6, // 65535 0o177777 - maxdigits_dec_nopfx = 6, // 65535 65535 - maxdigits_hex_nopfx = 4, // 65535 0xffff - }; - static constexpr csubstr max_value_dec() noexcept { return csubstr("65535"); } - static constexpr bool is_oct_overflow(csubstr str) noexcept { return !((str.len < 6) || (str.len == 6 && str[0] <= '1')); } -}; -template<> struct charconv_digits_<4u, true> // int32_t -{ - enum : size_t { - maxdigits_bin = 1 + 2 + 32, // len=35: -2147483648 -0b10000000000000000000000000000000 - maxdigits_oct = 1 + 2 + 11, // len=14: -2147483648 -0o20000000000 - maxdigits_dec = 1 + 10, // len=11: -2147483648 -2147483648 - maxdigits_hex = 1 + 2 + 8, // len=11: -2147483648 -0x80000000 - maxdigits_bin_nopfx = 32, // len=35: -2147483648 -0b10000000000000000000000000000000 - maxdigits_oct_nopfx = 11, // len=14: -2147483648 -0o20000000000 - maxdigits_dec_nopfx = 10, // len=11: -2147483648 -2147483648 - maxdigits_hex_nopfx = 8, // len=11: -2147483648 -0x80000000 - }; - // min values without sign! - static constexpr csubstr min_value_dec() noexcept { return csubstr("2147483648"); } - static constexpr csubstr min_value_hex() noexcept { return csubstr("80000000"); } - static constexpr csubstr min_value_oct() noexcept { return csubstr("20000000000"); } - static constexpr csubstr min_value_bin() noexcept { return csubstr("10000000000000000000000000000000"); } - static constexpr csubstr max_value_dec() noexcept { return csubstr("2147483647"); } - static constexpr bool is_oct_overflow(csubstr str) noexcept { return !((str.len < 11) || (str.len == 11 && str[0] <= '1')); } -}; -template<> struct charconv_digits_<4u, false> // uint32_t -{ - enum : size_t { - maxdigits_bin = 2 + 32, // len=34: 4294967295 0b11111111111111111111111111111111 - maxdigits_oct = 2 + 11, // len=13: 4294967295 0o37777777777 - maxdigits_dec = 10, // len=10: 4294967295 4294967295 - maxdigits_hex = 2 + 8, // len=10: 4294967295 0xffffffff - maxdigits_bin_nopfx = 32, // len=34: 4294967295 0b11111111111111111111111111111111 - maxdigits_oct_nopfx = 11, // len=13: 4294967295 0o37777777777 - maxdigits_dec_nopfx = 10, // len=10: 4294967295 4294967295 - maxdigits_hex_nopfx = 8, // len=10: 4294967295 0xffffffff - }; - static constexpr csubstr max_value_dec() noexcept { return csubstr("4294967295"); } - static constexpr bool is_oct_overflow(csubstr str) noexcept { return !((str.len < 11) || (str.len == 11 && str[0] <= '3')); } -}; -template<> struct charconv_digits_<8u, true> // int32_t -{ - enum : size_t { - maxdigits_bin = 1 + 2 + 64, // len=67: -9223372036854775808 -0b1000000000000000000000000000000000000000000000000000000000000000 - maxdigits_oct = 1 + 2 + 22, // len=25: -9223372036854775808 -0o1000000000000000000000 - maxdigits_dec = 1 + 19, // len=20: -9223372036854775808 -9223372036854775808 - maxdigits_hex = 1 + 2 + 16, // len=19: -9223372036854775808 -0x8000000000000000 - maxdigits_bin_nopfx = 64, // len=67: -9223372036854775808 -0b1000000000000000000000000000000000000000000000000000000000000000 - maxdigits_oct_nopfx = 22, // len=25: -9223372036854775808 -0o1000000000000000000000 - maxdigits_dec_nopfx = 19, // len=20: -9223372036854775808 -9223372036854775808 - maxdigits_hex_nopfx = 16, // len=19: -9223372036854775808 -0x8000000000000000 - }; - static constexpr csubstr min_value_dec() noexcept { return csubstr("9223372036854775808"); } - static constexpr csubstr min_value_hex() noexcept { return csubstr("8000000000000000"); } - static constexpr csubstr min_value_oct() noexcept { return csubstr("1000000000000000000000"); } - static constexpr csubstr min_value_bin() noexcept { return csubstr("1000000000000000000000000000000000000000000000000000000000000000"); } - static constexpr csubstr max_value_dec() noexcept { return csubstr("9223372036854775807"); } - static constexpr bool is_oct_overflow(csubstr str) noexcept { return !((str.len < 22)); } -}; -template<> struct charconv_digits_<8u, false> -{ - enum : size_t { - maxdigits_bin = 2 + 64, // len=66: 18446744073709551615 0b1111111111111111111111111111111111111111111111111111111111111111 - maxdigits_oct = 2 + 22, // len=24: 18446744073709551615 0o1777777777777777777777 - maxdigits_dec = 20, // len=20: 18446744073709551615 18446744073709551615 - maxdigits_hex = 2 + 16, // len=18: 18446744073709551615 0xffffffffffffffff - maxdigits_bin_nopfx = 64, // len=66: 18446744073709551615 0b1111111111111111111111111111111111111111111111111111111111111111 - maxdigits_oct_nopfx = 22, // len=24: 18446744073709551615 0o1777777777777777777777 - maxdigits_dec_nopfx = 20, // len=20: 18446744073709551615 18446744073709551615 - maxdigits_hex_nopfx = 16, // len=18: 18446744073709551615 0xffffffffffffffff - }; - static constexpr csubstr max_value_dec() noexcept { return csubstr("18446744073709551615"); } - static constexpr bool is_oct_overflow(csubstr str) noexcept { return !((str.len < 22) || (str.len == 22 && str[0] <= '1')); } -}; -} // namespace detail - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -// Helper macros, undefined below -#define _c4append(c) { if(C4_LIKELY(pos < buf.len)) { buf.str[pos++] = static_cast(c); } else { ++pos; } } -#define _c4appendhex(i) { if(C4_LIKELY(pos < buf.len)) { buf.str[pos++] = hexchars[i]; } else { ++pos; } } - -/** @name digits_dec return the number of digits required to encode a - * decimal number. - * - * @note At first sight this code may look heavily branchy and - * therefore inefficient. However, measurements revealed this to be - * the fastest among the alternatives. - * - * @see https://github.com/biojppm/c4core/pull/77 */ -/** @{ */ - -template -C4_CONSTEXPR14 C4_ALWAYS_INLINE -auto digits_dec(T v) noexcept - -> typename std::enable_if::type -{ - C4_STATIC_ASSERT(std::is_integral::value); - C4_ASSERT(v >= 0); - return ((v >= 100) ? 3u : ((v >= 10) ? 2u : 1u)); -} - -template -C4_CONSTEXPR14 C4_ALWAYS_INLINE -auto digits_dec(T v) noexcept - -> typename std::enable_if::type -{ - C4_STATIC_ASSERT(std::is_integral::value); - C4_ASSERT(v >= 0); - return ((v >= 10000) ? 5u : (v >= 1000) ? 4u : (v >= 100) ? 3u : (v >= 10) ? 2u : 1u); -} - -template -C4_CONSTEXPR14 C4_ALWAYS_INLINE -auto digits_dec(T v) noexcept - -> typename std::enable_if::type -{ - C4_STATIC_ASSERT(std::is_integral::value); - C4_ASSERT(v >= 0); - return ((v >= 1000000000) ? 10u : (v >= 100000000) ? 9u : (v >= 10000000) ? 8u : - (v >= 1000000) ? 7u : (v >= 100000) ? 6u : (v >= 10000) ? 5u : - (v >= 1000) ? 4u : (v >= 100) ? 3u : (v >= 10) ? 2u : 1u); -} - -template -C4_CONSTEXPR14 C4_ALWAYS_INLINE -auto digits_dec(T v) noexcept - -> typename std::enable_if::type -{ - // thanks @fargies!!! - // https://github.com/biojppm/c4core/pull/77#issuecomment-1063753568 - C4_STATIC_ASSERT(std::is_integral::value); - C4_ASSERT(v >= 0); - if(v >= 1000000000) // 10 - { - if(v >= 100000000000000) // 15 [15-20] range - { - if(v >= 100000000000000000) // 18 (15 + (20 - 15) / 2) - { - if((typename std::make_unsigned::type)v >= 10000000000000000000u) // 20 - return 20u; - else - return (v >= 1000000000000000000) ? 19u : 18u; - } - else if(v >= 10000000000000000) // 17 - return 17u; - else - return(v >= 1000000000000000) ? 16u : 15u; - } - else if(v >= 1000000000000) // 13 - return (v >= 10000000000000) ? 14u : 13u; - else if(v >= 100000000000) // 12 - return 12; - else - return(v >= 10000000000) ? 11u : 10u; - } - else if(v >= 10000) // 5 [5-9] range - { - if(v >= 10000000) // 8 - return (v >= 100000000) ? 9u : 8u; - else if(v >= 1000000) // 7 - return 7; - else - return (v >= 100000) ? 6u : 5u; - } - else if(v >= 100) - return (v >= 1000) ? 4u : 3u; - else - return (v >= 10) ? 2u : 1u; -} - -/** @} */ - - -template -C4_CONSTEXPR14 C4_ALWAYS_INLINE unsigned digits_hex(T v) noexcept -{ - C4_STATIC_ASSERT(std::is_integral::value); - C4_ASSERT(v >= 0); - return v ? 1u + (msb((typename std::make_unsigned::type)v) >> 2u) : 1u; -} - -template -C4_CONSTEXPR14 C4_ALWAYS_INLINE unsigned digits_bin(T v) noexcept -{ - C4_STATIC_ASSERT(std::is_integral::value); - C4_ASSERT(v >= 0); - return v ? 1u + msb((typename std::make_unsigned::type)v) : 1u; -} - -template -C4_CONSTEXPR14 C4_ALWAYS_INLINE unsigned digits_oct(T v_) noexcept -{ - // TODO: is there a better way? - C4_STATIC_ASSERT(std::is_integral::value); - C4_ASSERT(v_ >= 0); - using U = typename - std::conditional::type>::type; - U v = (U) v_; // safe because we require v_ >= 0 - unsigned __n = 1; - const unsigned __b2 = 64u; - const unsigned __b3 = __b2 * 8u; - const unsigned long __b4 = __b3 * 8u; - while(true) - { - if(v < 8u) - return __n; - if(v < __b2) - return __n + 1; - if(v < __b3) - return __n + 2; - if(v < __b4) - return __n + 3; - v /= (U) __b4; - __n += 4; - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -namespace detail { -C4_INLINE_CONSTEXPR const char hexchars[] = "0123456789abcdef"; -C4_INLINE_CONSTEXPR const char digits0099[] = - "0001020304050607080910111213141516171819" - "2021222324252627282930313233343536373839" - "4041424344454647484950515253545556575859" - "6061626364656667686970717273747576777879" - "8081828384858687888990919293949596979899"; -} // namespace detail - -C4_SUPPRESS_WARNING_GCC_PUSH -C4_SUPPRESS_WARNING_GCC("-Warray-bounds") // gcc has false positives here -#if (defined(__GNUC__) && (__GNUC__ >= 7)) -C4_SUPPRESS_WARNING_GCC("-Wstringop-overflow") // gcc has false positives here -#endif - -template -C4_HOT C4_ALWAYS_INLINE -void write_dec_unchecked(substr buf, T v, unsigned digits_v) noexcept -{ - C4_STATIC_ASSERT(std::is_integral::value); - C4_ASSERT(v >= 0); - C4_ASSERT(buf.len >= digits_v); - C4_XASSERT(digits_v == digits_dec(v)); - // in bm_xtoa: checkoncelog_singlediv_write2 - while(v >= T(100)) - { - const T quo = v / T(100); - const auto num = (v - quo * T(100)) << 1u; - v = quo; - buf.str[--digits_v] = detail::digits0099[num + 1]; - buf.str[--digits_v] = detail::digits0099[num]; - } - if(v >= T(10)) - { - C4_ASSERT(digits_v == 2); - const auto num = v << 1u; - buf.str[1] = detail::digits0099[num + 1]; - buf.str[0] = detail::digits0099[num]; - } - else - { - C4_ASSERT(digits_v == 1); - buf.str[0] = (char)('0' + v); - } -} - - -template -C4_HOT C4_ALWAYS_INLINE -void write_hex_unchecked(substr buf, T v, unsigned digits_v) noexcept -{ - C4_STATIC_ASSERT(std::is_integral::value); - C4_ASSERT(v >= 0); - C4_ASSERT(buf.len >= digits_v); - C4_XASSERT(digits_v == digits_hex(v)); - do { - buf.str[--digits_v] = detail::hexchars[v & T(15)]; - v >>= 4; - } while(v); - C4_ASSERT(digits_v == 0); -} - - -template -C4_HOT C4_ALWAYS_INLINE -void write_oct_unchecked(substr buf, T v, unsigned digits_v) noexcept -{ - C4_STATIC_ASSERT(std::is_integral::value); - C4_ASSERT(v >= 0); - C4_ASSERT(buf.len >= digits_v); - C4_XASSERT(digits_v == digits_oct(v)); - do { - buf.str[--digits_v] = (char)('0' + (v & T(7))); - v >>= 3; - } while(v); - C4_ASSERT(digits_v == 0); -} - - -template -C4_HOT C4_ALWAYS_INLINE -void write_bin_unchecked(substr buf, T v, unsigned digits_v) noexcept -{ - C4_STATIC_ASSERT(std::is_integral::value); - C4_ASSERT(v >= 0); - C4_ASSERT(buf.len >= digits_v); - C4_XASSERT(digits_v == digits_bin(v)); - do { - buf.str[--digits_v] = (char)('0' + (v & T(1))); - v >>= 1; - } while(v); - C4_ASSERT(digits_v == 0); -} - - -/** write an integer to a string in decimal format. This is the - * lowest level (and the fastest) function to do this task. - * @note does not accept negative numbers - * @note the resulting string is NOT zero-terminated. - * @note it is ok to call this with an empty or too-small buffer; - * no writes will occur, and the required size will be returned - * @return the number of characters required for the buffer. */ -template -C4_ALWAYS_INLINE size_t write_dec(substr buf, T v) noexcept -{ - C4_STATIC_ASSERT(std::is_integral::value); - C4_ASSERT(v >= 0); - unsigned digits = digits_dec(v); - if(C4_LIKELY(buf.len >= digits)) - write_dec_unchecked(buf, v, digits); - return digits; -} - -/** write an integer to a string in hexadecimal format. This is the - * lowest level (and the fastest) function to do this task. - * @note does not accept negative numbers - * @note does not prefix with 0x - * @note the resulting string is NOT zero-terminated. - * @note it is ok to call this with an empty or too-small buffer; - * no writes will occur, and the required size will be returned - * @return the number of characters required for the buffer. */ -template -C4_ALWAYS_INLINE size_t write_hex(substr buf, T v) noexcept -{ - C4_STATIC_ASSERT(std::is_integral::value); - C4_ASSERT(v >= 0); - unsigned digits = digits_hex(v); - if(C4_LIKELY(buf.len >= digits)) - write_hex_unchecked(buf, v, digits); - return digits; -} - -/** write an integer to a string in octal format. This is the - * lowest level (and the fastest) function to do this task. - * @note does not accept negative numbers - * @note does not prefix with 0o - * @note the resulting string is NOT zero-terminated. - * @note it is ok to call this with an empty or too-small buffer; - * no writes will occur, and the required size will be returned - * @return the number of characters required for the buffer. */ -template -C4_ALWAYS_INLINE size_t write_oct(substr buf, T v) noexcept -{ - C4_STATIC_ASSERT(std::is_integral::value); - C4_ASSERT(v >= 0); - unsigned digits = digits_oct(v); - if(C4_LIKELY(buf.len >= digits)) - write_oct_unchecked(buf, v, digits); - return digits; -} - -/** write an integer to a string in binary format. This is the - * lowest level (and the fastest) function to do this task. - * @note does not accept negative numbers - * @note does not prefix with 0b - * @note the resulting string is NOT zero-terminated. - * @note it is ok to call this with an empty or too-small buffer; - * no writes will occur, and the required size will be returned - * @return the number of characters required for the buffer. */ -template -C4_ALWAYS_INLINE size_t write_bin(substr buf, T v) noexcept -{ - C4_STATIC_ASSERT(std::is_integral::value); - C4_ASSERT(v >= 0); - unsigned digits = digits_bin(v); - C4_ASSERT(digits > 0); - if(C4_LIKELY(buf.len >= digits)) - write_bin_unchecked(buf, v, digits); - return digits; -} - - -namespace detail { -template using NumberWriter = size_t (*)(substr, U); -template writer> -size_t write_num_digits(substr buf, T v, size_t num_digits) noexcept -{ - C4_STATIC_ASSERT(std::is_integral::value); - size_t ret = writer(buf, v); - if(ret >= num_digits) - return ret; - else if(ret >= buf.len || num_digits > buf.len) - return num_digits; - C4_ASSERT(num_digits >= ret); - size_t delta = static_cast(num_digits - ret); - memmove(buf.str + delta, buf.str, ret); - memset(buf.str, '0', delta); - return num_digits; -} -} // namespace detail - - -/** same as c4::write_dec(), but pad with zeroes on the left - * such that the resulting string is @p num_digits wide. - * If the given number is requires more than num_digits, then the number prevails. */ -template -C4_ALWAYS_INLINE size_t write_dec(substr buf, T val, size_t num_digits) noexcept -{ - return detail::write_num_digits>(buf, val, num_digits); -} - -/** same as c4::write_hex(), but pad with zeroes on the left - * such that the resulting string is @p num_digits wide. - * If the given number is requires more than num_digits, then the number prevails. */ -template -C4_ALWAYS_INLINE size_t write_hex(substr buf, T val, size_t num_digits) noexcept -{ - return detail::write_num_digits>(buf, val, num_digits); -} - -/** same as c4::write_bin(), but pad with zeroes on the left - * such that the resulting string is @p num_digits wide. - * If the given number is requires more than num_digits, then the number prevails. */ -template -C4_ALWAYS_INLINE size_t write_bin(substr buf, T val, size_t num_digits) noexcept -{ - return detail::write_num_digits>(buf, val, num_digits); -} - -/** same as c4::write_oct(), but pad with zeroes on the left - * such that the resulting string is @p num_digits wide. - * If the given number is requires more than num_digits, then the number prevails. */ -template -C4_ALWAYS_INLINE size_t write_oct(substr buf, T val, size_t num_digits) noexcept -{ - return detail::write_num_digits>(buf, val, num_digits); -} - -C4_SUPPRESS_WARNING_GCC_POP - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -/** read a decimal integer from a string. This is the - * lowest level (and the fastest) function to do this task. - * @note does not accept negative numbers - * @note The string must be trimmed. Whitespace is not accepted. - * @note the string must not be empty - * @note there is no check for overflow; the value wraps around - * in a way similar to the standard C/C++ overflow behavior. - * For example, `read_dec("128", &val)` returns true - * and val will be set to 0 because 127 is the max i8 value. - * @see overflows() to find out if a number string overflows a type range - * @return true if the conversion was successful (no overflow check) */ -template -C4_ALWAYS_INLINE bool read_dec(csubstr s, I *C4_RESTRICT v) noexcept -{ - C4_STATIC_ASSERT(std::is_integral::value); - C4_ASSERT(!s.empty()); - *v = 0; - for(char c : s) - { - if(C4_UNLIKELY(c < '0' || c > '9')) - return false; - *v = (*v) * I(10) + (I(c) - I('0')); - } - return true; -} - -/** read an hexadecimal integer from a string. This is the - * lowest level (and the fastest) function to do this task. - * @note does not accept negative numbers - * @note does not accept leading 0x or 0X - * @note the string must not be empty - * @note the string must be trimmed. Whitespace is not accepted. - * @note there is no check for overflow; the value wraps around - * in a way similar to the standard C/C++ overflow behavior. - * For example, `read_hex("80", &val)` returns true - * and val will be set to 0 because 7f is the max i8 value. - * @see overflows() to find out if a number string overflows a type range - * @return true if the conversion was successful (no overflow check) */ -template -C4_ALWAYS_INLINE bool read_hex(csubstr s, I *C4_RESTRICT v) noexcept -{ - C4_STATIC_ASSERT(std::is_integral::value); - C4_ASSERT(!s.empty()); - *v = 0; - for(char c : s) - { - I cv; - if(c >= '0' && c <= '9') - cv = I(c) - I('0'); - else if(c >= 'a' && c <= 'f') - cv = I(10) + (I(c) - I('a')); - else if(c >= 'A' && c <= 'F') - cv = I(10) + (I(c) - I('A')); - else - return false; - *v = (*v) * I(16) + cv; - } - return true; -} - -/** read a binary integer from a string. This is the - * lowest level (and the fastest) function to do this task. - * @note does not accept negative numbers - * @note does not accept leading 0b or 0B - * @note the string must not be empty - * @note the string must be trimmed. Whitespace is not accepted. - * @note there is no check for overflow; the value wraps around - * in a way similar to the standard C/C++ overflow behavior. - * For example, `read_bin("10000000", &val)` returns true - * and val will be set to 0 because 1111111 is the max i8 value. - * @see overflows() to find out if a number string overflows a type range - * @return true if the conversion was successful (no overflow check) */ -template -C4_ALWAYS_INLINE bool read_bin(csubstr s, I *C4_RESTRICT v) noexcept -{ - C4_STATIC_ASSERT(std::is_integral::value); - C4_ASSERT(!s.empty()); - *v = 0; - for(char c : s) - { - *v <<= 1; - if(c == '1') - *v |= 1; - else if(c != '0') - return false; - } - return true; -} - -/** read an octal integer from a string. This is the - * lowest level (and the fastest) function to do this task. - * @note does not accept negative numbers - * @note does not accept leading 0o or 0O - * @note the string must not be empty - * @note the string must be trimmed. Whitespace is not accepted. - * @note there is no check for overflow; the value wraps around - * in a way similar to the standard C/C++ overflow behavior. - * For example, `read_oct("200", &val)` returns true - * and val will be set to 0 because 177 is the max i8 value. - * @see overflows() to find out if a number string overflows a type range - * @return true if the conversion was successful (no overflow check) */ -template -C4_ALWAYS_INLINE bool read_oct(csubstr s, I *C4_RESTRICT v) noexcept -{ - C4_STATIC_ASSERT(std::is_integral::value); - C4_ASSERT(!s.empty()); - *v = 0; - for(char c : s) - { - if(C4_UNLIKELY(c < '0' || c > '7')) - return false; - *v = (*v) * I(8) + (I(c) - I('0')); - } - return true; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -namespace detail { -inline size_t _itoa2buf(substr buf, size_t pos, csubstr val) noexcept -{ - C4_ASSERT(pos + val.len <= buf.len); - memcpy(buf.str + pos, val.str, val.len); - return pos + val.len; -} -inline size_t _itoa2bufwithdigits(substr buf, size_t pos, size_t num_digits, csubstr val) noexcept -{ - num_digits = num_digits > val.len ? num_digits - val.len : 0; - C4_ASSERT(num_digits + val.len <= buf.len); - for(size_t i = 0; i < num_digits; ++i) - _c4append('0'); - return detail::_itoa2buf(buf, pos, val); -} -template -C4_NO_INLINE size_t _itoadec2buf(substr buf) noexcept -{ - using digits_type = detail::charconv_digits; - if(C4_UNLIKELY(buf.len < digits_type::maxdigits_dec)) - return digits_type::maxdigits_dec; - buf.str[0] = '-'; - return detail::_itoa2buf(buf, 1, digits_type::min_value_dec()); -} -template -C4_NO_INLINE size_t _itoa2buf(substr buf, I radix) noexcept -{ - using digits_type = detail::charconv_digits; - size_t pos = 0; - if(C4_LIKELY(buf.len > 0)) - buf.str[pos++] = '-'; - switch(radix) - { - case I(10): - if(C4_UNLIKELY(buf.len < digits_type::maxdigits_dec)) - return digits_type::maxdigits_dec; - pos =_itoa2buf(buf, pos, digits_type::min_value_dec()); - break; - case I(16): - if(C4_UNLIKELY(buf.len < digits_type::maxdigits_hex)) - return digits_type::maxdigits_hex; - buf.str[pos++] = '0'; - buf.str[pos++] = 'x'; - pos = _itoa2buf(buf, pos, digits_type::min_value_hex()); - break; - case I( 2): - if(C4_UNLIKELY(buf.len < digits_type::maxdigits_bin)) - return digits_type::maxdigits_bin; - buf.str[pos++] = '0'; - buf.str[pos++] = 'b'; - pos = _itoa2buf(buf, pos, digits_type::min_value_bin()); - break; - case I( 8): - if(C4_UNLIKELY(buf.len < digits_type::maxdigits_oct)) - return digits_type::maxdigits_oct; - buf.str[pos++] = '0'; - buf.str[pos++] = 'o'; - pos = _itoa2buf(buf, pos, digits_type::min_value_oct()); - break; - } - return pos; -} -template -C4_NO_INLINE size_t _itoa2buf(substr buf, I radix, size_t num_digits) noexcept -{ - using digits_type = detail::charconv_digits; - size_t pos = 0; - size_t needed_digits = 0; - if(C4_LIKELY(buf.len > 0)) - buf.str[pos++] = '-'; - switch(radix) - { - case I(10): - // add 1 to account for - - needed_digits = num_digits+1 > digits_type::maxdigits_dec ? num_digits+1 : digits_type::maxdigits_dec; - if(C4_UNLIKELY(buf.len < needed_digits)) - return needed_digits; - pos = _itoa2bufwithdigits(buf, pos, num_digits, digits_type::min_value_dec()); - break; - case I(16): - // add 3 to account for -0x - needed_digits = num_digits+3 > digits_type::maxdigits_hex ? num_digits+3 : digits_type::maxdigits_hex; - if(C4_UNLIKELY(buf.len < needed_digits)) - return needed_digits; - buf.str[pos++] = '0'; - buf.str[pos++] = 'x'; - pos = _itoa2bufwithdigits(buf, pos, num_digits, digits_type::min_value_hex()); - break; - case I( 2): - // add 3 to account for -0b - needed_digits = num_digits+3 > digits_type::maxdigits_bin ? num_digits+3 : digits_type::maxdigits_bin; - if(C4_UNLIKELY(buf.len < needed_digits)) - return needed_digits; - C4_ASSERT(buf.len >= digits_type::maxdigits_bin); - buf.str[pos++] = '0'; - buf.str[pos++] = 'b'; - pos = _itoa2bufwithdigits(buf, pos, num_digits, digits_type::min_value_bin()); - break; - case I( 8): - // add 3 to account for -0o - needed_digits = num_digits+3 > digits_type::maxdigits_oct ? num_digits+3 : digits_type::maxdigits_oct; - if(C4_UNLIKELY(buf.len < needed_digits)) - return needed_digits; - C4_ASSERT(buf.len >= digits_type::maxdigits_oct); - buf.str[pos++] = '0'; - buf.str[pos++] = 'o'; - pos = _itoa2bufwithdigits(buf, pos, num_digits, digits_type::min_value_oct()); - break; - } - return pos; -} -} // namespace detail - - -/** convert an integral signed decimal to a string. - * @note the resulting string is NOT zero-terminated. - * @note it is ok to call this with an empty or too-small buffer; - * no writes will occur, and the needed size will be returned - * @return the number of characters required for the buffer. */ -template -C4_ALWAYS_INLINE size_t itoa(substr buf, T v) noexcept -{ - C4_STATIC_ASSERT(std::is_signed::value); - if(v >= T(0)) - { - // write_dec() checks the buffer size, so no need to check here - return write_dec(buf, v); - } - // when T is the min value (eg i8: -128), negating it - // will overflow, so treat the min as a special case - else if(C4_LIKELY(v != std::numeric_limits::min())) - { - v = -v; - unsigned digits = digits_dec(v); - if(C4_LIKELY(buf.len >= digits + 1u)) - { - buf.str[0] = '-'; - write_dec_unchecked(buf.sub(1), v, digits); - } - return digits + 1u; - } - return detail::_itoadec2buf(buf); -} - -/** convert an integral signed integer to a string, using a specific - * radix. The radix must be 2, 8, 10 or 16. - * - * @note the resulting string is NOT zero-terminated. - * @note it is ok to call this with an empty or too-small buffer; - * no writes will occur, and the needed size will be returned - * @return the number of characters required for the buffer. */ -template -C4_ALWAYS_INLINE size_t itoa(substr buf, T v, T radix) noexcept -{ - C4_STATIC_ASSERT(std::is_signed::value); - C4_ASSERT(radix == 2 || radix == 8 || radix == 10 || radix == 16); - C4_SUPPRESS_WARNING_GCC_PUSH - #if (defined(__GNUC__) && (__GNUC__ >= 7)) - C4_SUPPRESS_WARNING_GCC("-Wstringop-overflow") // gcc has a false positive here - #endif - // when T is the min value (eg i8: -128), negating it - // will overflow, so treat the min as a special case - if(C4_LIKELY(v != std::numeric_limits::min())) - { - unsigned pos = 0; - if(v < 0) - { - v = -v; - if(C4_LIKELY(buf.len > 0)) - buf.str[pos] = '-'; - ++pos; - } - unsigned digits = 0; - switch(radix) - { - case T(10): - digits = digits_dec(v); - if(C4_LIKELY(buf.len >= pos + digits)) - write_dec_unchecked(buf.sub(pos), v, digits); - break; - case T(16): - digits = digits_hex(v); - if(C4_LIKELY(buf.len >= pos + 2u + digits)) - { - buf.str[pos + 0] = '0'; - buf.str[pos + 1] = 'x'; - write_hex_unchecked(buf.sub(pos + 2), v, digits); - } - digits += 2u; - break; - case T(2): - digits = digits_bin(v); - if(C4_LIKELY(buf.len >= pos + 2u + digits)) - { - buf.str[pos + 0] = '0'; - buf.str[pos + 1] = 'b'; - write_bin_unchecked(buf.sub(pos + 2), v, digits); - } - digits += 2u; - break; - case T(8): - digits = digits_oct(v); - if(C4_LIKELY(buf.len >= pos + 2u + digits)) - { - buf.str[pos + 0] = '0'; - buf.str[pos + 1] = 'o'; - write_oct_unchecked(buf.sub(pos + 2), v, digits); - } - digits += 2u; - break; - } - return pos + digits; - } - C4_SUPPRESS_WARNING_GCC_POP - // when T is the min value (eg i8: -128), negating it - // will overflow - return detail::_itoa2buf(buf, radix); -} - - -/** same as c4::itoa(), but pad with zeroes on the left such that the - * resulting string is @p num_digits wide, not accounting for radix - * prefix (0x,0o,0b). The @p radix must be 2, 8, 10 or 16. - * - * @note the resulting string is NOT zero-terminated. - * @note it is ok to call this with an empty or too-small buffer; - * no writes will occur, and the needed size will be returned - * @return the number of characters required for the buffer. */ -template -C4_ALWAYS_INLINE size_t itoa(substr buf, T v, T radix, size_t num_digits) noexcept -{ - C4_STATIC_ASSERT(std::is_signed::value); - C4_ASSERT(radix == 2 || radix == 8 || radix == 10 || radix == 16); - C4_SUPPRESS_WARNING_GCC_PUSH - #if (defined(__GNUC__) && (__GNUC__ >= 7)) - C4_SUPPRESS_WARNING_GCC("-Wstringop-overflow") // gcc has a false positive here - #endif - // when T is the min value (eg i8: -128), negating it - // will overflow, so treat the min as a special case - if(C4_LIKELY(v != std::numeric_limits::min())) - { - unsigned pos = 0; - if(v < 0) - { - v = -v; - if(C4_LIKELY(buf.len > 0)) - buf.str[pos] = '-'; - ++pos; - } - unsigned total_digits = 0; - switch(radix) - { - case T(10): - total_digits = digits_dec(v); - total_digits = pos + (unsigned)(num_digits > total_digits ? num_digits : total_digits); - if(C4_LIKELY(buf.len >= total_digits)) - write_dec(buf.sub(pos), v, num_digits); - break; - case T(16): - total_digits = digits_hex(v); - total_digits = pos + 2u + (unsigned)(num_digits > total_digits ? num_digits : total_digits); - if(C4_LIKELY(buf.len >= total_digits)) - { - buf.str[pos + 0] = '0'; - buf.str[pos + 1] = 'x'; - write_hex(buf.sub(pos + 2), v, num_digits); - } - break; - case T(2): - total_digits = digits_bin(v); - total_digits = pos + 2u + (unsigned)(num_digits > total_digits ? num_digits : total_digits); - if(C4_LIKELY(buf.len >= total_digits)) - { - buf.str[pos + 0] = '0'; - buf.str[pos + 1] = 'b'; - write_bin(buf.sub(pos + 2), v, num_digits); - } - break; - case T(8): - total_digits = digits_oct(v); - total_digits = pos + 2u + (unsigned)(num_digits > total_digits ? num_digits : total_digits); - if(C4_LIKELY(buf.len >= total_digits)) - { - buf.str[pos + 0] = '0'; - buf.str[pos + 1] = 'o'; - write_oct(buf.sub(pos + 2), v, num_digits); - } - break; - } - return total_digits; - } - C4_SUPPRESS_WARNING_GCC_POP - // when T is the min value (eg i8: -128), negating it - // will overflow - return detail::_itoa2buf(buf, radix, num_digits); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -/** convert an integral unsigned decimal to a string. - * - * @note the resulting string is NOT zero-terminated. - * @note it is ok to call this with an empty or too-small buffer; - * no writes will occur, and the needed size will be returned - * @return the number of characters required for the buffer. */ -template -C4_ALWAYS_INLINE size_t utoa(substr buf, T v) noexcept -{ - C4_STATIC_ASSERT(std::is_unsigned::value); - // write_dec() does the buffer length check, so no need to check here - return write_dec(buf, v); -} - -/** convert an integral unsigned integer to a string, using a specific - * radix. The radix must be 2, 8, 10 or 16. - * - * @note the resulting string is NOT zero-terminated. - * @note it is ok to call this with an empty or too-small buffer; - * no writes will occur, and the needed size will be returned - * @return the number of characters required for the buffer. */ -template -C4_ALWAYS_INLINE size_t utoa(substr buf, T v, T radix) noexcept -{ - C4_STATIC_ASSERT(std::is_unsigned::value); - C4_ASSERT(radix == 10 || radix == 16 || radix == 2 || radix == 8); - unsigned digits = 0; - switch(radix) - { - case T(10): - digits = digits_dec(v); - if(C4_LIKELY(buf.len >= digits)) - write_dec_unchecked(buf, v, digits); - break; - case T(16): - digits = digits_hex(v); - if(C4_LIKELY(buf.len >= digits+2u)) - { - buf.str[0] = '0'; - buf.str[1] = 'x'; - write_hex_unchecked(buf.sub(2), v, digits); - } - digits += 2u; - break; - case T(2): - digits = digits_bin(v); - if(C4_LIKELY(buf.len >= digits+2u)) - { - buf.str[0] = '0'; - buf.str[1] = 'b'; - write_bin_unchecked(buf.sub(2), v, digits); - } - digits += 2u; - break; - case T(8): - digits = digits_oct(v); - if(C4_LIKELY(buf.len >= digits+2u)) - { - buf.str[0] = '0'; - buf.str[1] = 'o'; - write_oct_unchecked(buf.sub(2), v, digits); - } - digits += 2u; - break; - } - return digits; -} - -/** same as c4::utoa(), but pad with zeroes on the left such that the - * resulting string is @p num_digits wide. The @p radix must be 2, - * 8, 10 or 16. - * - * @note the resulting string is NOT zero-terminated. - * @note it is ok to call this with an empty or too-small buffer; - * no writes will occur, and the needed size will be returned - * @return the number of characters required for the buffer. */ -template -C4_ALWAYS_INLINE size_t utoa(substr buf, T v, T radix, size_t num_digits) noexcept -{ - C4_STATIC_ASSERT(std::is_unsigned::value); - C4_ASSERT(radix == 10 || radix == 16 || radix == 2 || radix == 8); - unsigned total_digits = 0; - switch(radix) - { - case T(10): - total_digits = digits_dec(v); - total_digits = (unsigned)(num_digits > total_digits ? num_digits : total_digits); - if(C4_LIKELY(buf.len >= total_digits)) - write_dec(buf, v, num_digits); - break; - case T(16): - total_digits = digits_hex(v); - total_digits = 2u + (unsigned)(num_digits > total_digits ? num_digits : total_digits); - if(C4_LIKELY(buf.len >= total_digits)) - { - buf.str[0] = '0'; - buf.str[1] = 'x'; - write_hex(buf.sub(2), v, num_digits); - } - break; - case T(2): - total_digits = digits_bin(v); - total_digits = 2u + (unsigned)(num_digits > total_digits ? num_digits : total_digits); - if(C4_LIKELY(buf.len >= total_digits)) - { - buf.str[0] = '0'; - buf.str[1] = 'b'; - write_bin(buf.sub(2), v, num_digits); - } - break; - case T(8): - total_digits = digits_oct(v); - total_digits = 2u + (unsigned)(num_digits > total_digits ? num_digits : total_digits); - if(C4_LIKELY(buf.len >= total_digits)) - { - buf.str[0] = '0'; - buf.str[1] = 'o'; - write_oct(buf.sub(2), v, num_digits); - } - break; - } - return total_digits; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -/** Convert a trimmed string to a signed integral value. The input - * string can be formatted as decimal, binary (prefix 0b or 0B), octal - * (prefix 0o or 0O) or hexadecimal (prefix 0x or 0X). Strings with - * leading zeroes are considered as decimal and not octal (unlike the - * C/C++ convention). Every character in the input string is read for - * the conversion; the input string must not contain any leading or - * trailing whitespace. - * - * @return true if the conversion was successful. - * - * @note overflow is not detected: the return status is true even if - * the conversion would return a value outside of the type's range, in - * which case the result will wrap around the type's range. - * This is similar to native behavior. - * - * @note a positive sign is not accepted. ie, the string must not - * start with '+' - * - * @see atoi_first() if the string is not trimmed to the value to read. */ -template -C4_ALWAYS_INLINE bool atoi(csubstr str, T * C4_RESTRICT v) noexcept -{ - C4_STATIC_ASSERT(std::is_integral::value); - C4_STATIC_ASSERT(std::is_signed::value); - - if(C4_UNLIKELY(str.len == 0)) - return false; - - C4_ASSERT(str.str[0] != '+'); - - T sign = 1; - size_t start = 0; - if(str.str[0] == '-') - { - if(C4_UNLIKELY(str.len == ++start)) - return false; - sign = -1; - } - - bool parsed_ok = true; - if(str.str[start] != '0') // this should be the common case, so put it first - { - parsed_ok = read_dec(str.sub(start), v); - } - else if(str.len > start + 1) - { - // starts with 0: is it 0x, 0o, 0b? - const char pfx = str.str[start + 1]; - if(pfx == 'x' || pfx == 'X') - parsed_ok = str.len > start + 2 && read_hex(str.sub(start + 2), v); - else if(pfx == 'b' || pfx == 'B') - parsed_ok = str.len > start + 2 && read_bin(str.sub(start + 2), v); - else if(pfx == 'o' || pfx == 'O') - parsed_ok = str.len > start + 2 && read_oct(str.sub(start + 2), v); - else - parsed_ok = read_dec(str.sub(start + 1), v); - } - else - { - parsed_ok = read_dec(str.sub(start), v); - } - if(C4_LIKELY(parsed_ok)) - *v *= sign; - return parsed_ok; -} - - -/** Select the next range of characters in the string that can be parsed - * as a signed integral value, and convert it using atoi(). Leading - * whitespace (space, newline, tabs) is skipped. - * @return the number of characters read for conversion, or csubstr::npos if the conversion failed - * @see atoi() if the string is already trimmed to the value to read. - * @see csubstr::first_int_span() */ -template -C4_ALWAYS_INLINE size_t atoi_first(csubstr str, T * C4_RESTRICT v) -{ - csubstr trimmed = str.first_int_span(); - if(trimmed.len == 0) - return csubstr::npos; - if(atoi(trimmed, v)) - return static_cast(trimmed.end() - str.begin()); - return csubstr::npos; -} - - -//----------------------------------------------------------------------------- - -/** Convert a trimmed string to an unsigned integral value. The string can be - * formatted as decimal, binary (prefix 0b or 0B), octal (prefix 0o or 0O) - * or hexadecimal (prefix 0x or 0X). Every character in the input string is read - * for the conversion; it must not contain any leading or trailing whitespace. - * - * @return true if the conversion was successful. - * - * @note overflow is not detected: the return status is true even if - * the conversion would return a value outside of the type's range, in - * which case the result will wrap around the type's range. - * - * @note If the string has a minus character, the return status - * will be false. - * - * @see atou_first() if the string is not trimmed to the value to read. */ -template -bool atou(csubstr str, T * C4_RESTRICT v) noexcept -{ - C4_STATIC_ASSERT(std::is_integral::value); - - if(C4_UNLIKELY(str.len == 0 || str.front() == '-')) - return false; - - bool parsed_ok = true; - if(str.str[0] != '0') - { - parsed_ok = read_dec(str, v); - } - else - { - if(str.len > 1) - { - const char pfx = str.str[1]; - if(pfx == 'x' || pfx == 'X') - parsed_ok = str.len > 2 && read_hex(str.sub(2), v); - else if(pfx == 'b' || pfx == 'B') - parsed_ok = str.len > 2 && read_bin(str.sub(2), v); - else if(pfx == 'o' || pfx == 'O') - parsed_ok = str.len > 2 && read_oct(str.sub(2), v); - else - parsed_ok = read_dec(str, v); - } - else - { - *v = 0; // we know the first character is 0 - } - } - return parsed_ok; -} - - -/** Select the next range of characters in the string that can be parsed - * as an unsigned integral value, and convert it using atou(). Leading - * whitespace (space, newline, tabs) is skipped. - * @return the number of characters read for conversion, or csubstr::npos if the conversion faileds - * @see atou() if the string is already trimmed to the value to read. - * @see csubstr::first_uint_span() */ -template -C4_ALWAYS_INLINE size_t atou_first(csubstr str, T *v) -{ - csubstr trimmed = str.first_uint_span(); - if(trimmed.len == 0) - return csubstr::npos; - if(atou(trimmed, v)) - return static_cast(trimmed.end() - str.begin()); - return csubstr::npos; -} - - -#ifdef _MSC_VER -# pragma warning(pop) -#elif defined(__clang__) -# pragma clang diagnostic pop -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#endif - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -namespace detail { -inline bool check_overflow(csubstr str, csubstr limit) noexcept -{ - if(str.len == limit.len) - { - for(size_t i = 0; i < limit.len; ++i) - { - if(str[i] < limit[i]) - return false; - else if(str[i] > limit[i]) - return true; - } - return false; - } - else - return str.len > limit.len; -} -} // namespace detail - - -/** Test if the following string would overflow when converted to associated - * types. - * @return true if number will overflow, false if it fits (or doesn't parse) - */ -template -auto overflows(csubstr str) noexcept - -> typename std::enable_if::value, bool>::type -{ - C4_STATIC_ASSERT(std::is_integral::value); - - if(C4_UNLIKELY(str.len == 0)) - { - return false; - } - else if(str.str[0] == '0') - { - if (str.len == 1) - return false; - switch (str.str[1]) - { - case 'x': - case 'X': - { - size_t fno = str.first_not_of('0', 2); - if (fno == csubstr::npos) - return false; - return !(str.len <= fno + (sizeof(T) * 2)); - } - case 'b': - case 'B': - { - size_t fno = str.first_not_of('0', 2); - if (fno == csubstr::npos) - return false; - return !(str.len <= fno +(sizeof(T) * 8)); - } - case 'o': - case 'O': - { - size_t fno = str.first_not_of('0', 2); - if(fno == csubstr::npos) - return false; - return detail::charconv_digits::is_oct_overflow(str.sub(fno)); - } - default: - { - size_t fno = str.first_not_of('0', 1); - if(fno == csubstr::npos) - return false; - return detail::check_overflow(str.sub(fno), detail::charconv_digits::max_value_dec()); - } - } - } - else if(C4_UNLIKELY(str[0] == '-')) - { - return true; - } - else - { - return detail::check_overflow(str, detail::charconv_digits::max_value_dec()); - } -} - - -/** Test if the following string would overflow when converted to associated - * types. - * @return true if number will overflow, false if it fits (or doesn't parse) - */ -template -auto overflows(csubstr str) - -> typename std::enable_if::value, bool>::type -{ - C4_STATIC_ASSERT(std::is_integral::value); - if(C4_UNLIKELY(str.len == 0)) - return false; - if(str.str[0] == '-') - { - if(str.str[1] == '0') - { - if(str.len == 2) - return false; - switch(str.str[2]) - { - case 'x': - case 'X': - { - size_t fno = str.first_not_of('0', 3); - if (fno == csubstr::npos) - return false; - return detail::check_overflow(str.sub(fno), detail::charconv_digits::min_value_hex()); - } - case 'b': - case 'B': - { - size_t fno = str.first_not_of('0', 3); - if (fno == csubstr::npos) - return false; - return detail::check_overflow(str.sub(fno), detail::charconv_digits::min_value_bin()); - } - case 'o': - case 'O': - { - size_t fno = str.first_not_of('0', 3); - if(fno == csubstr::npos) - return false; - return detail::check_overflow(str.sub(fno), detail::charconv_digits::min_value_oct()); - } - default: - { - size_t fno = str.first_not_of('0', 2); - if(fno == csubstr::npos) - return false; - return detail::check_overflow(str.sub(fno), detail::charconv_digits::min_value_dec()); - } - } - } - else - return detail::check_overflow(str.sub(1), detail::charconv_digits::min_value_dec()); - } - else if(str.str[0] == '0') - { - if (str.len == 1) - return false; - switch(str.str[1]) - { - case 'x': - case 'X': - { - size_t fno = str.first_not_of('0', 2); - if (fno == csubstr::npos) - return false; - const size_t len = str.len - fno; - return !((len < sizeof (T) * 2) || (len == sizeof(T) * 2 && str[fno] <= '7')); - } - case 'b': - case 'B': - { - size_t fno = str.first_not_of('0', 2); - if (fno == csubstr::npos) - return false; - return !(str.len <= fno + (sizeof(T) * 8 - 1)); - } - case 'o': - case 'O': - { - size_t fno = str.first_not_of('0', 2); - if(fno == csubstr::npos) - return false; - return detail::charconv_digits::is_oct_overflow(str.sub(fno)); - } - default: - { - size_t fno = str.first_not_of('0', 1); - if(fno == csubstr::npos) - return false; - return detail::check_overflow(str.sub(fno), detail::charconv_digits::max_value_dec()); - } - } - } - else - return detail::check_overflow(str, detail::charconv_digits::max_value_dec()); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -namespace detail { - - -#if (!C4CORE_HAVE_STD_FROMCHARS) -/** @see http://www.exploringbinary.com/ for many good examples on float-str conversion */ -template -void get_real_format_str(char (& C4_RESTRICT fmt)[N], int precision, RealFormat_e formatting, const char* length_modifier="") -{ - int iret; - if(precision == -1) - iret = snprintf(fmt, sizeof(fmt), "%%%s%c", length_modifier, formatting); - else if(precision == 0) - iret = snprintf(fmt, sizeof(fmt), "%%.%s%c", length_modifier, formatting); - else - iret = snprintf(fmt, sizeof(fmt), "%%.%d%s%c", precision, length_modifier, formatting); - C4_ASSERT(iret >= 2 && size_t(iret) < sizeof(fmt)); - C4_UNUSED(iret); -} - - -/** @todo we're depending on snprintf()/sscanf() for converting to/from - * floating point numbers. Apparently, this increases the binary size - * by a considerable amount. There are some lightweight printf - * implementations: - * - * @see http://www.sparetimelabs.com/tinyprintf/tinyprintf.php (BSD) - * @see https://github.com/weiss/c99-snprintf - * @see https://github.com/nothings/stb/blob/master/stb_sprintf.h - * @see http://www.exploringbinary.com/ - * @see https://blog.benoitblanchon.fr/lightweight-float-to-string/ - * @see http://www.ryanjuckett.com/programming/printing-floating-point-numbers/ - */ -template -size_t print_one(substr str, const char* full_fmt, T v) -{ -#ifdef _MSC_VER - /** use _snprintf() to prevent early termination of the output - * for writing the null character at the last position - * @see https://msdn.microsoft.com/en-us/library/2ts7cx93.aspx */ - int iret = _snprintf(str.str, str.len, full_fmt, v); - if(iret < 0) - { - /* when buf.len is not enough, VS returns a negative value. - * so call it again with a negative value for getting an - * actual length of the string */ - iret = snprintf(nullptr, 0, full_fmt, v); - C4_ASSERT(iret > 0); - } - size_t ret = (size_t) iret; - return ret; -#else - int iret = snprintf(str.str, str.len, full_fmt, v); - C4_ASSERT(iret >= 0); - size_t ret = (size_t) iret; - if(ret >= str.len) - ++ret; /* snprintf() reserves the last character to write \0 */ - return ret; -#endif -} -#endif // (!C4CORE_HAVE_STD_FROMCHARS) - - -#if (!C4CORE_HAVE_STD_FROMCHARS) && (!C4CORE_HAVE_FAST_FLOAT) -/** scans a string using the given type format, while at the same time - * allowing non-null-terminated strings AND guaranteeing that the given - * string length is strictly respected, so that no buffer overflows - * might occur. */ -template -inline size_t scan_one(csubstr str, const char *type_fmt, T *v) -{ - /* snscanf() is absolutely needed here as we must be sure that - * str.len is strictly respected, because substr is - * generally not null-terminated. - * - * Alas, there is no snscanf(). - * - * So we fake it by using a dynamic format with an explicit - * field size set to the length of the given span. - * This trick is taken from: - * https://stackoverflow.com/a/18368910/5875572 */ - - /* this is the actual format we'll use for scanning */ - char fmt[16]; - - /* write the length into it. Eg "%12f". - * Also, get the number of characters read from the string. - * So the final format ends up as "%12f%n"*/ - int iret = std::snprintf(fmt, sizeof(fmt), "%%" "%zu" "%s" "%%n", str.len, type_fmt); - /* no nasty surprises, please! */ - C4_ASSERT(iret >= 0 && size_t(iret) < C4_COUNTOF(fmt)); - - /* now we scan with confidence that the span length is respected */ - int num_chars; - iret = std::sscanf(str.str, fmt, v, &num_chars); - /* scanf returns the number of successful conversions */ - if(iret != 1) return csubstr::npos; - C4_ASSERT(num_chars >= 0); - return (size_t)(num_chars); -} -#endif // (!C4CORE_HAVE_STD_FROMCHARS) && (!C4CORE_HAVE_FAST_FLOAT) - - -#if C4CORE_HAVE_STD_TOCHARS -template -C4_ALWAYS_INLINE size_t rtoa(substr buf, T v, int precision=-1, RealFormat_e formatting=FTOA_FLEX) noexcept -{ - std::to_chars_result result; - size_t pos = 0; - if(formatting == FTOA_HEXA) - { - if(buf.len > size_t(2)) - { - buf.str[0] = '0'; - buf.str[1] = 'x'; - } - pos += size_t(2); - } - if(precision == -1) - result = std::to_chars(buf.str + pos, buf.str + buf.len, v, (std::chars_format)formatting); - else - result = std::to_chars(buf.str + pos, buf.str + buf.len, v, (std::chars_format)formatting, precision); - if(result.ec == std::errc()) - { - // all good, no errors. - C4_ASSERT(result.ptr >= buf.str); - ptrdiff_t delta = result.ptr - buf.str; - return static_cast(delta); - } - C4_ASSERT(result.ec == std::errc::value_too_large); - // This is unfortunate. - // - // When the result can't fit in the given buffer, - // std::to_chars() returns the end pointer it was originally - // given, which is useless because here we would like to know - // _exactly_ how many characters the buffer must have to fit - // the result. - // - // So we take the pessimistic view, and assume as many digits - // as could ever be required: - size_t ret = static_cast(std::numeric_limits::max_digits10); - return ret > buf.len ? ret : buf.len + 1; -} -#endif // C4CORE_HAVE_STD_TOCHARS - - -#if C4CORE_HAVE_FAST_FLOAT -template -C4_ALWAYS_INLINE bool scan_rhex(csubstr s, T *C4_RESTRICT val) noexcept -{ - C4_ASSERT(s.len > 0); - C4_ASSERT(s.str[0] != '-'); - C4_ASSERT(s.str[0] != '+'); - C4_ASSERT(!s.begins_with("0x")); - C4_ASSERT(!s.begins_with("0X")); - size_t pos = 0; - // integer part - for( ; pos < s.len; ++pos) - { - const char c = s.str[pos]; - if(c >= '0' && c <= '9') - *val = *val * T(16) + T(c - '0'); - else if(c >= 'a' && c <= 'f') - *val = *val * T(16) + T(c - 'a'); - else if(c >= 'A' && c <= 'F') - *val = *val * T(16) + T(c - 'A'); - else if(c == '.') - { - ++pos; - break; // follow on to mantissa - } - else if(c == 'p' || c == 'P') - { - ++pos; - goto power; // no mantissa given, jump to power - } - else - { - return false; - } - } - // mantissa - { - // 0.0625 == 1/16 == value of first digit after the comma - for(T digit = T(0.0625); pos < s.len; ++pos, digit /= T(16)) - { - const char c = s.str[pos]; - if(c >= '0' && c <= '9') - *val += digit * T(c - '0'); - else if(c >= 'a' && c <= 'f') - *val += digit * T(c - 'a'); - else if(c >= 'A' && c <= 'F') - *val += digit * T(c - 'A'); - else if(c == 'p' || c == 'P') - { - ++pos; - goto power; // mantissa finished, jump to power - } - else - { - return false; - } - } - } - return true; -power: - if(C4_LIKELY(pos < s.len)) - { - if(s.str[pos] == '+') // atoi() cannot handle a leading '+' - ++pos; - if(C4_LIKELY(pos < s.len)) - { - int16_t powval = {}; - if(C4_LIKELY(atoi(s.sub(pos), &powval))) - { - *val *= ipow(powval); - return true; - } - } - } - return false; -} -#endif - -} // namespace detail - - -#undef _c4appendhex -#undef _c4append - - -/** Convert a single-precision real number to string. The string will - * in general be NOT null-terminated. For FTOA_FLEX, \p precision is - * the number of significand digits. Otherwise \p precision is the - * number of decimals. It is safe to call this function with an empty - * or too-small buffer. - * - * @return the size of the buffer needed to write the number - */ -C4_ALWAYS_INLINE size_t ftoa(substr str, float v, int precision=-1, RealFormat_e formatting=FTOA_FLEX) noexcept -{ -#if C4CORE_HAVE_STD_TOCHARS - return detail::rtoa(str, v, precision, formatting); -#else - char fmt[16]; - detail::get_real_format_str(fmt, precision, formatting, /*length_modifier*/""); - return detail::print_one(str, fmt, v); -#endif -} - - -/** Convert a double-precision real number to string. The string will - * in general be NOT null-terminated. For FTOA_FLEX, \p precision is - * the number of significand digits. Otherwise \p precision is the - * number of decimals. It is safe to call this function with an empty - * or too-small buffer. - * - * @return the size of the buffer needed to write the number - */ -C4_ALWAYS_INLINE size_t dtoa(substr str, double v, int precision=-1, RealFormat_e formatting=FTOA_FLEX) noexcept -{ -#if C4CORE_HAVE_STD_TOCHARS - return detail::rtoa(str, v, precision, formatting); -#else - char fmt[16]; - detail::get_real_format_str(fmt, precision, formatting, /*length_modifier*/"l"); - return detail::print_one(str, fmt, v); -#endif -} - - -/** Convert a string to a single precision real number. - * The input string must be trimmed to the value, ie - * no leading or trailing whitespace can be present. - * @return true iff the conversion succeeded - * @see atof_first() if the string is not trimmed - */ -C4_ALWAYS_INLINE bool atof(csubstr str, float * C4_RESTRICT v) noexcept -{ - C4_ASSERT(str.len > 0); - C4_ASSERT(str.triml(" \r\t\n").len == str.len); -#if C4CORE_HAVE_FAST_FLOAT - // fastfloat cannot parse hexadecimal floats - bool isneg = (str.str[0] == '-'); - csubstr rem = str.sub(isneg || str.str[0] == '+'); - if(!(rem.len >= 2 && (rem.str[0] == '0' && (rem.str[1] == 'x' || rem.str[1] == 'X')))) - { - fast_float::from_chars_result result; - result = fast_float::from_chars(str.str, str.str + str.len, *v); - return result.ec == std::errc(); - } - else if(detail::scan_rhex(rem.sub(2), v)) - { - *v *= isneg ? -1.f : 1.f; - return true; - } - return false; -#elif C4CORE_HAVE_STD_FROMCHARS - std::from_chars_result result; - result = std::from_chars(str.str, str.str + str.len, *v); - return result.ec == std::errc(); -#else - csubstr rem = str.sub(str.str[0] == '-' || str.str[0] == '+'); - if(!(rem.len >= 2 && (rem.str[0] == '0' && (rem.str[1] == 'x' || rem.str[1] == 'X')))) - return detail::scan_one(str, "f", v) != csubstr::npos; - else - return detail::scan_one(str, "a", v) != csubstr::npos; -#endif -} - - -/** Convert a string to a double precision real number. - * The input string must be trimmed to the value, ie - * no leading or trailing whitespace can be present. - * @return true iff the conversion succeeded - * @see atod_first() if the string is not trimmed - */ -C4_ALWAYS_INLINE bool atod(csubstr str, double * C4_RESTRICT v) noexcept -{ - C4_ASSERT(str.triml(" \r\t\n").len == str.len); -#if C4CORE_HAVE_FAST_FLOAT - // fastfloat cannot parse hexadecimal floats - bool isneg = (str.str[0] == '-'); - csubstr rem = str.sub(isneg || str.str[0] == '+'); - if(!(rem.len >= 2 && (rem.str[0] == '0' && (rem.str[1] == 'x' || rem.str[1] == 'X')))) - { - fast_float::from_chars_result result; - result = fast_float::from_chars(str.str, str.str + str.len, *v); - return result.ec == std::errc(); - } - else if(detail::scan_rhex(rem.sub(2), v)) - { - *v *= isneg ? -1. : 1.; - return true; - } - return false; -#elif C4CORE_HAVE_STD_FROMCHARS - std::from_chars_result result; - result = std::from_chars(str.str, str.str + str.len, *v); - return result.ec == std::errc(); -#else - csubstr rem = str.sub(str.str[0] == '-' || str.str[0] == '+'); - if(!(rem.len >= 2 && (rem.str[0] == '0' && (rem.str[1] == 'x' || rem.str[1] == 'X')))) - return detail::scan_one(str, "lf", v) != csubstr::npos; - else - return detail::scan_one(str, "la", v) != csubstr::npos; -#endif -} - - -/** Convert a string to a single precision real number. - * Leading whitespace is skipped until valid characters are found. - * @return the number of characters read from the string, or npos if - * conversion was not successful or if the string was empty */ -inline size_t atof_first(csubstr str, float * C4_RESTRICT v) noexcept -{ - csubstr trimmed = str.first_real_span(); - if(trimmed.len == 0) - return csubstr::npos; - if(atof(trimmed, v)) - return static_cast(trimmed.end() - str.begin()); - return csubstr::npos; -} - - -/** Convert a string to a double precision real number. - * Leading whitespace is skipped until valid characters are found. - * @return the number of characters read from the string, or npos if - * conversion was not successful or if the string was empty */ -inline size_t atod_first(csubstr str, double * C4_RESTRICT v) noexcept -{ - csubstr trimmed = str.first_real_span(); - if(trimmed.len == 0) - return csubstr::npos; - if(atod(trimmed, v)) - return static_cast(trimmed.end() - str.begin()); - return csubstr::npos; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// generic versions - -C4_ALWAYS_INLINE size_t xtoa(substr s, uint8_t v) noexcept { return write_dec(s, v); } -C4_ALWAYS_INLINE size_t xtoa(substr s, uint16_t v) noexcept { return write_dec(s, v); } -C4_ALWAYS_INLINE size_t xtoa(substr s, uint32_t v) noexcept { return write_dec(s, v); } -C4_ALWAYS_INLINE size_t xtoa(substr s, uint64_t v) noexcept { return write_dec(s, v); } -C4_ALWAYS_INLINE size_t xtoa(substr s, int8_t v) noexcept { return itoa(s, v); } -C4_ALWAYS_INLINE size_t xtoa(substr s, int16_t v) noexcept { return itoa(s, v); } -C4_ALWAYS_INLINE size_t xtoa(substr s, int32_t v) noexcept { return itoa(s, v); } -C4_ALWAYS_INLINE size_t xtoa(substr s, int64_t v) noexcept { return itoa(s, v); } -C4_ALWAYS_INLINE size_t xtoa(substr s, float v) noexcept { return ftoa(s, v); } -C4_ALWAYS_INLINE size_t xtoa(substr s, double v) noexcept { return dtoa(s, v); } - -C4_ALWAYS_INLINE size_t xtoa(substr s, uint8_t v, uint8_t radix) noexcept { return utoa(s, v, radix); } -C4_ALWAYS_INLINE size_t xtoa(substr s, uint16_t v, uint16_t radix) noexcept { return utoa(s, v, radix); } -C4_ALWAYS_INLINE size_t xtoa(substr s, uint32_t v, uint32_t radix) noexcept { return utoa(s, v, radix); } -C4_ALWAYS_INLINE size_t xtoa(substr s, uint64_t v, uint64_t radix) noexcept { return utoa(s, v, radix); } -C4_ALWAYS_INLINE size_t xtoa(substr s, int8_t v, int8_t radix) noexcept { return itoa(s, v, radix); } -C4_ALWAYS_INLINE size_t xtoa(substr s, int16_t v, int16_t radix) noexcept { return itoa(s, v, radix); } -C4_ALWAYS_INLINE size_t xtoa(substr s, int32_t v, int32_t radix) noexcept { return itoa(s, v, radix); } -C4_ALWAYS_INLINE size_t xtoa(substr s, int64_t v, int64_t radix) noexcept { return itoa(s, v, radix); } - -C4_ALWAYS_INLINE size_t xtoa(substr s, uint8_t v, uint8_t radix, size_t num_digits) noexcept { return utoa(s, v, radix, num_digits); } -C4_ALWAYS_INLINE size_t xtoa(substr s, uint16_t v, uint16_t radix, size_t num_digits) noexcept { return utoa(s, v, radix, num_digits); } -C4_ALWAYS_INLINE size_t xtoa(substr s, uint32_t v, uint32_t radix, size_t num_digits) noexcept { return utoa(s, v, radix, num_digits); } -C4_ALWAYS_INLINE size_t xtoa(substr s, uint64_t v, uint64_t radix, size_t num_digits) noexcept { return utoa(s, v, radix, num_digits); } -C4_ALWAYS_INLINE size_t xtoa(substr s, int8_t v, int8_t radix, size_t num_digits) noexcept { return itoa(s, v, radix, num_digits); } -C4_ALWAYS_INLINE size_t xtoa(substr s, int16_t v, int16_t radix, size_t num_digits) noexcept { return itoa(s, v, radix, num_digits); } -C4_ALWAYS_INLINE size_t xtoa(substr s, int32_t v, int32_t radix, size_t num_digits) noexcept { return itoa(s, v, radix, num_digits); } -C4_ALWAYS_INLINE size_t xtoa(substr s, int64_t v, int64_t radix, size_t num_digits) noexcept { return itoa(s, v, radix, num_digits); } - -C4_ALWAYS_INLINE size_t xtoa(substr s, float v, int precision, RealFormat_e formatting=FTOA_FLEX) noexcept { return ftoa(s, v, precision, formatting); } -C4_ALWAYS_INLINE size_t xtoa(substr s, double v, int precision, RealFormat_e formatting=FTOA_FLEX) noexcept { return dtoa(s, v, precision, formatting); } - -C4_ALWAYS_INLINE bool atox(csubstr s, uint8_t *C4_RESTRICT v) noexcept { return atou(s, v); } -C4_ALWAYS_INLINE bool atox(csubstr s, uint16_t *C4_RESTRICT v) noexcept { return atou(s, v); } -C4_ALWAYS_INLINE bool atox(csubstr s, uint32_t *C4_RESTRICT v) noexcept { return atou(s, v); } -C4_ALWAYS_INLINE bool atox(csubstr s, uint64_t *C4_RESTRICT v) noexcept { return atou(s, v); } -C4_ALWAYS_INLINE bool atox(csubstr s, int8_t *C4_RESTRICT v) noexcept { return atoi(s, v); } -C4_ALWAYS_INLINE bool atox(csubstr s, int16_t *C4_RESTRICT v) noexcept { return atoi(s, v); } -C4_ALWAYS_INLINE bool atox(csubstr s, int32_t *C4_RESTRICT v) noexcept { return atoi(s, v); } -C4_ALWAYS_INLINE bool atox(csubstr s, int64_t *C4_RESTRICT v) noexcept { return atoi(s, v); } -C4_ALWAYS_INLINE bool atox(csubstr s, float *C4_RESTRICT v) noexcept { return atof(s, v); } -C4_ALWAYS_INLINE bool atox(csubstr s, double *C4_RESTRICT v) noexcept { return atod(s, v); } - -C4_ALWAYS_INLINE size_t to_chars(substr buf, uint8_t v) noexcept { return write_dec(buf, v); } -C4_ALWAYS_INLINE size_t to_chars(substr buf, uint16_t v) noexcept { return write_dec(buf, v); } -C4_ALWAYS_INLINE size_t to_chars(substr buf, uint32_t v) noexcept { return write_dec(buf, v); } -C4_ALWAYS_INLINE size_t to_chars(substr buf, uint64_t v) noexcept { return write_dec(buf, v); } -C4_ALWAYS_INLINE size_t to_chars(substr buf, int8_t v) noexcept { return itoa(buf, v); } -C4_ALWAYS_INLINE size_t to_chars(substr buf, int16_t v) noexcept { return itoa(buf, v); } -C4_ALWAYS_INLINE size_t to_chars(substr buf, int32_t v) noexcept { return itoa(buf, v); } -C4_ALWAYS_INLINE size_t to_chars(substr buf, int64_t v) noexcept { return itoa(buf, v); } -C4_ALWAYS_INLINE size_t to_chars(substr buf, float v) noexcept { return ftoa(buf, v); } -C4_ALWAYS_INLINE size_t to_chars(substr buf, double v) noexcept { return dtoa(buf, v); } - -C4_ALWAYS_INLINE bool from_chars(csubstr buf, uint8_t *C4_RESTRICT v) noexcept { return atou(buf, v); } -C4_ALWAYS_INLINE bool from_chars(csubstr buf, uint16_t *C4_RESTRICT v) noexcept { return atou(buf, v); } -C4_ALWAYS_INLINE bool from_chars(csubstr buf, uint32_t *C4_RESTRICT v) noexcept { return atou(buf, v); } -C4_ALWAYS_INLINE bool from_chars(csubstr buf, uint64_t *C4_RESTRICT v) noexcept { return atou(buf, v); } -C4_ALWAYS_INLINE bool from_chars(csubstr buf, int8_t *C4_RESTRICT v) noexcept { return atoi(buf, v); } -C4_ALWAYS_INLINE bool from_chars(csubstr buf, int16_t *C4_RESTRICT v) noexcept { return atoi(buf, v); } -C4_ALWAYS_INLINE bool from_chars(csubstr buf, int32_t *C4_RESTRICT v) noexcept { return atoi(buf, v); } -C4_ALWAYS_INLINE bool from_chars(csubstr buf, int64_t *C4_RESTRICT v) noexcept { return atoi(buf, v); } -C4_ALWAYS_INLINE bool from_chars(csubstr buf, float *C4_RESTRICT v) noexcept { return atof(buf, v); } -C4_ALWAYS_INLINE bool from_chars(csubstr buf, double *C4_RESTRICT v) noexcept { return atod(buf, v); } - -C4_ALWAYS_INLINE size_t from_chars_first(csubstr buf, uint8_t *C4_RESTRICT v) noexcept { return atou_first(buf, v); } -C4_ALWAYS_INLINE size_t from_chars_first(csubstr buf, uint16_t *C4_RESTRICT v) noexcept { return atou_first(buf, v); } -C4_ALWAYS_INLINE size_t from_chars_first(csubstr buf, uint32_t *C4_RESTRICT v) noexcept { return atou_first(buf, v); } -C4_ALWAYS_INLINE size_t from_chars_first(csubstr buf, uint64_t *C4_RESTRICT v) noexcept { return atou_first(buf, v); } -C4_ALWAYS_INLINE size_t from_chars_first(csubstr buf, int8_t *C4_RESTRICT v) noexcept { return atoi_first(buf, v); } -C4_ALWAYS_INLINE size_t from_chars_first(csubstr buf, int16_t *C4_RESTRICT v) noexcept { return atoi_first(buf, v); } -C4_ALWAYS_INLINE size_t from_chars_first(csubstr buf, int32_t *C4_RESTRICT v) noexcept { return atoi_first(buf, v); } -C4_ALWAYS_INLINE size_t from_chars_first(csubstr buf, int64_t *C4_RESTRICT v) noexcept { return atoi_first(buf, v); } -C4_ALWAYS_INLINE size_t from_chars_first(csubstr buf, float *C4_RESTRICT v) noexcept { return atof_first(buf, v); } -C4_ALWAYS_INLINE size_t from_chars_first(csubstr buf, double *C4_RESTRICT v) noexcept { return atod_first(buf, v); } - - -//----------------------------------------------------------------------------- -// on some platforms, (unsigned) int and (unsigned) long -// are not any of the fixed length types above - -#define _C4_IF_NOT_FIXED_LENGTH_I(T, ty) C4_ALWAYS_INLINE typename std::enable_if::value && !is_fixed_length::value_i, ty> -#define _C4_IF_NOT_FIXED_LENGTH_U(T, ty) C4_ALWAYS_INLINE typename std::enable_if::value && !is_fixed_length::value_u, ty> - -template _C4_IF_NOT_FIXED_LENGTH_I(T, size_t)::type xtoa(substr buf, T v) noexcept { return itoa(buf, v); } -template _C4_IF_NOT_FIXED_LENGTH_U(T, size_t)::type xtoa(substr buf, T v) noexcept { return write_dec(buf, v); } - -template _C4_IF_NOT_FIXED_LENGTH_I(T, bool )::type atox(csubstr buf, T *C4_RESTRICT v) noexcept { return atoi(buf, v); } -template _C4_IF_NOT_FIXED_LENGTH_U(T, bool )::type atox(csubstr buf, T *C4_RESTRICT v) noexcept { return atou(buf, v); } - -template _C4_IF_NOT_FIXED_LENGTH_I(T, size_t)::type to_chars(substr buf, T v) noexcept { return itoa(buf, v); } -template _C4_IF_NOT_FIXED_LENGTH_U(T, size_t)::type to_chars(substr buf, T v) noexcept { return write_dec(buf, v); } - -template _C4_IF_NOT_FIXED_LENGTH_I(T, bool )::type from_chars(csubstr buf, T *C4_RESTRICT v) noexcept { return atoi(buf, v); } -template _C4_IF_NOT_FIXED_LENGTH_U(T, bool )::type from_chars(csubstr buf, T *C4_RESTRICT v) noexcept { return atou(buf, v); } - -template _C4_IF_NOT_FIXED_LENGTH_I(T, size_t)::type from_chars_first(csubstr buf, T *C4_RESTRICT v) noexcept { return atoi_first(buf, v); } -template _C4_IF_NOT_FIXED_LENGTH_U(T, size_t)::type from_chars_first(csubstr buf, T *C4_RESTRICT v) noexcept { return atou_first(buf, v); } - -#undef _C4_IF_NOT_FIXED_LENGTH_I -#undef _C4_IF_NOT_FIXED_LENGTH_U - - -//----------------------------------------------------------------------------- -// for pointers - -template C4_ALWAYS_INLINE size_t xtoa(substr s, T *v) noexcept { return itoa(s, (intptr_t)v, (intptr_t)16); } -template C4_ALWAYS_INLINE bool atox(csubstr s, T **v) noexcept { intptr_t tmp; bool ret = atox(s, &tmp); if(ret) { *v = (T*)tmp; } return ret; } -template C4_ALWAYS_INLINE size_t to_chars(substr s, T *v) noexcept { return itoa(s, (intptr_t)v, (intptr_t)16); } -template C4_ALWAYS_INLINE bool from_chars(csubstr buf, T **v) noexcept { intptr_t tmp; bool ret = from_chars(buf, &tmp); if(ret) { *v = (T*)tmp; } return ret; } -template C4_ALWAYS_INLINE size_t from_chars_first(csubstr buf, T **v) noexcept { intptr_t tmp; bool ret = from_chars_first(buf, &tmp); if(ret) { *v = (T*)tmp; } return ret; } - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -/** call to_chars() and return a substr consisting of the - * written portion of the input buffer. Ie, same as to_chars(), - * but return a substr instead of a size_t. - * - * @see to_chars() */ -template -C4_ALWAYS_INLINE substr to_chars_sub(substr buf, T const& C4_RESTRICT v) noexcept -{ - size_t sz = to_chars(buf, v); - return buf.left_of(sz <= buf.len ? sz : buf.len); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// bool implementation - -C4_ALWAYS_INLINE size_t to_chars(substr buf, bool v) noexcept -{ - int val = v; - return to_chars(buf, val); -} - -inline bool from_chars(csubstr buf, bool * C4_RESTRICT v) noexcept -{ - if(buf == '0') - { - *v = false; return true; - } - else if(buf == '1') - { - *v = true; return true; - } - else if(buf == "false") - { - *v = false; return true; - } - else if(buf == "true") - { - *v = true; return true; - } - else if(buf == "False") - { - *v = false; return true; - } - else if(buf == "True") - { - *v = true; return true; - } - else if(buf == "FALSE") - { - *v = false; return true; - } - else if(buf == "TRUE") - { - *v = true; return true; - } - // fallback to c-style int bools - int val = 0; - bool ret = from_chars(buf, &val); - if(C4_LIKELY(ret)) - { - *v = (val != 0); - } - return ret; -} - -inline size_t from_chars_first(csubstr buf, bool * C4_RESTRICT v) noexcept -{ - csubstr trimmed = buf.first_non_empty_span(); - if(trimmed.len == 0 || !from_chars(buf, v)) - return csubstr::npos; - return trimmed.len; -} - - -//----------------------------------------------------------------------------- -// single-char implementation - -inline size_t to_chars(substr buf, char v) noexcept -{ - if(buf.len > 0) - buf[0] = v; - return 1; -} - -/** extract a single character from a substring - * @note to extract a string instead and not just a single character, use the csubstr overload */ -inline bool from_chars(csubstr buf, char * C4_RESTRICT v) noexcept -{ - if(buf.len != 1) - return false; - *v = buf[0]; - return true; -} - -inline size_t from_chars_first(csubstr buf, char * C4_RESTRICT v) noexcept -{ - if(buf.len < 1) - return csubstr::npos; - *v = buf[0]; - return 1; -} - - -//----------------------------------------------------------------------------- -// csubstr implementation - -inline size_t to_chars(substr buf, csubstr v) noexcept -{ - C4_ASSERT(!buf.overlaps(v)); - size_t len = buf.len < v.len ? buf.len : v.len; - // calling memcpy with null strings is undefined behavior - // and will wreak havoc in calling code's branches. - // see https://github.com/biojppm/rapidyaml/pull/264#issuecomment-1262133637 - if(len) - { - C4_ASSERT(buf.str != nullptr); - C4_ASSERT(v.str != nullptr); - memcpy(buf.str, v.str, len); - } - return v.len; -} - -inline bool from_chars(csubstr buf, csubstr *C4_RESTRICT v) noexcept -{ - *v = buf; - return true; -} - -inline size_t from_chars_first(substr buf, csubstr * C4_RESTRICT v) noexcept -{ - csubstr trimmed = buf.first_non_empty_span(); - if(trimmed.len == 0) - return csubstr::npos; - *v = trimmed; - return static_cast(trimmed.end() - buf.begin()); -} - - -//----------------------------------------------------------------------------- -// substr - -inline size_t to_chars(substr buf, substr v) noexcept -{ - C4_ASSERT(!buf.overlaps(v)); - size_t len = buf.len < v.len ? buf.len : v.len; - // calling memcpy with null strings is undefined behavior - // and will wreak havoc in calling code's branches. - // see https://github.com/biojppm/rapidyaml/pull/264#issuecomment-1262133637 - if(len) - { - C4_ASSERT(buf.str != nullptr); - C4_ASSERT(v.str != nullptr); - memcpy(buf.str, v.str, len); - } - return v.len; -} - -inline bool from_chars(csubstr buf, substr * C4_RESTRICT v) noexcept -{ - C4_ASSERT(!buf.overlaps(*v)); - // is the destination buffer wide enough? - if(v->len >= buf.len) - { - // calling memcpy with null strings is undefined behavior - // and will wreak havoc in calling code's branches. - // see https://github.com/biojppm/rapidyaml/pull/264#issuecomment-1262133637 - if(buf.len) - { - C4_ASSERT(buf.str != nullptr); - C4_ASSERT(v->str != nullptr); - memcpy(v->str, buf.str, buf.len); - } - v->len = buf.len; - return true; - } - return false; -} - -inline size_t from_chars_first(csubstr buf, substr * C4_RESTRICT v) noexcept -{ - csubstr trimmed = buf.first_non_empty_span(); - C4_ASSERT(!trimmed.overlaps(*v)); - if(C4_UNLIKELY(trimmed.len == 0)) - return csubstr::npos; - size_t len = trimmed.len > v->len ? v->len : trimmed.len; - // calling memcpy with null strings is undefined behavior - // and will wreak havoc in calling code's branches. - // see https://github.com/biojppm/rapidyaml/pull/264#issuecomment-1262133637 - if(len) - { - C4_ASSERT(buf.str != nullptr); - C4_ASSERT(v->str != nullptr); - memcpy(v->str, trimmed.str, len); - } - if(C4_UNLIKELY(trimmed.len > v->len)) - return csubstr::npos; - return static_cast(trimmed.end() - buf.begin()); -} - - -//----------------------------------------------------------------------------- - -template -inline size_t to_chars(substr buf, const char (& C4_RESTRICT v)[N]) noexcept -{ - csubstr sp(v); - return to_chars(buf, sp); -} - -inline size_t to_chars(substr buf, const char * C4_RESTRICT v) noexcept -{ - return to_chars(buf, to_csubstr(v)); -} - -} // namespace c4 - -#ifdef _MSC_VER -# pragma warning(pop) -#elif defined(__clang__) -# pragma clang diagnostic pop -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#endif - -#endif /* _C4_CHARCONV_HPP_ */ diff --git a/thirdparty/ryml/ext/c4core/src/c4/common.hpp b/thirdparty/ryml/ext/c4core/src/c4/common.hpp deleted file mode 100644 index e3063ffc0..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/common.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef _C4_COMMON_HPP_ -#define _C4_COMMON_HPP_ - -#include "c4/config.hpp" - -#include "c4/preprocessor.hpp" -#include "c4/platform.hpp" -#include "c4/cpu.hpp" -#include "c4/compiler.hpp" -#include "c4/language.hpp" -#include "c4/error.hpp" -#include "c4/time.hpp" -#include "c4/types.hpp" - -#endif /* _C4_COMMON_HPP_ */ diff --git a/thirdparty/ryml/ext/c4core/src/c4/compiler.hpp b/thirdparty/ryml/ext/c4core/src/c4/compiler.hpp deleted file mode 100644 index ba8e5b07c..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/compiler.hpp +++ /dev/null @@ -1,117 +0,0 @@ -#ifndef _C4_COMPILER_HPP_ -#define _C4_COMPILER_HPP_ - -/** @file compiler.hpp Provides compiler information macros - * @ingroup basic_headers */ - -#include "c4/platform.hpp" - -// Compilers: -// C4_MSVC -// Visual Studio 2022: MSVC++ 17, 1930 -// Visual Studio 2019: MSVC++ 16, 1920 -// Visual Studio 2017: MSVC++ 15 -// Visual Studio 2015: MSVC++ 14 -// Visual Studio 2013: MSVC++ 13 -// Visual Studio 2013: MSVC++ 12 -// Visual Studio 2012: MSVC++ 11 -// Visual Studio 2010: MSVC++ 10 -// Visual Studio 2008: MSVC++ 09 -// Visual Studio 2005: MSVC++ 08 -// C4_CLANG -// C4_GCC -// C4_ICC (intel compiler) -/** @see http://sourceforge.net/p/predef/wiki/Compilers/ for a list of compiler identifier macros */ -/** @see https://msdn.microsoft.com/en-us/library/b0084kay.aspx for VS2013 predefined macros */ - -#if defined(_MSC_VER)// && (defined(C4_WIN) || defined(C4_XBOX) || defined(C4_UE4)) -# define C4_MSVC -# define C4_MSVC_VERSION_2022 17 -# define C4_MSVC_VERSION_2019 16 -# define C4_MSVC_VERSION_2017 15 -# define C4_MSVC_VERSION_2015 14 -# define C4_MSVC_VERSION_2013 12 -# define C4_MSVC_VERSION_2012 11 -# if _MSC_VER >= 1930 -# define C4_MSVC_VERSION C4_MSVC_VERSION_2022 // visual studio 2022 -# define C4_MSVC_2022 -# elif _MSC_VER >= 1920 -# define C4_MSVC_VERSION C_4MSVC_VERSION_2019 // visual studio 2019 -# define C4_MSVC_2019 -# elif _MSC_VER >= 1910 -# define C4_MSVC_VERSION C4_MSVC_VERSION_2017 // visual studio 2017 -# define C4_MSVC_2017 -# elif _MSC_VER == 1900 -# define C4_MSVC_VERSION C4_MSVC_VERSION_2015 // visual studio 2015 -# define C4_MSVC_2015 -# elif _MSC_VER == 1800 -# error "MSVC version not supported" -# define C4_MSVC_VERSION C4_MSVC_VERSION_2013 // visual studio 2013 -# define C4_MSVC_2013 -# elif _MSC_VER == 1700 -# error "MSVC version not supported" -# define C4_MSVC_VERSION C4_MSVC_VERSION_2012 // visual studio 2012 -# define C4_MSVC_2012 -# elif _MSC_VER == 1600 -# error "MSVC version not supported" -# define C4_MSVC_VERSION 10 // visual studio 2010 -# define C4_MSVC_2010 -# elif _MSC_VER == 1500 -# error "MSVC version not supported" -# define C4_MSVC_VERSION 09 // visual studio 2008 -# define C4_MSVC_2008 -# elif _MSC_VER == 1400 -# error "MSVC version not supported" -# define C4_MSVC_VERSION 08 // visual studio 2005 -# define C4_MSVC_2005 -# else -# error "MSVC version not supported" -# endif // _MSC_VER -#else -# define C4_MSVC_VERSION 0 // visual studio not present -# define C4_GCC_LIKE -# ifdef __INTEL_COMPILER // check ICC before checking GCC, as ICC defines __GNUC__ too -# define C4_ICC -# define C4_ICC_VERSION __INTEL_COMPILER -# elif defined(__APPLE_CC__) -# define C4_XCODE -# if defined(__clang__) -# define C4_CLANG -# ifndef __apple_build_version__ -# define C4_CLANG_VERSION C4_VERSION_ENCODED(__clang_major__, __clang_minor__, __clang_patchlevel__) -# else -# define C4_CLANG_VERSION __apple_build_version__ -# endif -# else -# define C4_XCODE_VERSION __APPLE_CC__ -# endif -# elif defined(__clang__) -# define C4_CLANG -# ifndef __apple_build_version__ -# define C4_CLANG_VERSION C4_VERSION_ENCODED(__clang_major__, __clang_minor__, __clang_patchlevel__) -# else -# define C4_CLANG_VERSION __apple_build_version__ -# endif -# elif defined(__GNUC__) -# define C4_GCC -# if defined(__GNUC_PATCHLEVEL__) -# define C4_GCC_VERSION C4_VERSION_ENCODED(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) -# else -# define C4_GCC_VERSION C4_VERSION_ENCODED(__GNUC__, __GNUC_MINOR__, 0) -# endif -# if __GNUC__ < 5 -# if __GNUC__ == 4 && __GNUC_MINOR__ >= 8 -// provided by cmake sub-project -# include "c4/gcc-4.8.hpp" -# else -// we do not support GCC < 4.8: -// * misses std::is_trivially_copyable -// * misses std::align -// * -Wshadow has false positives when a local function parameter has the same name as a method -# error "GCC < 4.8 is not supported" -# endif -# endif -# endif -#endif // defined(C4_WIN) && defined(_MSC_VER) - -#endif /* _C4_COMPILER_HPP_ */ diff --git a/thirdparty/ryml/ext/c4core/src/c4/config.hpp b/thirdparty/ryml/ext/c4core/src/c4/config.hpp deleted file mode 100644 index bda8033b3..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/config.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef _C4_CONFIG_HPP_ -#define _C4_CONFIG_HPP_ - -/** @defgroup basic_headers Basic headers - * @brief Headers providing basic macros, platform+cpu+compiler information, - * C++ facilities and basic typedefs. */ - -/** @file config.hpp Contains configuration defines and includes the basic_headers. - * @ingroup basic_headers */ - -//#define C4_DEBUG - -#define C4_ERROR_SHOWS_FILELINE -//#define C4_ERROR_SHOWS_FUNC -//#define C4_ERROR_THROWS_EXCEPTION -//#define C4_NO_ALLOC_DEFAULTS -//#define C4_REDEFINE_CPPNEW - -#ifndef C4_SIZE_TYPE -# define C4_SIZE_TYPE size_t -#endif - -#ifndef C4_STR_SIZE_TYPE -# define C4_STR_SIZE_TYPE C4_SIZE_TYPE -#endif - -#ifndef C4_TIME_TYPE -# define C4_TIME_TYPE double -#endif - -#include "c4/export.hpp" -#include "c4/preprocessor.hpp" -#include "c4/platform.hpp" -#include "c4/cpu.hpp" -#include "c4/compiler.hpp" -#include "c4/language.hpp" -#include "c4/types.hpp" - -#endif // _C4_CONFIG_HPP_ diff --git a/thirdparty/ryml/ext/c4core/src/c4/cpu.hpp b/thirdparty/ryml/ext/c4core/src/c4/cpu.hpp deleted file mode 100644 index f8877d115..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/cpu.hpp +++ /dev/null @@ -1,139 +0,0 @@ -#ifndef _C4_CPU_HPP_ -#define _C4_CPU_HPP_ - -/** @file cpu.hpp Provides processor information macros - * @ingroup basic_headers */ - -// see also https://sourceforge.net/p/predef/wiki/Architectures/ -// see also https://sourceforge.net/p/predef/wiki/Endianness/ -// see also https://github.com/googlesamples/android-ndk/blob/android-mk/hello-jni/jni/hello-jni.c -// see http://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/global/qprocessordetection.h - -#ifdef __ORDER_LITTLE_ENDIAN__ - #define _C4EL __ORDER_LITTLE_ENDIAN__ -#else - #define _C4EL 1234 -#endif - -#ifdef __ORDER_BIG_ENDIAN__ - #define _C4EB __ORDER_BIG_ENDIAN__ -#else - #define _C4EB 4321 -#endif - -// mixed byte order (eg, PowerPC or ia64) -#define _C4EM 1111 - -#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64) - #define C4_CPU_X86_64 - #define C4_WORDSIZE 8 - #define C4_BYTE_ORDER _C4EL - -#elif defined(__i386) || defined(__i386__) || defined(_M_IX86) - #define C4_CPU_X86 - #define C4_WORDSIZE 4 - #define C4_BYTE_ORDER _C4EL - -#elif defined(__arm__) || defined(_M_ARM) \ - || defined(__TARGET_ARCH_ARM) || defined(__aarch64__) || defined(_M_ARM64) - #if defined(__aarch64__) || defined(_M_ARM64) - #define C4_CPU_ARM64 - #define C4_CPU_ARMV8 - #define C4_WORDSIZE 8 - #else - #define C4_CPU_ARM - #define C4_WORDSIZE 4 - #if defined(__ARM_ARCH_8__) || defined(__ARM_ARCH_8A__) \ - || (defined(__ARCH_ARM) && __ARCH_ARM >= 8) - || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM >= 8) \ - #define C4_CPU_ARMV8 - #elif defined(__ARM_ARCH_7__) || defined(_ARM_ARCH_7) \ - || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) \ - || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) \ - || defined(__ARM_ARCH_7EM__) \ - || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM >= 7) \ - || (defined(_M_ARM) && _M_ARM >= 7) - #define C4_CPU_ARMV7 - #elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \ - || defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) \ - || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6ZK__) \ - || defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_6KZ__) \ - || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM >= 6) - #define C4_CPU_ARMV6 - #elif defined(__ARM_ARCH_5TEJ__) \ - || defined(__ARM_ARCH_5TE__) \ - || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM >= 5) - #define C4_CPU_ARMV5 - #elif defined(__ARM_ARCH_4T__) \ - || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM >= 4) - #define C4_CPU_ARMV4 - #else - #error "unknown CPU architecture: ARM" - #endif - #endif - #if defined(__ARMEL__) || defined(__LITTLE_ENDIAN__) || defined(__AARCH64EL__) \ - || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) \ - || defined(_MSC_VER) // winarm64 does not provide any of the above macros, - // but advises little-endianess: - // https://docs.microsoft.com/en-us/cpp/build/overview-of-arm-abi-conventions?view=msvc-170 - // So if it is visual studio compiling, we'll assume little endian. - #define C4_BYTE_ORDER _C4EL - #elif defined(__ARMEB__) || defined(__BIG_ENDIAN__) || defined(__AARCH64EB__) \ - || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) - #define C4_BYTE_ORDER _C4EB - #elif defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_PDP_ENDIAN__) - #define C4_BYTE_ORDER _C4EM - #else - #error "unknown endianness" - #endif - -#elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64) - #define C4_CPU_IA64 - #define C4_WORDSIZE 8 - #define C4_BYTE_ORDER _C4EM - // itanium is bi-endian - check byte order below - -#elif defined(__ppc__) || defined(__ppc) || defined(__powerpc__) \ - || defined(_ARCH_COM) || defined(_ARCH_PWR) || defined(_ARCH_PPC) \ - || defined(_M_MPPC) || defined(_M_PPC) - #if defined(__ppc64__) || defined(__powerpc64__) || defined(__64BIT__) - #define C4_CPU_PPC64 - #define C4_WORDSIZE 8 - #else - #define C4_CPU_PPC - #define C4_WORDSIZE 4 - #endif - #define C4_BYTE_ORDER _C4EM - // ppc is bi-endian - check byte order below - -#elif defined(__s390x__) || defined(__zarch__) || defined(__SYSC_ZARCH_) -# define C4_CPU_S390_X -# define C4_WORDSIZE 8 -# define C4_BYTE_ORDER _C4EB - -#elif defined(__riscv) - #if __riscv_xlen == 64 - #define C4_CPU_RISCV64 - #define C4_WORDSIZE 8 - #else - #define C4_CPU_RISCV32 - #define C4_WORDSIZE 4 - #endif - #define C4_BYTE_ORDER _C4EL - -#elif defined(__EMSCRIPTEN__) -# define C4_BYTE_ORDER _C4EL -# define C4_WORDSIZE 4 - -#elif defined(SWIG) - #error "please define CPU architecture macros when compiling with swig" - -#else - #error "unknown CPU architecture" -#endif - -#define C4_LITTLE_ENDIAN (C4_BYTE_ORDER == _C4EL) -#define C4_BIG_ENDIAN (C4_BYTE_ORDER == _C4EB) -#define C4_MIXED_ENDIAN (C4_BYTE_ORDER == _C4EM) - -#endif /* _C4_CPU_HPP_ */ diff --git a/thirdparty/ryml/ext/c4core/src/c4/ctor_dtor.hpp b/thirdparty/ryml/ext/c4core/src/c4/ctor_dtor.hpp deleted file mode 100644 index 8624df7b5..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ctor_dtor.hpp +++ /dev/null @@ -1,462 +0,0 @@ -#ifndef _C4_CTOR_DTOR_HPP_ -#define _C4_CTOR_DTOR_HPP_ - -#include "c4/preprocessor.hpp" -#include "c4/language.hpp" -#include "c4/memory_util.hpp" -#include "c4/error.hpp" - -#include -#include // std::forward - -/** @file ctor_dtor.hpp object construction and destruction facilities. - * Some of these are not yet available in C++11. */ - -namespace c4 { - -/** default-construct an object, trivial version */ -template C4_ALWAYS_INLINE typename std::enable_if::value, void>::type -construct(U *ptr) noexcept -{ - memset(ptr, 0, sizeof(U)); -} -/** default-construct an object, non-trivial version */ -template C4_ALWAYS_INLINE typename std ::enable_if< ! std::is_trivially_default_constructible::value, void>::type -construct(U* ptr) noexcept -{ - new ((void*)ptr) U(); -} - -/** default-construct n objects, trivial version */ -template C4_ALWAYS_INLINE typename std::enable_if::value, void>::type -construct_n(U* ptr, I n) noexcept -{ - memset(ptr, 0, n * sizeof(U)); -} -/** default-construct n objects, non-trivial version */ -template C4_ALWAYS_INLINE typename std::enable_if< ! std::is_trivially_default_constructible::value, void>::type -construct_n(U* ptr, I n) noexcept -{ - for(I i = 0; i < n; ++i) - { - new ((void*)(ptr + i)) U(); - } -} - -#ifdef __clang__ -# pragma clang diagnostic push -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# if __GNUC__ >= 6 -# pragma GCC diagnostic ignored "-Wnull-dereference" -# endif -#endif - -template -inline void construct(U* ptr, Args&&... args) -{ - new ((void*)ptr) U(std::forward(args)...); -} -template -inline void construct_n(U* ptr, I n, Args&&... args) -{ - for(I i = 0; i < n; ++i) - { - new ((void*)(ptr + i)) U(args...); - } -} - -#ifdef __clang__ -# pragma clang diagnostic pop -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#endif - - -//----------------------------------------------------------------------------- -// copy-construct - -template C4_ALWAYS_INLINE typename std::enable_if::value, void>::type -copy_construct(U* dst, U const* src) noexcept -{ - C4_ASSERT(dst != src); - memcpy(dst, src, sizeof(U)); -} -template C4_ALWAYS_INLINE typename std::enable_if< ! std::is_trivially_copy_constructible::value, void>::type -copy_construct(U* dst, U const* src) -{ - C4_ASSERT(dst != src); - new ((void*)dst) U(*src); -} -template C4_ALWAYS_INLINE typename std::enable_if::value, void>::type -copy_construct_n(U* dst, U const* src, I n) noexcept -{ - C4_ASSERT(dst != src); - memcpy(dst, src, n * sizeof(U)); -} -template C4_ALWAYS_INLINE typename std::enable_if< ! std::is_trivially_copy_constructible::value, void>::type -copy_construct_n(U* dst, U const* src, I n) -{ - C4_ASSERT(dst != src); - for(I i = 0; i < n; ++i) - { - new ((void*)(dst + i)) U(*(src + i)); - } -} - -template C4_ALWAYS_INLINE typename std::enable_if::value, void>::type -copy_construct(U* dst, U src) noexcept // pass by value for scalar types -{ - *dst = src; -} -template C4_ALWAYS_INLINE typename std::enable_if< ! std::is_scalar::value, void>::type -copy_construct(U* dst, U const& src) // pass by reference for non-scalar types -{ - C4_ASSERT(dst != &src); - new ((void*)dst) U(src); -} -template C4_ALWAYS_INLINE typename std::enable_if::value, void>::type -copy_construct_n(U* dst, U src, I n) noexcept // pass by value for scalar types -{ - for(I i = 0; i < n; ++i) - { - dst[i] = src; - } -} -template C4_ALWAYS_INLINE typename std::enable_if< ! std::is_scalar::value, void>::type -copy_construct_n(U* dst, U const& src, I n) // pass by reference for non-scalar types -{ - C4_ASSERT(dst != &src); - for(I i = 0; i < n; ++i) - { - new ((void*)(dst + i)) U(src); - } -} - -template -C4_ALWAYS_INLINE void copy_construct(U (&dst)[N], U const (&src)[N]) noexcept -{ - copy_construct_n(dst, src, N); -} - -//----------------------------------------------------------------------------- -// copy-assign - -template C4_ALWAYS_INLINE typename std::enable_if::value, void>::type -copy_assign(U* dst, U const* src) noexcept -{ - C4_ASSERT(dst != src); - memcpy(dst, src, sizeof(U)); -} -template C4_ALWAYS_INLINE typename std::enable_if< ! std::is_trivially_copy_assignable::value, void>::type -copy_assign(U* dst, U const* src) noexcept -{ - C4_ASSERT(dst != src); - *dst = *src; -} -template C4_ALWAYS_INLINE typename std::enable_if::value, void>::type -copy_assign_n(U* dst, U const* src, I n) noexcept -{ - C4_ASSERT(dst != src); - memcpy(dst, src, n * sizeof(U)); -} -template C4_ALWAYS_INLINE typename std::enable_if< ! std::is_trivially_copy_assignable::value, void>::type -copy_assign_n(U* dst, U const* src, I n) noexcept -{ - C4_ASSERT(dst != src); - for(I i = 0; i < n; ++i) - { - dst[i] = src[i]; - } -} - -template C4_ALWAYS_INLINE typename std::enable_if::value, void>::type -copy_assign(U* dst, U src) noexcept // pass by value for scalar types -{ - *dst = src; -} -template C4_ALWAYS_INLINE typename std::enable_if< ! std::is_scalar::value, void>::type -copy_assign(U* dst, U const& src) noexcept // pass by reference for non-scalar types -{ - C4_ASSERT(dst != &src); - *dst = src; -} -template C4_ALWAYS_INLINE typename std::enable_if::value, void>::type -copy_assign_n(U* dst, U src, I n) noexcept // pass by value for scalar types -{ - for(I i = 0; i < n; ++i) - { - dst[i] = src; - } -} -template C4_ALWAYS_INLINE typename std::enable_if< ! std::is_scalar::value, void>::type -copy_assign_n(U* dst, U const& src, I n) noexcept // pass by reference for non-scalar types -{ - C4_ASSERT(dst != &src); - for(I i = 0; i < n; ++i) - { - dst[i] = src; - } -} - -template -C4_ALWAYS_INLINE void copy_assign(U (&dst)[N], U const (&src)[N]) noexcept -{ - copy_assign_n(dst, src, N); -} - -//----------------------------------------------------------------------------- -// move-construct - -template C4_ALWAYS_INLINE typename std::enable_if::value, void>::type -move_construct(U* dst, U* src) noexcept -{ - C4_ASSERT(dst != src); - memcpy(dst, src, sizeof(U)); -} -template C4_ALWAYS_INLINE typename std::enable_if< ! std::is_trivially_move_constructible::value, void>::type -move_construct(U* dst, U* src) noexcept -{ - C4_ASSERT(dst != src); - new ((void*)dst) U(std::move(*src)); -} -template C4_ALWAYS_INLINE typename std::enable_if::value, void>::type -move_construct_n(U* dst, U* src, I n) noexcept -{ - C4_ASSERT(dst != src); - memcpy(dst, src, n * sizeof(U)); -} -template C4_ALWAYS_INLINE typename std::enable_if< ! std::is_trivially_move_constructible::value, void>::type -move_construct_n(U* dst, U* src, I n) noexcept -{ - C4_ASSERT(dst != src); - for(I i = 0; i < n; ++i) - { - new ((void*)(dst + i)) U(std::move(src[i])); - } -} - -//----------------------------------------------------------------------------- -// move-assign - -template C4_ALWAYS_INLINE typename std::enable_if::value, void>::type -move_assign(U* dst, U* src) noexcept -{ - C4_ASSERT(dst != src); - memcpy(dst, src, sizeof(U)); -} -template C4_ALWAYS_INLINE typename std::enable_if< ! std::is_trivially_move_assignable::value, void>::type -move_assign(U* dst, U* src) noexcept -{ - C4_ASSERT(dst != src); - *dst = std::move(*src); -} -template C4_ALWAYS_INLINE typename std::enable_if::value, void>::type -move_assign_n(U* dst, U* src, I n) noexcept -{ - C4_ASSERT(dst != src); - memcpy(dst, src, n * sizeof(U)); -} -template C4_ALWAYS_INLINE typename std::enable_if< ! std::is_trivially_move_assignable::value, void>::type -move_assign_n(U* dst, U* src, I n) noexcept -{ - C4_ASSERT(dst != src); - for(I i = 0; i < n; ++i) - { - *(dst + i) = std::move(*(src + i)); - } -} - -//----------------------------------------------------------------------------- -// destroy - -template C4_ALWAYS_INLINE typename std::enable_if::value, void>::type -destroy(U* ptr) noexcept -{ - C4_UNUSED(ptr); // nothing to do -} -template C4_ALWAYS_INLINE typename std::enable_if< ! std::is_trivially_destructible::value, void>::type -destroy(U* ptr) noexcept -{ - ptr->~U(); -} -template C4_ALWAYS_INLINE typename std::enable_if::value, void>::type -destroy_n(U* ptr, I n) noexcept -{ - C4_UNUSED(ptr); - C4_UNUSED(n); // nothing to do -} -template C4_ALWAYS_INLINE typename std::enable_if< ! std::is_trivially_destructible::value, void>::type -destroy_n(U* ptr, I n) noexcept -{ - for(I i = 0; i C4_ALWAYS_INLINE typename std::enable_if::value, void>::type -make_room(U *buf, I bufsz, I room) C4_NOEXCEPT_A -{ - C4_ASSERT(bufsz >= 0 && room >= 0); - if(room >= bufsz) - { - memcpy (buf + room, buf, bufsz * sizeof(U)); - } - else - { - memmove(buf + room, buf, bufsz * sizeof(U)); - } -} -/** makes room at the beginning of buf, which has a current size of bufsz */ -template C4_ALWAYS_INLINE typename std::enable_if< ! std::is_trivially_move_constructible::value, void>::type -make_room(U *buf, I bufsz, I room) C4_NOEXCEPT_A -{ - C4_ASSERT(bufsz >= 0 && room >= 0); - if(room >= bufsz) - { - for(I i = 0; i < bufsz; ++i) - { - new ((void*)(buf + (i + room))) U(std::move(buf[i])); - } - } - else - { - for(I i = 0; i < bufsz; ++i) - { - I w = bufsz-1 - i; // do a backwards loop - new ((void*)(buf + (w + room))) U(std::move(buf[w])); - } - } -} - -/** make room to the right of pos */ -template -C4_ALWAYS_INLINE void make_room(U *buf, I bufsz, I currsz, I pos, I room) -{ - C4_ASSERT(pos >= 0 && pos <= currsz); - C4_ASSERT(currsz <= bufsz); - C4_ASSERT(room + currsz <= bufsz); - C4_UNUSED(bufsz); - make_room(buf + pos, currsz - pos, room); -} - - -/** make room to the right of pos, copying to the beginning of a different buffer */ -template C4_ALWAYS_INLINE typename std::enable_if::value, void>::type -make_room(U *dst, U const* src, I srcsz, I room, I pos) C4_NOEXCEPT_A -{ - C4_ASSERT(srcsz >= 0 && room >= 0 && pos >= 0); - C4_ASSERT(pos < srcsz || (pos == 0 && srcsz == 0)); - memcpy(dst , src , pos * sizeof(U)); - memcpy(dst + room + pos, src + pos, (srcsz - pos) * sizeof(U)); -} -/** make room to the right of pos, copying to the beginning of a different buffer */ -template C4_ALWAYS_INLINE typename std::enable_if< ! std::is_trivially_move_constructible::value, void>::type -make_room(U *dst, U const* src, I srcsz, I room, I pos) -{ - C4_ASSERT(srcsz >= 0 && room >= 0 && pos >= 0); - C4_ASSERT(pos < srcsz || (pos == 0 && srcsz == 0)); - for(I i = 0; i < pos; ++i) - { - new ((void*)(dst + i)) U(std::move(src[i])); - } - src += pos; - dst += room + pos; - for(I i = 0, e = srcsz - pos; i < e; ++i) - { - new ((void*)(dst + i)) U(std::move(src[i])); - } -} - -template -C4_ALWAYS_INLINE void make_room -( - U * dst, I dstsz, - U const* src, I srcsz, - I room, I pos -) -{ - C4_ASSERT(pos >= 0 && pos < srcsz || (srcsz == 0 && pos == 0)); - C4_ASSERT(pos >= 0 && pos < dstsz || (dstsz == 0 && pos == 0)); - C4_ASSERT(srcsz+room <= dstsz); - C4_UNUSED(dstsz); - make_room(dst, src, srcsz, room, pos); -} - - -//----------------------------------------------------------------------------- -/** destroy room at the beginning of buf, which has a current size of n */ -template C4_ALWAYS_INLINE typename std::enable_if::value || (std::is_standard_layout::value && std::is_trivial::value), void>::type -destroy_room(U *buf, I n, I room) C4_NOEXCEPT_A -{ - C4_ASSERT(n >= 0 && room >= 0); - C4_ASSERT(room <= n); - if(room < n) - { - memmove(buf, buf + room, (n - room) * sizeof(U)); - } - else - { - // nothing to do - no need to destroy scalar types - } -} -/** destroy room at the beginning of buf, which has a current size of n */ -template C4_ALWAYS_INLINE typename std::enable_if< ! (std::is_scalar::value || (std::is_standard_layout::value && std::is_trivial::value)), void>::type -destroy_room(U *buf, I n, I room) -{ - C4_ASSERT(n >= 0 && room >= 0); - C4_ASSERT(room <= n); - if(room < n) - { - for(I i = 0, e = n - room; i < e; ++i) - { - buf[i] = std::move(buf[i + room]); - } - } - else - { - for(I i = 0; i < n; ++i) - { - buf[i].~U(); - } - } -} - -/** destroy room to the right of pos, copying to a different buffer */ -template C4_ALWAYS_INLINE typename std::enable_if::value, void>::type -destroy_room(U *dst, U const* src, I n, I room, I pos) C4_NOEXCEPT_A -{ - C4_ASSERT(n >= 0 && room >= 0 && pos >= 0); - C4_ASSERT(pos C4_ALWAYS_INLINE typename std::enable_if< ! std::is_trivially_move_constructible::value, void>::type -destroy_room(U *dst, U const* src, I n, I room, I pos) -{ - C4_ASSERT(n >= 0 && room >= 0 && pos >= 0); - C4_ASSERT(pos < n); - C4_ASSERT(pos + room <= n); - for(I i = 0; i < pos; ++i) - { - new ((void*)(dst + i)) U(std::move(src[i])); - } - src += room + pos; - dst += pos; - for(I i = 0, e = n - pos - room; i < e; ++i) - { - new ((void*)(dst + i)) U(std::move(src[i])); - } -} - -} // namespace c4 - -#undef _C4REQUIRE - -#endif /* _C4_CTOR_DTOR_HPP_ */ diff --git a/thirdparty/ryml/ext/c4core/src/c4/dump.hpp b/thirdparty/ryml/ext/c4core/src/c4/dump.hpp deleted file mode 100644 index 483acf982..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/dump.hpp +++ /dev/null @@ -1,579 +0,0 @@ -#ifndef C4_DUMP_HPP_ -#define C4_DUMP_HPP_ - -#include - -namespace c4 { - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -/** type of the function to dump characters */ -using DumperPfn = void (*)(csubstr buf); - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -template -inline size_t dump(substr buf, Arg const& a) -{ - size_t sz = to_chars(buf, a); // need to serialize to the buffer - if(C4_LIKELY(sz <= buf.len)) - dumpfn(buf.first(sz)); - return sz; -} - -template -inline size_t dump(DumperFn &&dumpfn, substr buf, Arg const& a) -{ - size_t sz = to_chars(buf, a); // need to serialize to the buffer - if(C4_LIKELY(sz <= buf.len)) - dumpfn(buf.first(sz)); - return sz; -} - -template -inline size_t dump(substr buf, csubstr a) -{ - if(buf.len) - dumpfn(a); // dump directly, no need to serialize to the buffer - return 0; // no space was used in the buffer -} - -template -inline size_t dump(DumperFn &&dumpfn, substr buf, csubstr a) -{ - if(buf.len) - dumpfn(a); // dump directly, no need to serialize to the buffer - return 0; // no space was used in the buffer -} - -template -inline size_t dump(substr buf, const char (&a)[N]) -{ - if(buf.len) - dumpfn(csubstr(a)); // dump directly, no need to serialize to the buffer - return 0; // no space was used in the buffer -} - -template -inline size_t dump(DumperFn &&dumpfn, substr buf, const char (&a)[N]) -{ - if(buf.len) - dumpfn(csubstr(a)); // dump directly, no need to serialize to the buffer - return 0; // no space was used in the buffer -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -/** */ -struct DumpResults -{ - enum : size_t { noarg = (size_t)-1 }; - size_t bufsize = 0; - size_t lastok = noarg; - bool success_until(size_t expected) const { return lastok == noarg ? false : lastok >= expected; } - bool write_arg(size_t arg) const { return lastok == noarg || arg > lastok; } - size_t argfail() const { return lastok + 1; } -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -/// @cond dev -// terminates the variadic recursion -template -size_t cat_dump(DumperFn &&, substr) -{ - return 0; -} - -// terminates the variadic recursion -template -size_t cat_dump(substr) -{ - return 0; -} -/// @endcond - -/** take the function pointer as a function argument */ -template -size_t cat_dump(DumperFn &&dumpfn, substr buf, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more) -{ - size_t size_for_a = dump(dumpfn, buf, a); - if(C4_UNLIKELY(size_for_a > buf.len)) - buf = buf.first(0); // ensure no more calls - size_t size_for_more = cat_dump(dumpfn, buf, more...); - return size_for_more > size_for_a ? size_for_more : size_for_a; -} - -/** take the function pointer as a template argument */ -template -size_t cat_dump(substr buf, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more) -{ - size_t size_for_a = dump(buf, a); - if(C4_LIKELY(size_for_a > buf.len)) - buf = buf.first(0); // ensure no more calls - size_t size_for_more = cat_dump(buf, more...); - return size_for_more > size_for_a ? size_for_more : size_for_a; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -/// @cond dev -namespace detail { - -// terminates the variadic recursion -template -DumpResults cat_dump_resume(size_t currarg, DumpResults results, substr buf, Arg const& C4_RESTRICT a) -{ - if(C4_LIKELY(results.write_arg(currarg))) - { - size_t sz = dump(buf, a); // yield to the specialized function - if(currarg == results.lastok + 1 && sz <= buf.len) - results.lastok = currarg; - results.bufsize = sz > results.bufsize ? sz : results.bufsize; - } - return results; -} - -// terminates the variadic recursion -template -DumpResults cat_dump_resume(size_t currarg, DumperFn &&dumpfn, DumpResults results, substr buf, Arg const& C4_RESTRICT a) -{ - if(C4_LIKELY(results.write_arg(currarg))) - { - size_t sz = dump(dumpfn, buf, a); // yield to the specialized function - if(currarg == results.lastok + 1 && sz <= buf.len) - results.lastok = currarg; - results.bufsize = sz > results.bufsize ? sz : results.bufsize; - } - return results; -} - -template -DumpResults cat_dump_resume(size_t currarg, DumpResults results, substr buf, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more) -{ - results = detail::cat_dump_resume(currarg, results, buf, a); - return detail::cat_dump_resume(currarg + 1u, results, buf, more...); -} - -template -DumpResults cat_dump_resume(size_t currarg, DumperFn &&dumpfn, DumpResults results, substr buf, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more) -{ - results = detail::cat_dump_resume(currarg, dumpfn, results, buf, a); - return detail::cat_dump_resume(currarg + 1u, dumpfn, results, buf, more...); -} -} // namespace detail -/// @endcond - - -template -C4_ALWAYS_INLINE DumpResults cat_dump_resume(DumpResults results, substr buf, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more) -{ - if(results.bufsize > buf.len) - return results; - return detail::cat_dump_resume(0u, results, buf, a, more...); -} - -template -C4_ALWAYS_INLINE DumpResults cat_dump_resume(DumperFn &&dumpfn, DumpResults results, substr buf, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more) -{ - if(results.bufsize > buf.len) - return results; - return detail::cat_dump_resume(0u, dumpfn, results, buf, a, more...); -} - -template -C4_ALWAYS_INLINE DumpResults cat_dump_resume(substr buf, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more) -{ - return detail::cat_dump_resume(0u, DumpResults{}, buf, a, more...); -} - -template -C4_ALWAYS_INLINE DumpResults cat_dump_resume(DumperFn &&dumpfn, substr buf, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more) -{ - return detail::cat_dump_resume(0u, dumpfn, DumpResults{}, buf, a, more...); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -/// @cond dev -// terminate the recursion -template -size_t catsep_dump(DumperFn &&, substr, Sep const& C4_RESTRICT) -{ - return 0; -} - -// terminate the recursion -template -size_t catsep_dump(substr, Sep const& C4_RESTRICT) -{ - return 0; -} -/// @endcond - -/** take the function pointer as a function argument */ -template -size_t catsep_dump(DumperFn &&dumpfn, substr buf, Sep const& C4_RESTRICT sep, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more) -{ - size_t sz = dump(dumpfn, buf, a); - if(C4_UNLIKELY(sz > buf.len)) - buf = buf.first(0); // ensure no more calls - if C4_IF_CONSTEXPR (sizeof...(more) > 0) - { - size_t szsep = dump(dumpfn, buf, sep); - if(C4_UNLIKELY(szsep > buf.len)) - buf = buf.first(0); // ensure no more calls - sz = sz > szsep ? sz : szsep; - } - size_t size_for_more = catsep_dump(dumpfn, buf, sep, more...); - return size_for_more > sz ? size_for_more : sz; -} - -/** take the function pointer as a template argument */ -template -size_t catsep_dump(substr buf, Sep const& C4_RESTRICT sep, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more) -{ - size_t sz = dump(buf, a); - if(C4_UNLIKELY(sz > buf.len)) - buf = buf.first(0); // ensure no more calls - if C4_IF_CONSTEXPR (sizeof...(more) > 0) - { - size_t szsep = dump(buf, sep); - if(C4_UNLIKELY(szsep > buf.len)) - buf = buf.first(0); // ensure no more calls - sz = sz > szsep ? sz : szsep; - } - size_t size_for_more = catsep_dump(buf, sep, more...); - return size_for_more > sz ? size_for_more : sz; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -/// @cond dev -namespace detail { -template -void catsep_dump_resume_(size_t currarg, DumpResults *C4_RESTRICT results, substr *C4_RESTRICT buf, Arg const& C4_RESTRICT a) -{ - if(C4_LIKELY(results->write_arg(currarg))) - { - size_t sz = dump(*buf, a); - results->bufsize = sz > results->bufsize ? sz : results->bufsize; - if(C4_LIKELY(sz <= buf->len)) - results->lastok = currarg; - else - buf->len = 0; - } -} - -template -void catsep_dump_resume_(size_t currarg, DumperFn &&dumpfn, DumpResults *C4_RESTRICT results, substr *C4_RESTRICT buf, Arg const& C4_RESTRICT a) -{ - if(C4_LIKELY(results->write_arg(currarg))) - { - size_t sz = dump(dumpfn, *buf, a); - results->bufsize = sz > results->bufsize ? sz : results->bufsize; - if(C4_LIKELY(sz <= buf->len)) - results->lastok = currarg; - else - buf->len = 0; - } -} - -template -C4_ALWAYS_INLINE void catsep_dump_resume(size_t currarg, DumpResults *C4_RESTRICT results, substr *C4_RESTRICT buf, Sep const& C4_RESTRICT, Arg const& C4_RESTRICT a) -{ - detail::catsep_dump_resume_(currarg, results, buf, a); -} - -template -C4_ALWAYS_INLINE void catsep_dump_resume(size_t currarg, DumperFn &&dumpfn, DumpResults *C4_RESTRICT results, substr *C4_RESTRICT buf, Sep const& C4_RESTRICT, Arg const& C4_RESTRICT a) -{ - detail::catsep_dump_resume_(currarg, dumpfn, results, buf, a); -} - -template -C4_ALWAYS_INLINE void catsep_dump_resume(size_t currarg, DumpResults *C4_RESTRICT results, substr *C4_RESTRICT buf, Sep const& C4_RESTRICT sep, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more) -{ - detail::catsep_dump_resume_(currarg , results, buf, a); - detail::catsep_dump_resume_(currarg + 1u, results, buf, sep); - detail::catsep_dump_resume (currarg + 2u, results, buf, sep, more...); -} - -template -C4_ALWAYS_INLINE void catsep_dump_resume(size_t currarg, DumperFn &&dumpfn, DumpResults *C4_RESTRICT results, substr *C4_RESTRICT buf, Sep const& C4_RESTRICT sep, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more) -{ - detail::catsep_dump_resume_(currarg , dumpfn, results, buf, a); - detail::catsep_dump_resume_(currarg + 1u, dumpfn, results, buf, sep); - detail::catsep_dump_resume (currarg + 2u, dumpfn, results, buf, sep, more...); -} -} // namespace detail -/// @endcond - - -template -C4_ALWAYS_INLINE DumpResults catsep_dump_resume(DumpResults results, substr buf, Sep const& C4_RESTRICT sep, Args const& C4_RESTRICT ...more) -{ - detail::catsep_dump_resume(0u, &results, &buf, sep, more...); - return results; -} - -template -C4_ALWAYS_INLINE DumpResults catsep_dump_resume(DumperFn &&dumpfn, DumpResults results, substr buf, Sep const& C4_RESTRICT sep, Args const& C4_RESTRICT ...more) -{ - detail::catsep_dump_resume(0u, dumpfn, &results, &buf, sep, more...); - return results; -} - -template -C4_ALWAYS_INLINE DumpResults catsep_dump_resume(substr buf, Sep const& C4_RESTRICT sep, Args const& C4_RESTRICT ...more) -{ - DumpResults results; - detail::catsep_dump_resume(0u, &results, &buf, sep, more...); - return results; -} - -template -C4_ALWAYS_INLINE DumpResults catsep_dump_resume(DumperFn &&dumpfn, substr buf, Sep const& C4_RESTRICT sep, Args const& C4_RESTRICT ...more) -{ - DumpResults results; - detail::catsep_dump_resume(0u, dumpfn, &results, &buf, sep, more...); - return results; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -/** take the function pointer as a function argument */ -template -C4_ALWAYS_INLINE size_t format_dump(DumperFn &&dumpfn, substr buf, csubstr fmt) -{ - // we can dump without using buf - // but we'll only dump if the buffer is ok - if(C4_LIKELY(buf.len > 0 && fmt.len)) - dumpfn(fmt); - return 0u; -} - -/** take the function pointer as a function argument */ -template -C4_ALWAYS_INLINE size_t format_dump(substr buf, csubstr fmt) -{ - // we can dump without using buf - // but we'll only dump if the buffer is ok - if(C4_LIKELY(buf.len > 0 && fmt.len > 0)) - dumpfn(fmt); - return 0u; -} - -/** take the function pointer as a function argument */ -template -size_t format_dump(DumperFn &&dumpfn, substr buf, csubstr fmt, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more) -{ - // we can dump without using buf - // but we'll only dump if the buffer is ok - size_t pos = fmt.find("{}"); // @todo use _find_fmt() - if(C4_UNLIKELY(pos == csubstr::npos)) - { - if(C4_LIKELY(buf.len > 0 && fmt.len > 0)) - dumpfn(fmt); - return 0u; - } - if(C4_LIKELY(buf.len > 0 && pos > 0)) - dumpfn(fmt.first(pos)); // we can dump without using buf - fmt = fmt.sub(pos + 2); // skip {} do this before assigning to pos again - pos = dump(dumpfn, buf, a); - if(C4_UNLIKELY(pos > buf.len)) - buf.len = 0; // ensure no more calls to dump - size_t size_for_more = format_dump(dumpfn, buf, fmt, more...); - return size_for_more > pos ? size_for_more : pos; -} - -/** take the function pointer as a template argument */ -template -size_t format_dump(substr buf, csubstr fmt, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more) -{ - // we can dump without using buf - // but we'll only dump if the buffer is ok - size_t pos = fmt.find("{}"); // @todo use _find_fmt() - if(C4_UNLIKELY(pos == csubstr::npos)) - { - if(C4_LIKELY(buf.len > 0 && fmt.len > 0)) - dumpfn(fmt); - return 0u; - } - if(C4_LIKELY(buf.len > 0 && pos > 0)) - dumpfn(fmt.first(pos)); // we can dump without using buf - fmt = fmt.sub(pos + 2); // skip {} do this before assigning to pos again - pos = dump(buf, a); - if(C4_UNLIKELY(pos > buf.len)) - buf.len = 0; // ensure no more calls to dump - size_t size_for_more = format_dump(buf, fmt, more...); - return size_for_more > pos ? size_for_more : pos; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -/// @cond dev -namespace detail { - -template -DumpResults format_dump_resume(size_t currarg, DumpResults results, substr buf, csubstr fmt) -{ - // we can dump without using buf - // but we'll only dump if the buffer is ok - if(C4_LIKELY(buf.len > 0)) - { - dumpfn(fmt); - results.lastok = currarg; - } - return results; -} - -template -DumpResults format_dump_resume(size_t currarg, DumperFn &&dumpfn, DumpResults results, substr buf, csubstr fmt) -{ - // we can dump without using buf - // but we'll only dump if the buffer is ok - if(C4_LIKELY(buf.len > 0)) - { - dumpfn(fmt); - results.lastok = currarg; - } - return results; -} - -template -DumpResults format_dump_resume(size_t currarg, DumpResults results, substr buf, csubstr fmt, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more) -{ - // we need to process the format even if we're not - // going to print the first arguments because we're resuming - size_t pos = fmt.find("{}"); // @todo use _find_fmt() - // we can dump without using buf - // but we'll only dump if the buffer is ok - if(C4_LIKELY(results.write_arg(currarg))) - { - if(C4_UNLIKELY(pos == csubstr::npos)) - { - if(C4_LIKELY(buf.len > 0)) - { - results.lastok = currarg; - dumpfn(fmt); - } - return results; - } - if(C4_LIKELY(buf.len > 0)) - { - results.lastok = currarg; - dumpfn(fmt.first(pos)); - } - } - fmt = fmt.sub(pos + 2); - if(C4_LIKELY(results.write_arg(currarg + 1))) - { - pos = dump(buf, a); - results.bufsize = pos > results.bufsize ? pos : results.bufsize; - if(C4_LIKELY(pos <= buf.len)) - results.lastok = currarg + 1; - else - buf.len = 0; - } - return detail::format_dump_resume(currarg + 2u, results, buf, fmt, more...); -} -/// @endcond - - -template -DumpResults format_dump_resume(size_t currarg, DumperFn &&dumpfn, DumpResults results, substr buf, csubstr fmt, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more) -{ - // we need to process the format even if we're not - // going to print the first arguments because we're resuming - size_t pos = fmt.find("{}"); // @todo use _find_fmt() - // we can dump without using buf - // but we'll only dump if the buffer is ok - if(C4_LIKELY(results.write_arg(currarg))) - { - if(C4_UNLIKELY(pos == csubstr::npos)) - { - if(C4_LIKELY(buf.len > 0)) - { - results.lastok = currarg; - dumpfn(fmt); - } - return results; - } - if(C4_LIKELY(buf.len > 0)) - { - results.lastok = currarg; - dumpfn(fmt.first(pos)); - } - } - fmt = fmt.sub(pos + 2); - if(C4_LIKELY(results.write_arg(currarg + 1))) - { - pos = dump(dumpfn, buf, a); - results.bufsize = pos > results.bufsize ? pos : results.bufsize; - if(C4_LIKELY(pos <= buf.len)) - results.lastok = currarg + 1; - else - buf.len = 0; - } - return detail::format_dump_resume(currarg + 2u, dumpfn, results, buf, fmt, more...); -} -} // namespace detail - - -template -C4_ALWAYS_INLINE DumpResults format_dump_resume(DumpResults results, substr buf, csubstr fmt, Args const& C4_RESTRICT ...more) -{ - return detail::format_dump_resume(0u, results, buf, fmt, more...); -} - -template -C4_ALWAYS_INLINE DumpResults format_dump_resume(DumperFn &&dumpfn, DumpResults results, substr buf, csubstr fmt, Args const& C4_RESTRICT ...more) -{ - return detail::format_dump_resume(0u, dumpfn, results, buf, fmt, more...); -} - - -template -C4_ALWAYS_INLINE DumpResults format_dump_resume(substr buf, csubstr fmt, Args const& C4_RESTRICT ...more) -{ - return detail::format_dump_resume(0u, DumpResults{}, buf, fmt, more...); -} - -template -C4_ALWAYS_INLINE DumpResults format_dump_resume(DumperFn &&dumpfn, substr buf, csubstr fmt, Args const& C4_RESTRICT ...more) -{ - return detail::format_dump_resume(0u, dumpfn, DumpResults{}, buf, fmt, more...); -} - - -} // namespace c4 - - -#endif /* C4_DUMP_HPP_ */ diff --git a/thirdparty/ryml/ext/c4core/src/c4/enum.hpp b/thirdparty/ryml/ext/c4core/src/c4/enum.hpp deleted file mode 100644 index 785cf5b28..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/enum.hpp +++ /dev/null @@ -1,276 +0,0 @@ -#ifndef _C4_ENUM_HPP_ -#define _C4_ENUM_HPP_ - -#include "c4/error.hpp" -#include - -/** @file enum.hpp utilities for enums: convert to/from string - */ - - -namespace c4 { - -//! taken from http://stackoverflow.com/questions/15586163/c11-type-trait-to-differentiate-between-enum-class-and-regular-enum -template -using is_scoped_enum = std::integral_constant::value && !std::is_convertible::value>; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -typedef enum { - EOFFS_NONE = 0, ///< no offset - EOFFS_CLS = 1, ///< get the enum offset for the class name. @see eoffs_cls() - EOFFS_PFX = 2, ///< get the enum offset for the enum prefix. @see eoffs_pfx() - _EOFFS_LAST ///< reserved -} EnumOffsetType; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -/** A simple (proxy) container for the value-name pairs of an enum type. - * Uses linear search for finds; this could be improved for time-critical - * code. */ -template -class EnumSymbols -{ -public: - - struct Sym - { - Enum value; - const char *name; - - bool cmp(const char *s) const; - bool cmp(const char *s, size_t len) const; - - const char *name_offs(EnumOffsetType t) const; - }; - - using const_iterator = Sym const*; - -public: - - template - EnumSymbols(Sym const (&p)[N]) : m_symbols(p), m_num(N) {} - - size_t size() const { return m_num; } - bool empty() const { return m_num == 0; } - - Sym const* get(Enum v) const { auto p = find(v); C4_CHECK_MSG(p != nullptr, "could not find symbol=%zd", (std::ptrdiff_t)v); return p; } - Sym const* get(const char *s) const { auto p = find(s); C4_CHECK_MSG(p != nullptr, "could not find symbol \"%s\"", s); return p; } - Sym const* get(const char *s, size_t len) const { auto p = find(s, len); C4_CHECK_MSG(p != nullptr, "could not find symbol \"%.*s\"", len, s); return p; } - - Sym const* find(Enum v) const; - Sym const* find(const char *s) const; - Sym const* find(const char *s, size_t len) const; - - Sym const& operator[] (size_t i) const { C4_CHECK(i < m_num); return m_symbols[i]; } - - Sym const* begin() const { return m_symbols; } - Sym const* end () const { return m_symbols + m_num; } - -private: - - Sym const* m_symbols; - size_t const m_num; - -}; - -//----------------------------------------------------------------------------- -/** return an EnumSymbols object for the enum type T - * - * @warning SPECIALIZE! This needs to be specialized for each enum - * type. Failure to provide a specialization will cause a linker - * error. */ -template -EnumSymbols const esyms(); - - -/** return the offset for an enum symbol class. For example, - * eoffs_cls() would be 13=strlen("MyEnumClass::"). - * - * With this function you can announce that the full prefix (including - * an eventual enclosing class or C++11 enum class) is of a certain - * length. - * - * @warning Needs to be specialized for each enum class type that - * wants to use this. When no specialization is given, will return - * 0. */ -template -size_t eoffs_cls() -{ - return 0; -} - - -/** return the offset for an enum symbol prefix. This includes - * eoffs_cls(). With this function you can announce that the full - * prefix (including an eventual enclosing class or C++11 enum class - * plus the string prefix) is of a certain length. - * - * @warning Needs to be specialized for each enum class type that - * wants to use this. When no specialization is given, will return - * 0. */ -template -size_t eoffs_pfx() -{ - return 0; -} - - -template -size_t eoffs(EnumOffsetType which) -{ - switch(which) - { - case EOFFS_NONE: - return 0; - case EOFFS_CLS: - return eoffs_cls(); - case EOFFS_PFX: - { - size_t pfx = eoffs_pfx(); - return pfx > 0 ? pfx : eoffs_cls(); - } - default: - C4_ERROR("unknown offset type %d", (int)which); - return 0; - } -} - - -//----------------------------------------------------------------------------- -/** get the enum value corresponding to a c-string */ - -#ifdef __clang__ -# pragma clang diagnostic push -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# if __GNUC__ >= 6 -# pragma GCC diagnostic ignored "-Wnull-dereference" -# endif -#endif - -template -Enum str2e(const char* str) -{ - auto pairs = esyms(); - auto *p = pairs.get(str); - C4_CHECK_MSG(p != nullptr, "no valid enum pair name for '%s'", str); - return p->value; -} - -/** get the c-string corresponding to an enum value */ -template -const char* e2str(Enum e) -{ - auto es = esyms(); - auto *p = es.get(e); - C4_CHECK_MSG(p != nullptr, "no valid enum pair name"); - return p->name; -} - -/** like e2str(), but add an offset. */ -template -const char* e2stroffs(Enum e, EnumOffsetType ot=EOFFS_PFX) -{ - const char *s = e2str(e) + eoffs(ot); - return s; -} - -#ifdef __clang__ -# pragma clang diagnostic pop -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#endif - -//----------------------------------------------------------------------------- -/** Find a symbol by value. Returns nullptr when none is found */ -template -typename EnumSymbols::Sym const* EnumSymbols::find(Enum v) const -{ - for(Sym const* p = this->m_symbols, *e = p+this->m_num; p < e; ++p) - if(p->value == v) - return p; - return nullptr; -} - -/** Find a symbol by name. Returns nullptr when none is found */ -template -typename EnumSymbols::Sym const* EnumSymbols::find(const char *s) const -{ - for(Sym const* p = this->m_symbols, *e = p+this->m_num; p < e; ++p) - if(p->cmp(s)) - return p; - return nullptr; -} - -/** Find a symbol by name. Returns nullptr when none is found */ -template -typename EnumSymbols::Sym const* EnumSymbols::find(const char *s, size_t len) const -{ - for(Sym const* p = this->m_symbols, *e = p+this->m_num; p < e; ++p) - if(p->cmp(s, len)) - return p; - return nullptr; -} - -//----------------------------------------------------------------------------- -template -bool EnumSymbols::Sym::cmp(const char *s) const -{ - if(strcmp(name, s) == 0) - return true; - - for(int i = 1; i < _EOFFS_LAST; ++i) - { - auto o = eoffs((EnumOffsetType)i); - if(o > 0) - if(strcmp(name + o, s) == 0) - return true; - } - - return false; -} - -template -bool EnumSymbols::Sym::cmp(const char *s, size_t len) const -{ - if(strncmp(name, s, len) == 0) - return true; - - size_t nlen = 0; - for(int i = 1; i <_EOFFS_LAST; ++i) - { - auto o = eoffs((EnumOffsetType)i); - if(o > 0) - { - if(!nlen) - { - nlen = strlen(name); - } - C4_ASSERT(o < nlen); - size_t rem = nlen - o; - auto m = len > rem ? len : rem; - if(len >= m && strncmp(name + o, s, m) == 0) - return true; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -template -const char* EnumSymbols::Sym::name_offs(EnumOffsetType t) const -{ - C4_ASSERT(eoffs(t) < strlen(name)); - return name + eoffs(t); -} - -} // namespace c4 - -#endif // _C4_ENUM_HPP_ diff --git a/thirdparty/ryml/ext/c4core/src/c4/error.cpp b/thirdparty/ryml/ext/c4core/src/c4/error.cpp deleted file mode 100644 index ec2d2f81e..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/error.cpp +++ /dev/null @@ -1,227 +0,0 @@ -#include "c4/error.hpp" - -#include -#include -#include - -#define C4_LOGF_ERR(...) fprintf(stderr, __VA_ARGS__); fflush(stderr) -#define C4_LOGF_WARN(...) fprintf(stderr, __VA_ARGS__); fflush(stderr) -#define C4_LOGP(msg, ...) printf(msg) - -#if defined(C4_XBOX) || (defined(C4_WIN) && defined(C4_MSVC)) -# include "c4/windows.hpp" -#elif defined(C4_PS4) -# include -#elif defined(C4_UNIX) || defined(C4_LINUX) -# include -# include -# include -#elif defined(C4_MACOS) || defined(C4_IOS) -# include -# include -# include -# include -#endif -// the amalgamation tool is dumb and was omitting this include under MACOS. -// So do it only once: -#if defined(C4_UNIX) || defined(C4_LINUX) || defined(C4_MACOS) || defined(C4_IOS) -# include -#endif - -#if defined(C4_EXCEPTIONS_ENABLED) && defined(C4_ERROR_THROWS_EXCEPTION) -# include -#endif - -#ifdef __clang__ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wformat-nonliteral" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wformat-nonliteral" -#endif - - -//----------------------------------------------------------------------------- -namespace c4 { - -static error_flags s_error_flags = ON_ERROR_DEFAULTS; -static error_callback_type s_error_callback = nullptr; - -//----------------------------------------------------------------------------- - -error_flags get_error_flags() -{ - return s_error_flags; -} -void set_error_flags(error_flags flags) -{ - s_error_flags = flags; -} - -error_callback_type get_error_callback() -{ - return s_error_callback; -} -/** Set the function which is called when an error occurs. */ -void set_error_callback(error_callback_type cb) -{ - s_error_callback = cb; -} - -//----------------------------------------------------------------------------- - -void handle_error(srcloc where, const char *fmt, ...) -{ - char buf[1024]; - size_t msglen = 0; - if(s_error_flags & (ON_ERROR_LOG|ON_ERROR_CALLBACK)) - { - va_list args; - va_start(args, fmt); - int ilen = vsnprintf(buf, sizeof(buf), fmt, args); // ss.vprintf(fmt, args); - va_end(args); - msglen = ilen >= 0 && ilen < (int)sizeof(buf) ? static_cast(ilen) : sizeof(buf)-1; - } - - if(s_error_flags & ON_ERROR_LOG) - { - C4_LOGF_ERR("\n"); -#if defined(C4_ERROR_SHOWS_FILELINE) && defined(C4_ERROR_SHOWS_FUNC) - C4_LOGF_ERR("%s:%d: ERROR: %s\n", where.file, where.line, buf); - C4_LOGF_ERR("%s:%d: ERROR here: %s\n", where.file, where.line, where.func); -#elif defined(C4_ERROR_SHOWS_FILELINE) - C4_LOGF_ERR("%s:%d: ERROR: %s\n", where.file, where.line, buf); -#elif ! defined(C4_ERROR_SHOWS_FUNC) - C4_LOGF_ERR("ERROR: %s\n", buf); -#endif - } - - if(s_error_flags & ON_ERROR_CALLBACK) - { - if(s_error_callback) - { - s_error_callback(buf, msglen/*ss.c_strp(), ss.tellp()*/); - } - } - - if(s_error_flags & ON_ERROR_ABORT) - { - abort(); - } - - if(s_error_flags & ON_ERROR_THROW) - { -#if defined(C4_EXCEPTIONS_ENABLED) && defined(C4_ERROR_THROWS_EXCEPTION) - throw Exception(buf); -#else - abort(); -#endif - } -} - -//----------------------------------------------------------------------------- - -void handle_warning(srcloc where, const char *fmt, ...) -{ - va_list args; - char buf[1024]; //sstream ss; - va_start(args, fmt); - vsnprintf(buf, sizeof(buf), fmt, args); - va_end(args); - C4_LOGF_WARN("\n"); -#if defined(C4_ERROR_SHOWS_FILELINE) && defined(C4_ERROR_SHOWS_FUNC) - C4_LOGF_WARN("%s:%d: WARNING: %s\n", where.file, where.line, buf/*ss.c_strp()*/); - C4_LOGF_WARN("%s:%d: WARNING: here: %s\n", where.file, where.line, where.func); -#elif defined(C4_ERROR_SHOWS_FILELINE) - C4_LOGF_WARN("%s:%d: WARNING: %s\n", where.file, where.line, buf/*ss.c_strp()*/); -#elif ! defined(C4_ERROR_SHOWS_FUNC) - C4_LOGF_WARN("WARNING: %s\n", buf/*ss.c_strp()*/); -#endif - //c4::log.flush(); -} - -//----------------------------------------------------------------------------- -bool is_debugger_attached() -{ -#if defined(C4_UNIX) || defined(C4_LINUX) - static bool first_call = true; - static bool first_call_result = false; - if(first_call) - { - first_call = false; - //! @see http://stackoverflow.com/questions/3596781/how-to-detect-if-the-current-process-is-being-run-by-gdb - //! (this answer: http://stackoverflow.com/a/24969863/3968589 ) - char buf[1024] = ""; - - int status_fd = open("/proc/self/status", O_RDONLY); - if (status_fd == -1) - { - return 0; - } - - ssize_t num_read = ::read(status_fd, buf, sizeof(buf)); - - if (num_read > 0) - { - static const char TracerPid[] = "TracerPid:"; - char *tracer_pid; - - if(num_read < 1024) - { - buf[num_read] = 0; - } - tracer_pid = strstr(buf, TracerPid); - if (tracer_pid) - { - first_call_result = !!::atoi(tracer_pid + sizeof(TracerPid) - 1); - } - } - } - return first_call_result; -#elif defined(C4_PS4) - return (sceDbgIsDebuggerAttached() != 0); -#elif defined(C4_XBOX) || (defined(C4_WIN) && defined(C4_MSVC)) - return IsDebuggerPresent() != 0; -#elif defined(C4_MACOS) || defined(C4_IOS) - // https://stackoverflow.com/questions/2200277/detecting-debugger-on-mac-os-x - // Returns true if the current process is being debugged (either - // running under the debugger or has a debugger attached post facto). - int junk; - int mib[4]; - struct kinfo_proc info; - size_t size; - - // Initialize the flags so that, if sysctl fails for some bizarre - // reason, we get a predictable result. - - info.kp_proc.p_flag = 0; - - // Initialize mib, which tells sysctl the info we want, in this case - // we're looking for information about a specific process ID. - - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PID; - mib[3] = getpid(); - - // Call sysctl. - - size = sizeof(info); - junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0); - assert(junk == 0); - - // We're being debugged if the P_TRACED flag is set. - return ((info.kp_proc.p_flag & P_TRACED) != 0); -#else - return false; -#endif -} // is_debugger_attached() - -} // namespace c4 - - -#ifdef __clang__ -# pragma clang diagnostic pop -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#endif diff --git a/thirdparty/ryml/ext/c4core/src/c4/error.hpp b/thirdparty/ryml/ext/c4core/src/c4/error.hpp deleted file mode 100644 index 26e457bfa..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/error.hpp +++ /dev/null @@ -1,432 +0,0 @@ -#ifndef _C4_ERROR_HPP_ -#define _C4_ERROR_HPP_ - -/** @file error.hpp Facilities for error reporting and runtime assertions. */ - -/** @defgroup error_checking Error checking */ - -#include "c4/config.hpp" - -#ifdef _DOXYGEN_ - /** if this is defined and exceptions are enabled, then calls to C4_ERROR() - * will throw an exception - * @ingroup error_checking */ -# define C4_EXCEPTIONS_ENABLED - /** if this is defined and exceptions are enabled, then calls to C4_ERROR() - * will throw an exception - * @see C4_EXCEPTIONS_ENABLED - * @ingroup error_checking */ -# define C4_ERROR_THROWS_EXCEPTION - /** evaluates to noexcept when C4_ERROR might be called and - * exceptions are disabled. Otherwise, defaults to nothing. - * @ingroup error_checking */ -# define C4_NOEXCEPT -#endif // _DOXYGEN_ - -#if defined(C4_EXCEPTIONS_ENABLED) && defined(C4_ERROR_THROWS_EXCEPTION) -# define C4_NOEXCEPT -#else -# define C4_NOEXCEPT noexcept -#endif - - -namespace c4 { -namespace detail { -struct fail_type__ {}; -} // detail -} // c4 -#define C4_STATIC_ERROR(dummy_type, errmsg) \ - static_assert(std::is_same::value, errmsg) - - -//----------------------------------------------------------------------------- - -#define C4_ASSERT_SAME_TYPE(ty1, ty2) \ - C4_STATIC_ASSERT(std::is_same::value) - -#define C4_ASSERT_DIFF_TYPE(ty1, ty2) \ - C4_STATIC_ASSERT( ! std::is_same::value) - - -//----------------------------------------------------------------------------- - -#ifdef _DOXYGEN_ -/** utility macro that triggers a breakpoint when - * the debugger is attached and NDEBUG is not defined. - * @ingroup error_checking */ -# define C4_DEBUG_BREAK() -#endif // _DOXYGEN_ - - -#if defined(NDEBUG) || defined(C4_NO_DEBUG_BREAK) -# define C4_DEBUG_BREAK() -#else -# ifdef __clang__ -# pragma clang diagnostic push -# if !defined(__APPLE_CC__) -# if __clang_major__ >= 10 -# pragma clang diagnostic ignored "-Wgnu-inline-cpp-without-extern" // debugbreak/debugbreak.h:50:16: error: 'gnu_inline' attribute without 'extern' in C++ treated as externally available, this changed in Clang 10 [-Werror,-Wgnu-inline-cpp-without-extern] -# endif -# else -# if __clang_major__ >= 13 -# pragma clang diagnostic ignored "-Wgnu-inline-cpp-without-extern" // debugbreak/debugbreak.h:50:16: error: 'gnu_inline' attribute without 'extern' in C++ treated as externally available, this changed in Clang 10 [-Werror,-Wgnu-inline-cpp-without-extern] -# endif -# endif -# elif defined(__GNUC__) -# endif -# include -# define C4_DEBUG_BREAK() if(c4::is_debugger_attached()) { ::debug_break(); } -# ifdef __clang__ -# pragma clang diagnostic pop -# elif defined(__GNUC__) -# endif -#endif - -namespace c4 { -C4CORE_EXPORT bool is_debugger_attached(); -} // namespace c4 - - -//----------------------------------------------------------------------------- - -#ifdef __clang__ - /* NOTE: using , ## __VA_ARGS__ to deal with zero-args calls to - * variadic macros is not portable, but works in clang, gcc, msvc, icc. - * clang requires switching off compiler warnings for pedantic mode. - * @see http://stackoverflow.com/questions/32047685/variadic-macro-without-arguments */ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" // warning: token pasting of ',' and __VA_ARGS__ is a GNU extension -#elif defined(__GNUC__) - /* GCC also issues a warning for zero-args calls to variadic macros. - * This warning is switched on with -pedantic and apparently there is no - * easy way to turn it off as with clang. But marking this as a system - * header works. - * @see https://gcc.gnu.org/onlinedocs/cpp/System-Headers.html - * @see http://stackoverflow.com/questions/35587137/ */ -# pragma GCC system_header -#endif - - -//----------------------------------------------------------------------------- - -namespace c4 { - -typedef enum : uint32_t { - /** when an error happens and the debugger is attached, call C4_DEBUG_BREAK(). - * Without effect otherwise. */ - ON_ERROR_DEBUGBREAK = 0x01 << 0, - /** when an error happens log a message. */ - ON_ERROR_LOG = 0x01 << 1, - /** when an error happens invoke a callback if it was set with - * set_error_callback(). */ - ON_ERROR_CALLBACK = 0x01 << 2, - /** when an error happens call std::terminate(). */ - ON_ERROR_ABORT = 0x01 << 3, - /** when an error happens and exceptions are enabled throw an exception. - * Without effect otherwise. */ - ON_ERROR_THROW = 0x01 << 4, - /** the default flags. */ - ON_ERROR_DEFAULTS = ON_ERROR_DEBUGBREAK|ON_ERROR_LOG|ON_ERROR_CALLBACK|ON_ERROR_ABORT -} ErrorFlags_e; -using error_flags = uint32_t; -C4CORE_EXPORT void set_error_flags(error_flags f); -C4CORE_EXPORT error_flags get_error_flags(); - - -using error_callback_type = void (*)(const char* msg, size_t msg_size); -C4CORE_EXPORT void set_error_callback(error_callback_type cb); -C4CORE_EXPORT error_callback_type get_error_callback(); - - -//----------------------------------------------------------------------------- -/** RAII class controling the error settings inside a scope. */ -struct ScopedErrorSettings -{ - error_flags m_flags; - error_callback_type m_callback; - - explicit ScopedErrorSettings(error_callback_type cb) - : m_flags(get_error_flags()), - m_callback(get_error_callback()) - { - set_error_callback(cb); - } - explicit ScopedErrorSettings(error_flags flags) - : m_flags(get_error_flags()), - m_callback(get_error_callback()) - { - set_error_flags(flags); - } - explicit ScopedErrorSettings(error_flags flags, error_callback_type cb) - : m_flags(get_error_flags()), - m_callback(get_error_callback()) - { - set_error_flags(flags); - set_error_callback(cb); - } - ~ScopedErrorSettings() - { - set_error_flags(m_flags); - set_error_callback(m_callback); - } -}; - - -//----------------------------------------------------------------------------- - -/** source location */ -struct srcloc; - -C4CORE_EXPORT void handle_error(srcloc s, const char *fmt, ...); -C4CORE_EXPORT void handle_warning(srcloc s, const char *fmt, ...); - - -# define C4_ERROR(msg, ...) \ - do { \ - if(c4::get_error_flags() & c4::ON_ERROR_DEBUGBREAK) \ - { \ - C4_DEBUG_BREAK() \ - } \ - c4::handle_error(C4_SRCLOC(), msg, ## __VA_ARGS__); \ - } while(0) - - -# define C4_WARNING(msg, ...) \ - c4::handle_warning(C4_SRCLOC(), msg, ## __VA_ARGS__) - - -#if defined(C4_ERROR_SHOWS_FILELINE) && defined(C4_ERROR_SHOWS_FUNC) - -struct srcloc -{ - const char *file = ""; - const char *func = ""; - int line = 0; -}; -#define C4_SRCLOC() c4::srcloc{__FILE__, C4_PRETTY_FUNC, __LINE__} - -#elif defined(C4_ERROR_SHOWS_FILELINE) - -struct srcloc -{ - const char *file; - int line; -}; -#define C4_SRCLOC() c4::srcloc{__FILE__, __LINE__} - -#elif ! defined(C4_ERROR_SHOWS_FUNC) - -struct srcloc -{ -}; -#define C4_SRCLOC() c4::srcloc() - -#else -# error not implemented -#endif - - -//----------------------------------------------------------------------------- -// assertions - -// Doxygen needs this so that only one definition counts -#ifdef _DOXYGEN_ - /** Explicitly enables assertions, independently of NDEBUG status. - * This is meant to allow enabling assertions even when NDEBUG is defined. - * Defaults to undefined. - * @ingroup error_checking */ -# define C4_USE_ASSERT - /** assert that a condition is true; this is turned off when NDEBUG - * is defined and C4_USE_ASSERT is not true. - * @ingroup error_checking */ -# define C4_ASSERT - /** same as C4_ASSERT(), additionally prints a printf-formatted message - * @ingroup error_checking */ -# define C4_ASSERT_MSG - /** evaluates to C4_NOEXCEPT when C4_XASSERT is disabled; otherwise, defaults - * to noexcept - * @ingroup error_checking */ -# define C4_NOEXCEPT_A -#endif // _DOXYGEN_ - -#ifndef C4_USE_ASSERT -# ifdef NDEBUG -# define C4_USE_ASSERT 0 -# else -# define C4_USE_ASSERT 1 -# endif -#endif - -#if C4_USE_ASSERT -# define C4_ASSERT(cond) C4_CHECK(cond) -# define C4_ASSERT_MSG(cond, /*fmt, */...) C4_CHECK_MSG(cond, ## __VA_ARGS__) -# define C4_ASSERT_IF(predicate, cond) if(predicate) { C4_ASSERT(cond); } -# define C4_NOEXCEPT_A C4_NOEXCEPT -#else -# define C4_ASSERT(cond) -# define C4_ASSERT_MSG(cond, /*fmt, */...) -# define C4_ASSERT_IF(predicate, cond) -# define C4_NOEXCEPT_A noexcept -#endif - - -//----------------------------------------------------------------------------- -// extreme assertions - -// Doxygen needs this so that only one definition counts -#ifdef _DOXYGEN_ - /** Explicitly enables extreme assertions; this is meant to allow enabling - * assertions even when NDEBUG is defined. Defaults to undefined. - * @ingroup error_checking */ -# define C4_USE_XASSERT - /** extreme assertion: can be switched off independently of - * the regular assertion; use for example for bounds checking in hot code. - * Turned on only when C4_USE_XASSERT is defined - * @ingroup error_checking */ -# define C4_XASSERT - /** same as C4_XASSERT(), and additionally prints a printf-formatted message - * @ingroup error_checking */ -# define C4_XASSERT_MSG - /** evaluates to C4_NOEXCEPT when C4_XASSERT is disabled; otherwise, defaults to noexcept - * @ingroup error_checking */ -# define C4_NOEXCEPT_X -#endif // _DOXYGEN_ - -#ifndef C4_USE_XASSERT -# define C4_USE_XASSERT C4_USE_ASSERT -#endif - -#if C4_USE_XASSERT -# define C4_XASSERT(cond) C4_CHECK(cond) -# define C4_XASSERT_MSG(cond, /*fmt, */...) C4_CHECK_MSG(cond, ## __VA_ARGS__) -# define C4_XASSERT_IF(predicate, cond) if(predicate) { C4_XASSERT(cond); } -# define C4_NOEXCEPT_X C4_NOEXCEPT -#else -# define C4_XASSERT(cond) -# define C4_XASSERT_MSG(cond, /*fmt, */...) -# define C4_XASSERT_IF(predicate, cond) -# define C4_NOEXCEPT_X noexcept -#endif - - -//----------------------------------------------------------------------------- -// checks: never switched-off - -/** Check that a condition is true, or raise an error when not - * true. Unlike C4_ASSERT(), this check is not disabled in non-debug - * builds. - * @see C4_ASSERT - * @ingroup error_checking - * - * @todo add constexpr-compatible compile-time assert: - * https://akrzemi1.wordpress.com/2017/05/18/asserts-in-constexpr-functions/ - */ -#define C4_CHECK(cond) \ - do { \ - if(C4_UNLIKELY(!(cond))) \ - { \ - C4_ERROR("check failed: %s", #cond); \ - } \ - } while(0) - - -/** like C4_CHECK(), and additionally log a printf-style message. - * @see C4_CHECK - * @ingroup error_checking */ -#define C4_CHECK_MSG(cond, fmt, ...) \ - do { \ - if(C4_UNLIKELY(!(cond))) \ - { \ - C4_ERROR("check failed: " #cond "\n" fmt, ## __VA_ARGS__); \ - } \ - } while(0) - - -//----------------------------------------------------------------------------- -// Common error conditions - -#define C4_NOT_IMPLEMENTED() C4_ERROR("NOT IMPLEMENTED") -#define C4_NOT_IMPLEMENTED_MSG(/*msg, */...) C4_ERROR("NOT IMPLEMENTED: " ## __VA_ARGS__) -#define C4_NOT_IMPLEMENTED_IF(condition) do { if(C4_UNLIKELY(condition)) { C4_ERROR("NOT IMPLEMENTED"); } } while(0) -#define C4_NOT_IMPLEMENTED_IF_MSG(condition, /*msg, */...) do { if(C4_UNLIKELY(condition)) { C4_ERROR("NOT IMPLEMENTED: " ## __VA_ARGS__); } } while(0) - -#define C4_NEVER_REACH() do { C4_ERROR("never reach this point"); C4_UNREACHABLE(); } while(0) -#define C4_NEVER_REACH_MSG(/*msg, */...) do { C4_ERROR("never reach this point: " ## __VA_ARGS__); C4_UNREACHABLE(); } while(0) - - - -//----------------------------------------------------------------------------- -// helpers for warning suppression -// idea adapted from https://github.com/onqtam/doctest/ - - -#ifdef C4_MSVC -#define C4_SUPPRESS_WARNING_MSVC_PUSH __pragma(warning(push)) -#define C4_SUPPRESS_WARNING_MSVC(w) __pragma(warning(disable : w)) -#define C4_SUPPRESS_WARNING_MSVC_POP __pragma(warning(pop)) -#define C4_SUPPRESS_WARNING_MSVC_WITH_PUSH(w) \ - C4_SUPPRESS_WARNING_MSVC_PUSH \ - C4_SUPPRESS_WARNING_MSVC(w) -#else // C4_MSVC -#define C4_SUPPRESS_WARNING_MSVC_PUSH -#define C4_SUPPRESS_WARNING_MSVC(w) -#define C4_SUPPRESS_WARNING_MSVC_POP -#define C4_SUPPRESS_WARNING_MSVC_WITH_PUSH(w) -#endif // C4_MSVC - - -#ifdef C4_CLANG -#define C4_PRAGMA_TO_STR(x) _Pragma(#x) -#define C4_SUPPRESS_WARNING_CLANG_PUSH _Pragma("clang diagnostic push") -#define C4_SUPPRESS_WARNING_CLANG(w) C4_PRAGMA_TO_STR(clang diagnostic ignored w) -#define C4_SUPPRESS_WARNING_CLANG_POP _Pragma("clang diagnostic pop") -#define C4_SUPPRESS_WARNING_CLANG_WITH_PUSH(w) \ - C4_SUPPRESS_WARNING_CLANG_PUSH \ - C4_SUPPRESS_WARNING_CLANG(w) -#else // C4_CLANG -#define C4_SUPPRESS_WARNING_CLANG_PUSH -#define C4_SUPPRESS_WARNING_CLANG(w) -#define C4_SUPPRESS_WARNING_CLANG_POP -#define C4_SUPPRESS_WARNING_CLANG_WITH_PUSH(w) -#endif // C4_CLANG - - -#ifdef C4_GCC -#define C4_PRAGMA_TO_STR(x) _Pragma(#x) -#define C4_SUPPRESS_WARNING_GCC_PUSH _Pragma("GCC diagnostic push") -#define C4_SUPPRESS_WARNING_GCC(w) C4_PRAGMA_TO_STR(GCC diagnostic ignored w) -#define C4_SUPPRESS_WARNING_GCC_POP _Pragma("GCC diagnostic pop") -#define C4_SUPPRESS_WARNING_GCC_WITH_PUSH(w) \ - C4_SUPPRESS_WARNING_GCC_PUSH \ - C4_SUPPRESS_WARNING_GCC(w) -#else // C4_GCC -#define C4_SUPPRESS_WARNING_GCC_PUSH -#define C4_SUPPRESS_WARNING_GCC(w) -#define C4_SUPPRESS_WARNING_GCC_POP -#define C4_SUPPRESS_WARNING_GCC_WITH_PUSH(w) -#endif // C4_GCC - - -#define C4_SUPPRESS_WARNING_GCC_CLANG_PUSH \ - C4_SUPPRESS_WARNING_GCC_PUSH \ - C4_SUPPRESS_WARNING_CLANG_PUSH - -#define C4_SUPPRESS_WARNING_GCC_CLANG(w) \ - C4_SUPPRESS_WARNING_GCC(w) \ - C4_SUPPRESS_WARNING_CLANG(w) - -#define C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(w) \ - C4_SUPPRESS_WARNING_GCC_WITH_PUSH(w) \ - C4_SUPPRESS_WARNING_CLANG_WITH_PUSH(w) - -#define C4_SUPPRESS_WARNING_GCC_CLANG_POP \ - C4_SUPPRESS_WARNING_GCC_POP \ - C4_SUPPRESS_WARNING_CLANG_POP - -} // namespace c4 - -#ifdef __clang__ -# pragma clang diagnostic pop -#endif - -#endif /* _C4_ERROR_HPP_ */ diff --git a/thirdparty/ryml/ext/c4core/src/c4/export.hpp b/thirdparty/ryml/ext/c4core/src/c4/export.hpp deleted file mode 100644 index ffd02482f..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/export.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef C4_EXPORT_HPP_ -#define C4_EXPORT_HPP_ - -#ifdef _WIN32 - #ifdef C4CORE_SHARED - #ifdef C4CORE_EXPORTS - #define C4CORE_EXPORT __declspec(dllexport) - #else - #define C4CORE_EXPORT __declspec(dllimport) - #endif - #else - #define C4CORE_EXPORT - #endif -#else - #define C4CORE_EXPORT -#endif - -#endif /* C4CORE_EXPORT_HPP_ */ diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/.gitignore b/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/.gitignore deleted file mode 100644 index e44cb5a54..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -*.o -fib -core -core.* -cscope.out -tags -.gdb_history -test/trap -test/break -test/break-c++ diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/COPYING b/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/COPYING deleted file mode 100644 index 9e51088a5..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/COPYING +++ /dev/null @@ -1,23 +0,0 @@ -Copyright (c) 2011-2016, Scott Tsai - -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/GNUmakefile b/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/GNUmakefile deleted file mode 100644 index 17ab01f9b..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/GNUmakefile +++ /dev/null @@ -1,28 +0,0 @@ -CFLAGS := -Os -Wall -g -CXXFLAGS := $(CFLAGS) - -PROGRAMS := $(basename $(wildcard *.c test/*.c test/*.cc *.S)) - -.PHONY: all clean -all: $(PROGRAMS) -clean: - rm -f $(PROGRAMS) cscope.out tags - -%: %.S - $(CC) $(CFLAGS) -nostdlib $< -o $@ - -# Not using builtin rules due to debugbreak.h dependency -%: %.c - $(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ - -%: %.cc - $(CXX) $(CXXFLAGS) $(LDFLAGS) $< -o $@ - -test/%: CFLAGS +=-I. -test/%: CXXFLAGS +=-I. -$(PROGRAMS): debugbreak.h - -GDB ?= gdb -.PHONY: gdb -gdb: - $(GDB) -q -x debugbreak-gdb.py diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/HOW-TO-USE-DEBUGBREAK-GDB-PY.md b/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/HOW-TO-USE-DEBUGBREAK-GDB-PY.md deleted file mode 100644 index d5295c50c..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/HOW-TO-USE-DEBUGBREAK-GDB-PY.md +++ /dev/null @@ -1,33 +0,0 @@ -# How to use `debugbreak-gdb.py` - -Just add `-x debugbreak-gdb.py` to your usual GDB invocation or add `source debugbreak-gdb.py` to your `$HOME/.gdbinit`. - -Here's a sample session: - -``` -$ cd debugbreak -$ make -$ gdb -q -x debugbreak-gdb.py test/break -Reading symbols from test/break...done. - -(gdb) set disassemble-next-line 1 -(gdb) run -Starting program: /home/fedora/debugbreak/test/break - -Program received signal SIGTRAP, Trace/breakpoint trap. -main () at test/break.c:6 -6 debug_break(); - -Program received signal SIGTRAP, Trace/breakpoint trap. -main () at test/break.c:6 -6 debug_break(); -(gdb) debugbreak-step -7 printf("hello world\n"); -(gdb) debugbreak-continue -hello world -[Inferior 1 (process 12533) exited normally] -(gdb) - -``` - -On ARM and POWER, trying to use `step` or `stepi` in place of `debugbreak-step` in the sesion above wouldn't have worked as execution would be stock on the breakpoint instruction. diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/README.md b/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/README.md deleted file mode 100644 index 965092c08..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/README.md +++ /dev/null @@ -1,127 +0,0 @@ -# Debug Break - -[debugbreak.h](https://github.com/scottt/debugbreak/blob/master/debugbreak.h) allows you to put breakpoints in your C/C++ code with a call to **debug_break()**: -```C -#include -#include "debugbreak.h" - -int main() -{ - debug_break(); /* will break into debugger */ - printf("hello world\n"); - return 0; -} -``` -* Include one header file and insert calls to `debug_break()` in the code where you wish to break into the debugger. -* Supports GCC, Clang and MSVC. -* Works well on ARM, AArch64, i686, x86-64, POWER and has a fallback code path for other architectures. -* Works like the **DebugBreak()** fuction provided by [Windows](http://msdn.microsoft.com/en-us/library/ea9yy3ey.aspx) and [QNX](http://www.qnx.com/developers/docs/6.3.0SP3/neutrino/lib_ref/d/debugbreak.html). - -**License**: the very permissive [2-Clause BSD](https://github.com/scottt/debugbreak/blob/master/COPYING). - -Known Problem: if continuing execution after a debugbreak breakpoint hit doesn't work (e.g. on ARM or POWER), see [HOW-TO-USE-DEBUGBREAK-GDB-PY.md](HOW-TO-USE-DEBUGBREAK-GDB-PY.md) for a workaround. - -Implementation Notes -================================ - -The requirements for the **debug_break()** function are: -* Act as a compiler code motion barrier -* Don't cause the compiler optimizers to think the code following it can be removed -* Trigger a software breakpoint hit when executed (e.g. **SIGTRAP** on Linux) -* GDB commands like **continue**, **next**, **step**, **stepi** must work after a **debug_break()** hit - -Ideally, both GCC and Clang would provide a **__builtin_debugtrap()** that satisfies the above on all architectures and operating systems. Unfortunately, that is not the case (yet). -GCC's [__builtin_trap()](http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html#index-g_t_005f_005fbuiltin_005ftrap-3278) causes the optimizers to think the code follwing can be removed ([test/trap.c](https://github.com/scottt/debugbreak/blob/master/test/trap.c)): -```C -#include - -int main() -{ - __builtin_trap(); - printf("hello world\n"); - return 0; -} -``` -compiles to: -``` -main -0x0000000000400390 <+0>: 0f 0b ud2 -``` -Notice how the call to `printf()` is not present in the assembly output. - -Further, on i386 / x86-64 **__builtin_trap()** generates an **ud2** instruction which triggers **SIGILL** instead of **SIGTRAP**. This makes it necessary to change GDB's default behavior on **SIGILL** to not terminate the process being debugged: -``` -(gdb) handle SIGILL stop nopass -``` -Even after this, continuing execution in GDB doesn't work well on some GCC, GDB combinations. See [GCC Bugzilla 84595](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84595). - -On ARM, **__builtin_trap()** generates a call to **abort()**, making it even less suitable. - -**debug_break()** generates an **int3** instruction on i386 / x86-64 ([test/break.c](https://github.com/scottt/debugbreak/blob/master/test/break.c)): -```C -#include -#include "debugbreak.h" - -int main() -{ - debug_break(); - printf("hello world\n"); - return 0; -} -``` -compiles to: -``` -main -0x00000000004003d0 <+0>: 50 push %rax -0x00000000004003d1 <+1>: cc int3 -0x00000000004003d2 <+2>: bf a0 05 40 00 mov $0x4005a0,%edi -0x00000000004003d7 <+7>: e8 d4 ff ff ff callq 0x4003b0 -0x00000000004003dc <+12>: 31 c0 xor %eax,%eax -0x00000000004003de <+14>: 5a pop %rdx -0x00000000004003df <+15>: c3 retq -``` -which correctly trigges **SIGTRAP** and single-stepping in GDB after a **debug_break()** hit works well. - -Clang / LLVM also has a **__builtin_trap()** that generates **ud2** but further provides **__builtin_debugtrap()** that generates **int3** on i386 / x86-64 ([original LLVM intrinsic](http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20120507/142621.html), [further fixes](https://reviews.llvm.org/rL166300#96cef7d3), [Clang builtin support](https://reviews.llvm.org/rL166298)). - -On ARM, **debug_break()** generates **.inst 0xe7f001f0** in ARM mode and **.inst 0xde01** in Thumb mode which correctly triggers **SIGTRAP** on Linux. Unfortunately, stepping in GDB after a **debug_break()** hit doesn't work and requires a workaround like: -``` -(gdb) set $l = 2 -(gdb) tbreak *($pc + $l) -(gdb) jump *($pc + $l) -(gdb) # Change $l from 2 to 4 for ARM mode -``` -to jump over the instruction. -A new GDB command, **debugbreak-step**, is defined in [debugbreak-gdb.py](https://github.com/scottt/debugbreak/blob/master/debugbreak-gdb.py) to automate the above. See [HOW-TO-USE-DEBUGBREAK-GDB-PY.md](HOW-TO-USE-DEBUGBREAK-GDB-PY.md) for sample usage. -``` -$ arm-none-linux-gnueabi-gdb -x debugbreak-gdb.py test/break-c++ -<...> -(gdb) run -Program received signal SIGTRAP, Trace/breakpoint trap. -main () at test/break-c++.cc:6 -6 debug_break(); - -(gdb) debugbreak-step - -7 std::cout << "hello, world\n"; -``` - -On AArch64, **debug_break()** generates **.inst 0xd4200000**. - -See table below for the behavior of **debug_break()** on other architecturs. - -Behavior on Different Architectures ----------------- - -| Architecture | debug_break() | -| ------------- | ------------- | -| x86/x86-64 | `int3` | -| ARM mode, 32-bit | `.inst 0xe7f001f0` | -| Thumb mode, 32-bit | `.inst 0xde01` | -| AArch64, ARMv8 | `.inst 0xd4200000` | -| POWER | `.4byte 0x7d821008` | -| RISC-V | `.4byte 0x00100073` | -| MSVC compiler | `__debugbreak` | -| Apple compiler on AArch64 | `__builtin_trap()` | -| Otherwise | `raise(SIGTRAP)` | - diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/debugbreak-gdb.py b/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/debugbreak-gdb.py deleted file mode 100644 index 925f61a44..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/debugbreak-gdb.py +++ /dev/null @@ -1,183 +0,0 @@ -# Copyright (c) 2013, Scott Tsai -# -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# 1. Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. - - -# Usage: gdb -x debugbreak-gdb.py -# (gdb) debugbreak-step -# (gdb) debugbreak-continue -# -# To debug: -# (gdb) set python print-stack full - -import gdb -import re - -def _gdb_show_version_parse(version_str): - ''' - >>> s0 = 'This GDB was configured as "x86_64-redhat-linux-gnu".' - >>> s1 = 'This GDB was configured as "--host=i686-build_pc-linux-gnu --target=arm-linux-gnueabihf".' - >>> s2 = 'This GDB was configured as "x86_64-unknown-linux-gnu".' - >>> _gdb_show_version_parse(s0) == dict(target='x86_64-redhat-linux-gnu') - True - >>> _gdb_show_version_parse(s1) == dict(host='i686-build_pc-linux-gnu', target='arm-linux-gnueabihf') - True - >>> _gdb_show_version_parse(s2) == dict(target='x86_64-unknown-linux-gnu') - True - ''' - - t = version_str - msg = 'This GDB was configured as "' - s = t.find(msg) - if s == -1: - raise ValueError - s += len(msg) - e = t.find('".', s) - if e == -1: - raise ValueError - - config = t[s:e] - d = {} - for i in config.split(): - i = i.strip() - if i.startswith('--'): - (k, v) = i[2:].split('=') - d[k] = v - else: - if not i: - continue - d['target'] = i - return d - -def _target_triplet(): - ''' - -> 'arm-linux-gnueabihf' or 'x86_64-redhat-linux-gnu' or ... - - >>> import re - >>> not not re.match(r'\w*-\w*-\w*', target_triplet()) - True - ''' - t = gdb.execute('show version', to_string=True) - return _gdb_show_version_parse(t)['target'] - -temp_breakpoint_num = None - -def on_stop_event(e): - global temp_breakpoint_num - if not isinstance(e, gdb.BreakpointEvent): - return - for bp in e.breakpoints: - if bp.number == temp_breakpoint_num: - bp.delete() - gdb.events.stop.disconnect(on_stop_event) - l = gdb.find_pc_line(int(gdb.parse_and_eval('$pc'))).line - gdb.execute('list %d, %d' % (l, l)) - break - -def _next_instn_jump_len(gdb_frame): - '-> None means don\'t jump' - try: - arch_name = gdb_frame.architecture().name() - except AttributeError: - arch_name = None - - if arch_name.startswith('powerpc:'): - # 'powerpc:common64' on ppc64 big endian - i = bytes(gdb.selected_inferior().read_memory(gdb.parse_and_eval('$pc'), 4)) - if (i == b'\x7d\x82\x10\x08') or (i == b'\x08\x10\x82\x7d'): - return 4 - else: # not stopped on a breakpoint instruction - return None - - triplet = _target_triplet() - if re.match(r'^arm-', triplet): - i = bytes(gdb.selected_inferior().read_memory(gdb.parse_and_eval('$pc'), 4)) - if i == b'\xf0\x01\xf0\xe7': - return 4 - elif i.startswith(b'\x01\xde'): - return 2 - elif i == b'\xf0\xf7\x00\xa0 ': - # 'arm_linux_thumb2_le_breakpoint' from arm-linux-tdep.c in GDB - return 4 - else: # not stopped on a breakpoint instruction - return None - return None - -def _debugbreak_step(): - global temp_breakpoint_num - try: - frame = gdb.selected_frame() - except gdb.error as e: - # 'No frame is currently selected.' - gdb.write(e.args[0] + '\n', gdb.STDERR) - return - instn_len = _next_instn_jump_len(frame) - - if instn_len is None: - gdb.execute('stepi') - else: - loc = '*($pc + %d)' % (instn_len,) - bp = gdb.Breakpoint(loc, gdb.BP_BREAKPOINT, internal=True) - bp.silent = True - temp_breakpoint_num = bp.number - gdb.events.stop.connect(on_stop_event) - gdb.execute('jump ' + loc) - -def _debugbreak_continue(): - try: - frame = gdb.selected_frame() - except gdb.error as e: - # 'No frame is currently selected.' - gdb.write(e.args[0] + '\n', gdb.STDERR) - return - instn_len = _next_instn_jump_len(frame) - - if instn_len is None: - gdb.execute('continue') - else: - loc = '*($pc + %d)' % (instn_len,) - gdb.execute('jump ' + loc) - -class _DebugBreakStep(gdb.Command): - '''Usage: debugbreak-step - Step one instruction after a debug_break() breakpoint hit''' - - def __init__(self): - gdb.Command.__init__(self, 'debugbreak-step', gdb.COMMAND_BREAKPOINTS, gdb.COMPLETE_NONE) - - def invoke(self, arg, from_tty): - _debugbreak_step() - -class _DebugBreakContinue(gdb.Command): - '''Usage: debugbreak-continue - Continue execution after a debug_break() breakpoint hit''' - - def __init__(self): - gdb.Command.__init__(self, 'debugbreak-continue', gdb.COMMAND_BREAKPOINTS, gdb.COMPLETE_NONE) - - def invoke(self, arg, from_tty): - _debugbreak_continue() - -_DebugBreakStep() -_DebugBreakContinue() diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/debugbreak.h b/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/debugbreak.h deleted file mode 100644 index bfb828846..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/debugbreak.h +++ /dev/null @@ -1,174 +0,0 @@ -/* Copyright (c) 2011-2021, Scott Tsai - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef DEBUG_BREAK_H -#define DEBUG_BREAK_H - -#ifdef _MSC_VER - -#define debug_break __debugbreak - -#else - -#ifdef __cplusplus -extern "C" { -#endif - -#define DEBUG_BREAK_USE_TRAP_INSTRUCTION 1 -#define DEBUG_BREAK_USE_BULTIN_TRAP 2 -#define DEBUG_BREAK_USE_SIGTRAP 3 - -#if defined(__i386__) || defined(__x86_64__) - #define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_TRAP_INSTRUCTION -__inline__ static void trap_instruction(void) -{ - __asm__ volatile("int $0x03"); -} -#elif defined(__thumb__) - #define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_TRAP_INSTRUCTION -/* FIXME: handle __THUMB_INTERWORK__ */ -__attribute__((always_inline)) -__inline__ static void trap_instruction(void) -{ - /* See 'arm-linux-tdep.c' in GDB source. - * Both instruction sequences below work. */ -#if 1 - /* 'eabi_linux_thumb_le_breakpoint' */ - __asm__ volatile(".inst 0xde01"); -#else - /* 'eabi_linux_thumb2_le_breakpoint' */ - __asm__ volatile(".inst.w 0xf7f0a000"); -#endif - - /* Known problem: - * After a breakpoint hit, can't 'stepi', 'step', or 'continue' in GDB. - * 'step' would keep getting stuck on the same instruction. - * - * Workaround: use the new GDB commands 'debugbreak-step' and - * 'debugbreak-continue' that become available - * after you source the script from GDB: - * - * $ gdb -x debugbreak-gdb.py <... USUAL ARGUMENTS ...> - * - * 'debugbreak-step' would jump over the breakpoint instruction with - * roughly equivalent of: - * (gdb) set $instruction_len = 2 - * (gdb) tbreak *($pc + $instruction_len) - * (gdb) jump *($pc + $instruction_len) - */ -} -#elif defined(__arm__) && !defined(__thumb__) - #define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_TRAP_INSTRUCTION -__attribute__((always_inline)) -__inline__ static void trap_instruction(void) -{ - /* See 'arm-linux-tdep.c' in GDB source, - * 'eabi_linux_arm_le_breakpoint' */ - __asm__ volatile(".inst 0xe7f001f0"); - /* Known problem: - * Same problem and workaround as Thumb mode */ -} -#elif defined(__aarch64__) && defined(__APPLE__) - #define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_BULTIN_DEBUGTRAP -#elif defined(__aarch64__) - #define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_TRAP_INSTRUCTION -__attribute__((always_inline)) -__inline__ static void trap_instruction(void) -{ - /* See 'aarch64-tdep.c' in GDB source, - * 'aarch64_default_breakpoint' */ - __asm__ volatile(".inst 0xd4200000"); -} -#elif defined(__powerpc__) - /* PPC 32 or 64-bit, big or little endian */ - #define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_TRAP_INSTRUCTION -__attribute__((always_inline)) -__inline__ static void trap_instruction(void) -{ - /* See 'rs6000-tdep.c' in GDB source, - * 'rs6000_breakpoint' */ - __asm__ volatile(".4byte 0x7d821008"); - - /* Known problem: - * After a breakpoint hit, can't 'stepi', 'step', or 'continue' in GDB. - * 'step' stuck on the same instruction ("twge r2,r2"). - * - * The workaround is the same as ARM Thumb mode: use debugbreak-gdb.py - * or manually jump over the instruction. */ -} -#elif defined(__riscv) - /* RISC-V 32 or 64-bit, whether the "C" extension - * for compressed, 16-bit instructions are supported or not */ - #define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_TRAP_INSTRUCTION -__attribute__((always_inline)) -__inline__ static void trap_instruction(void) -{ - /* See 'riscv-tdep.c' in GDB source, - * 'riscv_sw_breakpoint_from_kind' */ - __asm__ volatile(".4byte 0x00100073"); -} -#else - #define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_SIGTRAP -#endif - - -#ifndef DEBUG_BREAK_IMPL -#error "debugbreak.h is not supported on this target" -#elif DEBUG_BREAK_IMPL == DEBUG_BREAK_USE_TRAP_INSTRUCTION -__attribute__((always_inline)) -__inline__ static void debug_break(void) -{ - trap_instruction(); -} -#elif DEBUG_BREAK_IMPL == DEBUG_BREAK_USE_BULTIN_DEBUGTRAP -__attribute__((always_inline)) -__inline__ static void debug_break(void) -{ - __builtin_debugtrap(); -} -#elif DEBUG_BREAK_IMPL == DEBUG_BREAK_USE_BULTIN_TRAP -__attribute__((always_inline)) -__inline__ static void debug_break(void) -{ - __builtin_trap(); -} -#elif DEBUG_BREAK_IMPL == DEBUG_BREAK_USE_SIGTRAP -#include -__attribute__((always_inline)) -__inline__ static void debug_break(void) -{ - raise(SIGTRAP); -} -#else -#error "invalid DEBUG_BREAK_IMPL value" -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* ifdef _MSC_VER */ - -#endif /* ifndef DEBUG_BREAK_H */ diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/test/break-c++.cc b/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/test/break-c++.cc deleted file mode 100644 index 0fcce848e..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/test/break-c++.cc +++ /dev/null @@ -1,9 +0,0 @@ -#include -#include "debugbreak.h" - -int main() -{ - debug_break(); - std::cout << "hello, world\n"; - return 0; -} diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/test/break.c b/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/test/break.c deleted file mode 100644 index fde701e56..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/test/break.c +++ /dev/null @@ -1,9 +0,0 @@ -#include -#include "debugbreak.h" - -int main() -{ - debug_break(); - printf("hello world\n"); - return 0; -} diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/test/break.gdb b/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/test/break.gdb deleted file mode 100644 index e8edab33a..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/test/break.gdb +++ /dev/null @@ -1,2 +0,0 @@ -file break -run diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/test/fib.c b/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/test/fib.c deleted file mode 100644 index 0bd26bc22..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/test/fib.c +++ /dev/null @@ -1,21 +0,0 @@ -#include - -#include "debugbreak.h" - -int fib(int n) -{ - int r; - if (n == 0 || n == 1) - return 1; - r = fib(n-1) + fib(n-2); - if (r == 89) { - debug_break(); - } - return r; -} - -int main() -{ - printf("%d\n", fib(15)); - return 0; -} diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/test/fib.gdb b/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/test/fib.gdb deleted file mode 100644 index 2cd54a4cb..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/test/fib.gdb +++ /dev/null @@ -1,2 +0,0 @@ -file fib -run diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/test/test-debugbreak.gdb b/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/test/test-debugbreak.gdb deleted file mode 100644 index 96e48484e..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/test/test-debugbreak.gdb +++ /dev/null @@ -1,6 +0,0 @@ -source ../debugbreak-gdb.py - -file break-c++ -# set remote exec-file break-c++ -run -#debugbreak-step diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/test/trap.c b/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/test/trap.c deleted file mode 100644 index 9def30b68..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/test/trap.c +++ /dev/null @@ -1,8 +0,0 @@ -#include - -int main() -{ - __builtin_trap(); - printf("hello world\n"); - return 0; -} diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/test/trap.gdb b/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/test/trap.gdb deleted file mode 100644 index 6cd59bd98..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/debugbreak/test/trap.gdb +++ /dev/null @@ -1,3 +0,0 @@ -file trap -handle SIGILL stop nopass -run diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float.hpp b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float.hpp deleted file mode 100644 index 9e75b5e14..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef _C4_EXT_FAST_FLOAT_HPP_ -#define _C4_EXT_FAST_FLOAT_HPP_ - -#ifdef _MSC_VER -# pragma warning(push) -# pragma warning(disable: 4996) // snprintf/scanf: this function or variable may be unsafe -#elif defined(__clang__) || defined(__APPLE_CC__) || defined(_LIBCPP_VERSION) -# pragma clang diagnostic push -# if (defined(__clang_major__) && _clang_major__ >= 9) || defined(__APPLE_CC__) -# pragma clang diagnostic ignored "-Wfortify-source" -# endif -# pragma clang diagnostic ignored "-Wshift-count-overflow" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wuseless-cast" -#endif - -#include "c4/ext/fast_float_all.h" - -#ifdef _MSC_VER -# pragma warning(pop) -#elif defined(__clang__) || defined(__APPLE_CC__) -# pragma clang diagnostic pop -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#endif - -#endif // _C4_EXT_FAST_FLOAT_HPP_ diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.cirrus.yml b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.cirrus.yml deleted file mode 100644 index ad6c3458b..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.cirrus.yml +++ /dev/null @@ -1,22 +0,0 @@ - -task: - timeout_in: 120m - freebsd_instance: - matrix: - - image_family: freebsd-13-0-snap - - env: - ASSUME_ALWAYS_YES: YES - setup_script: - - pkg update -f - - pkg install bash - - pkg install cmake - - pkg install git - build_script: - - mkdir build - - cd build - - cmake -DFASTFLOAT_TEST=ON .. - - make - test_script: - - cd build - - ctest --output-on-failure -R basictest diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/alpine.yml b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/alpine.yml deleted file mode 100644 index 825937673..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/alpine.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Alpine Linux -'on': - - push - - pull_request -jobs: - ubuntu-build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: start docker - run: | - docker run -w /src -dit --name alpine -v $PWD:/src alpine:latest - echo 'docker exec alpine "$@";' > ./alpine.sh - chmod +x ./alpine.sh - - name: install packages - run: | - ./alpine.sh apk update - ./alpine.sh apk add build-base cmake g++ linux-headers git bash - - name: cmake - run: | - ./alpine.sh cmake -DFASTFLOAT_TEST=ON -B build_for_alpine - - name: build - run: | - ./alpine.sh cmake --build build_for_alpine - - name: test - run: | - ./alpine.sh bash -c "cd build_for_alpine && ctest -R basictest" \ No newline at end of file diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/amalgamate-ubuntu20.yml b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/amalgamate-ubuntu20.yml deleted file mode 100644 index 3d4771431..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/amalgamate-ubuntu20.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: Amalgamate Ubuntu 20.04 CI (GCC 9, 8) - -on: [push, pull_request] - -jobs: - ubuntu-build: - runs-on: ubuntu-20.04 - strategy: - fail-fast: false - matrix: - include: - # Legacy/x86 compilers cause CI failures. - #- {cxx: -DCMAKE_CXX_COMPILER=g++-8, arch: } - - {cxx: , arch: } # default=gcc9 - #- {cxx: , arch: -DCMAKE_CXX_FLAGS="-m32"} # default=gcc9 - steps: - - uses: actions/checkout@v2 - - name: Compile with amalgamation - run: | - mkdir build && - mkdir build/fast_float && - python3 ./script/amalgamate.py > build/fast_float/fast_float.h && - cp tests/string_test.cpp build/ && - cd build && - g++ string_test.cpp diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/msys2-clang.yml b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/msys2-clang.yml deleted file mode 100644 index ba16f4367..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/msys2-clang.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: MSYS2-CLANG-CI - -on: [push, pull_request] - -jobs: - windows-mingw: - name: ${{ matrix.msystem }} - runs-on: windows-latest - defaults: - run: - shell: msys2 {0} - strategy: - fail-fast: false - matrix: - include: - - msystem: "MINGW64" - install: mingw-w64-x86_64-libxml2 mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja mingw-w64-x86_64-clang - type: Release - - msystem: "MINGW32" - install: mingw-w64-i686-libxml2 mingw-w64-i686-cmake mingw-w64-i686-ninja mingw-w64-i686-clang - type: Release - env: - CMAKE_GENERATOR: Ninja - - steps: - - uses: actions/checkout@v2 - - uses: msys2/setup-msys2@v2 - with: - update: true - msystem: ${{ matrix.msystem }} - install: ${{ matrix.install }} - - name: Prepare build dir - run: mkdir build - - name: Configure - run: cd build && cmake -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=${{ matrix.type }} -DFASTFLOAT_TEST=ON .. - - name: Build - run: cmake --build build - - name: Run basic tests - run: cd build && ctest --output-on-failure -R basictest diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/msys2.yml b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/msys2.yml deleted file mode 100644 index 665c53916..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/msys2.yml +++ /dev/null @@ -1,45 +0,0 @@ -name: MSYS2-CI - -on: [push, pull_request] - -jobs: - windows-mingw: - name: ${{ matrix.msystem }} - runs-on: windows-latest - defaults: - run: - shell: msys2 {0} - strategy: - fail-fast: false - matrix: - include: - - msystem: "MINGW64" - install: mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja mingw-w64-x86_64-gcc - type: Release - - msystem: "MINGW32" - install: mingw-w64-i686-cmake mingw-w64-i686-ninja mingw-w64-i686-gcc - type: Release - - msystem: "MINGW64" - install: mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja mingw-w64-x86_64-gcc - type: Debug - - msystem: "MINGW32" - install: mingw-w64-i686-cmake mingw-w64-i686-ninja mingw-w64-i686-gcc - type: Debug - env: - CMAKE_GENERATOR: Ninja - - steps: - - uses: actions/checkout@v2 - - uses: msys2/setup-msys2@v2 - with: - update: true - msystem: ${{ matrix.msystem }} - install: ${{ matrix.install }} - - name: Prepare build dir - run: mkdir build - - name: Configure - run: cd build && cmake -DCMAKE_BUILD_TYPE=${{ matrix.type }} -DFASTFLOAT_TEST=ON .. - - name: Build - run: cmake --build build - - name: Run basic tests - run: cd build && ctest --output-on-failure -R basictest diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/ubuntu18.yml b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/ubuntu18.yml deleted file mode 100644 index dbdaa7adc..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/ubuntu18.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: Ubuntu 18.04 CI (GCC 7, 6, 5) - -on: [push, pull_request] - -jobs: - ubuntu-build: - runs-on: ubuntu-18.04 - strategy: - fail-fast: false - matrix: - include: - # Legacy/x86 compilers cause CI failures. - #- {cxx: -DCMAKE_CXX_COMPILER=g++-5, arch: } - #- {cxx: -DCMAKE_CXX_COMPILER=g++-6, arch: } - - {cxx: , arch: } # default=gcc7 - #- {cxx: , arch: -DCMAKE_CXX_FLAGS="-m32"} # default=gcc7 - steps: - - uses: actions/checkout@v2 - - name: Setup cmake - uses: jwlawson/actions-setup-cmake@v1.4 - with: - cmake-version: '3.11.x' - #- name: Install older compilers - # run: | - # sudo -E dpkg --add-architecture i386 - # sudo -E apt-get update - # sudo -E apt-get install -y --force-yes g++-5 g++-6 g++-5-multilib g++-6-multilib g++-multilib linux-libc-dev:i386 libc6:i386 libc6-dev:i386 libc6-dbg:i386 - - name: Prepare build dir - run: mkdir build - - name: Configure - run: cd build && cmake ${{matrix.cxx}} ${{matrix.arch}} -DFASTFLOAT_TEST=ON .. - - name: Build - run: cmake --build build - - name: Run basic tests - run: cd build && ctest --output-on-failure -R basictest diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/ubuntu20-cxx20.yml b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/ubuntu20-cxx20.yml deleted file mode 100644 index a8b9acbc2..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/ubuntu20-cxx20.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: Ubuntu 20.04 CI (C++20) - -on: [push, pull_request] - -jobs: - ubuntu-build: - runs-on: ubuntu-20.04 - strategy: - fail-fast: false - steps: - - uses: actions/checkout@v2 - - name: Use cmake - run: | - mkdir build && - cd build && - cmake -DCMAKE_CXX_STANDARD=20 -DFASTFLOAT_TEST=ON -DCMAKE_INSTALL_PREFIX:PATH=destination .. && - cmake --build . && - ctest --output-on-failure && - cmake --install . diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/ubuntu20.yml b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/ubuntu20.yml deleted file mode 100644 index ebd8b23bc..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/ubuntu20.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: Ubuntu 20.04 CI (GCC 9) - -on: [push, pull_request] - -jobs: - ubuntu-build: - runs-on: ubuntu-20.04 - strategy: - fail-fast: false - matrix: - include: - # Legacy/x86 compilers cause CI failures. - #- {cxx: -DCMAKE_CXX_COMPILER=g++-8, arch: } - - {cxx: , arch: } # default=gcc9 - #- {cxx: , arch: -DCMAKE_CXX_FLAGS="-m32"} # default=gcc9 - steps: - - uses: actions/checkout@v2 - - name: Use cmake - run: | - mkdir build && - cd build && - cmake ${{matrix.cxx}} ${{matrix.arch}} -DFASTFLOAT_TEST=ON -DCMAKE_INSTALL_PREFIX:PATH=destination .. && - cmake --build . && - ctest --output-on-failure && - cmake --install . && - cd ../tests/installation_tests/find && - mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../build/destination .. && cmake --build . && - cd ../../issue72_installation && - mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../build/destination .. && cmake --build . diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/vs15-ci.yml b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/vs15-ci.yml deleted file mode 100644 index a6207a7ad..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/vs15-ci.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: VS15-CI - -on: [push, pull_request] - -jobs: - ci: - if: >- - ! contains(toJSON(github.event.commits.*.message), '[skip ci]') && - ! contains(toJSON(github.event.commits.*.message), '[skip github]') - name: windows-vs15 - runs-on: windows-2016 - strategy: - fail-fast: false - matrix: - include: - - {gen: Visual Studio 15 2017, arch: Win32} - - {gen: Visual Studio 15 2017, arch: x64} - steps: - - uses: actions/checkout@v2 - - name: Configure - run: | - mkdir build - cd build && cmake -G "${{matrix.gen}}" -A ${{matrix.arch}} -DFASTFLOAT_TEST=ON .. - - name: Build - run: cmake --build build --verbose --config Release --parallel - - name: 'Run CTest' - run: | - cd build - ctest -C Release --output-on-failure -R basictest \ No newline at end of file diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/vs16-arm-ci.yml b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/vs16-arm-ci.yml deleted file mode 100644 index 7c69e38f1..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/vs16-arm-ci.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: VS16-ARM-CI - -on: [push, pull_request] - -jobs: - ci: - name: windows-vs16 - runs-on: windows-latest - strategy: - fail-fast: false - matrix: - include: - - {arch: ARM} - - {arch: ARM64} - steps: - - name: checkout - uses: actions/checkout@v2 - - name: Use cmake - run: | - cmake -A ${{ matrix.arch }} -DCMAKE_CROSSCOMPILING=1 -DFASTFLOAT_TEST=ON -B build && - cmake --build build --verbose \ No newline at end of file diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/vs16-ci.yml b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/vs16-ci.yml deleted file mode 100644 index fe40dddc9..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/vs16-ci.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: VS16-CI - -on: [push, pull_request] - -jobs: - ci: - name: windows-vs16 - runs-on: windows-latest - strategy: - fail-fast: false - matrix: - include: - - {gen: Visual Studio 16 2019, arch: Win32} - - {gen: Visual Studio 16 2019, arch: x64} - steps: - - name: checkout - uses: actions/checkout@v2 - - name: Use cmake - run: | - mkdir build && - cd build && - cmake ${{matrix.cxx}} ${{matrix.arch}} -DFASTFLOAT_TEST=ON -DCMAKE_INSTALL_PREFIX:PATH=destination .. && - cmake --build . --verbose && - ctest --output-on-failure && - cmake --install . && - cd ../tests/installation_tests/find && - mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../build/destination .. && cmake --build . --verbose - cd ../../issue72_installation && - mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../build/destination .. && cmake --build . --verbose \ No newline at end of file diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/vs16-clang-ci.yml b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/vs16-clang-ci.yml deleted file mode 100644 index a32c6b822..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/vs16-clang-ci.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: VS16-CLANG-CI - -on: [push, pull_request] - -jobs: - ci: - name: windows-vs16 - runs-on: windows-latest - strategy: - fail-fast: false - matrix: - include: - - {gen: Visual Studio 16 2019, arch: Win32} - - {gen: Visual Studio 16 2019, arch: x64} - steps: - - name: checkout - uses: actions/checkout@v2 - - name: Configure - run: | - mkdir build - cd build && cmake -G "${{matrix.gen}}" -A ${{matrix.arch}} -T ClangCL -DFASTFLOAT_TEST=ON .. - - name: Build - run: cmake --build build --config Release --parallel - - name: Run basic tests - run: | - cd build - ctest -C Release --output-on-failure -R basictest diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/vs16-cxx20.yml b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/vs16-cxx20.yml deleted file mode 100644 index 3a770935f..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.github/workflows/vs16-cxx20.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: VS16-CI C++20 - -on: [push, pull_request] - -jobs: - ci: - name: windows-vs16 - runs-on: windows-latest - strategy: - fail-fast: false - matrix: - include: - - {gen: Visual Studio 16 2019, arch: Win32} - - {gen: Visual Studio 16 2019, arch: x64} - steps: - - name: checkout - uses: actions/checkout@v2 - - name: Use cmake - run: | - mkdir build && - cd build && - cmake ${{matrix.cxx}} ${{matrix.arch}} -DCMAKE_CXX_STANDARD=20 -DFASTFLOAT_TEST=ON -DCMAKE_INSTALL_PREFIX:PATH=destination .. && - cmake --build . --verbose && - ctest --output-on-failure diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.gitignore b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.gitignore deleted file mode 100644 index 15665575e..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -build/* -Testing/* -.cache/ -compile_commands.json diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.travis.yml b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.travis.yml deleted file mode 100644 index ae854aed8..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/.travis.yml +++ /dev/null @@ -1,242 +0,0 @@ -language: cpp - -dist: bionic - -cache: - directories: - - $HOME/.dep_cache - -env: - global: - - fastfloat_DEPENDENCY_CACHE_DIR=$HOME/.dep_cache - -services: - - docker - -# the ppc64le and s390x images use cmake 3.10, but fast_float requires 3.11. -# so we compile cmake from source in those images. -# - tried the kitware ppa but that is using 3.10 as well -# - tried also using snap to get a more recent version but that failed with -# udev errors. - -matrix: - include: - - arch: ppc64le - os: linux - env: - - CMAKE_SRC="https://github.com/Kitware/CMake/releases/download/v3.11.4/cmake-3.11.4.tar.gz" - - - arch: s390x - os: linux - env: - - CMAKE_SRC="https://github.com/Kitware/CMake/releases/download/v3.11.4/cmake-3.11.4.tar.gz" - - - arch: amd64 - os: linux - - - arch: amd64 - os: linux - addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - g++-8 - env: - - COMPILER="CC=gcc-8 && CXX=g++-8" - compiler: gcc-8 - - - arch: amd64 - os: linux - addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - g++-9 - env: - - COMPILER="CC=gcc-9 && CXX=g++-9" - compiler: gcc-9 - - - arch: amd64 - os: linux - addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - g++-10 - env: - - COMPILER="CC=gcc-10 && CXX=g++-10" - compiler: gcc-10 - - - arch: amd64 - os: linux - addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - g++-10 - env: - - COMPILER="CC=gcc-10 && CXX=g++-10" - - SANITIZE="on" - compiler: gcc-10-sanitize - - - arch: amd64 - os: linux - addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - g++-10 - env: - - COMPILER="CC=gcc-10 && CXX=g++-10" - - STATIC="on" - acompiler: gcc-10-static - - - arch: amd64 - os: linux - addons: - apt: - sources: - - llvm-toolchain-bionic-6.0 - packages: - - clang-6.0 - env: - - COMPILER="CC=clang-6.0 && CXX=clang++-6.0" - compiler: clang-6 - - - arch: amd64 - os: linux - addons: - apt: - sources: - - llvm-toolchain-bionic-7 - packages: - - clang-7 - env: - - COMPILER="CC=clang-7 && CXX=clang++-7" - compiler: clang-7 - - - arch: amd64 - os: linux - addons: - apt: - sources: - - llvm-toolchain-bionic-8 - packages: - - clang-8 - env: - - COMPILER="CC=clang-8 && CXX=clang++-8" - compiler: clang-8 - - - arch: amd64 - os: linux - addons: - apt: - sources: - - llvm-toolchain-bionic-9 - packages: - - clang-9 - env: - - COMPILER="CC=clang-9 && CXX=clang++-9" - compiler: clang-9 - - - arch: amd64 - os: linux - addons: - apt: - packages: - - clang-10 - sources: - - ubuntu-toolchain-r-test - - sourceline: 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main' - key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key' - env: - - COMPILER="CC=clang-10 && CXX=clang++-10" - compiler: clang-10 - - - arch: amd64 - os: linux - addons: - apt: - packages: - - clang-10 - sources: - - ubuntu-toolchain-r-test - - sourceline: 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main' - key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key' - env: - - COMPILER="CC=clang-10 && CXX=clang++-10" - - STATIC="on" - compiler: clang-10-static - - - arch: amd64 - os: linux - addons: - apt: - packages: - - clang-10 - sources: - - ubuntu-toolchain-r-test - - sourceline: 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main' - key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key' - env: - - COMPILER="CC=clang-10 && CXX=clang++-10" - - SANITIZE="on" - compiler: clang-10-sanitize - - - arch: amd64 - os: linux - env: - - TOOLCHAIN="mips64" - - - arch: amd64 - os: linux - env: - - TOOLCHAIN="riscv64" - -before_install: - - eval "${COMPILER}" - - | - if [ "$TOOLCHAIN" != "" ] ; then - docker pull ahuszagh/cross:"$TOOLCHAIN" - fi - -install: - - | - if [ "$CMAKE_SRC" != "" ] ; then - set -x - set -e - sudo -E apt remove --purge cmake - sudo -E apt-get update - sudo -E apt-get install -y build-essential libssl-dev - mkdir cmake_src - pushd cmake_src - wget "$CMAKE_SRC" - tar xfz $(basename "$CMAKE_SRC") - pushd $(basename "$CMAKE_SRC" | sed "s:.tar.gz::") - ./bootstrap - make -j2 - sudo make install - popd - popd - set +x - fi - - echo ${PATH} - - which cmake - - cmake --version - - which ${CC} - - ${CC} --version - - which ${CXX} - - ${CXX} --version - -script: - - | - if [ "$TOOLCHAIN" != "" ] ; then - docker run -v "$(pwd)":/ff ahuszagh/cross:"$TOOLCHAIN" /bin/bash -c "cd ff && ci/script.sh $TOOLCHAIN" - else - ci/script.sh - fi diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/AUTHORS b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/AUTHORS deleted file mode 100644 index 60c942582..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/AUTHORS +++ /dev/null @@ -1,2 +0,0 @@ -Daniel Lemire -João Paulo Magalhaes diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/CONTRIBUTORS b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/CONTRIBUTORS deleted file mode 100644 index 58a037cc5..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/CONTRIBUTORS +++ /dev/null @@ -1,6 +0,0 @@ -Eugene Golushkov -Maksim Kita -Marcin Wojdyr -Neal Richardson -Tim Paine -Fabio Pellacini diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/LICENSE-APACHE b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/LICENSE-APACHE deleted file mode 100644 index 79e59131d..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2020 The fast_float authors - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/LICENSE-MIT b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/LICENSE-MIT deleted file mode 100644 index 31aa79387..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/LICENSE-MIT +++ /dev/null @@ -1,23 +0,0 @@ -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/README.md b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/README.md deleted file mode 100644 index 059b9dade..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/README.md +++ /dev/null @@ -1,216 +0,0 @@ -## fast_float number parsing library: 4x faster than strtod - -![Ubuntu 20.04 CI (GCC 9)](https://github.com/lemire/fast_float/workflows/Ubuntu%2020.04%20CI%20(GCC%209)/badge.svg) -![Ubuntu 18.04 CI (GCC 7)](https://github.com/lemire/fast_float/workflows/Ubuntu%2018.04%20CI%20(GCC%207)/badge.svg) -![Alpine Linux](https://github.com/lemire/fast_float/workflows/Alpine%20Linux/badge.svg) -![MSYS2-CI](https://github.com/lemire/fast_float/workflows/MSYS2-CI/badge.svg) -![VS16-CLANG-CI](https://github.com/lemire/fast_float/workflows/VS16-CLANG-CI/badge.svg) -[![VS16-CI](https://github.com/fastfloat/fast_float/actions/workflows/vs16-ci.yml/badge.svg)](https://github.com/fastfloat/fast_float/actions/workflows/vs16-ci.yml) - -The fast_float library provides fast header-only implementations for the C++ from_chars -functions for `float` and `double` types. These functions convert ASCII strings representing -decimal values (e.g., `1.3e10`) into binary types. We provide exact rounding (including -round to even). In our experience, these `fast_float` functions many times faster than comparable number-parsing functions from existing C++ standard libraries. - -Specifically, `fast_float` provides the following two functions with a C++17-like syntax (the library itself only requires C++11): - -```C++ -from_chars_result from_chars(const char* first, const char* last, float& value, ...); -from_chars_result from_chars(const char* first, const char* last, double& value, ...); -``` - -The return type (`from_chars_result`) is defined as the struct: -```C++ -struct from_chars_result { - const char* ptr; - std::errc ec; -}; -``` - -It parses the character sequence [first,last) for a number. It parses floating-point numbers expecting -a locale-independent format equivalent to the C++17 from_chars function. -The resulting floating-point value is the closest floating-point values (using either float or double), -using the "round to even" convention for values that would otherwise fall right in-between two values. -That is, we provide exact parsing according to the IEEE standard. - - -Given a successful parse, the pointer (`ptr`) in the returned value is set to point right after the -parsed number, and the `value` referenced is set to the parsed value. In case of error, the returned -`ec` contains a representative error, otherwise the default (`std::errc()`) value is stored. - -The implementation does not throw and does not allocate memory (e.g., with `new` or `malloc`). - -It will parse infinity and nan values. - -Example: - -``` C++ -#include "fast_float/fast_float.h" -#include - -int main() { - const std::string input = "3.1416 xyz "; - double result; - auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result); - if(answer.ec != std::errc()) { std::cerr << "parsing failure\n"; return EXIT_FAILURE; } - std::cout << "parsed the number " << result << std::endl; - return EXIT_SUCCESS; -} -``` - - -Like the C++17 standard, the `fast_float::from_chars` functions take an optional last argument of -the type `fast_float::chars_format`. It is a bitset value: we check whether -`fmt & fast_float::chars_format::fixed` and `fmt & fast_float::chars_format::scientific` are set -to determine whether we allow the fixed point and scientific notation respectively. -The default is `fast_float::chars_format::general` which allows both `fixed` and `scientific`. - -The library seeks to follow the C++17 (see [20.19.3](http://eel.is/c++draft/charconv.from.chars).(7.1)) specification. -* The `from_chars` function does not skip leading white-space characters. -* [A leading `+` sign](https://en.cppreference.com/w/cpp/utility/from_chars) is forbidden. -* It is generally impossible to represent a decimal value exactly as binary floating-point number (`float` and `double` types). We seek the nearest value. We round to an even mantissa when we are in-between two binary floating-point numbers. - -Furthermore, we have the following restrictions: -* We only support `float` and `double` types at this time. -* We only support the decimal format: we do not support hexadecimal strings. -* For values that are either very large or very small (e.g., `1e9999`), we represent it using the infinity or negative infinity value. - -We support Visual Studio, macOS, Linux, freeBSD. We support big and little endian. We support 32-bit and 64-bit systems. - - - -## Using commas as decimal separator - - -The C++ standard stipulate that `from_chars` has to be locale-independent. In -particular, the decimal separator has to be the period (`.`). However, -some users still want to use the `fast_float` library with in a locale-dependent -manner. Using a separate function called `from_chars_advanced`, we allow the users -to pass a `parse_options` instance which contains a custom decimal separator (e.g., -the comma). You may use it as follows. - -```C++ -#include "fast_float/fast_float.h" -#include - -int main() { - const std::string input = "3,1416 xyz "; - double result; - fast_float::parse_options options{fast_float::chars_format::general, ','}; - auto answer = fast_float::from_chars_advanced(input.data(), input.data()+input.size(), result, options); - if((answer.ec != std::errc()) || ((result != 3.1416))) { std::cerr << "parsing failure\n"; return EXIT_FAILURE; } - std::cout << "parsed the number " << result << std::endl; - return EXIT_SUCCESS; -} -``` - - -## Reference - -- Daniel Lemire, [Number Parsing at a Gigabyte per Second](https://arxiv.org/abs/2101.11408), Software: Pratice and Experience 51 (8), 2021. - -## Other programming languages - -- [There is an R binding](https://github.com/eddelbuettel/rcppfastfloat) called `rcppfastfloat`. -- [There is a Rust port of the fast_float library](https://github.com/aldanor/fast-float-rust/) called `fast-float-rust`. -- [There is a Java port of the fast_float library](https://github.com/wrandelshofer/FastDoubleParser) called `FastDoubleParser`. -- [There is a C# port of the fast_float library](https://github.com/CarlVerret/csFastFloat) called `csFastFloat`. - - -## Relation With Other Work - -The fast_float library provides a performance similar to that of the [fast_double_parser](https://github.com/lemire/fast_double_parser) library but using an updated algorithm reworked from the ground up, and while offering an API more in line with the expectations of C++ programmers. The fast_double_parser library is part of the [Microsoft LightGBM machine-learning framework](https://github.com/microsoft/LightGBM). - -## Users - -The fast_float library is used by [Apache Arrow](https://github.com/apache/arrow/pull/8494) where it multiplied the number parsing speed by two or three times. It is also used by [Yandex ClickHouse](https://github.com/ClickHouse/ClickHouse) and by [Google Jsonnet](https://github.com/google/jsonnet). - - -## How fast is it? - -It can parse random floating-point numbers at a speed of 1 GB/s on some systems. We find that it is often twice as fast as the best available competitor, and many times faster than many standard-library implementations. - - - -``` -$ ./build/benchmarks/benchmark -# parsing random integers in the range [0,1) -volume = 2.09808 MB -netlib : 271.18 MB/s (+/- 1.2 %) 12.93 Mfloat/s -doubleconversion : 225.35 MB/s (+/- 1.2 %) 10.74 Mfloat/s -strtod : 190.94 MB/s (+/- 1.6 %) 9.10 Mfloat/s -abseil : 430.45 MB/s (+/- 2.2 %) 20.52 Mfloat/s -fastfloat : 1042.38 MB/s (+/- 9.9 %) 49.68 Mfloat/s -``` - -See https://github.com/lemire/simple_fastfloat_benchmark for our benchmarking code. - - -## Video - -[![Go Systems 2020](http://img.youtube.com/vi/AVXgvlMeIm4/0.jpg)](http://www.youtube.com/watch?v=AVXgvlMeIm4)
      - -## Using as a CMake dependency - -This library is header-only by design. The CMake file provides the `fast_float` target -which is merely a pointer to the `include` directory. - -If you drop the `fast_float` repository in your CMake project, you should be able to use -it in this manner: - -```cmake -add_subdirectory(fast_float) -target_link_libraries(myprogram PUBLIC fast_float) -``` - -Or you may want to retrieve the dependency automatically if you have a sufficiently recent version of CMake (3.11 or better at least): - -```cmake -FetchContent_Declare( - fast_float - GIT_REPOSITORY https://github.com/lemire/fast_float.git - GIT_TAG tags/v1.1.2 - GIT_SHALLOW TRUE) - -FetchContent_MakeAvailable(fast_float) -target_link_libraries(myprogram PUBLIC fast_float) - -``` - -You should change the `GIT_TAG` line so that you recover the version you wish to use. - -## Using as single header - -The script `script/amalgamate.py` may be used to generate a single header -version of the library if so desired. -Just run the script from the root directory of this repository. -You can customize the license type and output file if desired as described in -the command line help. - -You may directly download automatically generated single-header files: - -https://github.com/fastfloat/fast_float/releases/download/v1.1.2/fast_float.h - -## Credit - -Though this work is inspired by many different people, this work benefited especially from exchanges with -Michael Eisel, who motivated the original research with his key insights, and with Nigel Tao who provided -invaluable feedback. Rémy Oudompheng first implemented a fast path we use in the case of long digits. - -The library includes code adapted from Google Wuffs (written by Nigel Tao) which was originally published -under the Apache 2.0 license. - -## License - - -Licensed under either of Apache License, Version -2.0 or MIT license at your option. - - -
      - - -Unless you explicitly state otherwise, any contribution intentionally submitted -for inclusion in this repository by you, as defined in the Apache-2.0 license, -shall be dual licensed as above, without any additional terms or conditions. - diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/ci/script.sh b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/ci/script.sh deleted file mode 100755 index c9894c7a2..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/ci/script.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -TOOLCHAIN="$1" - -mkdir build -cd build - -if [ "$TOOLCHAIN" != "" ] ; then - cmake -DFASTFLOAT_TEST=ON .. -DCMAKE_TOOLCHAIN_FILE=/toolchains/"$TOOLCHAIN".cmake -else - cmake -DFASTFLOAT_TEST=ON .. -fi -make -j 2 -if [ "$TOOLCHAIN" != "" ] ; then - qemu-"$TOOLCHAIN" tests/basictest -else - ctest --output-on-failure -R basictest -fi diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/cmake/config.cmake.in b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/cmake/config.cmake.in deleted file mode 100644 index 035dc0fa0..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/cmake/config.cmake.in +++ /dev/null @@ -1,4 +0,0 @@ -@PACKAGE_INIT@ - -include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@-targets.cmake") -check_required_components("@PROJECT_NAME@") diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/include/fast_float/ascii_number.h b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/include/fast_float/ascii_number.h deleted file mode 100644 index 3e6bb3e9e..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/include/fast_float/ascii_number.h +++ /dev/null @@ -1,231 +0,0 @@ -#ifndef FASTFLOAT_ASCII_NUMBER_H -#define FASTFLOAT_ASCII_NUMBER_H - -#include -#include -#include -#include - -#include "float_common.h" - -namespace fast_float { - -// Next function can be micro-optimized, but compilers are entirely -// able to optimize it well. -fastfloat_really_inline bool is_integer(char c) noexcept { return c >= '0' && c <= '9'; } - -fastfloat_really_inline uint64_t byteswap(uint64_t val) { - return (val & 0xFF00000000000000) >> 56 - | (val & 0x00FF000000000000) >> 40 - | (val & 0x0000FF0000000000) >> 24 - | (val & 0x000000FF00000000) >> 8 - | (val & 0x00000000FF000000) << 8 - | (val & 0x0000000000FF0000) << 24 - | (val & 0x000000000000FF00) << 40 - | (val & 0x00000000000000FF) << 56; -} - -fastfloat_really_inline uint64_t read_u64(const char *chars) { - uint64_t val; - ::memcpy(&val, chars, sizeof(uint64_t)); -#if FASTFLOAT_IS_BIG_ENDIAN == 1 - // Need to read as-if the number was in little-endian order. - val = byteswap(val); -#endif - return val; -} - -fastfloat_really_inline void write_u64(uint8_t *chars, uint64_t val) { -#if FASTFLOAT_IS_BIG_ENDIAN == 1 - // Need to read as-if the number was in little-endian order. - val = byteswap(val); -#endif - ::memcpy(chars, &val, sizeof(uint64_t)); -} - -// credit @aqrit -fastfloat_really_inline uint32_t parse_eight_digits_unrolled(uint64_t val) { - const uint64_t mask = 0x000000FF000000FF; - const uint64_t mul1 = 0x000F424000000064; // 100 + (1000000ULL << 32) - const uint64_t mul2 = 0x0000271000000001; // 1 + (10000ULL << 32) - val -= 0x3030303030303030; - val = (val * 10) + (val >> 8); // val = (val * 2561) >> 8; - val = (((val & mask) * mul1) + (((val >> 16) & mask) * mul2)) >> 32; - return uint32_t(val); -} - -fastfloat_really_inline uint32_t parse_eight_digits_unrolled(const char *chars) noexcept { - return parse_eight_digits_unrolled(read_u64(chars)); -} - -// credit @aqrit -fastfloat_really_inline bool is_made_of_eight_digits_fast(uint64_t val) noexcept { - return !((((val + 0x4646464646464646) | (val - 0x3030303030303030)) & - 0x8080808080808080)); -} - -fastfloat_really_inline bool is_made_of_eight_digits_fast(const char *chars) noexcept { - return is_made_of_eight_digits_fast(read_u64(chars)); -} - -typedef span byte_span; - -struct parsed_number_string { - int64_t exponent{0}; - uint64_t mantissa{0}; - const char *lastmatch{nullptr}; - bool negative{false}; - bool valid{false}; - bool too_many_digits{false}; - // contains the range of the significant digits - byte_span integer{}; // non-nullable - byte_span fraction{}; // nullable -}; - -// Assuming that you use no more than 19 digits, this will -// parse an ASCII string. -fastfloat_really_inline -parsed_number_string parse_number_string(const char *p, const char *pend, parse_options options) noexcept { - const chars_format fmt = options.format; - const char decimal_point = options.decimal_point; - - parsed_number_string answer; - answer.valid = false; - answer.too_many_digits = false; - answer.negative = (*p == '-'); - if (*p == '-') { // C++17 20.19.3.(7.1) explicitly forbids '+' sign here - ++p; - if (p == pend) { - return answer; - } - if (!is_integer(*p) && (*p != decimal_point)) { // a sign must be followed by an integer or the dot - return answer; - } - } - const char *const start_digits = p; - - uint64_t i = 0; // an unsigned int avoids signed overflows (which are bad) - - while ((std::distance(p, pend) >= 8) && is_made_of_eight_digits_fast(p)) { - i = i * 100000000 + parse_eight_digits_unrolled(p); // in rare cases, this will overflow, but that's ok - p += 8; - } - while ((p != pend) && is_integer(*p)) { - // a multiplication by 10 is cheaper than an arbitrary integer - // multiplication - i = 10 * i + - uint64_t(*p - '0'); // might overflow, we will handle the overflow later - ++p; - } - const char *const end_of_integer_part = p; - int64_t digit_count = int64_t(end_of_integer_part - start_digits); - answer.integer = byte_span(start_digits, size_t(digit_count)); - int64_t exponent = 0; - if ((p != pend) && (*p == decimal_point)) { - ++p; - const char* before = p; - // can occur at most twice without overflowing, but let it occur more, since - // for integers with many digits, digit parsing is the primary bottleneck. - while ((std::distance(p, pend) >= 8) && is_made_of_eight_digits_fast(p)) { - i = i * 100000000 + parse_eight_digits_unrolled(p); // in rare cases, this will overflow, but that's ok - p += 8; - } - while ((p != pend) && is_integer(*p)) { - uint8_t digit = uint8_t(*p - '0'); - ++p; - i = i * 10 + digit; // in rare cases, this will overflow, but that's ok - } - exponent = before - p; - answer.fraction = byte_span(before, size_t(p - before)); - digit_count -= exponent; - } - // we must have encountered at least one integer! - if (digit_count == 0) { - return answer; - } - int64_t exp_number = 0; // explicit exponential part - if ((fmt & chars_format::scientific) && (p != pend) && (('e' == *p) || ('E' == *p))) { - const char * location_of_e = p; - ++p; - bool neg_exp = false; - if ((p != pend) && ('-' == *p)) { - neg_exp = true; - ++p; - } else if ((p != pend) && ('+' == *p)) { // '+' on exponent is allowed by C++17 20.19.3.(7.1) - ++p; - } - if ((p == pend) || !is_integer(*p)) { - if(!(fmt & chars_format::fixed)) { - // We are in error. - return answer; - } - // Otherwise, we will be ignoring the 'e'. - p = location_of_e; - } else { - while ((p != pend) && is_integer(*p)) { - uint8_t digit = uint8_t(*p - '0'); - if (exp_number < 0x10000000) { - exp_number = 10 * exp_number + digit; - } - ++p; - } - if(neg_exp) { exp_number = - exp_number; } - exponent += exp_number; - } - } else { - // If it scientific and not fixed, we have to bail out. - if((fmt & chars_format::scientific) && !(fmt & chars_format::fixed)) { return answer; } - } - answer.lastmatch = p; - answer.valid = true; - - // If we frequently had to deal with long strings of digits, - // we could extend our code by using a 128-bit integer instead - // of a 64-bit integer. However, this is uncommon. - // - // We can deal with up to 19 digits. - if (digit_count > 19) { // this is uncommon - // It is possible that the integer had an overflow. - // We have to handle the case where we have 0.0000somenumber. - // We need to be mindful of the case where we only have zeroes... - // E.g., 0.000000000...000. - const char *start = start_digits; - while ((start != pend) && (*start == '0' || *start == decimal_point)) { - if(*start == '0') { digit_count --; } - start++; - } - if (digit_count > 19) { - answer.too_many_digits = true; - // Let us start again, this time, avoiding overflows. - // We don't need to check if is_integer, since we use the - // pre-tokenized spans from above. - i = 0; - p = answer.integer.ptr; - const char* int_end = p + answer.integer.len(); - const uint64_t minimal_nineteen_digit_integer{1000000000000000000}; - while((i < minimal_nineteen_digit_integer) && (p != int_end)) { - i = i * 10 + uint64_t(*p - '0'); - ++p; - } - if (i >= minimal_nineteen_digit_integer) { // We have a big integers - exponent = end_of_integer_part - p + exp_number; - } else { // We have a value with a fractional component. - p = answer.fraction.ptr; - const char* frac_end = p + answer.fraction.len(); - while((i < minimal_nineteen_digit_integer) && (p != frac_end)) { - i = i * 10 + uint64_t(*p - '0'); - ++p; - } - exponent = answer.fraction.ptr - p + exp_number; - } - // We have now corrected both exponent and i, to a truncated value - } - } - answer.exponent = exponent; - answer.mantissa = i; - return answer; -} - -} // namespace fast_float - -#endif diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/include/fast_float/bigint.h b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/include/fast_float/bigint.h deleted file mode 100644 index b56cb9b03..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/include/fast_float/bigint.h +++ /dev/null @@ -1,590 +0,0 @@ -#ifndef FASTFLOAT_BIGINT_H -#define FASTFLOAT_BIGINT_H - -#include -#include -#include -#include - -#include "float_common.h" - -namespace fast_float { - -// the limb width: we want efficient multiplication of double the bits in -// limb, or for 64-bit limbs, at least 64-bit multiplication where we can -// extract the high and low parts efficiently. this is every 64-bit -// architecture except for sparc, which emulates 128-bit multiplication. -// we might have platforms where `CHAR_BIT` is not 8, so let's avoid -// doing `8 * sizeof(limb)`. -#if defined(FASTFLOAT_64BIT) && !defined(__sparc) -#define FASTFLOAT_64BIT_LIMB -typedef uint64_t limb; -constexpr size_t limb_bits = 64; -#else -#define FASTFLOAT_32BIT_LIMB -typedef uint32_t limb; -constexpr size_t limb_bits = 32; -#endif - -typedef span limb_span; - -// number of bits in a bigint. this needs to be at least the number -// of bits required to store the largest bigint, which is -// `log2(10**(digits + max_exp))`, or `log2(10**(767 + 342))`, or -// ~3600 bits, so we round to 4000. -constexpr size_t bigint_bits = 4000; -constexpr size_t bigint_limbs = bigint_bits / limb_bits; - -// vector-like type that is allocated on the stack. the entire -// buffer is pre-allocated, and only the length changes. -template -struct stackvec { - limb data[size]; - // we never need more than 150 limbs - uint16_t length{0}; - - stackvec() = default; - stackvec(const stackvec &) = delete; - stackvec &operator=(const stackvec &) = delete; - stackvec(stackvec &&) = delete; - stackvec &operator=(stackvec &&other) = delete; - - // create stack vector from existing limb span. - stackvec(limb_span s) { - FASTFLOAT_ASSERT(try_extend(s)); - } - - limb& operator[](size_t index) noexcept { - FASTFLOAT_DEBUG_ASSERT(index < length); - return data[index]; - } - const limb& operator[](size_t index) const noexcept { - FASTFLOAT_DEBUG_ASSERT(index < length); - return data[index]; - } - // index from the end of the container - const limb& rindex(size_t index) const noexcept { - FASTFLOAT_DEBUG_ASSERT(index < length); - size_t rindex = length - index - 1; - return data[rindex]; - } - - // set the length, without bounds checking. - void set_len(size_t len) noexcept { - length = uint16_t(len); - } - constexpr size_t len() const noexcept { - return length; - } - constexpr bool is_empty() const noexcept { - return length == 0; - } - constexpr size_t capacity() const noexcept { - return size; - } - // append item to vector, without bounds checking - void push_unchecked(limb value) noexcept { - data[length] = value; - length++; - } - // append item to vector, returning if item was added - bool try_push(limb value) noexcept { - if (len() < capacity()) { - push_unchecked(value); - return true; - } else { - return false; - } - } - // add items to the vector, from a span, without bounds checking - void extend_unchecked(limb_span s) noexcept { - limb* ptr = data + length; - ::memcpy((void*)ptr, (const void*)s.ptr, sizeof(limb) * s.len()); - set_len(len() + s.len()); - } - // try to add items to the vector, returning if items were added - bool try_extend(limb_span s) noexcept { - if (len() + s.len() <= capacity()) { - extend_unchecked(s); - return true; - } else { - return false; - } - } - // resize the vector, without bounds checking - // if the new size is longer than the vector, assign value to each - // appended item. - void resize_unchecked(size_t new_len, limb value) noexcept { - if (new_len > len()) { - size_t count = new_len - len(); - limb* first = data + len(); - limb* last = first + count; - ::std::fill(first, last, value); - set_len(new_len); - } else { - set_len(new_len); - } - } - // try to resize the vector, returning if the vector was resized. - bool try_resize(size_t new_len, limb value) noexcept { - if (new_len > capacity()) { - return false; - } else { - resize_unchecked(new_len, value); - return true; - } - } - // check if any limbs are non-zero after the given index. - // this needs to be done in reverse order, since the index - // is relative to the most significant limbs. - bool nonzero(size_t index) const noexcept { - while (index < len()) { - if (rindex(index) != 0) { - return true; - } - index++; - } - return false; - } - // normalize the big integer, so most-significant zero limbs are removed. - void normalize() noexcept { - while (len() > 0 && rindex(0) == 0) { - length--; - } - } -}; - -fastfloat_really_inline -uint64_t empty_hi64(bool& truncated) noexcept { - truncated = false; - return 0; -} - -fastfloat_really_inline -uint64_t uint64_hi64(uint64_t r0, bool& truncated) noexcept { - truncated = false; - int shl = leading_zeroes(r0); - return r0 << shl; -} - -fastfloat_really_inline -uint64_t uint64_hi64(uint64_t r0, uint64_t r1, bool& truncated) noexcept { - int shl = leading_zeroes(r0); - if (shl == 0) { - truncated = r1 != 0; - return r0; - } else { - int shr = 64 - shl; - truncated = (r1 << shl) != 0; - return (r0 << shl) | (r1 >> shr); - } -} - -fastfloat_really_inline -uint64_t uint32_hi64(uint32_t r0, bool& truncated) noexcept { - return uint64_hi64(r0, truncated); -} - -fastfloat_really_inline -uint64_t uint32_hi64(uint32_t r0, uint32_t r1, bool& truncated) noexcept { - uint64_t x0 = r0; - uint64_t x1 = r1; - return uint64_hi64((x0 << 32) | x1, truncated); -} - -fastfloat_really_inline -uint64_t uint32_hi64(uint32_t r0, uint32_t r1, uint32_t r2, bool& truncated) noexcept { - uint64_t x0 = r0; - uint64_t x1 = r1; - uint64_t x2 = r2; - return uint64_hi64(x0, (x1 << 32) | x2, truncated); -} - -// add two small integers, checking for overflow. -// we want an efficient operation. for msvc, where -// we don't have built-in intrinsics, this is still -// pretty fast. -fastfloat_really_inline -limb scalar_add(limb x, limb y, bool& overflow) noexcept { - limb z; - -// gcc and clang -#if defined(__has_builtin) - #if __has_builtin(__builtin_add_overflow) - overflow = __builtin_add_overflow(x, y, &z); - return z; - #endif -#endif - - // generic, this still optimizes correctly on MSVC. - z = x + y; - overflow = z < x; - return z; -} - -// multiply two small integers, getting both the high and low bits. -fastfloat_really_inline -limb scalar_mul(limb x, limb y, limb& carry) noexcept { -#ifdef FASTFLOAT_64BIT_LIMB - #if defined(__SIZEOF_INT128__) - // GCC and clang both define it as an extension. - __uint128_t z = __uint128_t(x) * __uint128_t(y) + __uint128_t(carry); - carry = limb(z >> limb_bits); - return limb(z); - #else - // fallback, no native 128-bit integer multiplication with carry. - // on msvc, this optimizes identically, somehow. - value128 z = full_multiplication(x, y); - bool overflow; - z.low = scalar_add(z.low, carry, overflow); - z.high += uint64_t(overflow); // cannot overflow - carry = z.high; - return z.low; - #endif -#else - uint64_t z = uint64_t(x) * uint64_t(y) + uint64_t(carry); - carry = limb(z >> limb_bits); - return limb(z); -#endif -} - -// add scalar value to bigint starting from offset. -// used in grade school multiplication -template -inline bool small_add_from(stackvec& vec, limb y, size_t start) noexcept { - size_t index = start; - limb carry = y; - bool overflow; - while (carry != 0 && index < vec.len()) { - vec[index] = scalar_add(vec[index], carry, overflow); - carry = limb(overflow); - index += 1; - } - if (carry != 0) { - FASTFLOAT_TRY(vec.try_push(carry)); - } - return true; -} - -// add scalar value to bigint. -template -fastfloat_really_inline bool small_add(stackvec& vec, limb y) noexcept { - return small_add_from(vec, y, 0); -} - -// multiply bigint by scalar value. -template -inline bool small_mul(stackvec& vec, limb y) noexcept { - limb carry = 0; - for (size_t index = 0; index < vec.len(); index++) { - vec[index] = scalar_mul(vec[index], y, carry); - } - if (carry != 0) { - FASTFLOAT_TRY(vec.try_push(carry)); - } - return true; -} - -// add bigint to bigint starting from index. -// used in grade school multiplication -template -bool large_add_from(stackvec& x, limb_span y, size_t start) noexcept { - // the effective x buffer is from `xstart..x.len()`, so exit early - // if we can't get that current range. - if (x.len() < start || y.len() > x.len() - start) { - FASTFLOAT_TRY(x.try_resize(y.len() + start, 0)); - } - - bool carry = false; - for (size_t index = 0; index < y.len(); index++) { - limb xi = x[index + start]; - limb yi = y[index]; - bool c1 = false; - bool c2 = false; - xi = scalar_add(xi, yi, c1); - if (carry) { - xi = scalar_add(xi, 1, c2); - } - x[index + start] = xi; - carry = c1 | c2; - } - - // handle overflow - if (carry) { - FASTFLOAT_TRY(small_add_from(x, 1, y.len() + start)); - } - return true; -} - -// add bigint to bigint. -template -fastfloat_really_inline bool large_add_from(stackvec& x, limb_span y) noexcept { - return large_add_from(x, y, 0); -} - -// grade-school multiplication algorithm -template -bool long_mul(stackvec& x, limb_span y) noexcept { - limb_span xs = limb_span(x.data, x.len()); - stackvec z(xs); - limb_span zs = limb_span(z.data, z.len()); - - if (y.len() != 0) { - limb y0 = y[0]; - FASTFLOAT_TRY(small_mul(x, y0)); - for (size_t index = 1; index < y.len(); index++) { - limb yi = y[index]; - stackvec zi; - if (yi != 0) { - // re-use the same buffer throughout - zi.set_len(0); - FASTFLOAT_TRY(zi.try_extend(zs)); - FASTFLOAT_TRY(small_mul(zi, yi)); - limb_span zis = limb_span(zi.data, zi.len()); - FASTFLOAT_TRY(large_add_from(x, zis, index)); - } - } - } - - x.normalize(); - return true; -} - -// grade-school multiplication algorithm -template -bool large_mul(stackvec& x, limb_span y) noexcept { - if (y.len() == 1) { - FASTFLOAT_TRY(small_mul(x, y[0])); - } else { - FASTFLOAT_TRY(long_mul(x, y)); - } - return true; -} - -// big integer type. implements a small subset of big integer -// arithmetic, using simple algorithms since asymptotically -// faster algorithms are slower for a small number of limbs. -// all operations assume the big-integer is normalized. -struct bigint { - // storage of the limbs, in little-endian order. - stackvec vec; - - bigint(): vec() {} - bigint(const bigint &) = delete; - bigint &operator=(const bigint &) = delete; - bigint(bigint &&) = delete; - bigint &operator=(bigint &&other) = delete; - - bigint(uint64_t value): vec() { -#ifdef FASTFLOAT_64BIT_LIMB - vec.push_unchecked(value); -#else - vec.push_unchecked(uint32_t(value)); - vec.push_unchecked(uint32_t(value >> 32)); -#endif - vec.normalize(); - } - - // get the high 64 bits from the vector, and if bits were truncated. - // this is to get the significant digits for the float. - uint64_t hi64(bool& truncated) const noexcept { -#ifdef FASTFLOAT_64BIT_LIMB - if (vec.len() == 0) { - return empty_hi64(truncated); - } else if (vec.len() == 1) { - return uint64_hi64(vec.rindex(0), truncated); - } else { - uint64_t result = uint64_hi64(vec.rindex(0), vec.rindex(1), truncated); - truncated |= vec.nonzero(2); - return result; - } -#else - if (vec.len() == 0) { - return empty_hi64(truncated); - } else if (vec.len() == 1) { - return uint32_hi64(vec.rindex(0), truncated); - } else if (vec.len() == 2) { - return uint32_hi64(vec.rindex(0), vec.rindex(1), truncated); - } else { - uint64_t result = uint32_hi64(vec.rindex(0), vec.rindex(1), vec.rindex(2), truncated); - truncated |= vec.nonzero(3); - return result; - } -#endif - } - - // compare two big integers, returning the large value. - // assumes both are normalized. if the return value is - // negative, other is larger, if the return value is - // positive, this is larger, otherwise they are equal. - // the limbs are stored in little-endian order, so we - // must compare the limbs in ever order. - int compare(const bigint& other) const noexcept { - if (vec.len() > other.vec.len()) { - return 1; - } else if (vec.len() < other.vec.len()) { - return -1; - } else { - for (size_t index = vec.len(); index > 0; index--) { - limb xi = vec[index - 1]; - limb yi = other.vec[index - 1]; - if (xi > yi) { - return 1; - } else if (xi < yi) { - return -1; - } - } - return 0; - } - } - - // shift left each limb n bits, carrying over to the new limb - // returns true if we were able to shift all the digits. - bool shl_bits(size_t n) noexcept { - // Internally, for each item, we shift left by n, and add the previous - // right shifted limb-bits. - // For example, we transform (for u8) shifted left 2, to: - // b10100100 b01000010 - // b10 b10010001 b00001000 - FASTFLOAT_DEBUG_ASSERT(n != 0); - FASTFLOAT_DEBUG_ASSERT(n < sizeof(limb) * 8); - - size_t shl = n; - size_t shr = limb_bits - shl; - limb prev = 0; - for (size_t index = 0; index < vec.len(); index++) { - limb xi = vec[index]; - vec[index] = (xi << shl) | (prev >> shr); - prev = xi; - } - - limb carry = prev >> shr; - if (carry != 0) { - return vec.try_push(carry); - } - return true; - } - - // move the limbs left by `n` limbs. - bool shl_limbs(size_t n) noexcept { - FASTFLOAT_DEBUG_ASSERT(n != 0); - if (n + vec.len() > vec.capacity()) { - return false; - } else if (!vec.is_empty()) { - // move limbs - limb* dst = vec.data + n; - const limb* src = vec.data; - ::memmove(dst, src, sizeof(limb) * vec.len()); - // fill in empty limbs - limb* first = vec.data; - limb* last = first + n; - ::std::fill(first, last, 0); - vec.set_len(n + vec.len()); - return true; - } else { - return true; - } - } - - // move the limbs left by `n` bits. - bool shl(size_t n) noexcept { - size_t rem = n % limb_bits; - size_t div = n / limb_bits; - if (rem != 0) { - FASTFLOAT_TRY(shl_bits(rem)); - } - if (div != 0) { - FASTFLOAT_TRY(shl_limbs(div)); - } - return true; - } - - // get the number of leading zeros in the bigint. - int ctlz() const noexcept { - if (vec.is_empty()) { - return 0; - } else { -#ifdef FASTFLOAT_64BIT_LIMB - return leading_zeroes(vec.rindex(0)); -#else - // no use defining a specialized leading_zeroes for a 32-bit type. - uint64_t r0 = vec.rindex(0); - return leading_zeroes(r0 << 32); -#endif - } - } - - // get the number of bits in the bigint. - int bit_length() const noexcept { - int lz = ctlz(); - return int(limb_bits * vec.len()) - lz; - } - - bool mul(limb y) noexcept { - return small_mul(vec, y); - } - - bool add(limb y) noexcept { - return small_add(vec, y); - } - - // multiply as if by 2 raised to a power. - bool pow2(uint32_t exp) noexcept { - return shl(exp); - } - - // multiply as if by 5 raised to a power. - bool pow5(uint32_t exp) noexcept { - // multiply by a power of 5 - static constexpr uint32_t large_step = 135; - static constexpr uint64_t small_power_of_5[] = { - 1UL, 5UL, 25UL, 125UL, 625UL, 3125UL, 15625UL, 78125UL, 390625UL, - 1953125UL, 9765625UL, 48828125UL, 244140625UL, 1220703125UL, - 6103515625UL, 30517578125UL, 152587890625UL, 762939453125UL, - 3814697265625UL, 19073486328125UL, 95367431640625UL, 476837158203125UL, - 2384185791015625UL, 11920928955078125UL, 59604644775390625UL, - 298023223876953125UL, 1490116119384765625UL, 7450580596923828125UL, - }; -#ifdef FASTFLOAT_64BIT_LIMB - constexpr static limb large_power_of_5[] = { - 1414648277510068013UL, 9180637584431281687UL, 4539964771860779200UL, - 10482974169319127550UL, 198276706040285095UL}; -#else - constexpr static limb large_power_of_5[] = { - 4279965485U, 329373468U, 4020270615U, 2137533757U, 4287402176U, - 1057042919U, 1071430142U, 2440757623U, 381945767U, 46164893U}; -#endif - size_t large_length = sizeof(large_power_of_5) / sizeof(limb); - limb_span large = limb_span(large_power_of_5, large_length); - while (exp >= large_step) { - FASTFLOAT_TRY(large_mul(vec, large)); - exp -= large_step; - } -#ifdef FASTFLOAT_64BIT_LIMB - uint32_t small_step = 27; - limb max_native = 7450580596923828125UL; -#else - uint32_t small_step = 13; - limb max_native = 1220703125U; -#endif - while (exp >= small_step) { - FASTFLOAT_TRY(small_mul(vec, max_native)); - exp -= small_step; - } - if (exp != 0) { - FASTFLOAT_TRY(small_mul(vec, limb(small_power_of_5[exp]))); - } - - return true; - } - - // multiply as if by 10 raised to a power. - bool pow10(uint32_t exp) noexcept { - FASTFLOAT_TRY(pow5(exp)); - return pow2(exp); - } -}; - -} // namespace fast_float - -#endif diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/include/fast_float/decimal_to_binary.h b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/include/fast_float/decimal_to_binary.h deleted file mode 100644 index 6da6c66a3..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/include/fast_float/decimal_to_binary.h +++ /dev/null @@ -1,194 +0,0 @@ -#ifndef FASTFLOAT_DECIMAL_TO_BINARY_H -#define FASTFLOAT_DECIMAL_TO_BINARY_H - -#include "float_common.h" -#include "fast_table.h" -#include -#include -#include -#include -#include -#include - -namespace fast_float { - -// This will compute or rather approximate w * 5**q and return a pair of 64-bit words approximating -// the result, with the "high" part corresponding to the most significant bits and the -// low part corresponding to the least significant bits. -// -template -fastfloat_really_inline -value128 compute_product_approximation(int64_t q, uint64_t w) { - const int index = 2 * int(q - powers::smallest_power_of_five); - // For small values of q, e.g., q in [0,27], the answer is always exact because - // The line value128 firstproduct = full_multiplication(w, power_of_five_128[index]); - // gives the exact answer. - value128 firstproduct = full_multiplication(w, powers::power_of_five_128[index]); - static_assert((bit_precision >= 0) && (bit_precision <= 64), " precision should be in (0,64]"); - constexpr uint64_t precision_mask = (bit_precision < 64) ? - (uint64_t(0xFFFFFFFFFFFFFFFF) >> bit_precision) - : uint64_t(0xFFFFFFFFFFFFFFFF); - if((firstproduct.high & precision_mask) == precision_mask) { // could further guard with (lower + w < lower) - // regarding the second product, we only need secondproduct.high, but our expectation is that the compiler will optimize this extra work away if needed. - value128 secondproduct = full_multiplication(w, powers::power_of_five_128[index + 1]); - firstproduct.low += secondproduct.high; - if(secondproduct.high > firstproduct.low) { - firstproduct.high++; - } - } - return firstproduct; -} - -namespace detail { -/** - * For q in (0,350), we have that - * f = (((152170 + 65536) * q ) >> 16); - * is equal to - * floor(p) + q - * where - * p = log(5**q)/log(2) = q * log(5)/log(2) - * - * For negative values of q in (-400,0), we have that - * f = (((152170 + 65536) * q ) >> 16); - * is equal to - * -ceil(p) + q - * where - * p = log(5**-q)/log(2) = -q * log(5)/log(2) - */ - constexpr fastfloat_really_inline int32_t power(int32_t q) noexcept { - return (((152170 + 65536) * q) >> 16) + 63; - } -} // namespace detail - -// create an adjusted mantissa, biased by the invalid power2 -// for significant digits already multiplied by 10 ** q. -template -fastfloat_really_inline -adjusted_mantissa compute_error_scaled(int64_t q, uint64_t w, int lz) noexcept { - int hilz = int(w >> 63) ^ 1; - adjusted_mantissa answer; - answer.mantissa = w << hilz; - int bias = binary::mantissa_explicit_bits() - binary::minimum_exponent(); - answer.power2 = int32_t(detail::power(int32_t(q)) + bias - hilz - lz - 62 + invalid_am_bias); - return answer; -} - -// w * 10 ** q, without rounding the representation up. -// the power2 in the exponent will be adjusted by invalid_am_bias. -template -fastfloat_really_inline -adjusted_mantissa compute_error(int64_t q, uint64_t w) noexcept { - int lz = leading_zeroes(w); - w <<= lz; - value128 product = compute_product_approximation(q, w); - return compute_error_scaled(q, product.high, lz); -} - -// w * 10 ** q -// The returned value should be a valid ieee64 number that simply need to be packed. -// However, in some very rare cases, the computation will fail. In such cases, we -// return an adjusted_mantissa with a negative power of 2: the caller should recompute -// in such cases. -template -fastfloat_really_inline -adjusted_mantissa compute_float(int64_t q, uint64_t w) noexcept { - adjusted_mantissa answer; - if ((w == 0) || (q < binary::smallest_power_of_ten())) { - answer.power2 = 0; - answer.mantissa = 0; - // result should be zero - return answer; - } - if (q > binary::largest_power_of_ten()) { - // we want to get infinity: - answer.power2 = binary::infinite_power(); - answer.mantissa = 0; - return answer; - } - // At this point in time q is in [powers::smallest_power_of_five, powers::largest_power_of_five]. - - // We want the most significant bit of i to be 1. Shift if needed. - int lz = leading_zeroes(w); - w <<= lz; - - // The required precision is binary::mantissa_explicit_bits() + 3 because - // 1. We need the implicit bit - // 2. We need an extra bit for rounding purposes - // 3. We might lose a bit due to the "upperbit" routine (result too small, requiring a shift) - - value128 product = compute_product_approximation(q, w); - if(product.low == 0xFFFFFFFFFFFFFFFF) { // could guard it further - // In some very rare cases, this could happen, in which case we might need a more accurate - // computation that what we can provide cheaply. This is very, very unlikely. - // - const bool inside_safe_exponent = (q >= -27) && (q <= 55); // always good because 5**q <2**128 when q>=0, - // and otherwise, for q<0, we have 5**-q<2**64 and the 128-bit reciprocal allows for exact computation. - if(!inside_safe_exponent) { - return compute_error_scaled(q, product.high, lz); - } - } - // The "compute_product_approximation" function can be slightly slower than a branchless approach: - // value128 product = compute_product(q, w); - // but in practice, we can win big with the compute_product_approximation if its additional branch - // is easily predicted. Which is best is data specific. - int upperbit = int(product.high >> 63); - - answer.mantissa = product.high >> (upperbit + 64 - binary::mantissa_explicit_bits() - 3); - - answer.power2 = int32_t(detail::power(int32_t(q)) + upperbit - lz - binary::minimum_exponent()); - if (answer.power2 <= 0) { // we have a subnormal? - // Here have that answer.power2 <= 0 so -answer.power2 >= 0 - if(-answer.power2 + 1 >= 64) { // if we have more than 64 bits below the minimum exponent, you have a zero for sure. - answer.power2 = 0; - answer.mantissa = 0; - // result should be zero - return answer; - } - // next line is safe because -answer.power2 + 1 < 64 - answer.mantissa >>= -answer.power2 + 1; - // Thankfully, we can't have both "round-to-even" and subnormals because - // "round-to-even" only occurs for powers close to 0. - answer.mantissa += (answer.mantissa & 1); // round up - answer.mantissa >>= 1; - // There is a weird scenario where we don't have a subnormal but just. - // Suppose we start with 2.2250738585072013e-308, we end up - // with 0x3fffffffffffff x 2^-1023-53 which is technically subnormal - // whereas 0x40000000000000 x 2^-1023-53 is normal. Now, we need to round - // up 0x3fffffffffffff x 2^-1023-53 and once we do, we are no longer - // subnormal, but we can only know this after rounding. - // So we only declare a subnormal if we are smaller than the threshold. - answer.power2 = (answer.mantissa < (uint64_t(1) << binary::mantissa_explicit_bits())) ? 0 : 1; - return answer; - } - - // usually, we round *up*, but if we fall right in between and and we have an - // even basis, we need to round down - // We are only concerned with the cases where 5**q fits in single 64-bit word. - if ((product.low <= 1) && (q >= binary::min_exponent_round_to_even()) && (q <= binary::max_exponent_round_to_even()) && - ((answer.mantissa & 3) == 1) ) { // we may fall between two floats! - // To be in-between two floats we need that in doing - // answer.mantissa = product.high >> (upperbit + 64 - binary::mantissa_explicit_bits() - 3); - // ... we dropped out only zeroes. But if this happened, then we can go back!!! - if((answer.mantissa << (upperbit + 64 - binary::mantissa_explicit_bits() - 3)) == product.high) { - answer.mantissa &= ~uint64_t(1); // flip it so that we do not round up - } - } - - answer.mantissa += (answer.mantissa & 1); // round up - answer.mantissa >>= 1; - if (answer.mantissa >= (uint64_t(2) << binary::mantissa_explicit_bits())) { - answer.mantissa = (uint64_t(1) << binary::mantissa_explicit_bits()); - answer.power2++; // undo previous addition - } - - answer.mantissa &= ~(uint64_t(1) << binary::mantissa_explicit_bits()); - if (answer.power2 >= binary::infinite_power()) { // infinity - answer.power2 = binary::infinite_power(); - answer.mantissa = 0; - } - return answer; -} - -} // namespace fast_float - -#endif diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/include/fast_float/digit_comparison.h b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/include/fast_float/digit_comparison.h deleted file mode 100644 index 7ffe87430..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/include/fast_float/digit_comparison.h +++ /dev/null @@ -1,423 +0,0 @@ -#ifndef FASTFLOAT_DIGIT_COMPARISON_H -#define FASTFLOAT_DIGIT_COMPARISON_H - -#include -#include -#include -#include - -#include "float_common.h" -#include "bigint.h" -#include "ascii_number.h" - -namespace fast_float { - -// 1e0 to 1e19 -constexpr static uint64_t powers_of_ten_uint64[] = { - 1UL, 10UL, 100UL, 1000UL, 10000UL, 100000UL, 1000000UL, 10000000UL, 100000000UL, - 1000000000UL, 10000000000UL, 100000000000UL, 1000000000000UL, 10000000000000UL, - 100000000000000UL, 1000000000000000UL, 10000000000000000UL, 100000000000000000UL, - 1000000000000000000UL, 10000000000000000000UL}; - -// calculate the exponent, in scientific notation, of the number. -// this algorithm is not even close to optimized, but it has no practical -// effect on performance: in order to have a faster algorithm, we'd need -// to slow down performance for faster algorithms, and this is still fast. -fastfloat_really_inline int32_t scientific_exponent(parsed_number_string& num) noexcept { - uint64_t mantissa = num.mantissa; - int32_t exponent = int32_t(num.exponent); - while (mantissa >= 10000) { - mantissa /= 10000; - exponent += 4; - } - while (mantissa >= 100) { - mantissa /= 100; - exponent += 2; - } - while (mantissa >= 10) { - mantissa /= 10; - exponent += 1; - } - return exponent; -} - -// this converts a native floating-point number to an extended-precision float. -template -fastfloat_really_inline adjusted_mantissa to_extended(T value) noexcept { - adjusted_mantissa am; - int32_t bias = binary_format::mantissa_explicit_bits() - binary_format::minimum_exponent(); - if (std::is_same::value) { - constexpr uint32_t exponent_mask = 0x7F800000; - constexpr uint32_t mantissa_mask = 0x007FFFFF; - constexpr uint64_t hidden_bit_mask = 0x00800000; - uint32_t bits; - ::memcpy(&bits, &value, sizeof(T)); - if ((bits & exponent_mask) == 0) { - // denormal - am.power2 = 1 - bias; - am.mantissa = bits & mantissa_mask; - } else { - // normal - am.power2 = int32_t((bits & exponent_mask) >> binary_format::mantissa_explicit_bits()); - am.power2 -= bias; - am.mantissa = (bits & mantissa_mask) | hidden_bit_mask; - } - } else { - constexpr uint64_t exponent_mask = 0x7FF0000000000000; - constexpr uint64_t mantissa_mask = 0x000FFFFFFFFFFFFF; - constexpr uint64_t hidden_bit_mask = 0x0010000000000000; - uint64_t bits; - ::memcpy(&bits, &value, sizeof(T)); - if ((bits & exponent_mask) == 0) { - // denormal - am.power2 = 1 - bias; - am.mantissa = bits & mantissa_mask; - } else { - // normal - am.power2 = int32_t((bits & exponent_mask) >> binary_format::mantissa_explicit_bits()); - am.power2 -= bias; - am.mantissa = (bits & mantissa_mask) | hidden_bit_mask; - } - } - - return am; -} - -// get the extended precision value of the halfway point between b and b+u. -// we are given a native float that represents b, so we need to adjust it -// halfway between b and b+u. -template -fastfloat_really_inline adjusted_mantissa to_extended_halfway(T value) noexcept { - adjusted_mantissa am = to_extended(value); - am.mantissa <<= 1; - am.mantissa += 1; - am.power2 -= 1; - return am; -} - -// round an extended-precision float to the nearest machine float. -template -fastfloat_really_inline void round(adjusted_mantissa& am, callback cb) noexcept { - int32_t mantissa_shift = 64 - binary_format::mantissa_explicit_bits() - 1; - if (-am.power2 >= mantissa_shift) { - // have a denormal float - int32_t shift = -am.power2 + 1; - cb(am, std::min(shift, 64)); - // check for round-up: if rounding-nearest carried us to the hidden bit. - am.power2 = (am.mantissa < (uint64_t(1) << binary_format::mantissa_explicit_bits())) ? 0 : 1; - return; - } - - // have a normal float, use the default shift. - cb(am, mantissa_shift); - - // check for carry - if (am.mantissa >= (uint64_t(2) << binary_format::mantissa_explicit_bits())) { - am.mantissa = (uint64_t(1) << binary_format::mantissa_explicit_bits()); - am.power2++; - } - - // check for infinite: we could have carried to an infinite power - am.mantissa &= ~(uint64_t(1) << binary_format::mantissa_explicit_bits()); - if (am.power2 >= binary_format::infinite_power()) { - am.power2 = binary_format::infinite_power(); - am.mantissa = 0; - } -} - -template -fastfloat_really_inline -void round_nearest_tie_even(adjusted_mantissa& am, int32_t shift, callback cb) noexcept { - uint64_t mask; - uint64_t halfway; - if (shift == 64) { - mask = UINT64_MAX; - } else { - mask = (uint64_t(1) << shift) - 1; - } - if (shift == 0) { - halfway = 0; - } else { - halfway = uint64_t(1) << (shift - 1); - } - uint64_t truncated_bits = am.mantissa & mask; - uint64_t is_above = truncated_bits > halfway; - uint64_t is_halfway = truncated_bits == halfway; - - // shift digits into position - if (shift == 64) { - am.mantissa = 0; - } else { - am.mantissa >>= shift; - } - am.power2 += shift; - - bool is_odd = (am.mantissa & 1) == 1; - am.mantissa += uint64_t(cb(is_odd, is_halfway, is_above)); -} - -fastfloat_really_inline void round_down(adjusted_mantissa& am, int32_t shift) noexcept { - if (shift == 64) { - am.mantissa = 0; - } else { - am.mantissa >>= shift; - } - am.power2 += shift; -} - -fastfloat_really_inline void skip_zeros(const char*& first, const char* last) noexcept { - uint64_t val; - while (std::distance(first, last) >= 8) { - ::memcpy(&val, first, sizeof(uint64_t)); - if (val != 0x3030303030303030) { - break; - } - first += 8; - } - while (first != last) { - if (*first != '0') { - break; - } - first++; - } -} - -// determine if any non-zero digits were truncated. -// all characters must be valid digits. -fastfloat_really_inline bool is_truncated(const char* first, const char* last) noexcept { - // do 8-bit optimizations, can just compare to 8 literal 0s. - uint64_t val; - while (std::distance(first, last) >= 8) { - ::memcpy(&val, first, sizeof(uint64_t)); - if (val != 0x3030303030303030) { - return true; - } - first += 8; - } - while (first != last) { - if (*first != '0') { - return true; - } - first++; - } - return false; -} - -fastfloat_really_inline bool is_truncated(byte_span s) noexcept { - return is_truncated(s.ptr, s.ptr + s.len()); -} - -fastfloat_really_inline -void parse_eight_digits(const char*& p, limb& value, size_t& counter, size_t& count) noexcept { - value = value * 100000000 + parse_eight_digits_unrolled(p); - p += 8; - counter += 8; - count += 8; -} - -fastfloat_really_inline -void parse_one_digit(const char*& p, limb& value, size_t& counter, size_t& count) noexcept { - value = value * 10 + limb(*p - '0'); - p++; - counter++; - count++; -} - -fastfloat_really_inline -void add_native(bigint& big, limb power, limb value) noexcept { - big.mul(power); - big.add(value); -} - -fastfloat_really_inline void round_up_bigint(bigint& big, size_t& count) noexcept { - // need to round-up the digits, but need to avoid rounding - // ....9999 to ...10000, which could cause a false halfway point. - add_native(big, 10, 1); - count++; -} - -// parse the significant digits into a big integer -inline void parse_mantissa(bigint& result, parsed_number_string& num, size_t max_digits, size_t& digits) noexcept { - // try to minimize the number of big integer and scalar multiplication. - // therefore, try to parse 8 digits at a time, and multiply by the largest - // scalar value (9 or 19 digits) for each step. - size_t counter = 0; - digits = 0; - limb value = 0; -#ifdef FASTFLOAT_64BIT_LIMB - size_t step = 19; -#else - size_t step = 9; -#endif - - // process all integer digits. - const char* p = num.integer.ptr; - const char* pend = p + num.integer.len(); - skip_zeros(p, pend); - // process all digits, in increments of step per loop - while (p != pend) { - while ((std::distance(p, pend) >= 8) && (step - counter >= 8) && (max_digits - digits >= 8)) { - parse_eight_digits(p, value, counter, digits); - } - while (counter < step && p != pend && digits < max_digits) { - parse_one_digit(p, value, counter, digits); - } - if (digits == max_digits) { - // add the temporary value, then check if we've truncated any digits - add_native(result, limb(powers_of_ten_uint64[counter]), value); - bool truncated = is_truncated(p, pend); - if (num.fraction.ptr != nullptr) { - truncated |= is_truncated(num.fraction); - } - if (truncated) { - round_up_bigint(result, digits); - } - return; - } else { - add_native(result, limb(powers_of_ten_uint64[counter]), value); - counter = 0; - value = 0; - } - } - - // add our fraction digits, if they're available. - if (num.fraction.ptr != nullptr) { - p = num.fraction.ptr; - pend = p + num.fraction.len(); - if (digits == 0) { - skip_zeros(p, pend); - } - // process all digits, in increments of step per loop - while (p != pend) { - while ((std::distance(p, pend) >= 8) && (step - counter >= 8) && (max_digits - digits >= 8)) { - parse_eight_digits(p, value, counter, digits); - } - while (counter < step && p != pend && digits < max_digits) { - parse_one_digit(p, value, counter, digits); - } - if (digits == max_digits) { - // add the temporary value, then check if we've truncated any digits - add_native(result, limb(powers_of_ten_uint64[counter]), value); - bool truncated = is_truncated(p, pend); - if (truncated) { - round_up_bigint(result, digits); - } - return; - } else { - add_native(result, limb(powers_of_ten_uint64[counter]), value); - counter = 0; - value = 0; - } - } - } - - if (counter != 0) { - add_native(result, limb(powers_of_ten_uint64[counter]), value); - } -} - -template -inline adjusted_mantissa positive_digit_comp(bigint& bigmant, int32_t exponent) noexcept { - FASTFLOAT_ASSERT(bigmant.pow10(uint32_t(exponent))); - adjusted_mantissa answer; - bool truncated; - answer.mantissa = bigmant.hi64(truncated); - int bias = binary_format::mantissa_explicit_bits() - binary_format::minimum_exponent(); - answer.power2 = bigmant.bit_length() - 64 + bias; - - round(answer, [truncated](adjusted_mantissa& a, int32_t shift) { - round_nearest_tie_even(a, shift, [truncated](bool is_odd, bool is_halfway, bool is_above) -> bool { - return is_above || (is_halfway && truncated) || (is_odd && is_halfway); - }); - }); - - return answer; -} - -// the scaling here is quite simple: we have, for the real digits `m * 10^e`, -// and for the theoretical digits `n * 2^f`. Since `e` is always negative, -// to scale them identically, we do `n * 2^f * 5^-f`, so we now have `m * 2^e`. -// we then need to scale by `2^(f- e)`, and then the two significant digits -// are of the same magnitude. -template -inline adjusted_mantissa negative_digit_comp(bigint& bigmant, adjusted_mantissa am, int32_t exponent) noexcept { - bigint& real_digits = bigmant; - int32_t real_exp = exponent; - - // get the value of `b`, rounded down, and get a bigint representation of b+h - adjusted_mantissa am_b = am; - // gcc7 buf: use a lambda to remove the noexcept qualifier bug with -Wnoexcept-type. - round(am_b, [](adjusted_mantissa&a, int32_t shift) { round_down(a, shift); }); - T b; - to_float(false, am_b, b); - adjusted_mantissa theor = to_extended_halfway(b); - bigint theor_digits(theor.mantissa); - int32_t theor_exp = theor.power2; - - // scale real digits and theor digits to be same power. - int32_t pow2_exp = theor_exp - real_exp; - uint32_t pow5_exp = uint32_t(-real_exp); - if (pow5_exp != 0) { - FASTFLOAT_ASSERT(theor_digits.pow5(pow5_exp)); - } - if (pow2_exp > 0) { - FASTFLOAT_ASSERT(theor_digits.pow2(uint32_t(pow2_exp))); - } else if (pow2_exp < 0) { - FASTFLOAT_ASSERT(real_digits.pow2(uint32_t(-pow2_exp))); - } - - // compare digits, and use it to director rounding - int ord = real_digits.compare(theor_digits); - adjusted_mantissa answer = am; - round(answer, [ord](adjusted_mantissa& a, int32_t shift) { - round_nearest_tie_even(a, shift, [ord](bool is_odd, bool _, bool __) -> bool { - (void)_; // not needed, since we've done our comparison - (void)__; // not needed, since we've done our comparison - if (ord > 0) { - return true; - } else if (ord < 0) { - return false; - } else { - return is_odd; - } - }); - }); - - return answer; -} - -// parse the significant digits as a big integer to unambiguously round the -// the significant digits. here, we are trying to determine how to round -// an extended float representation close to `b+h`, halfway between `b` -// (the float rounded-down) and `b+u`, the next positive float. this -// algorithm is always correct, and uses one of two approaches. when -// the exponent is positive relative to the significant digits (such as -// 1234), we create a big-integer representation, get the high 64-bits, -// determine if any lower bits are truncated, and use that to direct -// rounding. in case of a negative exponent relative to the significant -// digits (such as 1.2345), we create a theoretical representation of -// `b` as a big-integer type, scaled to the same binary exponent as -// the actual digits. we then compare the big integer representations -// of both, and use that to direct rounding. -template -inline adjusted_mantissa digit_comp(parsed_number_string& num, adjusted_mantissa am) noexcept { - // remove the invalid exponent bias - am.power2 -= invalid_am_bias; - - int32_t sci_exp = scientific_exponent(num); - size_t max_digits = binary_format::max_digits(); - size_t digits = 0; - bigint bigmant; - parse_mantissa(bigmant, num, max_digits, digits); - // can't underflow, since digits is at most max_digits. - int32_t exponent = sci_exp + 1 - int32_t(digits); - if (exponent >= 0) { - return positive_digit_comp(bigmant, exponent); - } else { - return negative_digit_comp(bigmant, am, exponent); - } -} - -} // namespace fast_float - -#endif diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/include/fast_float/fast_float.h b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/include/fast_float/fast_float.h deleted file mode 100644 index 3c483803a..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/include/fast_float/fast_float.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef FASTFLOAT_FAST_FLOAT_H -#define FASTFLOAT_FAST_FLOAT_H - -#include - -namespace fast_float { -enum chars_format { - scientific = 1<<0, - fixed = 1<<2, - hex = 1<<3, - general = fixed | scientific -}; - - -struct from_chars_result { - const char *ptr; - std::errc ec; -}; - -struct parse_options { - constexpr explicit parse_options(chars_format fmt = chars_format::general, - char dot = '.') - : format(fmt), decimal_point(dot) {} - - /** Which number formats are accepted */ - chars_format format; - /** The character used as decimal point */ - char decimal_point; -}; - -/** - * This function parses the character sequence [first,last) for a number. It parses floating-point numbers expecting - * a locale-indepent format equivalent to what is used by std::strtod in the default ("C") locale. - * The resulting floating-point value is the closest floating-point values (using either float or double), - * using the "round to even" convention for values that would otherwise fall right in-between two values. - * That is, we provide exact parsing according to the IEEE standard. - * - * Given a successful parse, the pointer (`ptr`) in the returned value is set to point right after the - * parsed number, and the `value` referenced is set to the parsed value. In case of error, the returned - * `ec` contains a representative error, otherwise the default (`std::errc()`) value is stored. - * - * The implementation does not throw and does not allocate memory (e.g., with `new` or `malloc`). - * - * Like the C++17 standard, the `fast_float::from_chars` functions take an optional last argument of - * the type `fast_float::chars_format`. It is a bitset value: we check whether - * `fmt & fast_float::chars_format::fixed` and `fmt & fast_float::chars_format::scientific` are set - * to determine whether we allowe the fixed point and scientific notation respectively. - * The default is `fast_float::chars_format::general` which allows both `fixed` and `scientific`. - */ -template -from_chars_result from_chars(const char *first, const char *last, - T &value, chars_format fmt = chars_format::general) noexcept; - -/** - * Like from_chars, but accepts an `options` argument to govern number parsing. - */ -template -from_chars_result from_chars_advanced(const char *first, const char *last, - T &value, parse_options options) noexcept; - -} -#include "parse_number.h" -#endif // FASTFLOAT_FAST_FLOAT_H diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/include/fast_float/fast_table.h b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/include/fast_float/fast_table.h deleted file mode 100644 index 5766274ca..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/include/fast_float/fast_table.h +++ /dev/null @@ -1,699 +0,0 @@ -#ifndef FASTFLOAT_FAST_TABLE_H -#define FASTFLOAT_FAST_TABLE_H - -#include - -namespace fast_float { - -/** - * When mapping numbers from decimal to binary, - * we go from w * 10^q to m * 2^p but we have - * 10^q = 5^q * 2^q, so effectively - * we are trying to match - * w * 2^q * 5^q to m * 2^p. Thus the powers of two - * are not a concern since they can be represented - * exactly using the binary notation, only the powers of five - * affect the binary significand. - */ - -/** - * The smallest non-zero float (binary64) is 2^−1074. - * We take as input numbers of the form w x 10^q where w < 2^64. - * We have that w * 10^-343 < 2^(64-344) 5^-343 < 2^-1076. - * However, we have that - * (2^64-1) * 10^-342 = (2^64-1) * 2^-342 * 5^-342 > 2^−1074. - * Thus it is possible for a number of the form w * 10^-342 where - * w is a 64-bit value to be a non-zero floating-point number. - ********* - * Any number of form w * 10^309 where w>= 1 is going to be - * infinite in binary64 so we never need to worry about powers - * of 5 greater than 308. - */ -template -struct powers_template { - -constexpr static int smallest_power_of_five = binary_format::smallest_power_of_ten(); -constexpr static int largest_power_of_five = binary_format::largest_power_of_ten(); -constexpr static int number_of_entries = 2 * (largest_power_of_five - smallest_power_of_five + 1); -// Powers of five from 5^-342 all the way to 5^308 rounded toward one. -static const uint64_t power_of_five_128[number_of_entries]; -}; - -template -const uint64_t powers_template::power_of_five_128[number_of_entries] = { - 0xeef453d6923bd65a,0x113faa2906a13b3f, - 0x9558b4661b6565f8,0x4ac7ca59a424c507, - 0xbaaee17fa23ebf76,0x5d79bcf00d2df649, - 0xe95a99df8ace6f53,0xf4d82c2c107973dc, - 0x91d8a02bb6c10594,0x79071b9b8a4be869, - 0xb64ec836a47146f9,0x9748e2826cdee284, - 0xe3e27a444d8d98b7,0xfd1b1b2308169b25, - 0x8e6d8c6ab0787f72,0xfe30f0f5e50e20f7, - 0xb208ef855c969f4f,0xbdbd2d335e51a935, - 0xde8b2b66b3bc4723,0xad2c788035e61382, - 0x8b16fb203055ac76,0x4c3bcb5021afcc31, - 0xaddcb9e83c6b1793,0xdf4abe242a1bbf3d, - 0xd953e8624b85dd78,0xd71d6dad34a2af0d, - 0x87d4713d6f33aa6b,0x8672648c40e5ad68, - 0xa9c98d8ccb009506,0x680efdaf511f18c2, - 0xd43bf0effdc0ba48,0x212bd1b2566def2, - 0x84a57695fe98746d,0x14bb630f7604b57, - 0xa5ced43b7e3e9188,0x419ea3bd35385e2d, - 0xcf42894a5dce35ea,0x52064cac828675b9, - 0x818995ce7aa0e1b2,0x7343efebd1940993, - 0xa1ebfb4219491a1f,0x1014ebe6c5f90bf8, - 0xca66fa129f9b60a6,0xd41a26e077774ef6, - 0xfd00b897478238d0,0x8920b098955522b4, - 0x9e20735e8cb16382,0x55b46e5f5d5535b0, - 0xc5a890362fddbc62,0xeb2189f734aa831d, - 0xf712b443bbd52b7b,0xa5e9ec7501d523e4, - 0x9a6bb0aa55653b2d,0x47b233c92125366e, - 0xc1069cd4eabe89f8,0x999ec0bb696e840a, - 0xf148440a256e2c76,0xc00670ea43ca250d, - 0x96cd2a865764dbca,0x380406926a5e5728, - 0xbc807527ed3e12bc,0xc605083704f5ecf2, - 0xeba09271e88d976b,0xf7864a44c633682e, - 0x93445b8731587ea3,0x7ab3ee6afbe0211d, - 0xb8157268fdae9e4c,0x5960ea05bad82964, - 0xe61acf033d1a45df,0x6fb92487298e33bd, - 0x8fd0c16206306bab,0xa5d3b6d479f8e056, - 0xb3c4f1ba87bc8696,0x8f48a4899877186c, - 0xe0b62e2929aba83c,0x331acdabfe94de87, - 0x8c71dcd9ba0b4925,0x9ff0c08b7f1d0b14, - 0xaf8e5410288e1b6f,0x7ecf0ae5ee44dd9, - 0xdb71e91432b1a24a,0xc9e82cd9f69d6150, - 0x892731ac9faf056e,0xbe311c083a225cd2, - 0xab70fe17c79ac6ca,0x6dbd630a48aaf406, - 0xd64d3d9db981787d,0x92cbbccdad5b108, - 0x85f0468293f0eb4e,0x25bbf56008c58ea5, - 0xa76c582338ed2621,0xaf2af2b80af6f24e, - 0xd1476e2c07286faa,0x1af5af660db4aee1, - 0x82cca4db847945ca,0x50d98d9fc890ed4d, - 0xa37fce126597973c,0xe50ff107bab528a0, - 0xcc5fc196fefd7d0c,0x1e53ed49a96272c8, - 0xff77b1fcbebcdc4f,0x25e8e89c13bb0f7a, - 0x9faacf3df73609b1,0x77b191618c54e9ac, - 0xc795830d75038c1d,0xd59df5b9ef6a2417, - 0xf97ae3d0d2446f25,0x4b0573286b44ad1d, - 0x9becce62836ac577,0x4ee367f9430aec32, - 0xc2e801fb244576d5,0x229c41f793cda73f, - 0xf3a20279ed56d48a,0x6b43527578c1110f, - 0x9845418c345644d6,0x830a13896b78aaa9, - 0xbe5691ef416bd60c,0x23cc986bc656d553, - 0xedec366b11c6cb8f,0x2cbfbe86b7ec8aa8, - 0x94b3a202eb1c3f39,0x7bf7d71432f3d6a9, - 0xb9e08a83a5e34f07,0xdaf5ccd93fb0cc53, - 0xe858ad248f5c22c9,0xd1b3400f8f9cff68, - 0x91376c36d99995be,0x23100809b9c21fa1, - 0xb58547448ffffb2d,0xabd40a0c2832a78a, - 0xe2e69915b3fff9f9,0x16c90c8f323f516c, - 0x8dd01fad907ffc3b,0xae3da7d97f6792e3, - 0xb1442798f49ffb4a,0x99cd11cfdf41779c, - 0xdd95317f31c7fa1d,0x40405643d711d583, - 0x8a7d3eef7f1cfc52,0x482835ea666b2572, - 0xad1c8eab5ee43b66,0xda3243650005eecf, - 0xd863b256369d4a40,0x90bed43e40076a82, - 0x873e4f75e2224e68,0x5a7744a6e804a291, - 0xa90de3535aaae202,0x711515d0a205cb36, - 0xd3515c2831559a83,0xd5a5b44ca873e03, - 0x8412d9991ed58091,0xe858790afe9486c2, - 0xa5178fff668ae0b6,0x626e974dbe39a872, - 0xce5d73ff402d98e3,0xfb0a3d212dc8128f, - 0x80fa687f881c7f8e,0x7ce66634bc9d0b99, - 0xa139029f6a239f72,0x1c1fffc1ebc44e80, - 0xc987434744ac874e,0xa327ffb266b56220, - 0xfbe9141915d7a922,0x4bf1ff9f0062baa8, - 0x9d71ac8fada6c9b5,0x6f773fc3603db4a9, - 0xc4ce17b399107c22,0xcb550fb4384d21d3, - 0xf6019da07f549b2b,0x7e2a53a146606a48, - 0x99c102844f94e0fb,0x2eda7444cbfc426d, - 0xc0314325637a1939,0xfa911155fefb5308, - 0xf03d93eebc589f88,0x793555ab7eba27ca, - 0x96267c7535b763b5,0x4bc1558b2f3458de, - 0xbbb01b9283253ca2,0x9eb1aaedfb016f16, - 0xea9c227723ee8bcb,0x465e15a979c1cadc, - 0x92a1958a7675175f,0xbfacd89ec191ec9, - 0xb749faed14125d36,0xcef980ec671f667b, - 0xe51c79a85916f484,0x82b7e12780e7401a, - 0x8f31cc0937ae58d2,0xd1b2ecb8b0908810, - 0xb2fe3f0b8599ef07,0x861fa7e6dcb4aa15, - 0xdfbdcece67006ac9,0x67a791e093e1d49a, - 0x8bd6a141006042bd,0xe0c8bb2c5c6d24e0, - 0xaecc49914078536d,0x58fae9f773886e18, - 0xda7f5bf590966848,0xaf39a475506a899e, - 0x888f99797a5e012d,0x6d8406c952429603, - 0xaab37fd7d8f58178,0xc8e5087ba6d33b83, - 0xd5605fcdcf32e1d6,0xfb1e4a9a90880a64, - 0x855c3be0a17fcd26,0x5cf2eea09a55067f, - 0xa6b34ad8c9dfc06f,0xf42faa48c0ea481e, - 0xd0601d8efc57b08b,0xf13b94daf124da26, - 0x823c12795db6ce57,0x76c53d08d6b70858, - 0xa2cb1717b52481ed,0x54768c4b0c64ca6e, - 0xcb7ddcdda26da268,0xa9942f5dcf7dfd09, - 0xfe5d54150b090b02,0xd3f93b35435d7c4c, - 0x9efa548d26e5a6e1,0xc47bc5014a1a6daf, - 0xc6b8e9b0709f109a,0x359ab6419ca1091b, - 0xf867241c8cc6d4c0,0xc30163d203c94b62, - 0x9b407691d7fc44f8,0x79e0de63425dcf1d, - 0xc21094364dfb5636,0x985915fc12f542e4, - 0xf294b943e17a2bc4,0x3e6f5b7b17b2939d, - 0x979cf3ca6cec5b5a,0xa705992ceecf9c42, - 0xbd8430bd08277231,0x50c6ff782a838353, - 0xece53cec4a314ebd,0xa4f8bf5635246428, - 0x940f4613ae5ed136,0x871b7795e136be99, - 0xb913179899f68584,0x28e2557b59846e3f, - 0xe757dd7ec07426e5,0x331aeada2fe589cf, - 0x9096ea6f3848984f,0x3ff0d2c85def7621, - 0xb4bca50b065abe63,0xfed077a756b53a9, - 0xe1ebce4dc7f16dfb,0xd3e8495912c62894, - 0x8d3360f09cf6e4bd,0x64712dd7abbbd95c, - 0xb080392cc4349dec,0xbd8d794d96aacfb3, - 0xdca04777f541c567,0xecf0d7a0fc5583a0, - 0x89e42caaf9491b60,0xf41686c49db57244, - 0xac5d37d5b79b6239,0x311c2875c522ced5, - 0xd77485cb25823ac7,0x7d633293366b828b, - 0x86a8d39ef77164bc,0xae5dff9c02033197, - 0xa8530886b54dbdeb,0xd9f57f830283fdfc, - 0xd267caa862a12d66,0xd072df63c324fd7b, - 0x8380dea93da4bc60,0x4247cb9e59f71e6d, - 0xa46116538d0deb78,0x52d9be85f074e608, - 0xcd795be870516656,0x67902e276c921f8b, - 0x806bd9714632dff6,0xba1cd8a3db53b6, - 0xa086cfcd97bf97f3,0x80e8a40eccd228a4, - 0xc8a883c0fdaf7df0,0x6122cd128006b2cd, - 0xfad2a4b13d1b5d6c,0x796b805720085f81, - 0x9cc3a6eec6311a63,0xcbe3303674053bb0, - 0xc3f490aa77bd60fc,0xbedbfc4411068a9c, - 0xf4f1b4d515acb93b,0xee92fb5515482d44, - 0x991711052d8bf3c5,0x751bdd152d4d1c4a, - 0xbf5cd54678eef0b6,0xd262d45a78a0635d, - 0xef340a98172aace4,0x86fb897116c87c34, - 0x9580869f0e7aac0e,0xd45d35e6ae3d4da0, - 0xbae0a846d2195712,0x8974836059cca109, - 0xe998d258869facd7,0x2bd1a438703fc94b, - 0x91ff83775423cc06,0x7b6306a34627ddcf, - 0xb67f6455292cbf08,0x1a3bc84c17b1d542, - 0xe41f3d6a7377eeca,0x20caba5f1d9e4a93, - 0x8e938662882af53e,0x547eb47b7282ee9c, - 0xb23867fb2a35b28d,0xe99e619a4f23aa43, - 0xdec681f9f4c31f31,0x6405fa00e2ec94d4, - 0x8b3c113c38f9f37e,0xde83bc408dd3dd04, - 0xae0b158b4738705e,0x9624ab50b148d445, - 0xd98ddaee19068c76,0x3badd624dd9b0957, - 0x87f8a8d4cfa417c9,0xe54ca5d70a80e5d6, - 0xa9f6d30a038d1dbc,0x5e9fcf4ccd211f4c, - 0xd47487cc8470652b,0x7647c3200069671f, - 0x84c8d4dfd2c63f3b,0x29ecd9f40041e073, - 0xa5fb0a17c777cf09,0xf468107100525890, - 0xcf79cc9db955c2cc,0x7182148d4066eeb4, - 0x81ac1fe293d599bf,0xc6f14cd848405530, - 0xa21727db38cb002f,0xb8ada00e5a506a7c, - 0xca9cf1d206fdc03b,0xa6d90811f0e4851c, - 0xfd442e4688bd304a,0x908f4a166d1da663, - 0x9e4a9cec15763e2e,0x9a598e4e043287fe, - 0xc5dd44271ad3cdba,0x40eff1e1853f29fd, - 0xf7549530e188c128,0xd12bee59e68ef47c, - 0x9a94dd3e8cf578b9,0x82bb74f8301958ce, - 0xc13a148e3032d6e7,0xe36a52363c1faf01, - 0xf18899b1bc3f8ca1,0xdc44e6c3cb279ac1, - 0x96f5600f15a7b7e5,0x29ab103a5ef8c0b9, - 0xbcb2b812db11a5de,0x7415d448f6b6f0e7, - 0xebdf661791d60f56,0x111b495b3464ad21, - 0x936b9fcebb25c995,0xcab10dd900beec34, - 0xb84687c269ef3bfb,0x3d5d514f40eea742, - 0xe65829b3046b0afa,0xcb4a5a3112a5112, - 0x8ff71a0fe2c2e6dc,0x47f0e785eaba72ab, - 0xb3f4e093db73a093,0x59ed216765690f56, - 0xe0f218b8d25088b8,0x306869c13ec3532c, - 0x8c974f7383725573,0x1e414218c73a13fb, - 0xafbd2350644eeacf,0xe5d1929ef90898fa, - 0xdbac6c247d62a583,0xdf45f746b74abf39, - 0x894bc396ce5da772,0x6b8bba8c328eb783, - 0xab9eb47c81f5114f,0x66ea92f3f326564, - 0xd686619ba27255a2,0xc80a537b0efefebd, - 0x8613fd0145877585,0xbd06742ce95f5f36, - 0xa798fc4196e952e7,0x2c48113823b73704, - 0xd17f3b51fca3a7a0,0xf75a15862ca504c5, - 0x82ef85133de648c4,0x9a984d73dbe722fb, - 0xa3ab66580d5fdaf5,0xc13e60d0d2e0ebba, - 0xcc963fee10b7d1b3,0x318df905079926a8, - 0xffbbcfe994e5c61f,0xfdf17746497f7052, - 0x9fd561f1fd0f9bd3,0xfeb6ea8bedefa633, - 0xc7caba6e7c5382c8,0xfe64a52ee96b8fc0, - 0xf9bd690a1b68637b,0x3dfdce7aa3c673b0, - 0x9c1661a651213e2d,0x6bea10ca65c084e, - 0xc31bfa0fe5698db8,0x486e494fcff30a62, - 0xf3e2f893dec3f126,0x5a89dba3c3efccfa, - 0x986ddb5c6b3a76b7,0xf89629465a75e01c, - 0xbe89523386091465,0xf6bbb397f1135823, - 0xee2ba6c0678b597f,0x746aa07ded582e2c, - 0x94db483840b717ef,0xa8c2a44eb4571cdc, - 0xba121a4650e4ddeb,0x92f34d62616ce413, - 0xe896a0d7e51e1566,0x77b020baf9c81d17, - 0x915e2486ef32cd60,0xace1474dc1d122e, - 0xb5b5ada8aaff80b8,0xd819992132456ba, - 0xe3231912d5bf60e6,0x10e1fff697ed6c69, - 0x8df5efabc5979c8f,0xca8d3ffa1ef463c1, - 0xb1736b96b6fd83b3,0xbd308ff8a6b17cb2, - 0xddd0467c64bce4a0,0xac7cb3f6d05ddbde, - 0x8aa22c0dbef60ee4,0x6bcdf07a423aa96b, - 0xad4ab7112eb3929d,0x86c16c98d2c953c6, - 0xd89d64d57a607744,0xe871c7bf077ba8b7, - 0x87625f056c7c4a8b,0x11471cd764ad4972, - 0xa93af6c6c79b5d2d,0xd598e40d3dd89bcf, - 0xd389b47879823479,0x4aff1d108d4ec2c3, - 0x843610cb4bf160cb,0xcedf722a585139ba, - 0xa54394fe1eedb8fe,0xc2974eb4ee658828, - 0xce947a3da6a9273e,0x733d226229feea32, - 0x811ccc668829b887,0x806357d5a3f525f, - 0xa163ff802a3426a8,0xca07c2dcb0cf26f7, - 0xc9bcff6034c13052,0xfc89b393dd02f0b5, - 0xfc2c3f3841f17c67,0xbbac2078d443ace2, - 0x9d9ba7832936edc0,0xd54b944b84aa4c0d, - 0xc5029163f384a931,0xa9e795e65d4df11, - 0xf64335bcf065d37d,0x4d4617b5ff4a16d5, - 0x99ea0196163fa42e,0x504bced1bf8e4e45, - 0xc06481fb9bcf8d39,0xe45ec2862f71e1d6, - 0xf07da27a82c37088,0x5d767327bb4e5a4c, - 0x964e858c91ba2655,0x3a6a07f8d510f86f, - 0xbbe226efb628afea,0x890489f70a55368b, - 0xeadab0aba3b2dbe5,0x2b45ac74ccea842e, - 0x92c8ae6b464fc96f,0x3b0b8bc90012929d, - 0xb77ada0617e3bbcb,0x9ce6ebb40173744, - 0xe55990879ddcaabd,0xcc420a6a101d0515, - 0x8f57fa54c2a9eab6,0x9fa946824a12232d, - 0xb32df8e9f3546564,0x47939822dc96abf9, - 0xdff9772470297ebd,0x59787e2b93bc56f7, - 0x8bfbea76c619ef36,0x57eb4edb3c55b65a, - 0xaefae51477a06b03,0xede622920b6b23f1, - 0xdab99e59958885c4,0xe95fab368e45eced, - 0x88b402f7fd75539b,0x11dbcb0218ebb414, - 0xaae103b5fcd2a881,0xd652bdc29f26a119, - 0xd59944a37c0752a2,0x4be76d3346f0495f, - 0x857fcae62d8493a5,0x6f70a4400c562ddb, - 0xa6dfbd9fb8e5b88e,0xcb4ccd500f6bb952, - 0xd097ad07a71f26b2,0x7e2000a41346a7a7, - 0x825ecc24c873782f,0x8ed400668c0c28c8, - 0xa2f67f2dfa90563b,0x728900802f0f32fa, - 0xcbb41ef979346bca,0x4f2b40a03ad2ffb9, - 0xfea126b7d78186bc,0xe2f610c84987bfa8, - 0x9f24b832e6b0f436,0xdd9ca7d2df4d7c9, - 0xc6ede63fa05d3143,0x91503d1c79720dbb, - 0xf8a95fcf88747d94,0x75a44c6397ce912a, - 0x9b69dbe1b548ce7c,0xc986afbe3ee11aba, - 0xc24452da229b021b,0xfbe85badce996168, - 0xf2d56790ab41c2a2,0xfae27299423fb9c3, - 0x97c560ba6b0919a5,0xdccd879fc967d41a, - 0xbdb6b8e905cb600f,0x5400e987bbc1c920, - 0xed246723473e3813,0x290123e9aab23b68, - 0x9436c0760c86e30b,0xf9a0b6720aaf6521, - 0xb94470938fa89bce,0xf808e40e8d5b3e69, - 0xe7958cb87392c2c2,0xb60b1d1230b20e04, - 0x90bd77f3483bb9b9,0xb1c6f22b5e6f48c2, - 0xb4ecd5f01a4aa828,0x1e38aeb6360b1af3, - 0xe2280b6c20dd5232,0x25c6da63c38de1b0, - 0x8d590723948a535f,0x579c487e5a38ad0e, - 0xb0af48ec79ace837,0x2d835a9df0c6d851, - 0xdcdb1b2798182244,0xf8e431456cf88e65, - 0x8a08f0f8bf0f156b,0x1b8e9ecb641b58ff, - 0xac8b2d36eed2dac5,0xe272467e3d222f3f, - 0xd7adf884aa879177,0x5b0ed81dcc6abb0f, - 0x86ccbb52ea94baea,0x98e947129fc2b4e9, - 0xa87fea27a539e9a5,0x3f2398d747b36224, - 0xd29fe4b18e88640e,0x8eec7f0d19a03aad, - 0x83a3eeeef9153e89,0x1953cf68300424ac, - 0xa48ceaaab75a8e2b,0x5fa8c3423c052dd7, - 0xcdb02555653131b6,0x3792f412cb06794d, - 0x808e17555f3ebf11,0xe2bbd88bbee40bd0, - 0xa0b19d2ab70e6ed6,0x5b6aceaeae9d0ec4, - 0xc8de047564d20a8b,0xf245825a5a445275, - 0xfb158592be068d2e,0xeed6e2f0f0d56712, - 0x9ced737bb6c4183d,0x55464dd69685606b, - 0xc428d05aa4751e4c,0xaa97e14c3c26b886, - 0xf53304714d9265df,0xd53dd99f4b3066a8, - 0x993fe2c6d07b7fab,0xe546a8038efe4029, - 0xbf8fdb78849a5f96,0xde98520472bdd033, - 0xef73d256a5c0f77c,0x963e66858f6d4440, - 0x95a8637627989aad,0xdde7001379a44aa8, - 0xbb127c53b17ec159,0x5560c018580d5d52, - 0xe9d71b689dde71af,0xaab8f01e6e10b4a6, - 0x9226712162ab070d,0xcab3961304ca70e8, - 0xb6b00d69bb55c8d1,0x3d607b97c5fd0d22, - 0xe45c10c42a2b3b05,0x8cb89a7db77c506a, - 0x8eb98a7a9a5b04e3,0x77f3608e92adb242, - 0xb267ed1940f1c61c,0x55f038b237591ed3, - 0xdf01e85f912e37a3,0x6b6c46dec52f6688, - 0x8b61313bbabce2c6,0x2323ac4b3b3da015, - 0xae397d8aa96c1b77,0xabec975e0a0d081a, - 0xd9c7dced53c72255,0x96e7bd358c904a21, - 0x881cea14545c7575,0x7e50d64177da2e54, - 0xaa242499697392d2,0xdde50bd1d5d0b9e9, - 0xd4ad2dbfc3d07787,0x955e4ec64b44e864, - 0x84ec3c97da624ab4,0xbd5af13bef0b113e, - 0xa6274bbdd0fadd61,0xecb1ad8aeacdd58e, - 0xcfb11ead453994ba,0x67de18eda5814af2, - 0x81ceb32c4b43fcf4,0x80eacf948770ced7, - 0xa2425ff75e14fc31,0xa1258379a94d028d, - 0xcad2f7f5359a3b3e,0x96ee45813a04330, - 0xfd87b5f28300ca0d,0x8bca9d6e188853fc, - 0x9e74d1b791e07e48,0x775ea264cf55347e, - 0xc612062576589dda,0x95364afe032a819e, - 0xf79687aed3eec551,0x3a83ddbd83f52205, - 0x9abe14cd44753b52,0xc4926a9672793543, - 0xc16d9a0095928a27,0x75b7053c0f178294, - 0xf1c90080baf72cb1,0x5324c68b12dd6339, - 0x971da05074da7bee,0xd3f6fc16ebca5e04, - 0xbce5086492111aea,0x88f4bb1ca6bcf585, - 0xec1e4a7db69561a5,0x2b31e9e3d06c32e6, - 0x9392ee8e921d5d07,0x3aff322e62439fd0, - 0xb877aa3236a4b449,0x9befeb9fad487c3, - 0xe69594bec44de15b,0x4c2ebe687989a9b4, - 0x901d7cf73ab0acd9,0xf9d37014bf60a11, - 0xb424dc35095cd80f,0x538484c19ef38c95, - 0xe12e13424bb40e13,0x2865a5f206b06fba, - 0x8cbccc096f5088cb,0xf93f87b7442e45d4, - 0xafebff0bcb24aafe,0xf78f69a51539d749, - 0xdbe6fecebdedd5be,0xb573440e5a884d1c, - 0x89705f4136b4a597,0x31680a88f8953031, - 0xabcc77118461cefc,0xfdc20d2b36ba7c3e, - 0xd6bf94d5e57a42bc,0x3d32907604691b4d, - 0x8637bd05af6c69b5,0xa63f9a49c2c1b110, - 0xa7c5ac471b478423,0xfcf80dc33721d54, - 0xd1b71758e219652b,0xd3c36113404ea4a9, - 0x83126e978d4fdf3b,0x645a1cac083126ea, - 0xa3d70a3d70a3d70a,0x3d70a3d70a3d70a4, - 0xcccccccccccccccc,0xcccccccccccccccd, - 0x8000000000000000,0x0, - 0xa000000000000000,0x0, - 0xc800000000000000,0x0, - 0xfa00000000000000,0x0, - 0x9c40000000000000,0x0, - 0xc350000000000000,0x0, - 0xf424000000000000,0x0, - 0x9896800000000000,0x0, - 0xbebc200000000000,0x0, - 0xee6b280000000000,0x0, - 0x9502f90000000000,0x0, - 0xba43b74000000000,0x0, - 0xe8d4a51000000000,0x0, - 0x9184e72a00000000,0x0, - 0xb5e620f480000000,0x0, - 0xe35fa931a0000000,0x0, - 0x8e1bc9bf04000000,0x0, - 0xb1a2bc2ec5000000,0x0, - 0xde0b6b3a76400000,0x0, - 0x8ac7230489e80000,0x0, - 0xad78ebc5ac620000,0x0, - 0xd8d726b7177a8000,0x0, - 0x878678326eac9000,0x0, - 0xa968163f0a57b400,0x0, - 0xd3c21bcecceda100,0x0, - 0x84595161401484a0,0x0, - 0xa56fa5b99019a5c8,0x0, - 0xcecb8f27f4200f3a,0x0, - 0x813f3978f8940984,0x4000000000000000, - 0xa18f07d736b90be5,0x5000000000000000, - 0xc9f2c9cd04674ede,0xa400000000000000, - 0xfc6f7c4045812296,0x4d00000000000000, - 0x9dc5ada82b70b59d,0xf020000000000000, - 0xc5371912364ce305,0x6c28000000000000, - 0xf684df56c3e01bc6,0xc732000000000000, - 0x9a130b963a6c115c,0x3c7f400000000000, - 0xc097ce7bc90715b3,0x4b9f100000000000, - 0xf0bdc21abb48db20,0x1e86d40000000000, - 0x96769950b50d88f4,0x1314448000000000, - 0xbc143fa4e250eb31,0x17d955a000000000, - 0xeb194f8e1ae525fd,0x5dcfab0800000000, - 0x92efd1b8d0cf37be,0x5aa1cae500000000, - 0xb7abc627050305ad,0xf14a3d9e40000000, - 0xe596b7b0c643c719,0x6d9ccd05d0000000, - 0x8f7e32ce7bea5c6f,0xe4820023a2000000, - 0xb35dbf821ae4f38b,0xdda2802c8a800000, - 0xe0352f62a19e306e,0xd50b2037ad200000, - 0x8c213d9da502de45,0x4526f422cc340000, - 0xaf298d050e4395d6,0x9670b12b7f410000, - 0xdaf3f04651d47b4c,0x3c0cdd765f114000, - 0x88d8762bf324cd0f,0xa5880a69fb6ac800, - 0xab0e93b6efee0053,0x8eea0d047a457a00, - 0xd5d238a4abe98068,0x72a4904598d6d880, - 0x85a36366eb71f041,0x47a6da2b7f864750, - 0xa70c3c40a64e6c51,0x999090b65f67d924, - 0xd0cf4b50cfe20765,0xfff4b4e3f741cf6d, - 0x82818f1281ed449f,0xbff8f10e7a8921a4, - 0xa321f2d7226895c7,0xaff72d52192b6a0d, - 0xcbea6f8ceb02bb39,0x9bf4f8a69f764490, - 0xfee50b7025c36a08,0x2f236d04753d5b4, - 0x9f4f2726179a2245,0x1d762422c946590, - 0xc722f0ef9d80aad6,0x424d3ad2b7b97ef5, - 0xf8ebad2b84e0d58b,0xd2e0898765a7deb2, - 0x9b934c3b330c8577,0x63cc55f49f88eb2f, - 0xc2781f49ffcfa6d5,0x3cbf6b71c76b25fb, - 0xf316271c7fc3908a,0x8bef464e3945ef7a, - 0x97edd871cfda3a56,0x97758bf0e3cbb5ac, - 0xbde94e8e43d0c8ec,0x3d52eeed1cbea317, - 0xed63a231d4c4fb27,0x4ca7aaa863ee4bdd, - 0x945e455f24fb1cf8,0x8fe8caa93e74ef6a, - 0xb975d6b6ee39e436,0xb3e2fd538e122b44, - 0xe7d34c64a9c85d44,0x60dbbca87196b616, - 0x90e40fbeea1d3a4a,0xbc8955e946fe31cd, - 0xb51d13aea4a488dd,0x6babab6398bdbe41, - 0xe264589a4dcdab14,0xc696963c7eed2dd1, - 0x8d7eb76070a08aec,0xfc1e1de5cf543ca2, - 0xb0de65388cc8ada8,0x3b25a55f43294bcb, - 0xdd15fe86affad912,0x49ef0eb713f39ebe, - 0x8a2dbf142dfcc7ab,0x6e3569326c784337, - 0xacb92ed9397bf996,0x49c2c37f07965404, - 0xd7e77a8f87daf7fb,0xdc33745ec97be906, - 0x86f0ac99b4e8dafd,0x69a028bb3ded71a3, - 0xa8acd7c0222311bc,0xc40832ea0d68ce0c, - 0xd2d80db02aabd62b,0xf50a3fa490c30190, - 0x83c7088e1aab65db,0x792667c6da79e0fa, - 0xa4b8cab1a1563f52,0x577001b891185938, - 0xcde6fd5e09abcf26,0xed4c0226b55e6f86, - 0x80b05e5ac60b6178,0x544f8158315b05b4, - 0xa0dc75f1778e39d6,0x696361ae3db1c721, - 0xc913936dd571c84c,0x3bc3a19cd1e38e9, - 0xfb5878494ace3a5f,0x4ab48a04065c723, - 0x9d174b2dcec0e47b,0x62eb0d64283f9c76, - 0xc45d1df942711d9a,0x3ba5d0bd324f8394, - 0xf5746577930d6500,0xca8f44ec7ee36479, - 0x9968bf6abbe85f20,0x7e998b13cf4e1ecb, - 0xbfc2ef456ae276e8,0x9e3fedd8c321a67e, - 0xefb3ab16c59b14a2,0xc5cfe94ef3ea101e, - 0x95d04aee3b80ece5,0xbba1f1d158724a12, - 0xbb445da9ca61281f,0x2a8a6e45ae8edc97, - 0xea1575143cf97226,0xf52d09d71a3293bd, - 0x924d692ca61be758,0x593c2626705f9c56, - 0xb6e0c377cfa2e12e,0x6f8b2fb00c77836c, - 0xe498f455c38b997a,0xb6dfb9c0f956447, - 0x8edf98b59a373fec,0x4724bd4189bd5eac, - 0xb2977ee300c50fe7,0x58edec91ec2cb657, - 0xdf3d5e9bc0f653e1,0x2f2967b66737e3ed, - 0x8b865b215899f46c,0xbd79e0d20082ee74, - 0xae67f1e9aec07187,0xecd8590680a3aa11, - 0xda01ee641a708de9,0xe80e6f4820cc9495, - 0x884134fe908658b2,0x3109058d147fdcdd, - 0xaa51823e34a7eede,0xbd4b46f0599fd415, - 0xd4e5e2cdc1d1ea96,0x6c9e18ac7007c91a, - 0x850fadc09923329e,0x3e2cf6bc604ddb0, - 0xa6539930bf6bff45,0x84db8346b786151c, - 0xcfe87f7cef46ff16,0xe612641865679a63, - 0x81f14fae158c5f6e,0x4fcb7e8f3f60c07e, - 0xa26da3999aef7749,0xe3be5e330f38f09d, - 0xcb090c8001ab551c,0x5cadf5bfd3072cc5, - 0xfdcb4fa002162a63,0x73d9732fc7c8f7f6, - 0x9e9f11c4014dda7e,0x2867e7fddcdd9afa, - 0xc646d63501a1511d,0xb281e1fd541501b8, - 0xf7d88bc24209a565,0x1f225a7ca91a4226, - 0x9ae757596946075f,0x3375788de9b06958, - 0xc1a12d2fc3978937,0x52d6b1641c83ae, - 0xf209787bb47d6b84,0xc0678c5dbd23a49a, - 0x9745eb4d50ce6332,0xf840b7ba963646e0, - 0xbd176620a501fbff,0xb650e5a93bc3d898, - 0xec5d3fa8ce427aff,0xa3e51f138ab4cebe, - 0x93ba47c980e98cdf,0xc66f336c36b10137, - 0xb8a8d9bbe123f017,0xb80b0047445d4184, - 0xe6d3102ad96cec1d,0xa60dc059157491e5, - 0x9043ea1ac7e41392,0x87c89837ad68db2f, - 0xb454e4a179dd1877,0x29babe4598c311fb, - 0xe16a1dc9d8545e94,0xf4296dd6fef3d67a, - 0x8ce2529e2734bb1d,0x1899e4a65f58660c, - 0xb01ae745b101e9e4,0x5ec05dcff72e7f8f, - 0xdc21a1171d42645d,0x76707543f4fa1f73, - 0x899504ae72497eba,0x6a06494a791c53a8, - 0xabfa45da0edbde69,0x487db9d17636892, - 0xd6f8d7509292d603,0x45a9d2845d3c42b6, - 0x865b86925b9bc5c2,0xb8a2392ba45a9b2, - 0xa7f26836f282b732,0x8e6cac7768d7141e, - 0xd1ef0244af2364ff,0x3207d795430cd926, - 0x8335616aed761f1f,0x7f44e6bd49e807b8, - 0xa402b9c5a8d3a6e7,0x5f16206c9c6209a6, - 0xcd036837130890a1,0x36dba887c37a8c0f, - 0x802221226be55a64,0xc2494954da2c9789, - 0xa02aa96b06deb0fd,0xf2db9baa10b7bd6c, - 0xc83553c5c8965d3d,0x6f92829494e5acc7, - 0xfa42a8b73abbf48c,0xcb772339ba1f17f9, - 0x9c69a97284b578d7,0xff2a760414536efb, - 0xc38413cf25e2d70d,0xfef5138519684aba, - 0xf46518c2ef5b8cd1,0x7eb258665fc25d69, - 0x98bf2f79d5993802,0xef2f773ffbd97a61, - 0xbeeefb584aff8603,0xaafb550ffacfd8fa, - 0xeeaaba2e5dbf6784,0x95ba2a53f983cf38, - 0x952ab45cfa97a0b2,0xdd945a747bf26183, - 0xba756174393d88df,0x94f971119aeef9e4, - 0xe912b9d1478ceb17,0x7a37cd5601aab85d, - 0x91abb422ccb812ee,0xac62e055c10ab33a, - 0xb616a12b7fe617aa,0x577b986b314d6009, - 0xe39c49765fdf9d94,0xed5a7e85fda0b80b, - 0x8e41ade9fbebc27d,0x14588f13be847307, - 0xb1d219647ae6b31c,0x596eb2d8ae258fc8, - 0xde469fbd99a05fe3,0x6fca5f8ed9aef3bb, - 0x8aec23d680043bee,0x25de7bb9480d5854, - 0xada72ccc20054ae9,0xaf561aa79a10ae6a, - 0xd910f7ff28069da4,0x1b2ba1518094da04, - 0x87aa9aff79042286,0x90fb44d2f05d0842, - 0xa99541bf57452b28,0x353a1607ac744a53, - 0xd3fa922f2d1675f2,0x42889b8997915ce8, - 0x847c9b5d7c2e09b7,0x69956135febada11, - 0xa59bc234db398c25,0x43fab9837e699095, - 0xcf02b2c21207ef2e,0x94f967e45e03f4bb, - 0x8161afb94b44f57d,0x1d1be0eebac278f5, - 0xa1ba1ba79e1632dc,0x6462d92a69731732, - 0xca28a291859bbf93,0x7d7b8f7503cfdcfe, - 0xfcb2cb35e702af78,0x5cda735244c3d43e, - 0x9defbf01b061adab,0x3a0888136afa64a7, - 0xc56baec21c7a1916,0x88aaa1845b8fdd0, - 0xf6c69a72a3989f5b,0x8aad549e57273d45, - 0x9a3c2087a63f6399,0x36ac54e2f678864b, - 0xc0cb28a98fcf3c7f,0x84576a1bb416a7dd, - 0xf0fdf2d3f3c30b9f,0x656d44a2a11c51d5, - 0x969eb7c47859e743,0x9f644ae5a4b1b325, - 0xbc4665b596706114,0x873d5d9f0dde1fee, - 0xeb57ff22fc0c7959,0xa90cb506d155a7ea, - 0x9316ff75dd87cbd8,0x9a7f12442d588f2, - 0xb7dcbf5354e9bece,0xc11ed6d538aeb2f, - 0xe5d3ef282a242e81,0x8f1668c8a86da5fa, - 0x8fa475791a569d10,0xf96e017d694487bc, - 0xb38d92d760ec4455,0x37c981dcc395a9ac, - 0xe070f78d3927556a,0x85bbe253f47b1417, - 0x8c469ab843b89562,0x93956d7478ccec8e, - 0xaf58416654a6babb,0x387ac8d1970027b2, - 0xdb2e51bfe9d0696a,0x6997b05fcc0319e, - 0x88fcf317f22241e2,0x441fece3bdf81f03, - 0xab3c2fddeeaad25a,0xd527e81cad7626c3, - 0xd60b3bd56a5586f1,0x8a71e223d8d3b074, - 0x85c7056562757456,0xf6872d5667844e49, - 0xa738c6bebb12d16c,0xb428f8ac016561db, - 0xd106f86e69d785c7,0xe13336d701beba52, - 0x82a45b450226b39c,0xecc0024661173473, - 0xa34d721642b06084,0x27f002d7f95d0190, - 0xcc20ce9bd35c78a5,0x31ec038df7b441f4, - 0xff290242c83396ce,0x7e67047175a15271, - 0x9f79a169bd203e41,0xf0062c6e984d386, - 0xc75809c42c684dd1,0x52c07b78a3e60868, - 0xf92e0c3537826145,0xa7709a56ccdf8a82, - 0x9bbcc7a142b17ccb,0x88a66076400bb691, - 0xc2abf989935ddbfe,0x6acff893d00ea435, - 0xf356f7ebf83552fe,0x583f6b8c4124d43, - 0x98165af37b2153de,0xc3727a337a8b704a, - 0xbe1bf1b059e9a8d6,0x744f18c0592e4c5c, - 0xeda2ee1c7064130c,0x1162def06f79df73, - 0x9485d4d1c63e8be7,0x8addcb5645ac2ba8, - 0xb9a74a0637ce2ee1,0x6d953e2bd7173692, - 0xe8111c87c5c1ba99,0xc8fa8db6ccdd0437, - 0x910ab1d4db9914a0,0x1d9c9892400a22a2, - 0xb54d5e4a127f59c8,0x2503beb6d00cab4b, - 0xe2a0b5dc971f303a,0x2e44ae64840fd61d, - 0x8da471a9de737e24,0x5ceaecfed289e5d2, - 0xb10d8e1456105dad,0x7425a83e872c5f47, - 0xdd50f1996b947518,0xd12f124e28f77719, - 0x8a5296ffe33cc92f,0x82bd6b70d99aaa6f, - 0xace73cbfdc0bfb7b,0x636cc64d1001550b, - 0xd8210befd30efa5a,0x3c47f7e05401aa4e, - 0x8714a775e3e95c78,0x65acfaec34810a71, - 0xa8d9d1535ce3b396,0x7f1839a741a14d0d, - 0xd31045a8341ca07c,0x1ede48111209a050, - 0x83ea2b892091e44d,0x934aed0aab460432, - 0xa4e4b66b68b65d60,0xf81da84d5617853f, - 0xce1de40642e3f4b9,0x36251260ab9d668e, - 0x80d2ae83e9ce78f3,0xc1d72b7c6b426019, - 0xa1075a24e4421730,0xb24cf65b8612f81f, - 0xc94930ae1d529cfc,0xdee033f26797b627, - 0xfb9b7cd9a4a7443c,0x169840ef017da3b1, - 0x9d412e0806e88aa5,0x8e1f289560ee864e, - 0xc491798a08a2ad4e,0xf1a6f2bab92a27e2, - 0xf5b5d7ec8acb58a2,0xae10af696774b1db, - 0x9991a6f3d6bf1765,0xacca6da1e0a8ef29, - 0xbff610b0cc6edd3f,0x17fd090a58d32af3, - 0xeff394dcff8a948e,0xddfc4b4cef07f5b0, - 0x95f83d0a1fb69cd9,0x4abdaf101564f98e, - 0xbb764c4ca7a4440f,0x9d6d1ad41abe37f1, - 0xea53df5fd18d5513,0x84c86189216dc5ed, - 0x92746b9be2f8552c,0x32fd3cf5b4e49bb4, - 0xb7118682dbb66a77,0x3fbc8c33221dc2a1, - 0xe4d5e82392a40515,0xfabaf3feaa5334a, - 0x8f05b1163ba6832d,0x29cb4d87f2a7400e, - 0xb2c71d5bca9023f8,0x743e20e9ef511012, - 0xdf78e4b2bd342cf6,0x914da9246b255416, - 0x8bab8eefb6409c1a,0x1ad089b6c2f7548e, - 0xae9672aba3d0c320,0xa184ac2473b529b1, - 0xda3c0f568cc4f3e8,0xc9e5d72d90a2741e, - 0x8865899617fb1871,0x7e2fa67c7a658892, - 0xaa7eebfb9df9de8d,0xddbb901b98feeab7, - 0xd51ea6fa85785631,0x552a74227f3ea565, - 0x8533285c936b35de,0xd53a88958f87275f, - 0xa67ff273b8460356,0x8a892abaf368f137, - 0xd01fef10a657842c,0x2d2b7569b0432d85, - 0x8213f56a67f6b29b,0x9c3b29620e29fc73, - 0xa298f2c501f45f42,0x8349f3ba91b47b8f, - 0xcb3f2f7642717713,0x241c70a936219a73, - 0xfe0efb53d30dd4d7,0xed238cd383aa0110, - 0x9ec95d1463e8a506,0xf4363804324a40aa, - 0xc67bb4597ce2ce48,0xb143c6053edcd0d5, - 0xf81aa16fdc1b81da,0xdd94b7868e94050a, - 0x9b10a4e5e9913128,0xca7cf2b4191c8326, - 0xc1d4ce1f63f57d72,0xfd1c2f611f63a3f0, - 0xf24a01a73cf2dccf,0xbc633b39673c8cec, - 0x976e41088617ca01,0xd5be0503e085d813, - 0xbd49d14aa79dbc82,0x4b2d8644d8a74e18, - 0xec9c459d51852ba2,0xddf8e7d60ed1219e, - 0x93e1ab8252f33b45,0xcabb90e5c942b503, - 0xb8da1662e7b00a17,0x3d6a751f3b936243, - 0xe7109bfba19c0c9d,0xcc512670a783ad4, - 0x906a617d450187e2,0x27fb2b80668b24c5, - 0xb484f9dc9641e9da,0xb1f9f660802dedf6, - 0xe1a63853bbd26451,0x5e7873f8a0396973, - 0x8d07e33455637eb2,0xdb0b487b6423e1e8, - 0xb049dc016abc5e5f,0x91ce1a9a3d2cda62, - 0xdc5c5301c56b75f7,0x7641a140cc7810fb, - 0x89b9b3e11b6329ba,0xa9e904c87fcb0a9d, - 0xac2820d9623bf429,0x546345fa9fbdcd44, - 0xd732290fbacaf133,0xa97c177947ad4095, - 0x867f59a9d4bed6c0,0x49ed8eabcccc485d, - 0xa81f301449ee8c70,0x5c68f256bfff5a74, - 0xd226fc195c6a2f8c,0x73832eec6fff3111, - 0x83585d8fd9c25db7,0xc831fd53c5ff7eab, - 0xa42e74f3d032f525,0xba3e7ca8b77f5e55, - 0xcd3a1230c43fb26f,0x28ce1bd2e55f35eb, - 0x80444b5e7aa7cf85,0x7980d163cf5b81b3, - 0xa0555e361951c366,0xd7e105bcc332621f, - 0xc86ab5c39fa63440,0x8dd9472bf3fefaa7, - 0xfa856334878fc150,0xb14f98f6f0feb951, - 0x9c935e00d4b9d8d2,0x6ed1bf9a569f33d3, - 0xc3b8358109e84f07,0xa862f80ec4700c8, - 0xf4a642e14c6262c8,0xcd27bb612758c0fa, - 0x98e7e9cccfbd7dbd,0x8038d51cb897789c, - 0xbf21e44003acdd2c,0xe0470a63e6bd56c3, - 0xeeea5d5004981478,0x1858ccfce06cac74, - 0x95527a5202df0ccb,0xf37801e0c43ebc8, - 0xbaa718e68396cffd,0xd30560258f54e6ba, - 0xe950df20247c83fd,0x47c6b82ef32a2069, - 0x91d28b7416cdd27e,0x4cdc331d57fa5441, - 0xb6472e511c81471d,0xe0133fe4adf8e952, - 0xe3d8f9e563a198e5,0x58180fddd97723a6, - 0x8e679c2f5e44ff8f,0x570f09eaa7ea7648,}; -using powers = powers_template<>; - -} - -#endif diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/include/fast_float/float_common.h b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/include/fast_float/float_common.h deleted file mode 100644 index c8e7e4fc9..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/include/fast_float/float_common.h +++ /dev/null @@ -1,362 +0,0 @@ -#ifndef FASTFLOAT_FLOAT_COMMON_H -#define FASTFLOAT_FLOAT_COMMON_H - -#include -#include -#include -#include - -#if (defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) \ - || defined(__amd64) || defined(__aarch64__) || defined(_M_ARM64) \ - || defined(__MINGW64__) \ - || defined(__s390x__) \ - || (defined(__ppc64__) || defined(__PPC64__) || defined(__ppc64le__) || defined(__PPC64LE__)) \ - || defined(__EMSCRIPTEN__)) -#define FASTFLOAT_64BIT -#elif (defined(__i386) || defined(__i386__) || defined(_M_IX86) \ - || defined(__arm__) || defined(_M_ARM) \ - || defined(__MINGW32__)) -#define FASTFLOAT_32BIT -#else - // Need to check incrementally, since SIZE_MAX is a size_t, avoid overflow. - // We can never tell the register width, but the SIZE_MAX is a good approximation. - // UINTPTR_MAX and INTPTR_MAX are optional, so avoid them for max portability. - #if SIZE_MAX == 0xffff - #error Unknown platform (16-bit, unsupported) - #elif SIZE_MAX == 0xffffffff - #define FASTFLOAT_32BIT - #elif SIZE_MAX == 0xffffffffffffffff - #define FASTFLOAT_64BIT - #else - #error Unknown platform (not 32-bit, not 64-bit?) - #endif -#endif - -#if ((defined(_WIN32) || defined(_WIN64)) && !defined(__clang__)) -#include -#endif - -#if defined(_MSC_VER) && !defined(__clang__) -#define FASTFLOAT_VISUAL_STUDIO 1 -#endif - -#ifdef _WIN32 -#define FASTFLOAT_IS_BIG_ENDIAN 0 -#else -#if defined(__APPLE__) || defined(__FreeBSD__) -#include -#elif defined(sun) || defined(__sun) -#include -#else -#include -#endif -# -#ifndef __BYTE_ORDER__ -// safe choice -#define FASTFLOAT_IS_BIG_ENDIAN 0 -#endif -# -#ifndef __ORDER_LITTLE_ENDIAN__ -// safe choice -#define FASTFLOAT_IS_BIG_ENDIAN 0 -#endif -# -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -#define FASTFLOAT_IS_BIG_ENDIAN 0 -#else -#define FASTFLOAT_IS_BIG_ENDIAN 1 -#endif -#endif - -#ifdef FASTFLOAT_VISUAL_STUDIO -#define fastfloat_really_inline __forceinline -#else -#define fastfloat_really_inline inline __attribute__((always_inline)) -#endif - -#ifndef FASTFLOAT_ASSERT -#define FASTFLOAT_ASSERT(x) { if (!(x)) abort(); } -#endif - -#ifndef FASTFLOAT_DEBUG_ASSERT -#include -#define FASTFLOAT_DEBUG_ASSERT(x) assert(x) -#endif - -// rust style `try!()` macro, or `?` operator -#define FASTFLOAT_TRY(x) { if (!(x)) return false; } - -namespace fast_float { - -// Compares two ASCII strings in a case insensitive manner. -inline bool fastfloat_strncasecmp(const char *input1, const char *input2, - size_t length) { - char running_diff{0}; - for (size_t i = 0; i < length; i++) { - running_diff |= (input1[i] ^ input2[i]); - } - return (running_diff == 0) || (running_diff == 32); -} - -#ifndef FLT_EVAL_METHOD -#error "FLT_EVAL_METHOD should be defined, please include cfloat." -#endif - -// a pointer and a length to a contiguous block of memory -template -struct span { - const T* ptr; - size_t length; - span(const T* _ptr, size_t _length) : ptr(_ptr), length(_length) {} - span() : ptr(nullptr), length(0) {} - - constexpr size_t len() const noexcept { - return length; - } - - const T& operator[](size_t index) const noexcept { - FASTFLOAT_DEBUG_ASSERT(index < length); - return ptr[index]; - } -}; - -struct value128 { - uint64_t low; - uint64_t high; - value128(uint64_t _low, uint64_t _high) : low(_low), high(_high) {} - value128() : low(0), high(0) {} -}; - -/* result might be undefined when input_num is zero */ -fastfloat_really_inline int leading_zeroes(uint64_t input_num) { - assert(input_num > 0); -#ifdef FASTFLOAT_VISUAL_STUDIO - #if defined(_M_X64) || defined(_M_ARM64) - unsigned long leading_zero = 0; - // Search the mask data from most significant bit (MSB) - // to least significant bit (LSB) for a set bit (1). - _BitScanReverse64(&leading_zero, input_num); - return (int)(63 - leading_zero); - #else - int last_bit = 0; - if(input_num & uint64_t(0xffffffff00000000)) input_num >>= 32, last_bit |= 32; - if(input_num & uint64_t( 0xffff0000)) input_num >>= 16, last_bit |= 16; - if(input_num & uint64_t( 0xff00)) input_num >>= 8, last_bit |= 8; - if(input_num & uint64_t( 0xf0)) input_num >>= 4, last_bit |= 4; - if(input_num & uint64_t( 0xc)) input_num >>= 2, last_bit |= 2; - if(input_num & uint64_t( 0x2)) input_num >>= 1, last_bit |= 1; - return 63 - last_bit; - #endif -#else - return __builtin_clzll(input_num); -#endif -} - -#ifdef FASTFLOAT_32BIT - -// slow emulation routine for 32-bit -fastfloat_really_inline uint64_t emulu(uint32_t x, uint32_t y) { - return x * (uint64_t)y; -} - -// slow emulation routine for 32-bit -#if !defined(__MINGW64__) -fastfloat_really_inline uint64_t _umul128(uint64_t ab, uint64_t cd, - uint64_t *hi) { - uint64_t ad = emulu((uint32_t)(ab >> 32), (uint32_t)cd); - uint64_t bd = emulu((uint32_t)ab, (uint32_t)cd); - uint64_t adbc = ad + emulu((uint32_t)ab, (uint32_t)(cd >> 32)); - uint64_t adbc_carry = !!(adbc < ad); - uint64_t lo = bd + (adbc << 32); - *hi = emulu((uint32_t)(ab >> 32), (uint32_t)(cd >> 32)) + (adbc >> 32) + - (adbc_carry << 32) + !!(lo < bd); - return lo; -} -#endif // !__MINGW64__ - -#endif // FASTFLOAT_32BIT - - -// compute 64-bit a*b -fastfloat_really_inline value128 full_multiplication(uint64_t a, - uint64_t b) { - value128 answer; -#ifdef _M_ARM64 - // ARM64 has native support for 64-bit multiplications, no need to emulate - answer.high = __umulh(a, b); - answer.low = a * b; -#elif defined(FASTFLOAT_32BIT) || (defined(_WIN64) && !defined(__clang__)) - answer.low = _umul128(a, b, &answer.high); // _umul128 not available on ARM64 -#elif defined(FASTFLOAT_64BIT) - __uint128_t r = ((__uint128_t)a) * b; - answer.low = uint64_t(r); - answer.high = uint64_t(r >> 64); -#else - #error Not implemented -#endif - return answer; -} - -struct adjusted_mantissa { - uint64_t mantissa{0}; - int32_t power2{0}; // a negative value indicates an invalid result - adjusted_mantissa() = default; - bool operator==(const adjusted_mantissa &o) const { - return mantissa == o.mantissa && power2 == o.power2; - } - bool operator!=(const adjusted_mantissa &o) const { - return mantissa != o.mantissa || power2 != o.power2; - } -}; - -// Bias so we can get the real exponent with an invalid adjusted_mantissa. -constexpr static int32_t invalid_am_bias = -0x8000; - -constexpr static double powers_of_ten_double[] = { - 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, - 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22}; -constexpr static float powers_of_ten_float[] = {1e0, 1e1, 1e2, 1e3, 1e4, 1e5, - 1e6, 1e7, 1e8, 1e9, 1e10}; - -template struct binary_format { - static inline constexpr int mantissa_explicit_bits(); - static inline constexpr int minimum_exponent(); - static inline constexpr int infinite_power(); - static inline constexpr int sign_index(); - static inline constexpr int min_exponent_fast_path(); - static inline constexpr int max_exponent_fast_path(); - static inline constexpr int max_exponent_round_to_even(); - static inline constexpr int min_exponent_round_to_even(); - static inline constexpr uint64_t max_mantissa_fast_path(); - static inline constexpr int largest_power_of_ten(); - static inline constexpr int smallest_power_of_ten(); - static inline constexpr T exact_power_of_ten(int64_t power); - static inline constexpr size_t max_digits(); -}; - -template <> inline constexpr int binary_format::mantissa_explicit_bits() { - return 52; -} -template <> inline constexpr int binary_format::mantissa_explicit_bits() { - return 23; -} - -template <> inline constexpr int binary_format::max_exponent_round_to_even() { - return 23; -} - -template <> inline constexpr int binary_format::max_exponent_round_to_even() { - return 10; -} - -template <> inline constexpr int binary_format::min_exponent_round_to_even() { - return -4; -} - -template <> inline constexpr int binary_format::min_exponent_round_to_even() { - return -17; -} - -template <> inline constexpr int binary_format::minimum_exponent() { - return -1023; -} -template <> inline constexpr int binary_format::minimum_exponent() { - return -127; -} - -template <> inline constexpr int binary_format::infinite_power() { - return 0x7FF; -} -template <> inline constexpr int binary_format::infinite_power() { - return 0xFF; -} - -template <> inline constexpr int binary_format::sign_index() { return 63; } -template <> inline constexpr int binary_format::sign_index() { return 31; } - -template <> inline constexpr int binary_format::min_exponent_fast_path() { -#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0) - return 0; -#else - return -22; -#endif -} -template <> inline constexpr int binary_format::min_exponent_fast_path() { -#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0) - return 0; -#else - return -10; -#endif -} - -template <> inline constexpr int binary_format::max_exponent_fast_path() { - return 22; -} -template <> inline constexpr int binary_format::max_exponent_fast_path() { - return 10; -} - -template <> inline constexpr uint64_t binary_format::max_mantissa_fast_path() { - return uint64_t(2) << mantissa_explicit_bits(); -} -template <> inline constexpr uint64_t binary_format::max_mantissa_fast_path() { - return uint64_t(2) << mantissa_explicit_bits(); -} - -template <> -inline constexpr double binary_format::exact_power_of_ten(int64_t power) { - return powers_of_ten_double[power]; -} -template <> -inline constexpr float binary_format::exact_power_of_ten(int64_t power) { - - return powers_of_ten_float[power]; -} - - -template <> -inline constexpr int binary_format::largest_power_of_ten() { - return 308; -} -template <> -inline constexpr int binary_format::largest_power_of_ten() { - return 38; -} - -template <> -inline constexpr int binary_format::smallest_power_of_ten() { - return -342; -} -template <> -inline constexpr int binary_format::smallest_power_of_ten() { - return -65; -} - -template <> inline constexpr size_t binary_format::max_digits() { - return 769; -} -template <> inline constexpr size_t binary_format::max_digits() { - return 114; -} - -template -fastfloat_really_inline void to_float(bool negative, adjusted_mantissa am, T &value) { - uint64_t word = am.mantissa; - word |= uint64_t(am.power2) << binary_format::mantissa_explicit_bits(); - word = negative - ? word | (uint64_t(1) << binary_format::sign_index()) : word; -#if FASTFLOAT_IS_BIG_ENDIAN == 1 - if (std::is_same::value) { - ::memcpy(&value, (char *)&word + 4, sizeof(T)); // extract value at offset 4-7 if float on big-endian - } else { - ::memcpy(&value, &word, sizeof(T)); - } -#else - // For little-endian systems: - ::memcpy(&value, &word, sizeof(T)); -#endif -} - -} // namespace fast_float - -#endif diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/include/fast_float/parse_number.h b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/include/fast_float/parse_number.h deleted file mode 100644 index 62ae3b039..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/include/fast_float/parse_number.h +++ /dev/null @@ -1,113 +0,0 @@ -#ifndef FASTFLOAT_PARSE_NUMBER_H -#define FASTFLOAT_PARSE_NUMBER_H - -#include "ascii_number.h" -#include "decimal_to_binary.h" -#include "digit_comparison.h" - -#include -#include -#include -#include - -namespace fast_float { - - -namespace detail { -/** - * Special case +inf, -inf, nan, infinity, -infinity. - * The case comparisons could be made much faster given that we know that the - * strings a null-free and fixed. - **/ -template -from_chars_result parse_infnan(const char *first, const char *last, T &value) noexcept { - from_chars_result answer; - answer.ptr = first; - answer.ec = std::errc(); // be optimistic - bool minusSign = false; - if (*first == '-') { // assume first < last, so dereference without checks; C++17 20.19.3.(7.1) explicitly forbids '+' here - minusSign = true; - ++first; - } - if (last - first >= 3) { - if (fastfloat_strncasecmp(first, "nan", 3)) { - answer.ptr = (first += 3); - value = minusSign ? -std::numeric_limits::quiet_NaN() : std::numeric_limits::quiet_NaN(); - // Check for possible nan(n-char-seq-opt), C++17 20.19.3.7, C11 7.20.1.3.3. At least MSVC produces nan(ind) and nan(snan). - if(first != last && *first == '(') { - for(const char* ptr = first + 1; ptr != last; ++ptr) { - if (*ptr == ')') { - answer.ptr = ptr + 1; // valid nan(n-char-seq-opt) - break; - } - else if(!(('a' <= *ptr && *ptr <= 'z') || ('A' <= *ptr && *ptr <= 'Z') || ('0' <= *ptr && *ptr <= '9') || *ptr == '_')) - break; // forbidden char, not nan(n-char-seq-opt) - } - } - return answer; - } - if (fastfloat_strncasecmp(first, "inf", 3)) { - if ((last - first >= 8) && fastfloat_strncasecmp(first + 3, "inity", 5)) { - answer.ptr = first + 8; - } else { - answer.ptr = first + 3; - } - value = minusSign ? -std::numeric_limits::infinity() : std::numeric_limits::infinity(); - return answer; - } - } - answer.ec = std::errc::invalid_argument; - return answer; -} - -} // namespace detail - -template -from_chars_result from_chars(const char *first, const char *last, - T &value, chars_format fmt /*= chars_format::general*/) noexcept { - return from_chars_advanced(first, last, value, parse_options{fmt}); -} - -template -from_chars_result from_chars_advanced(const char *first, const char *last, - T &value, parse_options options) noexcept { - - static_assert (std::is_same::value || std::is_same::value, "only float and double are supported"); - - - from_chars_result answer; - if (first == last) { - answer.ec = std::errc::invalid_argument; - answer.ptr = first; - return answer; - } - parsed_number_string pns = parse_number_string(first, last, options); - if (!pns.valid) { - return detail::parse_infnan(first, last, value); - } - answer.ec = std::errc(); // be optimistic - answer.ptr = pns.lastmatch; - // Next is Clinger's fast path. - if (binary_format::min_exponent_fast_path() <= pns.exponent && pns.exponent <= binary_format::max_exponent_fast_path() && pns.mantissa <=binary_format::max_mantissa_fast_path() && !pns.too_many_digits) { - value = T(pns.mantissa); - if (pns.exponent < 0) { value = value / binary_format::exact_power_of_ten(-pns.exponent); } - else { value = value * binary_format::exact_power_of_ten(pns.exponent); } - if (pns.negative) { value = -value; } - return answer; - } - adjusted_mantissa am = compute_float>(pns.exponent, pns.mantissa); - if(pns.too_many_digits && am.power2 >= 0) { - if(am != compute_float>(pns.exponent, pns.mantissa + 1)) { - am = compute_error>(pns.exponent, pns.mantissa); - } - } - // If we called compute_float>(pns.exponent, pns.mantissa) and we have an invalid power (am.power2 < 0), - // then we need to go the long way around again. This is very uncommon. - if(am.power2 < 0) { am = digit_comp(pns, am); } - to_float(pns.negative, am, value); - return answer; -} - -} // namespace fast_float - -#endif diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/include/fast_float/simple_decimal_conversion.h b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/include/fast_float/simple_decimal_conversion.h deleted file mode 100644 index e87801480..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/include/fast_float/simple_decimal_conversion.h +++ /dev/null @@ -1,360 +0,0 @@ -#ifndef FASTFLOAT_GENERIC_DECIMAL_TO_BINARY_H -#define FASTFLOAT_GENERIC_DECIMAL_TO_BINARY_H - -/** - * This code is meant to handle the case where we have more than 19 digits. - * - * It is based on work by Nigel Tao (at https://github.com/google/wuffs/) - * who credits Ken Thompson for the design (via a reference to the Go source - * code). - * - * Rob Pike suggested that this algorithm be called "Simple Decimal Conversion". - * - * It is probably not very fast but it is a fallback that should almost never - * be used in real life. Though it is not fast, it is "easily" understood and debugged. - **/ -#include "ascii_number.h" -#include "decimal_to_binary.h" -#include - -namespace fast_float { - -namespace detail { - -// remove all final zeroes -inline void trim(decimal &h) { - while ((h.num_digits > 0) && (h.digits[h.num_digits - 1] == 0)) { - h.num_digits--; - } -} - - - -inline uint32_t number_of_digits_decimal_left_shift(const decimal &h, uint32_t shift) { - shift &= 63; - constexpr uint16_t number_of_digits_decimal_left_shift_table[65] = { - 0x0000, 0x0800, 0x0801, 0x0803, 0x1006, 0x1009, 0x100D, 0x1812, 0x1817, - 0x181D, 0x2024, 0x202B, 0x2033, 0x203C, 0x2846, 0x2850, 0x285B, 0x3067, - 0x3073, 0x3080, 0x388E, 0x389C, 0x38AB, 0x38BB, 0x40CC, 0x40DD, 0x40EF, - 0x4902, 0x4915, 0x4929, 0x513E, 0x5153, 0x5169, 0x5180, 0x5998, 0x59B0, - 0x59C9, 0x61E3, 0x61FD, 0x6218, 0x6A34, 0x6A50, 0x6A6D, 0x6A8B, 0x72AA, - 0x72C9, 0x72E9, 0x7B0A, 0x7B2B, 0x7B4D, 0x8370, 0x8393, 0x83B7, 0x83DC, - 0x8C02, 0x8C28, 0x8C4F, 0x9477, 0x949F, 0x94C8, 0x9CF2, 0x051C, 0x051C, - 0x051C, 0x051C, - }; - uint32_t x_a = number_of_digits_decimal_left_shift_table[shift]; - uint32_t x_b = number_of_digits_decimal_left_shift_table[shift + 1]; - uint32_t num_new_digits = x_a >> 11; - uint32_t pow5_a = 0x7FF & x_a; - uint32_t pow5_b = 0x7FF & x_b; - constexpr uint8_t - number_of_digits_decimal_left_shift_table_powers_of_5[0x051C] = { - 5, 2, 5, 1, 2, 5, 6, 2, 5, 3, 1, 2, 5, 1, 5, 6, 2, 5, 7, 8, 1, 2, 5, 3, - 9, 0, 6, 2, 5, 1, 9, 5, 3, 1, 2, 5, 9, 7, 6, 5, 6, 2, 5, 4, 8, 8, 2, 8, - 1, 2, 5, 2, 4, 4, 1, 4, 0, 6, 2, 5, 1, 2, 2, 0, 7, 0, 3, 1, 2, 5, 6, 1, - 0, 3, 5, 1, 5, 6, 2, 5, 3, 0, 5, 1, 7, 5, 7, 8, 1, 2, 5, 1, 5, 2, 5, 8, - 7, 8, 9, 0, 6, 2, 5, 7, 6, 2, 9, 3, 9, 4, 5, 3, 1, 2, 5, 3, 8, 1, 4, 6, - 9, 7, 2, 6, 5, 6, 2, 5, 1, 9, 0, 7, 3, 4, 8, 6, 3, 2, 8, 1, 2, 5, 9, 5, - 3, 6, 7, 4, 3, 1, 6, 4, 0, 6, 2, 5, 4, 7, 6, 8, 3, 7, 1, 5, 8, 2, 0, 3, - 1, 2, 5, 2, 3, 8, 4, 1, 8, 5, 7, 9, 1, 0, 1, 5, 6, 2, 5, 1, 1, 9, 2, 0, - 9, 2, 8, 9, 5, 5, 0, 7, 8, 1, 2, 5, 5, 9, 6, 0, 4, 6, 4, 4, 7, 7, 5, 3, - 9, 0, 6, 2, 5, 2, 9, 8, 0, 2, 3, 2, 2, 3, 8, 7, 6, 9, 5, 3, 1, 2, 5, 1, - 4, 9, 0, 1, 1, 6, 1, 1, 9, 3, 8, 4, 7, 6, 5, 6, 2, 5, 7, 4, 5, 0, 5, 8, - 0, 5, 9, 6, 9, 2, 3, 8, 2, 8, 1, 2, 5, 3, 7, 2, 5, 2, 9, 0, 2, 9, 8, 4, - 6, 1, 9, 1, 4, 0, 6, 2, 5, 1, 8, 6, 2, 6, 4, 5, 1, 4, 9, 2, 3, 0, 9, 5, - 7, 0, 3, 1, 2, 5, 9, 3, 1, 3, 2, 2, 5, 7, 4, 6, 1, 5, 4, 7, 8, 5, 1, 5, - 6, 2, 5, 4, 6, 5, 6, 6, 1, 2, 8, 7, 3, 0, 7, 7, 3, 9, 2, 5, 7, 8, 1, 2, - 5, 2, 3, 2, 8, 3, 0, 6, 4, 3, 6, 5, 3, 8, 6, 9, 6, 2, 8, 9, 0, 6, 2, 5, - 1, 1, 6, 4, 1, 5, 3, 2, 1, 8, 2, 6, 9, 3, 4, 8, 1, 4, 4, 5, 3, 1, 2, 5, - 5, 8, 2, 0, 7, 6, 6, 0, 9, 1, 3, 4, 6, 7, 4, 0, 7, 2, 2, 6, 5, 6, 2, 5, - 2, 9, 1, 0, 3, 8, 3, 0, 4, 5, 6, 7, 3, 3, 7, 0, 3, 6, 1, 3, 2, 8, 1, 2, - 5, 1, 4, 5, 5, 1, 9, 1, 5, 2, 2, 8, 3, 6, 6, 8, 5, 1, 8, 0, 6, 6, 4, 0, - 6, 2, 5, 7, 2, 7, 5, 9, 5, 7, 6, 1, 4, 1, 8, 3, 4, 2, 5, 9, 0, 3, 3, 2, - 0, 3, 1, 2, 5, 3, 6, 3, 7, 9, 7, 8, 8, 0, 7, 0, 9, 1, 7, 1, 2, 9, 5, 1, - 6, 6, 0, 1, 5, 6, 2, 5, 1, 8, 1, 8, 9, 8, 9, 4, 0, 3, 5, 4, 5, 8, 5, 6, - 4, 7, 5, 8, 3, 0, 0, 7, 8, 1, 2, 5, 9, 0, 9, 4, 9, 4, 7, 0, 1, 7, 7, 2, - 9, 2, 8, 2, 3, 7, 9, 1, 5, 0, 3, 9, 0, 6, 2, 5, 4, 5, 4, 7, 4, 7, 3, 5, - 0, 8, 8, 6, 4, 6, 4, 1, 1, 8, 9, 5, 7, 5, 1, 9, 5, 3, 1, 2, 5, 2, 2, 7, - 3, 7, 3, 6, 7, 5, 4, 4, 3, 2, 3, 2, 0, 5, 9, 4, 7, 8, 7, 5, 9, 7, 6, 5, - 6, 2, 5, 1, 1, 3, 6, 8, 6, 8, 3, 7, 7, 2, 1, 6, 1, 6, 0, 2, 9, 7, 3, 9, - 3, 7, 9, 8, 8, 2, 8, 1, 2, 5, 5, 6, 8, 4, 3, 4, 1, 8, 8, 6, 0, 8, 0, 8, - 0, 1, 4, 8, 6, 9, 6, 8, 9, 9, 4, 1, 4, 0, 6, 2, 5, 2, 8, 4, 2, 1, 7, 0, - 9, 4, 3, 0, 4, 0, 4, 0, 0, 7, 4, 3, 4, 8, 4, 4, 9, 7, 0, 7, 0, 3, 1, 2, - 5, 1, 4, 2, 1, 0, 8, 5, 4, 7, 1, 5, 2, 0, 2, 0, 0, 3, 7, 1, 7, 4, 2, 2, - 4, 8, 5, 3, 5, 1, 5, 6, 2, 5, 7, 1, 0, 5, 4, 2, 7, 3, 5, 7, 6, 0, 1, 0, - 0, 1, 8, 5, 8, 7, 1, 1, 2, 4, 2, 6, 7, 5, 7, 8, 1, 2, 5, 3, 5, 5, 2, 7, - 1, 3, 6, 7, 8, 8, 0, 0, 5, 0, 0, 9, 2, 9, 3, 5, 5, 6, 2, 1, 3, 3, 7, 8, - 9, 0, 6, 2, 5, 1, 7, 7, 6, 3, 5, 6, 8, 3, 9, 4, 0, 0, 2, 5, 0, 4, 6, 4, - 6, 7, 7, 8, 1, 0, 6, 6, 8, 9, 4, 5, 3, 1, 2, 5, 8, 8, 8, 1, 7, 8, 4, 1, - 9, 7, 0, 0, 1, 2, 5, 2, 3, 2, 3, 3, 8, 9, 0, 5, 3, 3, 4, 4, 7, 2, 6, 5, - 6, 2, 5, 4, 4, 4, 0, 8, 9, 2, 0, 9, 8, 5, 0, 0, 6, 2, 6, 1, 6, 1, 6, 9, - 4, 5, 2, 6, 6, 7, 2, 3, 6, 3, 2, 8, 1, 2, 5, 2, 2, 2, 0, 4, 4, 6, 0, 4, - 9, 2, 5, 0, 3, 1, 3, 0, 8, 0, 8, 4, 7, 2, 6, 3, 3, 3, 6, 1, 8, 1, 6, 4, - 0, 6, 2, 5, 1, 1, 1, 0, 2, 2, 3, 0, 2, 4, 6, 2, 5, 1, 5, 6, 5, 4, 0, 4, - 2, 3, 6, 3, 1, 6, 6, 8, 0, 9, 0, 8, 2, 0, 3, 1, 2, 5, 5, 5, 5, 1, 1, 1, - 5, 1, 2, 3, 1, 2, 5, 7, 8, 2, 7, 0, 2, 1, 1, 8, 1, 5, 8, 3, 4, 0, 4, 5, - 4, 1, 0, 1, 5, 6, 2, 5, 2, 7, 7, 5, 5, 5, 7, 5, 6, 1, 5, 6, 2, 8, 9, 1, - 3, 5, 1, 0, 5, 9, 0, 7, 9, 1, 7, 0, 2, 2, 7, 0, 5, 0, 7, 8, 1, 2, 5, 1, - 3, 8, 7, 7, 7, 8, 7, 8, 0, 7, 8, 1, 4, 4, 5, 6, 7, 5, 5, 2, 9, 5, 3, 9, - 5, 8, 5, 1, 1, 3, 5, 2, 5, 3, 9, 0, 6, 2, 5, 6, 9, 3, 8, 8, 9, 3, 9, 0, - 3, 9, 0, 7, 2, 2, 8, 3, 7, 7, 6, 4, 7, 6, 9, 7, 9, 2, 5, 5, 6, 7, 6, 2, - 6, 9, 5, 3, 1, 2, 5, 3, 4, 6, 9, 4, 4, 6, 9, 5, 1, 9, 5, 3, 6, 1, 4, 1, - 8, 8, 8, 2, 3, 8, 4, 8, 9, 6, 2, 7, 8, 3, 8, 1, 3, 4, 7, 6, 5, 6, 2, 5, - 1, 7, 3, 4, 7, 2, 3, 4, 7, 5, 9, 7, 6, 8, 0, 7, 0, 9, 4, 4, 1, 1, 9, 2, - 4, 4, 8, 1, 3, 9, 1, 9, 0, 6, 7, 3, 8, 2, 8, 1, 2, 5, 8, 6, 7, 3, 6, 1, - 7, 3, 7, 9, 8, 8, 4, 0, 3, 5, 4, 7, 2, 0, 5, 9, 6, 2, 2, 4, 0, 6, 9, 5, - 9, 5, 3, 3, 6, 9, 1, 4, 0, 6, 2, 5, - }; - const uint8_t *pow5 = - &number_of_digits_decimal_left_shift_table_powers_of_5[pow5_a]; - uint32_t i = 0; - uint32_t n = pow5_b - pow5_a; - for (; i < n; i++) { - if (i >= h.num_digits) { - return num_new_digits - 1; - } else if (h.digits[i] == pow5[i]) { - continue; - } else if (h.digits[i] < pow5[i]) { - return num_new_digits - 1; - } else { - return num_new_digits; - } - } - return num_new_digits; -} - -inline uint64_t round(decimal &h) { - if ((h.num_digits == 0) || (h.decimal_point < 0)) { - return 0; - } else if (h.decimal_point > 18) { - return UINT64_MAX; - } - // at this point, we know that h.decimal_point >= 0 - uint32_t dp = uint32_t(h.decimal_point); - uint64_t n = 0; - for (uint32_t i = 0; i < dp; i++) { - n = (10 * n) + ((i < h.num_digits) ? h.digits[i] : 0); - } - bool round_up = false; - if (dp < h.num_digits) { - round_up = h.digits[dp] >= 5; // normally, we round up - // but we may need to round to even! - if ((h.digits[dp] == 5) && (dp + 1 == h.num_digits)) { - round_up = h.truncated || ((dp > 0) && (1 & h.digits[dp - 1])); - } - } - if (round_up) { - n++; - } - return n; -} - -// computes h * 2^-shift -inline void decimal_left_shift(decimal &h, uint32_t shift) { - if (h.num_digits == 0) { - return; - } - uint32_t num_new_digits = number_of_digits_decimal_left_shift(h, shift); - int32_t read_index = int32_t(h.num_digits - 1); - uint32_t write_index = h.num_digits - 1 + num_new_digits; - uint64_t n = 0; - - while (read_index >= 0) { - n += uint64_t(h.digits[read_index]) << shift; - uint64_t quotient = n / 10; - uint64_t remainder = n - (10 * quotient); - if (write_index < max_digits) { - h.digits[write_index] = uint8_t(remainder); - } else if (remainder > 0) { - h.truncated = true; - } - n = quotient; - write_index--; - read_index--; - } - while (n > 0) { - uint64_t quotient = n / 10; - uint64_t remainder = n - (10 * quotient); - if (write_index < max_digits) { - h.digits[write_index] = uint8_t(remainder); - } else if (remainder > 0) { - h.truncated = true; - } - n = quotient; - write_index--; - } - h.num_digits += num_new_digits; - if (h.num_digits > max_digits) { - h.num_digits = max_digits; - } - h.decimal_point += int32_t(num_new_digits); - trim(h); -} - -// computes h * 2^shift -inline void decimal_right_shift(decimal &h, uint32_t shift) { - uint32_t read_index = 0; - uint32_t write_index = 0; - - uint64_t n = 0; - - while ((n >> shift) == 0) { - if (read_index < h.num_digits) { - n = (10 * n) + h.digits[read_index++]; - } else if (n == 0) { - return; - } else { - while ((n >> shift) == 0) { - n = 10 * n; - read_index++; - } - break; - } - } - h.decimal_point -= int32_t(read_index - 1); - if (h.decimal_point < -decimal_point_range) { // it is zero - h.num_digits = 0; - h.decimal_point = 0; - h.negative = false; - h.truncated = false; - return; - } - uint64_t mask = (uint64_t(1) << shift) - 1; - while (read_index < h.num_digits) { - uint8_t new_digit = uint8_t(n >> shift); - n = (10 * (n & mask)) + h.digits[read_index++]; - h.digits[write_index++] = new_digit; - } - while (n > 0) { - uint8_t new_digit = uint8_t(n >> shift); - n = 10 * (n & mask); - if (write_index < max_digits) { - h.digits[write_index++] = new_digit; - } else if (new_digit > 0) { - h.truncated = true; - } - } - h.num_digits = write_index; - trim(h); -} - -} // namespace detail - -template -adjusted_mantissa compute_float(decimal &d) { - adjusted_mantissa answer; - if (d.num_digits == 0) { - // should be zero - answer.power2 = 0; - answer.mantissa = 0; - return answer; - } - // At this point, going further, we can assume that d.num_digits > 0. - // - // We want to guard against excessive decimal point values because - // they can result in long running times. Indeed, we do - // shifts by at most 60 bits. We have that log(10**400)/log(2**60) ~= 22 - // which is fine, but log(10**299995)/log(2**60) ~= 16609 which is not - // fine (runs for a long time). - // - if(d.decimal_point < -324) { - // We have something smaller than 1e-324 which is always zero - // in binary64 and binary32. - // It should be zero. - answer.power2 = 0; - answer.mantissa = 0; - return answer; - } else if(d.decimal_point >= 310) { - // We have something at least as large as 0.1e310 which is - // always infinite. - answer.power2 = binary::infinite_power(); - answer.mantissa = 0; - return answer; - } - constexpr uint32_t max_shift = 60; - constexpr uint32_t num_powers = 19; - constexpr uint8_t decimal_powers[19] = { - 0, 3, 6, 9, 13, 16, 19, 23, 26, 29, // - 33, 36, 39, 43, 46, 49, 53, 56, 59, // - }; - int32_t exp2 = 0; - while (d.decimal_point > 0) { - uint32_t n = uint32_t(d.decimal_point); - uint32_t shift = (n < num_powers) ? decimal_powers[n] : max_shift; - detail::decimal_right_shift(d, shift); - if (d.decimal_point < -decimal_point_range) { - // should be zero - answer.power2 = 0; - answer.mantissa = 0; - return answer; - } - exp2 += int32_t(shift); - } - // We shift left toward [1/2 ... 1]. - while (d.decimal_point <= 0) { - uint32_t shift; - if (d.decimal_point == 0) { - if (d.digits[0] >= 5) { - break; - } - shift = (d.digits[0] < 2) ? 2 : 1; - } else { - uint32_t n = uint32_t(-d.decimal_point); - shift = (n < num_powers) ? decimal_powers[n] : max_shift; - } - detail::decimal_left_shift(d, shift); - if (d.decimal_point > decimal_point_range) { - // we want to get infinity: - answer.power2 = binary::infinite_power(); - answer.mantissa = 0; - return answer; - } - exp2 -= int32_t(shift); - } - // We are now in the range [1/2 ... 1] but the binary format uses [1 ... 2]. - exp2--; - constexpr int32_t minimum_exponent = binary::minimum_exponent(); - while ((minimum_exponent + 1) > exp2) { - uint32_t n = uint32_t((minimum_exponent + 1) - exp2); - if (n > max_shift) { - n = max_shift; - } - detail::decimal_right_shift(d, n); - exp2 += int32_t(n); - } - if ((exp2 - minimum_exponent) >= binary::infinite_power()) { - answer.power2 = binary::infinite_power(); - answer.mantissa = 0; - return answer; - } - - const int mantissa_size_in_bits = binary::mantissa_explicit_bits() + 1; - detail::decimal_left_shift(d, mantissa_size_in_bits); - - uint64_t mantissa = detail::round(d); - // It is possible that we have an overflow, in which case we need - // to shift back. - if(mantissa >= (uint64_t(1) << mantissa_size_in_bits)) { - detail::decimal_right_shift(d, 1); - exp2 += 1; - mantissa = detail::round(d); - if ((exp2 - minimum_exponent) >= binary::infinite_power()) { - answer.power2 = binary::infinite_power(); - answer.mantissa = 0; - return answer; - } - } - answer.power2 = exp2 - binary::minimum_exponent(); - if(mantissa < (uint64_t(1) << binary::mantissa_explicit_bits())) { answer.power2--; } - answer.mantissa = mantissa & ((uint64_t(1) << binary::mantissa_explicit_bits()) - 1); - return answer; -} - -template -adjusted_mantissa parse_long_mantissa(const char *first, const char* last, parse_options options) { - decimal d = parse_decimal(first, last, options); - return compute_float(d); -} - -} // namespace fast_float -#endif diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/script/amalgamate.py b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/script/amalgamate.py deleted file mode 100644 index b360d9988..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/script/amalgamate.py +++ /dev/null @@ -1,56 +0,0 @@ -# text parts -processed_files = { } - -# authors -for filename in ['AUTHORS', 'CONTRIBUTORS']: - with open(filename) as f: - text = '' - for line in f: - if filename == 'AUTHORS': - text += '// fast_float by ' + line - if filename == 'CONTRIBUTORS': - text += '// with contributions from ' + line - processed_files[filename] = text - -# licenses -for filename in ['LICENSE-MIT', 'LICENSE-APACHE']: - with open(filename) as f: - text = '' - for line in f: - text += '// ' + line - processed_files[filename] = text - -# code -for filename in [ 'fast_float.h', 'float_common.h', 'ascii_number.h', - 'fast_table.h', 'decimal_to_binary.h', 'bigint.h', - 'ascii_number.h', 'digit_comparison.h', 'parse_number.h']: - with open('include/fast_float/' + filename) as f: - text = '' - for line in f: - if line.startswith('#include "'): continue - text += line - processed_files[filename] = text - -# command line -import argparse - -parser = argparse.ArgumentParser(description='Amalgamate fast_float.') -parser.add_argument('--license', default='MIT', help='choose license') -parser.add_argument('--output', default='', help='output file (stdout if none') - -args = parser.parse_args() - -text = '\n\n'.join([ - processed_files['AUTHORS'], processed_files['CONTRIBUTORS'], - processed_files['LICENSE-' + args.license], - processed_files['fast_float.h'], processed_files['float_common.h'], - processed_files['ascii_number.h'], processed_files['fast_table.h'], - processed_files['decimal_to_binary.h'], processed_files['bigint.h'], - processed_files['ascii_number.h'], processed_files['digit_comparison.h'], - processed_files['parse_number.h']]) - -if args.output: - with open(args.output, 'wt') as f: - f.write(text) -else: - print(text) diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/script/analysis.py b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/script/analysis.py deleted file mode 100644 index 8dcbcd533..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/script/analysis.py +++ /dev/null @@ -1,36 +0,0 @@ -from math import floor - -def log2(x): - """returns ceil(log2(x)))""" - y = 0 - while((1<= 2**127 - K = 2**127 - if(not(c * K * d<=( K + 1) * t)): - print(q) - top = floor(t/(c * d - t)) - sys.exit(-1) - -for q in range(18, 344+1): - d = 5**q - b = 64 + 2*log2(d) - t = 2**b - c = t//d + 1 - assert c > 2**(64 +log2(d)) - K = 2**64 - if(not(c * K * d<=( K + 1) * t)): - print(q) - top = floor(t/(c * d - t)) - sys.exit(-1) - -print("all good") \ No newline at end of file diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/script/table_generation.py b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/script/table_generation.py deleted file mode 100644 index 24fec7cdd..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/script/table_generation.py +++ /dev/null @@ -1,31 +0,0 @@ -def format(number): - upper = number // (1<<64) - lower = number % (1<<64) - print(""+hex(upper)+","+hex(lower)+",") - -for q in range(-342,0): - power5 = 5 ** -q - z = 0 - while( (1<= -27): - b = z + 127 - c = 2 ** b // power5 + 1 - format(c) - else: - b = 2 * z + 2 * 64 - c = 2 ** b // power5 + 1 - # truncate - while(c >= (1<<128)): - c //= 2 - format(c) - -for q in range(0,308+1): - power5 = 5 ** q - # move the most significant bit in position - while(power5 < (1<<127)): - power5 *= 2 - # *truncate* - while(power5 >= (1<<128)): - power5 //= 2 - format(power5) diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/basictest.cpp b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/basictest.cpp deleted file mode 100644 index 1dd924e5b..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/basictest.cpp +++ /dev/null @@ -1,704 +0,0 @@ -#define DOCTEST_CONFIG_SUPER_FAST_ASSERTS -#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN -#include - -#include "fast_float/fast_float.h" -#include -#include -#include -#include -#include -#include -#include - -#ifndef SUPPLEMENTAL_TEST_DATA_DIR -#define SUPPLEMENTAL_TEST_DATA_DIR "data/" -#endif - -#ifndef __cplusplus -#error fastfloat requires a C++ compiler -#endif - -#ifndef FASTFLOAT_CPLUSPLUS -#if defined(_MSVC_LANG) && !defined(__clang__) -#define FASTFLOAT_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG) -#else -#define FASTFLOAT_CPLUSPLUS __cplusplus -#endif -#endif - - -#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun) -#define FASTFLOAT_ODDPLATFORM 1 -#endif -#if defined __has_include -#if __has_include () -#else -// filesystem is not available -#define FASTFLOAT_ODDPLATFORM 1 -#endif -#else -// __has_include is not available -#define FASTFLOAT_ODDPLATFORM 1 -#endif - -// C++ 17 because it is otherwise annoying to browse all files in a directory. -// We also only run these tests on little endian systems. -#if (FASTFLOAT_CPLUSPLUS >= 201703L) && (FASTFLOAT_IS_BIG_ENDIAN == 0) && !defined(FASTFLOAT_ODDPLATFORM) - -#include -#include -#include - -// return true on succcess -bool check_file(std::string file_name) { - std::cout << "Checking " << file_name << std::endl; - size_t number{0}; - std::fstream newfile(file_name, std::ios::in); - if (newfile.is_open()) { - std::string str; - while (std::getline(newfile, str)) { - if (str.size() > 0) { - // Read 32-bit hex - uint32_t float32; - auto r32 = std::from_chars(str.data() + 5, str.data() + str.size(), - float32, 16); - if(r32.ec != std::errc()) { std::cerr << "32-bit parsing failure\n"; return false; } - // Read 64-bit hex - uint64_t float64; - auto r64 = std::from_chars(str.data() + 14, str.data() + str.size(), - float64, 16); - if(r64.ec != std::errc()) { std::cerr << "64-bit parsing failure\n"; return false; } - // The string to parse: - const char *number_string = str.data() + 31; - const char *end_of_string = str.data() + str.size(); - // Parse as 32-bit float - float parsed_32; - auto fast_float_r32 = fast_float::from_chars(number_string, end_of_string, parsed_32); - if(fast_float_r32.ec != std::errc()) { std::cerr << "parsing failure\n"; return false; } - // Parse as 64-bit float - double parsed_64; - auto fast_float_r64 = fast_float::from_chars(number_string, end_of_string, parsed_64); - if(fast_float_r64.ec != std::errc()) { std::cerr << "parsing failure\n"; return false; } - // Convert the floats to unsigned ints. - uint32_t float32_parsed; - uint64_t float64_parsed; - ::memcpy(&float32_parsed, &parsed_32, sizeof(parsed_32)); - ::memcpy(&float64_parsed, &parsed_64, sizeof(parsed_64)); - // Compare with expected results - if (float32_parsed != float32) { - std::cout << "bad 32 " << str << std::endl; - return false; - } - if (float64_parsed != float64) { - std::cout << "bad 64 " << str << std::endl; - return false; - } - number++; - } - } - std::cout << "checked " << std::defaultfloat << number << " values" << std::endl; - newfile.close(); // close the file object - } else { - std::cout << "Could not read " << file_name << std::endl; - return false; - } - return true; -} - - -TEST_CASE("supplemental") { - std::string path = SUPPLEMENTAL_TEST_DATA_DIR; - for (const auto & entry : std::filesystem::directory_iterator(path)) { - CHECK(check_file(entry.path().string())); - } -} -#endif - -TEST_CASE("leading_zeroes") { - constexpr const uint64_t bit = 1; - CHECK(fast_float::leading_zeroes(bit << 0) == 63); - CHECK(fast_float::leading_zeroes(bit << 1) == 62); - CHECK(fast_float::leading_zeroes(bit << 2) == 61); - CHECK(fast_float::leading_zeroes(bit << 61) == 2); - CHECK(fast_float::leading_zeroes(bit << 62) == 1); - CHECK(fast_float::leading_zeroes(bit << 63) == 0); -} - -#define iHexAndDec(v) std::hex << "0x" << (v) << " (" << std::dec << (v) << ")" -#define fHexAndDec(v) std::hexfloat << (v) << " (" << std::defaultfloat << (v) << ")" - -void test_full_multiplication(uint64_t lhs, uint64_t rhs, uint64_t expected_lo, uint64_t expected_hi) { - fast_float::value128 v; - v = fast_float::full_multiplication(lhs, rhs); - INFO("lhs=" << iHexAndDec(lhs) << " " << "rhs=" << iHexAndDec(rhs) - << "\n actualLo=" << iHexAndDec(v.low) << " " << "actualHi=" << iHexAndDec(v.high) - << "\n expectedLo=" << iHexAndDec(expected_lo) << " " << "expectedHi=" << iHexAndDec(expected_hi)); - CHECK_EQ(v.low, expected_lo); - CHECK_EQ(v.high, expected_hi); - v = fast_float::full_multiplication(rhs, lhs); - CHECK_EQ(v.low, expected_lo); - CHECK_EQ(v.high, expected_hi); -} - -TEST_CASE("full_multiplication") { - constexpr const uint64_t bit = 1; - // lhs rhs lo hi - test_full_multiplication(bit << 0 , bit << 0, 1u , 0u); - test_full_multiplication(bit << 0 , bit << 63, bit << 63, 0u); - test_full_multiplication(bit << 1 , bit << 63, 0u , 1u); - test_full_multiplication(bit << 63, bit << 0, bit << 63, 0u); - test_full_multiplication(bit << 63, bit << 1, 0u , 1u); - test_full_multiplication(bit << 63, bit << 2, 0u , 2u); - test_full_multiplication(bit << 63, bit << 63, 0u , bit << 62); -} - - -TEST_CASE("issue8") { - const char* s = - "3." - "141592653589793238462643383279502884197169399375105820974944592307816406" - "286208998628034825342117067982148086513282306647093844609550582231725359" - "408128481117450284102701938521105559644622948954930381964428810975665933" - "446128475648233786783165271201909145648566923460348610454326648213393607" - "260249141273724587006606315588174881520920962829254091715364367892590360" - "011330530548820466521384146951941511609433057270365759591953092186117381" - "932611793105118548074462379962749567351885752724891227938183011949129833" - "673362440656643086021394946395224737190702179860943702770539217176293176" - "752384674818467669405132000568127145263560827785771342757789609173637178" - "721468440901224953430146549585371050792279689258923542019956112129021960" - "864034418159813629774771309960518707211349999998372978"; - for (int i = 0; i < 16; i++) { - // Parse all but the last i chars. We should still get 3.141ish. - double d = 0.0; - auto answer = fast_float::from_chars(s, s + strlen(s) - i, d); - CHECK_MESSAGE(answer.ec == std::errc(), "i=" << i); - CHECK_MESSAGE(d == 0x1.921fb54442d18p+1, "i=" << i << "\n" - << std::string(s, strlen(s) - size_t(i)) << "\n" - << std::hexfloat << d << "\n" - << std::defaultfloat << "\n"); - } -} - -TEST_CASE("check_behavior") { - const std::string input = "abc"; - double result; - auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result); - CHECK_MESSAGE(answer.ec != std::errc(), "expected parse failure"); - CHECK_MESSAGE(answer.ptr == input.data(), "If there is no pattern match, we should have ptr equals first"); -} - - -TEST_CASE("decimal_point_parsing") { - double result; - fast_float::parse_options options{}; - { - const std::string input = "1,25"; - auto answer = fast_float::from_chars_advanced(input.data(), input.data()+input.size(), result, options); - CHECK_MESSAGE(answer.ec == std::errc(), "expected parse success"); - CHECK_MESSAGE(answer.ptr == input.data() + 1, - "Parsing should have stopped at comma"); - CHECK_EQ(result, 1.0); - - options.decimal_point = ','; - answer = fast_float::from_chars_advanced(input.data(), input.data()+input.size(), result, options); - CHECK_MESSAGE(answer.ec == std::errc(), "expected parse success"); - CHECK_MESSAGE(answer.ptr == input.data() + input.size(), - "Parsing should have stopped at end"); - CHECK_EQ(result, 1.25); - } - { - const std::string input = "1.25"; - auto answer = fast_float::from_chars_advanced(input.data(), input.data()+input.size(), result, options); - CHECK_MESSAGE(answer.ec == std::errc(), "expected parse success"); - CHECK_MESSAGE(answer.ptr == input.data() + 1, - "Parsing should have stopped at dot"); - CHECK_EQ(result, 1.0); - - options.decimal_point = '.'; - answer = fast_float::from_chars_advanced(input.data(), input.data()+input.size(), result, options); - CHECK_MESSAGE(answer.ec == std::errc(), "expected parse success"); - CHECK_MESSAGE(answer.ptr == input.data() + input.size(), - "Parsing should have stopped at end"); - CHECK_EQ(result, 1.25); - } -} - -TEST_CASE("issue19") { - const std::string input = "3.14e"; - double result; - auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result); - CHECK_MESSAGE(answer.ec == std::errc(), "We want to parse up to 3.14\n"); - CHECK_MESSAGE(answer.ptr == input.data() + 4, - "Parsed the number " << result - << " and stopped at the wrong character: after " << (answer.ptr - input.data()) << " characters"); -} - - -TEST_CASE("scientific_only") { - // first, we try with something that should fail... - std::string input = "3.14"; - double result; - auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result, fast_float::chars_format::scientific); - CHECK_MESSAGE(answer.ec != std::errc(), "It is not scientific! Parsed: " << result); - - input = "3.14e10"; - answer = fast_float::from_chars(input.data(), input.data()+input.size(), result, fast_float::chars_format::scientific); - CHECK_MESSAGE(answer.ec == std::errc(), "It is scientific! Parsed: " << result); - CHECK_MESSAGE(answer.ptr == input.data() + input.size(), - "Parsed the number " << result - << " and stopped at the wrong character: after " << (answer.ptr - input.data()) << " characters"); -} - - -TEST_CASE("test_fixed_only") { - const std::string input = "3.14e10"; - double result; - auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result, fast_float::chars_format::fixed); - CHECK_MESSAGE(answer.ec == std::errc(), "We want to parse up to 3.14; parsed: " << result); - CHECK_MESSAGE(answer.ptr == input.data() + 4, - "Parsed the number " << result - << " and stopped at the wrong character: after " << (answer.ptr - input.data()) << " characters"); -} - - -static const double testing_power_of_ten[] = { - 1e-307, 1e-306, 1e-305, 1e-304, 1e-303, 1e-302, 1e-301, 1e-300, 1e-299, - 1e-298, 1e-297, 1e-296, 1e-295, 1e-294, 1e-293, 1e-292, 1e-291, 1e-290, - 1e-289, 1e-288, 1e-287, 1e-286, 1e-285, 1e-284, 1e-283, 1e-282, 1e-281, - 1e-280, 1e-279, 1e-278, 1e-277, 1e-276, 1e-275, 1e-274, 1e-273, 1e-272, - 1e-271, 1e-270, 1e-269, 1e-268, 1e-267, 1e-266, 1e-265, 1e-264, 1e-263, - 1e-262, 1e-261, 1e-260, 1e-259, 1e-258, 1e-257, 1e-256, 1e-255, 1e-254, - 1e-253, 1e-252, 1e-251, 1e-250, 1e-249, 1e-248, 1e-247, 1e-246, 1e-245, - 1e-244, 1e-243, 1e-242, 1e-241, 1e-240, 1e-239, 1e-238, 1e-237, 1e-236, - 1e-235, 1e-234, 1e-233, 1e-232, 1e-231, 1e-230, 1e-229, 1e-228, 1e-227, - 1e-226, 1e-225, 1e-224, 1e-223, 1e-222, 1e-221, 1e-220, 1e-219, 1e-218, - 1e-217, 1e-216, 1e-215, 1e-214, 1e-213, 1e-212, 1e-211, 1e-210, 1e-209, - 1e-208, 1e-207, 1e-206, 1e-205, 1e-204, 1e-203, 1e-202, 1e-201, 1e-200, - 1e-199, 1e-198, 1e-197, 1e-196, 1e-195, 1e-194, 1e-193, 1e-192, 1e-191, - 1e-190, 1e-189, 1e-188, 1e-187, 1e-186, 1e-185, 1e-184, 1e-183, 1e-182, - 1e-181, 1e-180, 1e-179, 1e-178, 1e-177, 1e-176, 1e-175, 1e-174, 1e-173, - 1e-172, 1e-171, 1e-170, 1e-169, 1e-168, 1e-167, 1e-166, 1e-165, 1e-164, - 1e-163, 1e-162, 1e-161, 1e-160, 1e-159, 1e-158, 1e-157, 1e-156, 1e-155, - 1e-154, 1e-153, 1e-152, 1e-151, 1e-150, 1e-149, 1e-148, 1e-147, 1e-146, - 1e-145, 1e-144, 1e-143, 1e-142, 1e-141, 1e-140, 1e-139, 1e-138, 1e-137, - 1e-136, 1e-135, 1e-134, 1e-133, 1e-132, 1e-131, 1e-130, 1e-129, 1e-128, - 1e-127, 1e-126, 1e-125, 1e-124, 1e-123, 1e-122, 1e-121, 1e-120, 1e-119, - 1e-118, 1e-117, 1e-116, 1e-115, 1e-114, 1e-113, 1e-112, 1e-111, 1e-110, - 1e-109, 1e-108, 1e-107, 1e-106, 1e-105, 1e-104, 1e-103, 1e-102, 1e-101, - 1e-100, 1e-99, 1e-98, 1e-97, 1e-96, 1e-95, 1e-94, 1e-93, 1e-92, - 1e-91, 1e-90, 1e-89, 1e-88, 1e-87, 1e-86, 1e-85, 1e-84, 1e-83, - 1e-82, 1e-81, 1e-80, 1e-79, 1e-78, 1e-77, 1e-76, 1e-75, 1e-74, - 1e-73, 1e-72, 1e-71, 1e-70, 1e-69, 1e-68, 1e-67, 1e-66, 1e-65, - 1e-64, 1e-63, 1e-62, 1e-61, 1e-60, 1e-59, 1e-58, 1e-57, 1e-56, - 1e-55, 1e-54, 1e-53, 1e-52, 1e-51, 1e-50, 1e-49, 1e-48, 1e-47, - 1e-46, 1e-45, 1e-44, 1e-43, 1e-42, 1e-41, 1e-40, 1e-39, 1e-38, - 1e-37, 1e-36, 1e-35, 1e-34, 1e-33, 1e-32, 1e-31, 1e-30, 1e-29, - 1e-28, 1e-27, 1e-26, 1e-25, 1e-24, 1e-23, 1e-22, 1e-21, 1e-20, - 1e-19, 1e-18, 1e-17, 1e-16, 1e-15, 1e-14, 1e-13, 1e-12, 1e-11, - 1e-10, 1e-9, 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, - 1e-1, 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, - 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, - 1e17, 1e18, 1e19, 1e20, 1e21, 1e22, 1e23, 1e24, 1e25, - 1e26, 1e27, 1e28, 1e29, 1e30, 1e31, 1e32, 1e33, 1e34, - 1e35, 1e36, 1e37, 1e38, 1e39, 1e40, 1e41, 1e42, 1e43, - 1e44, 1e45, 1e46, 1e47, 1e48, 1e49, 1e50, 1e51, 1e52, - 1e53, 1e54, 1e55, 1e56, 1e57, 1e58, 1e59, 1e60, 1e61, - 1e62, 1e63, 1e64, 1e65, 1e66, 1e67, 1e68, 1e69, 1e70, - 1e71, 1e72, 1e73, 1e74, 1e75, 1e76, 1e77, 1e78, 1e79, - 1e80, 1e81, 1e82, 1e83, 1e84, 1e85, 1e86, 1e87, 1e88, - 1e89, 1e90, 1e91, 1e92, 1e93, 1e94, 1e95, 1e96, 1e97, - 1e98, 1e99, 1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106, - 1e107, 1e108, 1e109, 1e110, 1e111, 1e112, 1e113, 1e114, 1e115, - 1e116, 1e117, 1e118, 1e119, 1e120, 1e121, 1e122, 1e123, 1e124, - 1e125, 1e126, 1e127, 1e128, 1e129, 1e130, 1e131, 1e132, 1e133, - 1e134, 1e135, 1e136, 1e137, 1e138, 1e139, 1e140, 1e141, 1e142, - 1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149, 1e150, 1e151, - 1e152, 1e153, 1e154, 1e155, 1e156, 1e157, 1e158, 1e159, 1e160, - 1e161, 1e162, 1e163, 1e164, 1e165, 1e166, 1e167, 1e168, 1e169, - 1e170, 1e171, 1e172, 1e173, 1e174, 1e175, 1e176, 1e177, 1e178, - 1e179, 1e180, 1e181, 1e182, 1e183, 1e184, 1e185, 1e186, 1e187, - 1e188, 1e189, 1e190, 1e191, 1e192, 1e193, 1e194, 1e195, 1e196, - 1e197, 1e198, 1e199, 1e200, 1e201, 1e202, 1e203, 1e204, 1e205, - 1e206, 1e207, 1e208, 1e209, 1e210, 1e211, 1e212, 1e213, 1e214, - 1e215, 1e216, 1e217, 1e218, 1e219, 1e220, 1e221, 1e222, 1e223, - 1e224, 1e225, 1e226, 1e227, 1e228, 1e229, 1e230, 1e231, 1e232, - 1e233, 1e234, 1e235, 1e236, 1e237, 1e238, 1e239, 1e240, 1e241, - 1e242, 1e243, 1e244, 1e245, 1e246, 1e247, 1e248, 1e249, 1e250, - 1e251, 1e252, 1e253, 1e254, 1e255, 1e256, 1e257, 1e258, 1e259, - 1e260, 1e261, 1e262, 1e263, 1e264, 1e265, 1e266, 1e267, 1e268, - 1e269, 1e270, 1e271, 1e272, 1e273, 1e274, 1e275, 1e276, 1e277, - 1e278, 1e279, 1e280, 1e281, 1e282, 1e283, 1e284, 1e285, 1e286, - 1e287, 1e288, 1e289, 1e290, 1e291, 1e292, 1e293, 1e294, 1e295, - 1e296, 1e297, 1e298, 1e299, 1e300, 1e301, 1e302, 1e303, 1e304, - 1e305, 1e306, 1e307, 1e308}; - - -TEST_CASE("powers_of_ten") { - char buf[1024]; - WARN_MESSAGE(1e-308 == std::pow(10, -308), "On your system, the pow function is busted. Sorry about that."); - bool is_pow_correct{1e-308 == std::pow(10,-308)}; - // large negative values should be zero. - int start_point = is_pow_correct ? -1000 : -307; - for (int i = start_point; i <= 308; ++i) { - INFO("i=" << i); - size_t n = size_t(snprintf(buf, sizeof(buf), "1e%d", i)); - REQUIRE(n < sizeof(buf)); // if false, fails the test and exits - double actual; - auto result = fast_float::from_chars(buf, buf + 1000, actual); - CHECK_MESSAGE(result.ec == std::errc(), " I could not parse " << buf); - double expected = ((i >= -307) ? testing_power_of_ten[i + 307] : std::pow(10, i)); - CHECK_MESSAGE(actual == expected, "String '" << buf << "'parsed to " << actual); - } -} - - -template std::string to_string(T d) { - std::string s(64, '\0'); - auto written = std::snprintf(&s[0], s.size(), "%.*e", - std::numeric_limits::max_digits10 - 1, d); - s.resize(size_t(written)); - return s; -} - -template std::string to_long_string(T d) { - std::string s(4096, '\0'); - auto written = std::snprintf(&s[0], s.size(), "%.*e", - std::numeric_limits::max_digits10 * 10, d); - s.resize(size_t(written)); - return s; -} - -uint32_t get_mantissa(float f) { - uint32_t m; - memcpy(&m, &f, sizeof(f)); - return (m & ((uint32_t(1)<<23)-1)); -} - -uint64_t get_mantissa(double f) { - uint64_t m; - memcpy(&m, &f, sizeof(f)); - return (m & ((uint64_t(1)<<57)-1)); -} - - -std::string append_zeros(std::string str, size_t number_of_zeros) { - std::string answer(str); - for(size_t i = 0; i < number_of_zeros; i++) { answer += "0"; } - return answer; -} - -template -void check_basic_test_result(const std::string& str, fast_float::from_chars_result result, - T actual, T expected) { - INFO("str=" << str << "\n" - << " expected=" << fHexAndDec(expected) << "\n" - << " ..actual=" << fHexAndDec(actual) << "\n" - << " expected mantissa=" << iHexAndDec(get_mantissa(expected)) << "\n" - << " ..actual mantissa=" << iHexAndDec(get_mantissa(actual))); - CHECK_EQ(result.ec, std::errc()); - CHECK_EQ(result.ptr, str.data() + str.size()); - CHECK_EQ(copysign(1, actual), copysign(1, expected)); - CHECK_EQ(std::isnan(actual), std::isnan(expected)); - CHECK_EQ(actual, expected); -} - -template -void basic_test(std::string str, T expected) { - T actual; - auto result = fast_float::from_chars(str.data(), str.data() + str.size(), actual); - check_basic_test_result(str, result, actual, expected); -} - -template -void basic_test(std::string str, T expected, fast_float::parse_options options) { - T actual; - auto result = fast_float::from_chars_advanced(str.data(), str.data() + str.size(), actual, options); - check_basic_test_result(str, result, actual, expected); -} - -void basic_test(float val) { - { - std::string long_vals = to_long_string(val); - INFO("long vals: " << long_vals); - basic_test(long_vals, val); - } - { - std::string vals = to_string(val); - INFO("vals: " << vals); - basic_test(vals, val); - } -} - -#define verify(lhs, rhs) { INFO(lhs); basic_test(lhs, rhs); } -#define verify32(val) { INFO(#val); basic_test(val); } - -#define verify_options(lhs, rhs) { INFO(lhs); basic_test(lhs, rhs, options); } - -TEST_CASE("64bit.inf") { - verify("INF", std::numeric_limits::infinity()); - verify("-INF", -std::numeric_limits::infinity()); - verify("INFINITY", std::numeric_limits::infinity()); - verify("-INFINITY", -std::numeric_limits::infinity()); - verify("infinity", std::numeric_limits::infinity()); - verify("-infinity", -std::numeric_limits::infinity()); - verify("inf", std::numeric_limits::infinity()); - verify("-inf", -std::numeric_limits::infinity()); - verify("1234456789012345678901234567890e9999999999999999999999999999", std::numeric_limits::infinity()); - verify("-2139879401095466344511101915470454744.9813888656856943E+272", -std::numeric_limits::infinity()); - verify("1.8e308", std::numeric_limits::infinity()); - verify("1.832312213213213232132132143451234453123412321321312e308", std::numeric_limits::infinity()); - verify("2e30000000000000000", std::numeric_limits::infinity()); - verify("2e3000", std::numeric_limits::infinity()); - verify("1.9e308", std::numeric_limits::infinity()); -} - -TEST_CASE("64bit.general") { - verify("-2.2222222222223e-322",-0x1.68p-1069); - verify("9007199254740993.0", 0x1p+53); - verify("860228122.6654514319E+90", 0x1.92bb20990715fp+328); - verify(append_zeros("9007199254740993.0",1000), 0x1p+53); - verify("10000000000000000000", 0x1.158e460913dp+63); - verify("10000000000000000000000000000001000000000000", 0x1.cb2d6f618c879p+142); - verify("10000000000000000000000000000000000000000001", 0x1.cb2d6f618c879p+142); - verify("1.1920928955078125e-07", 1.1920928955078125e-07); - verify("9355950000000000000.00000000000000000000000000000000001844674407370955161600000184467440737095516161844674407370955161407370955161618446744073709551616000184467440737095516166000001844674407370955161618446744073709551614073709551616184467440737095516160001844674407370955161601844674407370955674451616184467440737095516140737095516161844674407370955161600018446744073709551616018446744073709551611616000184467440737095001844674407370955161600184467440737095516160018446744073709551168164467440737095516160001844073709551616018446744073709551616184467440737095516160001844674407536910751601611616000184467440737095001844674407370955161600184467440737095516160018446744073709551616184467440737095516160001844955161618446744073709551616000184467440753691075160018446744073709",0x1.03ae05e8fca1cp+63); - verify("-0",-0.0); - verify("2.22507385850720212418870147920222032907240528279439037814303133837435107319244194686754406432563881851382188218502438069999947733013005649884107791928741341929297200970481951993067993290969042784064731682041565926728632933630474670123316852983422152744517260835859654566319282835244787787799894310779783833699159288594555213714181128458251145584319223079897504395086859412457230891738946169368372321191373658977977723286698840356390251044443035457396733706583981055420456693824658413747607155981176573877626747665912387199931904006317334709003012790188175203447190250028061277777916798391090578584006464715943810511489154282775041174682194133952466682503431306181587829379004205392375072083366693241580002758391118854188641513168478436313080237596295773983001708984375e-308", 0x1.0000000000002p-1022); - verify("1.0000000000000006661338147750939242541790008544921875",1.0000000000000007); - verify("1090544144181609348835077142190",0x1.b8779f2474dfbp+99); - verify("2.2250738585072013e-308", 2.2250738585072013e-308); - verify("-92666518056446206563E3", -92666518056446206563E3); - verify("-92666518056446206563E3", -92666518056446206563E3); - verify("-42823146028335318693e-128",-42823146028335318693e-128); - verify("90054602635948575728E72",90054602635948575728E72); - verify("1.00000000000000188558920870223463870174566020691753515394643550663070558368373221972569761144603605635692374830246134201063722058e-309", 1.00000000000000188558920870223463870174566020691753515394643550663070558368373221972569761144603605635692374830246134201063722058e-309); - verify("0e9999999999999999999999999999", 0.0); - verify("-2402844368454405395.2", -2402844368454405395.2); - verify("2402844368454405395.2", 2402844368454405395.2); - verify("7.0420557077594588669468784357561207962098443483187940792729600000e+59", 7.0420557077594588669468784357561207962098443483187940792729600000e+59); - verify("7.0420557077594588669468784357561207962098443483187940792729600000e+59", 7.0420557077594588669468784357561207962098443483187940792729600000e+59); - verify("-1.7339253062092163730578609458683877051596800000000000000000000000e+42", -1.7339253062092163730578609458683877051596800000000000000000000000e+42); - verify("-2.0972622234386619214559824785284023792871122537545728000000000000e+52", -2.0972622234386619214559824785284023792871122537545728000000000000e+52); - verify("-1.0001803374372191849407179462120053338028379051879898808320000000e+57", -1.0001803374372191849407179462120053338028379051879898808320000000e+57); - verify("-1.8607245283054342363818436991534856973992070520151142825984000000e+58", -1.8607245283054342363818436991534856973992070520151142825984000000e+58); - verify("-1.9189205311132686907264385602245237137907390376574976000000000000e+52", -1.9189205311132686907264385602245237137907390376574976000000000000e+52); - verify("-2.8184483231688951563253238886553506793085187889855201280000000000e+54", -2.8184483231688951563253238886553506793085187889855201280000000000e+54); - verify("-1.7664960224650106892054063261344555646357024359107788800000000000e+53", -1.7664960224650106892054063261344555646357024359107788800000000000e+53); - verify("-2.1470977154320536489471030463761883783915110400000000000000000000e+45", -2.1470977154320536489471030463761883783915110400000000000000000000e+45); - verify("-4.4900312744003159009338275160799498340862630046359789166919680000e+61", -4.4900312744003159009338275160799498340862630046359789166919680000e+61); - verify("1", 1.0); - verify("1.797693134862315700000000000000001e308", 1.7976931348623157e308); - verify("3e-324", 0x0.0000000000001p-1022); - verify("1.00000006e+09", 0x1.dcd651ep+29); - verify("4.9406564584124653e-324", 0x0.0000000000001p-1022); - verify("4.9406564584124654e-324", 0x0.0000000000001p-1022); - verify("2.2250738585072009e-308", 0x0.fffffffffffffp-1022); - verify("2.2250738585072014e-308", 0x1p-1022); - verify("1.7976931348623157e308", 0x1.fffffffffffffp+1023); - verify("1.7976931348623158e308", 0x1.fffffffffffffp+1023); - verify("4503599627370496.5", 4503599627370496.5); - verify("4503599627475352.5", 4503599627475352.5); - verify("4503599627475353.5", 4503599627475353.5); - verify("2251799813685248.25", 2251799813685248.25); - verify("1125899906842624.125", 1125899906842624.125); - verify("1125899906842901.875", 1125899906842901.875); - verify("2251799813685803.75", 2251799813685803.75); - verify("4503599627370497.5", 4503599627370497.5); - verify("45035996.273704995", 45035996.273704995); - verify("45035996.273704985", 45035996.273704985); - verify("0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044501477170144022721148195934182639518696390927032912960468522194496444440421538910330590478162701758282983178260792422137401728773891892910553144148156412434867599762821265346585071045737627442980259622449029037796981144446145705102663115100318287949527959668236039986479250965780342141637013812613333119898765515451440315261253813266652951306000184917766328660755595837392240989947807556594098101021612198814605258742579179000071675999344145086087205681577915435923018910334964869420614052182892431445797605163650903606514140377217442262561590244668525767372446430075513332450079650686719491377688478005309963967709758965844137894433796621993967316936280457084866613206797017728916080020698679408551343728867675409720757232455434770912461317493580281734466552734375", 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044501477170144022721148195934182639518696390927032912960468522194496444440421538910330590478162701758282983178260792422137401728773891892910553144148156412434867599762821265346585071045737627442980259622449029037796981144446145705102663115100318287949527959668236039986479250965780342141637013812613333119898765515451440315261253813266652951306000184917766328660755595837392240989947807556594098101021612198814605258742579179000071675999344145086087205681577915435923018910334964869420614052182892431445797605163650903606514140377217442262561590244668525767372446430075513332450079650686719491377688478005309963967709758965844137894433796621993967316936280457084866613206797017728916080020698679408551343728867675409720757232455434770912461317493580281734466552734375); - verify("0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022250738585072008890245868760858598876504231122409594654935248025624400092282356951787758888037591552642309780950434312085877387158357291821993020294379224223559819827501242041788969571311791082261043971979604000454897391938079198936081525613113376149842043271751033627391549782731594143828136275113838604094249464942286316695429105080201815926642134996606517803095075913058719846423906068637102005108723282784678843631944515866135041223479014792369585208321597621066375401613736583044193603714778355306682834535634005074073040135602968046375918583163124224521599262546494300836851861719422417646455137135420132217031370496583210154654068035397417906022589503023501937519773030945763173210852507299305089761582519159720757232455434770912461317493580281734466552734375", 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022250738585072008890245868760858598876504231122409594654935248025624400092282356951787758888037591552642309780950434312085877387158357291821993020294379224223559819827501242041788969571311791082261043971979604000454897391938079198936081525613113376149842043271751033627391549782731594143828136275113838604094249464942286316695429105080201815926642134996606517803095075913058719846423906068637102005108723282784678843631944515866135041223479014792369585208321597621066375401613736583044193603714778355306682834535634005074073040135602968046375918583163124224521599262546494300836851861719422417646455137135420132217031370496583210154654068035397417906022589503023501937519773030945763173210852507299305089761582519159720757232455434770912461317493580281734466552734375); - verify("1438456663141390273526118207642235581183227845246331231162636653790368152091394196930365828634687637948157940776599182791387527135353034738357134110310609455693900824193549772792016543182680519740580354365467985440183598701312257624545562331397018329928613196125590274187720073914818062530830316533158098624984118889298281371812288789537310599037529113415438738954894752124724983067241108764488346454376699018673078404751121414804937224240805993123816932326223683090770561597570457793932985826162604255884529134126396282202126526253389383421806727954588525596114379801269094096329805054803089299736996870951258573010877404407451953846698609198213926882692078557033228265259305481198526059813164469187586693257335779522020407645498684263339921905227556616698129967412891282231685504660671277927198290009824680186319750978665734576683784255802269708917361719466043175201158849097881370477111850171579869056016061666173029059588433776015644439705050377554277696143928278093453792803846252715966016733222646442382892123940052441346822429721593884378212558701004356924243030059517489346646577724622498919752597382095222500311124181823512251071356181769376577651390028297796156208815375089159128394945710515861334486267101797497111125909272505194792870889617179758703442608016143343262159998149700606597792535574457560429226974273443630323818747730771316763398572110874959981923732463076884528677392654150010269822239401993427482376513231389212353583573566376915572650916866553612366187378959554983566712767093372906030188976220169058025354973622211666504549316958271880975697143546564469806791358707318873075708383345004090151974068325838177531266954177406661392229801349994695941509935655355652985723782153570084089560139142231.738475042362596875449154552392299548947138162081694168675340677843807613129780449323363759027012972466987370921816813162658754726545121090545507240267000456594786540949605260722461937870630634874991729398208026467698131898691830012167897399682179601734569071423681e-733", std::numeric_limits::infinity()); - verify("-2240084132271013504.131248280843119943687942846658579428", -0x1.f1660a65b00bfp+60); -} - -TEST_CASE("64bit.decimal_point") { - fast_float::parse_options options{}; - options.decimal_point = ','; - - // infinities - verify_options("1,8e308", std::numeric_limits::infinity()); - verify_options("1,832312213213213232132132143451234453123412321321312e308", std::numeric_limits::infinity()); - verify_options("2e30000000000000000", std::numeric_limits::infinity()); - verify_options("2e3000", std::numeric_limits::infinity()); - verify_options("1,9e308", std::numeric_limits::infinity()); - - // finites - verify_options("-2,2222222222223e-322",-0x1.68p-1069); - verify_options("9007199254740993,0", 0x1p+53); - verify_options("860228122,6654514319E+90", 0x1.92bb20990715fp+328); - verify_options(append_zeros("9007199254740993,0",1000), 0x1p+53); - verify_options("1,1920928955078125e-07", 1.1920928955078125e-07); - verify_options("9355950000000000000,00000000000000000000000000000000001844674407370955161600000184467440737095516161844674407370955161407370955161618446744073709551616000184467440737095516166000001844674407370955161618446744073709551614073709551616184467440737095516160001844674407370955161601844674407370955674451616184467440737095516140737095516161844674407370955161600018446744073709551616018446744073709551611616000184467440737095001844674407370955161600184467440737095516160018446744073709551168164467440737095516160001844073709551616018446744073709551616184467440737095516160001844674407536910751601611616000184467440737095001844674407370955161600184467440737095516160018446744073709551616184467440737095516160001844955161618446744073709551616000184467440753691075160018446744073709",0x1.03ae05e8fca1cp+63); - verify_options("2,22507385850720212418870147920222032907240528279439037814303133837435107319244194686754406432563881851382188218502438069999947733013005649884107791928741341929297200970481951993067993290969042784064731682041565926728632933630474670123316852983422152744517260835859654566319282835244787787799894310779783833699159288594555213714181128458251145584319223079897504395086859412457230891738946169368372321191373658977977723286698840356390251044443035457396733706583981055420456693824658413747607155981176573877626747665912387199931904006317334709003012790188175203447190250028061277777916798391090578584006464715943810511489154282775041174682194133952466682503431306181587829379004205392375072083366693241580002758391118854188641513168478436313080237596295773983001708984375e-308", 0x1.0000000000002p-1022); - verify_options("1,0000000000000006661338147750939242541790008544921875",1.0000000000000007); - verify_options("2,2250738585072013e-308", 2.2250738585072013e-308); - verify_options("1,00000000000000188558920870223463870174566020691753515394643550663070558368373221972569761144603605635692374830246134201063722058e-309", 1.00000000000000188558920870223463870174566020691753515394643550663070558368373221972569761144603605635692374830246134201063722058e-309); - verify_options("-2402844368454405395,2", -2402844368454405395.2); - verify_options("2402844368454405395,2", 2402844368454405395.2); - verify_options("7,0420557077594588669468784357561207962098443483187940792729600000e+59", 7.0420557077594588669468784357561207962098443483187940792729600000e+59); - verify_options("7,0420557077594588669468784357561207962098443483187940792729600000e+59", 7.0420557077594588669468784357561207962098443483187940792729600000e+59); - verify_options("-1,7339253062092163730578609458683877051596800000000000000000000000e+42", -1.7339253062092163730578609458683877051596800000000000000000000000e+42); - verify_options("-2,0972622234386619214559824785284023792871122537545728000000000000e+52", -2.0972622234386619214559824785284023792871122537545728000000000000e+52); - verify_options("-1,0001803374372191849407179462120053338028379051879898808320000000e+57", -1.0001803374372191849407179462120053338028379051879898808320000000e+57); - verify_options("-1,8607245283054342363818436991534856973992070520151142825984000000e+58", -1.8607245283054342363818436991534856973992070520151142825984000000e+58); - verify_options("-1,9189205311132686907264385602245237137907390376574976000000000000e+52", -1.9189205311132686907264385602245237137907390376574976000000000000e+52); - verify_options("-2,8184483231688951563253238886553506793085187889855201280000000000e+54", -2.8184483231688951563253238886553506793085187889855201280000000000e+54); - verify_options("-1,7664960224650106892054063261344555646357024359107788800000000000e+53", -1.7664960224650106892054063261344555646357024359107788800000000000e+53); - verify_options("-2,1470977154320536489471030463761883783915110400000000000000000000e+45", -2.1470977154320536489471030463761883783915110400000000000000000000e+45); - verify_options("-4,4900312744003159009338275160799498340862630046359789166919680000e+61", -4.4900312744003159009338275160799498340862630046359789166919680000e+61); - verify_options("1", 1.0); - verify_options("1,797693134862315700000000000000001e308", 1.7976931348623157e308); - verify_options("3e-324", 0x0.0000000000001p-1022); - verify_options("1,00000006e+09", 0x1.dcd651ep+29); - verify_options("4,9406564584124653e-324", 0x0.0000000000001p-1022); - verify_options("4,9406564584124654e-324", 0x0.0000000000001p-1022); - verify_options("2,2250738585072009e-308", 0x0.fffffffffffffp-1022); - verify_options("2,2250738585072014e-308", 0x1p-1022); - verify_options("1,7976931348623157e308", 0x1.fffffffffffffp+1023); - verify_options("1,7976931348623158e308", 0x1.fffffffffffffp+1023); - verify_options("4503599627370496,5", 4503599627370496.5); - verify_options("4503599627475352,5", 4503599627475352.5); - verify_options("4503599627475353,5", 4503599627475353.5); - verify_options("2251799813685248,25", 2251799813685248.25); - verify_options("1125899906842624,125", 1125899906842624.125); - verify_options("1125899906842901,875", 1125899906842901.875); - verify_options("2251799813685803,75", 2251799813685803.75); - verify_options("4503599627370497,5", 4503599627370497.5); - verify_options("45035996,273704995", 45035996.273704995); - verify_options("45035996,273704985", 45035996.273704985); - verify_options("0,000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044501477170144022721148195934182639518696390927032912960468522194496444440421538910330590478162701758282983178260792422137401728773891892910553144148156412434867599762821265346585071045737627442980259622449029037796981144446145705102663115100318287949527959668236039986479250965780342141637013812613333119898765515451440315261253813266652951306000184917766328660755595837392240989947807556594098101021612198814605258742579179000071675999344145086087205681577915435923018910334964869420614052182892431445797605163650903606514140377217442262561590244668525767372446430075513332450079650686719491377688478005309963967709758965844137894433796621993967316936280457084866613206797017728916080020698679408551343728867675409720757232455434770912461317493580281734466552734375", 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044501477170144022721148195934182639518696390927032912960468522194496444440421538910330590478162701758282983178260792422137401728773891892910553144148156412434867599762821265346585071045737627442980259622449029037796981144446145705102663115100318287949527959668236039986479250965780342141637013812613333119898765515451440315261253813266652951306000184917766328660755595837392240989947807556594098101021612198814605258742579179000071675999344145086087205681577915435923018910334964869420614052182892431445797605163650903606514140377217442262561590244668525767372446430075513332450079650686719491377688478005309963967709758965844137894433796621993967316936280457084866613206797017728916080020698679408551343728867675409720757232455434770912461317493580281734466552734375); - verify_options("0,000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022250738585072008890245868760858598876504231122409594654935248025624400092282356951787758888037591552642309780950434312085877387158357291821993020294379224223559819827501242041788969571311791082261043971979604000454897391938079198936081525613113376149842043271751033627391549782731594143828136275113838604094249464942286316695429105080201815926642134996606517803095075913058719846423906068637102005108723282784678843631944515866135041223479014792369585208321597621066375401613736583044193603714778355306682834535634005074073040135602968046375918583163124224521599262546494300836851861719422417646455137135420132217031370496583210154654068035397417906022589503023501937519773030945763173210852507299305089761582519159720757232455434770912461317493580281734466552734375", 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022250738585072008890245868760858598876504231122409594654935248025624400092282356951787758888037591552642309780950434312085877387158357291821993020294379224223559819827501242041788969571311791082261043971979604000454897391938079198936081525613113376149842043271751033627391549782731594143828136275113838604094249464942286316695429105080201815926642134996606517803095075913058719846423906068637102005108723282784678843631944515866135041223479014792369585208321597621066375401613736583044193603714778355306682834535634005074073040135602968046375918583163124224521599262546494300836851861719422417646455137135420132217031370496583210154654068035397417906022589503023501937519773030945763173210852507299305089761582519159720757232455434770912461317493580281734466552734375); -} - - -TEST_CASE("32bit.inf") { - verify("INF", std::numeric_limits::infinity()); - verify("-INF", -std::numeric_limits::infinity()); - verify("INFINITY", std::numeric_limits::infinity()); - verify("-INFINITY", -std::numeric_limits::infinity()); - verify("infinity", std::numeric_limits::infinity()); - verify("-infinity", -std::numeric_limits::infinity()); - verify("inf", std::numeric_limits::infinity()); - verify("-inf", -std::numeric_limits::infinity()); - verify("1234456789012345678901234567890e9999999999999999999999999999", std::numeric_limits::infinity()); - verify("2e3000", std::numeric_limits::infinity()); - verify("3.5028234666e38", std::numeric_limits::infinity()); -} - -TEST_CASE("32bit.general") { - verify("1.1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125", 0x1.2ced3p+0f); - verify("1.1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125e-38", 0x1.fffff8p-127f); - verify(append_zeros("1.1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125",655), 0x1.2ced3p+0f); - verify(append_zeros("1.1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125",656), 0x1.2ced3p+0f); - verify(append_zeros("1.1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125",1000), 0x1.2ced3p+0f); - std::string test_string; - test_string = append_zeros("1.1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125",655) + std::string("e-38"); - verify(test_string, 0x1.fffff8p-127f); - test_string = append_zeros("1.1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125",656) + std::string("e-38"); - verify(test_string, 0x1.fffff8p-127f); - test_string = append_zeros("1.1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125",1000) + std::string("e-38"); - verify(test_string, 0x1.fffff8p-127f); - verify32(1.00000006e+09f); - verify32(1.4012984643e-45f); - verify32(1.1754942107e-38f); - verify32(1.1754943508e-45f); - verify("-0", -0.0f); - verify("1090544144181609348835077142190", 0x1.b877ap+99f); - verify("1.1754943508e-38", 1.1754943508e-38f); - verify("30219.0830078125", 30219.0830078125f); - verify("16252921.5", 16252921.5f); - verify("5322519.25", 5322519.25f); - verify("3900245.875", 3900245.875f); - verify("1510988.3125", 1510988.3125f); - verify("782262.28125", 782262.28125f); - verify("328381.484375", 328381.484375f); - verify("156782.0703125", 156782.0703125f); - verify("85003.24609375", 85003.24609375f); - verify("17419.6494140625", 17419.6494140625f); - verify("15498.36376953125", 15498.36376953125f); - verify("6318.580322265625", 6318.580322265625f); - verify("2525.2840576171875", 2525.2840576171875f); - verify("1370.9265747070312", 1370.9265747070312f); - verify("936.3702087402344", 936.3702087402344f); - verify("411.88682556152344", 411.88682556152344f); - verify("206.50310516357422", 206.50310516357422f); - verify("124.16878890991211", 124.16878890991211f); - verify("50.811574935913086", 50.811574935913086f); - verify("17.486443519592285", 17.486443519592285f); - verify("13.91745138168335", 13.91745138168335f); - verify("7.5464513301849365", 0x1.e2f90ep+2f); - verify("2.687217116355896", 2.687217116355896f); - verify("1.1877630352973938", 0x1.30113ep+0f); - verify("0.7622503340244293", 0.7622503340244293f); - verify("0.30531780421733856", 0x1.38a53ap-2f); - verify("0.21791061013936996", 0x1.be47eap-3f); - verify("0.09289376810193062", 0x1.7c7e2ep-4f); - verify("0.03706067614257336", 0.03706067614257336f); - verify("0.028068351559340954", 0.028068351559340954f); - verify("0.012114629615098238", 0x1.8cf8e2p-7f); - verify("0.004221370676532388", 0x1.14a6dap-8f); - verify("0.002153817447833717", 0.002153817447833717f); - verify("0.0015924838953651488", 0x1.a175cap-10f); - verify("0.0008602388261351734", 0.0008602388261351734f); - verify("0.00036393293703440577", 0x1.7d9c82p-12f); - verify("0.00013746770127909258", 0.00013746770127909258f); - verify("16407.9462890625", 16407.9462890625f); - verify("1.1754947011469036e-38", 0x1.000006p-126f); - verify("7.0064923216240854e-46", 0x1p-149f); - verify("8388614.5", 8388614.5f); - verify("0e9999999999999999999999999999", 0.f); - verify("4.7019774032891500318749461488889827112746622270883500860350068251e-38",4.7019774032891500318749461488889827112746622270883500860350068251e-38f); - verify("3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679", 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679f); - verify("2.3509887016445750159374730744444913556373311135441750430175034126e-38", 2.3509887016445750159374730744444913556373311135441750430175034126e-38f); - verify("1", 1.f); - verify("7.0060e-46", 0.f); - verify("3.4028234664e38", 0x1.fffffep+127f); - verify("3.4028234665e38", 0x1.fffffep+127f); - verify("3.4028234666e38", 0x1.fffffep+127f); - verify("0.000000000000000000000000000000000000011754943508222875079687365372222456778186655567720875215087517062784172594547271728515625", 0.000000000000000000000000000000000000011754943508222875079687365372222456778186655567720875215087517062784172594547271728515625); - verify("0.00000000000000000000000000000000000000000000140129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125", 0.00000000000000000000000000000000000000000000140129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125f); - verify("0.00000000000000000000000000000000000002350988561514728583455765982071533026645717985517980855365926236850006129930346077117064851336181163787841796875", 0.00000000000000000000000000000000000002350988561514728583455765982071533026645717985517980855365926236850006129930346077117064851336181163787841796875f); - verify("0.00000000000000000000000000000000000001175494210692441075487029444849287348827052428745893333857174530571588870475618904265502351336181163787841796875", 0.00000000000000000000000000000000000001175494210692441075487029444849287348827052428745893333857174530571588870475618904265502351336181163787841796875f); -} - -TEST_CASE("32bit.decimal_point") { - fast_float::parse_options options{}; - options.decimal_point = ','; - - // infinity - verify_options("3,5028234666e38", std::numeric_limits::infinity()); - - // finites - verify_options("1,1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125", 0x1.2ced3p+0f); - verify_options("1,1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125e-38", 0x1.fffff8p-127f); - verify_options(append_zeros("1,1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125",655), 0x1.2ced3p+0f); - verify_options(append_zeros("1,1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125",656), 0x1.2ced3p+0f); - verify_options(append_zeros("1,1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125",1000), 0x1.2ced3p+0f); - std::string test_string; - test_string = append_zeros("1,1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125",655) + std::string("e-38"); - verify_options(test_string, 0x1.fffff8p-127f); - test_string = append_zeros("1,1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125",656) + std::string("e-38"); - verify_options(test_string, 0x1.fffff8p-127f); - test_string = append_zeros("1,1754941406275178592461758986628081843312458647327962400313859427181746759860647699724722770042717456817626953125",1000) + std::string("e-38"); - verify_options(test_string, 0x1.fffff8p-127f); - verify_options("1,1754943508e-38", 1.1754943508e-38f); - verify_options("30219,0830078125", 30219.0830078125f); - verify_options("1,1754947011469036e-38", 0x1.000006p-126f); - verify_options("7,0064923216240854e-46", 0x1p-149f); - verify_options("8388614,5", 8388614.5f); - verify_options("0e9999999999999999999999999999", 0.f); - verify_options("4,7019774032891500318749461488889827112746622270883500860350068251e-38",4.7019774032891500318749461488889827112746622270883500860350068251e-38f); - verify_options("3,1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679", 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679f); - verify_options("2,3509887016445750159374730744444913556373311135441750430175034126e-38", 2.3509887016445750159374730744444913556373311135441750430175034126e-38f); - verify_options("1", 1.f); - verify_options("7,0060e-46", 0.f); - verify_options("3,4028234664e38", 0x1.fffffep+127f); - verify_options("3,4028234665e38", 0x1.fffffep+127f); - verify_options("3,4028234666e38", 0x1.fffffep+127f); - verify_options("0,000000000000000000000000000000000000011754943508222875079687365372222456778186655567720875215087517062784172594547271728515625", 0.000000000000000000000000000000000000011754943508222875079687365372222456778186655567720875215087517062784172594547271728515625); - verify_options("0,00000000000000000000000000000000000000000000140129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125", 0.00000000000000000000000000000000000000000000140129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125f); - verify_options("0,00000000000000000000000000000000000002350988561514728583455765982071533026645717985517980855365926236850006129930346077117064851336181163787841796875", 0.00000000000000000000000000000000000002350988561514728583455765982071533026645717985517980855365926236850006129930346077117064851336181163787841796875f); - verify_options("0,00000000000000000000000000000000000001175494210692441075487029444849287348827052428745893333857174530571588870475618904265502351336181163787841796875", 0.00000000000000000000000000000000000001175494210692441075487029444849287348827052428745893333857174530571588870475618904265502351336181163787841796875f); -} diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/build_tests/issue72/foo.cpp b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/build_tests/issue72/foo.cpp deleted file mode 100644 index cbe241275..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/build_tests/issue72/foo.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#include "test.h" -void foo() { } \ No newline at end of file diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/build_tests/issue72/main.cpp b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/build_tests/issue72/main.cpp deleted file mode 100644 index 3d46c0abc..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/build_tests/issue72/main.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#include "test.h" -int main() { return 0; } \ No newline at end of file diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/build_tests/issue72/test.h b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/build_tests/issue72/test.h deleted file mode 100644 index 550a31b5a..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/build_tests/issue72/test.h +++ /dev/null @@ -1,2 +0,0 @@ -#pragma once -#include "fast_float/fast_float.h" \ No newline at end of file diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/example_comma_test.cpp b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/example_comma_test.cpp deleted file mode 100644 index 12f488d1a..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/example_comma_test.cpp +++ /dev/null @@ -1,15 +0,0 @@ - -#include "fast_float/fast_float.h" -#include -#include -#include - -int main() { - const std::string input = "3,1416 xyz "; - double result; - fast_float::parse_options options{fast_float::chars_format::general, ','}; - auto answer = fast_float::from_chars_advanced(input.data(), input.data()+input.size(), result, options); - if((answer.ec != std::errc()) || ((result != 3.1416))) { std::cerr << "parsing failure\n"; return EXIT_FAILURE; } - std::cout << "parsed the number " << result << std::endl; - return EXIT_SUCCESS; -} diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/example_test.cpp b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/example_test.cpp deleted file mode 100644 index db1bae829..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/example_test.cpp +++ /dev/null @@ -1,14 +0,0 @@ - -#include "fast_float/fast_float.h" -#include -#include -#include - -int main() { - const std::string input = "3.1416 xyz "; - double result; - auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result); - if((answer.ec != std::errc()) || ((result != 3.1416))) { std::cerr << "parsing failure\n"; return EXIT_FAILURE; } - std::cout << "parsed the number " << result << std::endl; - return EXIT_SUCCESS; -} diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/exhaustive32.cpp b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/exhaustive32.cpp deleted file mode 100644 index 9e1e42f26..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/exhaustive32.cpp +++ /dev/null @@ -1,63 +0,0 @@ - -#include "fast_float/fast_float.h" - -#include -#include -#include -#include -#include -#include -#include - -template char *to_string(T d, char *buffer) { - auto written = std::snprintf(buffer, 64, "%.*e", - std::numeric_limits::max_digits10 - 1, d); - return buffer + written; -} - -void allvalues() { - char buffer[64]; - for (uint64_t w = 0; w <= 0xFFFFFFFF; w++) { - float v; - if ((w % 1048576) == 0) { - std::cout << "."; - std::cout.flush(); - } - uint32_t word = uint32_t(w); - memcpy(&v, &word, sizeof(v)); - - { - const char *string_end = to_string(v, buffer); - float result_value; - auto result = fast_float::from_chars(buffer, string_end, result_value); - if (result.ec != std::errc()) { - std::cerr << "parsing error ? " << buffer << std::endl; - abort(); - } - if (std::isnan(v)) { - if (!std::isnan(result_value)) { - std::cerr << "not nan" << buffer << std::endl; - abort(); - } - } else if(copysign(1,result_value) != copysign(1,v)) { - std::cerr << "I got " << std::hexfloat << result_value << " but I was expecting " << v - << std::endl; - abort(); - } else if (result_value != v) { - std::cerr << "no match ? " << buffer << std::endl; - std::cout << "started with " << std::hexfloat << v << std::endl; - std::cout << "got back " << std::hexfloat << result_value << std::endl; - std::cout << std::dec; - abort(); - } - } - } - std::cout << std::endl; -} - -int main() { - allvalues(); - std::cout << std::endl; - std::cout << "all ok" << std::endl; - return EXIT_SUCCESS; -} diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/exhaustive32_64.cpp b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/exhaustive32_64.cpp deleted file mode 100644 index e02757bd3..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/exhaustive32_64.cpp +++ /dev/null @@ -1,78 +0,0 @@ - -#include "fast_float/fast_float.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -template char *to_string(T d, char *buffer) { - auto written = std::snprintf(buffer, 64, "%.*e", - std::numeric_limits::max_digits10 - 1, d); - return buffer + written; -} - - -bool basic_test_64bit(std::string vals, double val) { - double result_value; - auto result = fast_float::from_chars(vals.data(), vals.data() + vals.size(), - result_value); - if (result.ec != std::errc()) { - std::cerr << " I could not parse " << vals << std::endl; - return false; - } - if (std::isnan(val)) { - if (!std::isnan(result_value)) { - std::cerr << vals << std::endl; - std::cerr << "not nan" << result_value << std::endl; - return false; - } - } else if(copysign(1,result_value) != copysign(1,val)) { - std::cerr << "I got " << std::hexfloat << result_value << " but I was expecting " << val - << std::endl; - return false; - } else if (result_value != val) { - std::cerr << vals << std::endl; - std::cerr << "I got " << std::hexfloat << result_value << " but I was expecting " << val - << std::endl; - std::cerr << std::dec; - std::cerr << "string: " << vals << std::endl; - return false; - } - return true; -} - - -void all_32bit_values() { - char buffer[64]; - for (uint64_t w = 0; w <= 0xFFFFFFFF; w++) { - float v32; - if ((w % 1048576) == 0) { - std::cout << "."; - std::cout.flush(); - } - uint32_t word = uint32_t(w); - memcpy(&v32, &word, sizeof(v32)); - double v = v32; - - { - const char *string_end = to_string(v, buffer); - std::string s(buffer, size_t(string_end-buffer)); - if(!basic_test_64bit(s,v)) { - return; - } - } - } - std::cout << std::endl; -} - -int main() { - all_32bit_values(); - std::cout << std::endl; - std::cout << "all ok" << std::endl; - return EXIT_SUCCESS; -} diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/exhaustive32_midpoint.cpp b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/exhaustive32_midpoint.cpp deleted file mode 100644 index f64f4e481..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/exhaustive32_midpoint.cpp +++ /dev/null @@ -1,148 +0,0 @@ -#include "fast_float/fast_float.h" - -#include -#include -#include -#include -#include -#include -#include - -#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) -// Anything at all that is related to cygwin, msys and so forth will -// always use this fallback because we cannot rely on it behaving as normal -// gcc. -#include -#include -// workaround for CYGWIN -double cygwin_strtod_l(const char* start, char** end) { - double d; - std::stringstream ss; - ss.imbue(std::locale::classic()); - ss << start; - ss >> d; - if(ss.fail()) { *end = nullptr; } - if(ss.eof()) { ss.clear(); } - auto nread = ss.tellg(); - *end = const_cast(start) + nread; - return d; -} -float cygwin_strtof_l(const char* start, char** end) { - float d; - std::stringstream ss; - ss.imbue(std::locale::classic()); - ss << start; - ss >> d; - if(ss.fail()) { *end = nullptr; } - if(ss.eof()) { ss.clear(); } - auto nread = ss.tellg(); - *end = const_cast(start) + nread; - return d; -} -#endif - -template char *to_string(T d, char *buffer) { - auto written = std::snprintf(buffer, 64, "%.*e", - std::numeric_limits::max_digits10 - 1, d); - return buffer + written; -} - -void strtof_from_string(const char * st, float& d) { - char *pr = (char *)st; -#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun) - d = cygwin_strtof_l(st, &pr); -#elif defined(_WIN32) - static _locale_t c_locale = _create_locale(LC_ALL, "C"); - d = _strtof_l(st, &pr, c_locale); -#else - static locale_t c_locale = newlocale(LC_ALL_MASK, "C", NULL); - d = strtof_l(st, &pr, c_locale); -#endif - if (pr == st) { - throw std::runtime_error("bug in strtod_from_string"); - } -} - -bool allvalues() { - char buffer[64]; - for (uint64_t w = 0; w <= 0xFFFFFFFF; w++) { - float v; - if ((w % 1048576) == 0) { - std::cout << "."; - std::cout.flush(); - } - uint32_t word = uint32_t(w); - memcpy(&v, &word, sizeof(v)); - if(std::isfinite(v)) { - float nextf = std::nextafterf(v, INFINITY); - if(copysign(1,v) != copysign(1,nextf)) { continue; } - if(!std::isfinite(nextf)) { continue; } - double v1{v}; - assert(float(v1) == v); - double v2{nextf}; - assert(float(v2) == nextf); - double midv{v1 + (v2 - v1) / 2}; - float expected_midv = float(midv); - - const char *string_end = to_string(midv, buffer); - float str_answer; - strtof_from_string(buffer, str_answer); - - float result_value; - auto result = fast_float::from_chars(buffer, string_end, result_value); - if (result.ec != std::errc()) { - std::cerr << "parsing error ? " << buffer << std::endl; - return false; - } - if (std::isnan(v)) { - if (!std::isnan(result_value)) { - std::cerr << "not nan" << buffer << std::endl; - std::cerr << "v " << std::hexfloat << v << std::endl; - std::cerr << "v2 " << std::hexfloat << v2 << std::endl; - std::cerr << "midv " << std::hexfloat << midv << std::endl; - std::cerr << "expected_midv " << std::hexfloat << expected_midv << std::endl; - return false; - } - } else if(copysign(1,result_value) != copysign(1,v)) { - std::cerr << buffer << std::endl; - std::cerr << "v " << std::hexfloat << v << std::endl; - std::cerr << "v2 " << std::hexfloat << v2 << std::endl; - std::cerr << "midv " << std::hexfloat << midv << std::endl; - std::cerr << "expected_midv " << std::hexfloat << expected_midv << std::endl; - std::cerr << "I got " << std::hexfloat << result_value << " but I was expecting " << v - << std::endl; - return false; - } else if (result_value != str_answer) { - std::cerr << "no match ? " << buffer << std::endl; - std::cerr << "v " << std::hexfloat << v << std::endl; - std::cerr << "v2 " << std::hexfloat << v2 << std::endl; - std::cerr << "midv " << std::hexfloat << midv << std::endl; - std::cerr << "expected_midv " << std::hexfloat << expected_midv << std::endl; - std::cout << "started with " << std::hexfloat << midv << std::endl; - std::cout << "round down to " << std::hexfloat << str_answer << std::endl; - std::cout << "got back " << std::hexfloat << result_value << std::endl; - std::cout << std::dec; - return false; - } - } - } - std::cout << std::endl; - return true; -} - -inline void Assert(bool Assertion) { -#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun) - if (!Assertion) { std::cerr << "Omitting hard falure on msys/cygwin/sun systems."; } -#else - if (!Assertion) { throw std::runtime_error("bug"); } -#endif -} -int main() { -#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun) - std::cout << "Warning: msys/cygwin or solaris detected. This particular test is likely to generate false failures due to our reliance on the underlying runtime library as a gold standard." << std::endl; -#endif - Assert(allvalues()); - std::cout << std::endl; - std::cout << "all ok" << std::endl; - return EXIT_SUCCESS; -} diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/long_exhaustive32.cpp b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/long_exhaustive32.cpp deleted file mode 100644 index 0a6b53d81..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/long_exhaustive32.cpp +++ /dev/null @@ -1,63 +0,0 @@ - -#include "fast_float/fast_float.h" - -#include -#include -#include -#include -#include -#include - -template char *to_string(T d, char *buffer) { - auto written = std::snprintf(buffer, 128, "%.*e", - 64, d); - return buffer + written; -} - -void allvalues() { - char buffer[128]; - for (uint64_t w = 0; w <= 0xFFFFFFFF; w++) { - float v; - if ((w % 1048576) == 0) { - std::cout << "."; - std::cout.flush(); - } - uint32_t word = uint32_t(w); - memcpy(&v, &word, sizeof(v)); - - { - const char *string_end = to_string(v, buffer); - float result_value; - auto result = fast_float::from_chars(buffer, string_end, result_value); - if (result.ec != std::errc()) { - std::cerr << "parsing error ? " << buffer << std::endl; - abort(); - } - if (std::isnan(v)) { - if (!std::isnan(result_value)) { - std::cerr << "not nan" << buffer << std::endl; - abort(); - } - } else if(copysign(1,result_value) != copysign(1,v)) { - std::cerr << buffer << std::endl; - std::cerr << "I got " << std::hexfloat << result_value << " but I was expecting " << v - << std::endl; - abort(); - } else if (result_value != v) { - std::cerr << "no match ? " << buffer << " got " << result_value << " expected " << v << std::endl; - std::cout << "started with " << std::hexfloat << v << std::endl; - std::cout << "got back " << std::hexfloat << result_value << std::endl; - std::cout << std::dec; - abort(); - } - } - } - std::cout << std::endl; -} - -int main() { - allvalues(); - std::cout << std::endl; - std::cout << "all ok" << std::endl; - return EXIT_SUCCESS; -} diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/long_exhaustive32_64.cpp b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/long_exhaustive32_64.cpp deleted file mode 100644 index cea8497f9..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/long_exhaustive32_64.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include "fast_float/fast_float.h" - -#include -#include -#include -#include -#include - -template char *to_string(T d, char *buffer) { - auto written = std::snprintf(buffer, 128, "%.*e", - 64, d); - return buffer + written; -} - -void all_32bit_values() { - char buffer[128]; - for (uint64_t w = 0; w <= 0xFFFFFFFF; w++) { - float v32; - if ((w % 1048576) == 0) { - std::cout << "."; - std::cout.flush(); - } - uint32_t word = uint32_t(w); - memcpy(&v32, &word, sizeof(v32)); - double v = v32; - - { - const char *string_end = to_string(v, buffer); - double result_value; - auto result = fast_float::from_chars(buffer, string_end, result_value); - if (result.ec != std::errc()) { - std::cerr << "parsing error ? " << buffer << std::endl; - abort(); - } - if (std::isnan(v)) { - if (!std::isnan(result_value)) { - std::cerr << "not nan" << buffer << std::endl; - abort(); - } - } else if(copysign(1,result_value) != copysign(1,v)) { - std::cerr << "I got " << std::hexfloat << result_value << " but I was expecting " << v - << std::endl; - abort(); - } else if (std::isnan(v)) { - if (!std::isnan(result_value)) { - std::cerr << "not nan" << buffer << std::endl; - abort(); - } - } else if (result_value != v) { - std::cerr << "no match ? " << buffer << std::endl; - std::cout << "started with " << std::hexfloat << v << std::endl; - std::cout << "got back " << std::hexfloat << result_value << std::endl; - std::cout << std::dec; - abort(); - } - } - } - std::cout << std::endl; -} - -int main() { - all_32bit_values(); - std::cout << std::endl; - std::cout << "all ok" << std::endl; - return EXIT_SUCCESS; -} diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/long_random64.cpp b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/long_random64.cpp deleted file mode 100644 index a6680e82c..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/long_random64.cpp +++ /dev/null @@ -1,106 +0,0 @@ -#include "fast_float/fast_float.h" - -#include -#include -#include -#include -#include -#include - -template char *to_string(T d, char *buffer) { - auto written = std::snprintf(buffer, 128, "%.*e", - 64, d); - return buffer + written; -} - -static fast_float::value128 g_lehmer64_state; - -/** - * D. H. Lehmer, Mathematical methods in large-scale computing units. - * Proceedings of a Second Symposium on Large Scale Digital Calculating - * Machinery; - * Annals of the Computation Laboratory, Harvard Univ. 26 (1951), pp. 141-146. - * - * P L'Ecuyer, Tables of linear congruential generators of different sizes and - * good lattice structure. Mathematics of Computation of the American - * Mathematical - * Society 68.225 (1999): 249-260. - */ - -static inline void lehmer64_seed(uint64_t seed) { - g_lehmer64_state.high = 0; - g_lehmer64_state.low = seed; -} - -static inline uint64_t lehmer64() { - fast_float::value128 v = fast_float::full_multiplication(g_lehmer64_state.low,UINT64_C(0xda942042e4dd58b5)); - v.high += g_lehmer64_state.high * UINT64_C(0xda942042e4dd58b5); - g_lehmer64_state = v; - return v.high; -} - -size_t errors; - -void random_values(size_t N) { - char buffer[128]; - lehmer64_seed(N); - for (size_t t = 0; t < N; t++) { - if ((t % 1048576) == 0) { - std::cout << "."; - std::cout.flush(); - } - uint64_t word = lehmer64(); - double v; - memcpy(&v, &word, sizeof(v)); - { - const char *string_end = to_string(v, buffer); - double result_value; - auto result = fast_float::from_chars(buffer, string_end, result_value); - if (result.ec != std::errc()) { - std::cerr << "parsing error ? " << buffer << std::endl; - errors++; - if (errors > 10) { - abort(); - } - } - if (std::isnan(v)) { - if (!std::isnan(result_value)) { - std::cerr << "not nan" << buffer << std::endl; - errors++; - if (errors > 10) { - abort(); - } - } - } else if(copysign(1,result_value) != copysign(1,v)) { - std::cerr << buffer << std::endl; - std::cerr << "I got " << std::hexfloat << result_value << " but I was expecting " << v - << std::endl; - abort(); - } else if (result_value != v) { - std::cerr << "no match ? '" << buffer << "'" << std::endl; - std::cout << "started with " << std::hexfloat << v << std::endl; - std::cout << "got back " << std::hexfloat << result_value << std::endl; - std::cout << std::dec; - errors++; - if (errors > 10) { - abort(); - } - } - } - } - std::cout << std::endl; -} - -int main() { - errors = 0; - size_t N = size_t(1) << (sizeof(size_t) * 4); // shift: 32 for 64bit, 16 for 32bit - random_values(N); - if (errors == 0) { - std::cout << std::endl; - std::cout << "all ok" << std::endl; - return EXIT_SUCCESS; - } - std::cerr << std::endl; - std::cerr << "errors were encountered" << std::endl; - return EXIT_FAILURE; -} diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/long_test.cpp b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/long_test.cpp deleted file mode 100644 index 36b92104e..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/long_test.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include "fast_float/fast_float.h" - -#include -#include -#include -#include -#include -#include - -inline void Assert(bool Assertion) { - if (!Assertion) { throw std::runtime_error("bug"); } -} - -template -bool test() { - std::string input = "0.156250000000000000000000000000000000000000 3.14159265358979323846264338327950288419716939937510 2.71828182845904523536028747135266249775724709369995"; - std::vector answers = {T(0.15625), T(3.141592653589793), T(2.718281828459045)}; - const char * begin = input.data(); - const char * end = input.data() + input.size(); - for(size_t i = 0; i < answers.size(); i++) { - T result_value; - while((begin < end) && (std::isspace(*begin))) { begin++; } - auto result = fast_float::from_chars(begin, end, - result_value); - if (result.ec != std::errc()) { - printf("parsing %.*s\n", int(end - begin), begin); - std::cerr << " I could not parse " << std::endl; - return false; - } - if(result_value != answers[i]) { - printf("parsing %.*s\n", int(end - begin), begin); - std::cerr << " Mismatch " << std::endl; - std::cerr << " Expected " << answers[i] << std::endl; - std::cerr << " Got " << result_value << std::endl; - - return false; - - } - begin = result.ptr; - } - if(begin != end) { - std::cerr << " bad ending " << std::endl; - return false; - } - return true; -} - -int main() { - - std::cout << "32 bits checks" << std::endl; - Assert(test()); - - std::cout << "64 bits checks" << std::endl; - Assert(test()); - - std::cout << "All ok" << std::endl; - return EXIT_SUCCESS; -} diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/powersoffive_hardround.cpp b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/powersoffive_hardround.cpp deleted file mode 100644 index 09b95bd59..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/powersoffive_hardround.cpp +++ /dev/null @@ -1,134 +0,0 @@ -#include "fast_float/fast_float.h" - -#include -#include -#include -#include -#include -#include -#include -#include - - -#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun) -// Anything at all that is related to cygwin, msys and so forth will -// always use this fallback because we cannot rely on it behaving as normal -// gcc. -#include -// workaround for CYGWIN -double cygwin_strtod_l(const char* start, char** end) { - double d; - std::stringstream ss; - ss.imbue(std::locale::classic()); - ss << start; - ss >> d; - if(ss.fail()) { *end = nullptr; } - if(ss.eof()) { ss.clear(); } - auto nread = ss.tellg(); - *end = const_cast(start) + nread; - return d; -} -float cygwin_strtof_l(const char* start, char** end) { - float d; - std::stringstream ss; - ss.imbue(std::locale::classic()); - ss << start; - ss >> d; - if(ss.fail()) { *end = nullptr; } - if(ss.eof()) { ss.clear(); } - auto nread = ss.tellg(); - *end = const_cast(start) + nread; - return d; -} -#endif - - -std::pair strtod_from_string(const char *st) { - double d; - char *pr; -#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun) - d = cygwin_strtod_l(st, &pr); -#elif defined(_WIN32) - static _locale_t c_locale = _create_locale(LC_ALL, "C"); - d = _strtod_l(st, &pr, c_locale); -#else - static locale_t c_locale = newlocale(LC_ALL_MASK, "C", NULL); - d = strtod_l(st, &pr, c_locale); -#endif - if (st == pr) { - std::cerr << "strtod_l could not parse '" << st << std::endl; - return std::make_pair(0, false); - } - return std::make_pair(d, true); -} - -std::pair strtof_from_string(char *st) { - float d; - char *pr; -#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun) - d = cygwin_strtof_l(st, &pr); -#elif defined(_WIN32) - static _locale_t c_locale = _create_locale(LC_ALL, "C"); - d = _strtof_l(st, &pr, c_locale); -#else - static locale_t c_locale = newlocale(LC_ALL_MASK, "C", NULL); - d = strtof_l(st, &pr, c_locale); -#endif - if (st == pr) { - std::cerr << "strtof_l could not parse '" << st << std::endl; - return std::make_pair(0.0f, false); - } - return std::make_pair(d, true); -} - -bool tester() { - std::random_device rd; - std::mt19937 gen(rd()); - for (int q = 18; q <= 27; q++) { - std::cout << "q = " << -q << std::endl; - uint64_t power5 = 1; - for (int k = 0; k < q; k++) { - power5 *= 5; - } - uint64_t low_threshold = 0x20000000000000 / power5 + 1; - uint64_t threshold = 0xFFFFFFFFFFFFFFFF / power5; - std::uniform_int_distribution dis(low_threshold, threshold); - for (size_t i = 0; i < 10000; i++) { - uint64_t mantissa = dis(gen) * power5; - std::stringstream ss; - ss << mantissa; - ss << "e"; - ss << -q; - std::string to_be_parsed = ss.str(); - std::pair expected_double = - strtod_from_string(to_be_parsed.c_str()); - double result_value; - auto result = - fast_float::from_chars(to_be_parsed.data(), to_be_parsed.data() + to_be_parsed.size(), result_value); - if (result.ec != std::errc()) { - std::cout << to_be_parsed << std::endl; - std::cerr << " I could not parse " << std::endl; - return false; - } - if (result_value != expected_double.first) { - std::cout << to_be_parsed << std::endl; - std::cerr << std::hexfloat << result_value << std::endl; - std::cerr << std::hexfloat << expected_double.first << std::endl; - std::cerr << " Mismatch " << std::endl; - return false; - } - } - } - return true; -} - -int main() { - if (tester()) { - std::cout << std::endl; - std::cout << "all ok" << std::endl; - return EXIT_SUCCESS; - } - std::cerr << std::endl; - std::cerr << "errors were encountered" << std::endl; - return EXIT_FAILURE; -} diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/random64.cpp b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/random64.cpp deleted file mode 100644 index 0775993a4..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/random64.cpp +++ /dev/null @@ -1,109 +0,0 @@ -#include "fast_float/fast_float.h" - -#include -#include -#include -#include -#include -#include -#include - -template char *to_string(T d, char *buffer) { - auto written = std::snprintf(buffer, 64, "%.*e", - std::numeric_limits::max_digits10 - 1, d); - return buffer + written; -} - - -static fast_float::value128 g_lehmer64_state; - -/** - * D. H. Lehmer, Mathematical methods in large-scale computing units. - * Proceedings of a Second Symposium on Large Scale Digital Calculating - * Machinery; - * Annals of the Computation Laboratory, Harvard Univ. 26 (1951), pp. 141-146. - * - * P L'Ecuyer, Tables of linear congruential generators of different sizes and - * good lattice structure. Mathematics of Computation of the American - * Mathematical - * Society 68.225 (1999): 249-260. - */ - -static inline void lehmer64_seed(uint64_t seed) { - g_lehmer64_state.high = 0; - g_lehmer64_state.low = seed; -} - -static inline uint64_t lehmer64() { - fast_float::value128 v = fast_float::full_multiplication(g_lehmer64_state.low,UINT64_C(0xda942042e4dd58b5)); - v.high += g_lehmer64_state.high * UINT64_C(0xda942042e4dd58b5); - g_lehmer64_state = v; - return v.high; -} - -size_t errors; - -void random_values(size_t N) { - char buffer[64]; - lehmer64_seed(N); - for (size_t t = 0; t < N; t++) { - if ((t % 1048576) == 0) { - std::cout << "."; - std::cout.flush(); - } - uint64_t word = lehmer64(); - double v; - memcpy(&v, &word, sizeof(v)); - // if (!std::isnormal(v)) - { - const char *string_end = to_string(v, buffer); - double result_value; - auto result = fast_float::from_chars(buffer, string_end, result_value); - if (result.ec != std::errc()) { - std::cerr << "parsing error ? " << buffer << std::endl; - errors++; - if (errors > 10) { - abort(); - } - } - if (std::isnan(v)) { - if (!std::isnan(result_value)) { - std::cerr << "not nan" << buffer << std::endl; - errors++; - if (errors > 10) { - abort(); - } - } - } else if(copysign(1,result_value) != copysign(1,v)) { - std::cerr << buffer << std::endl; - std::cerr << "I got " << std::hexfloat << result_value << " but I was expecting " << v - << std::endl; - abort(); - } else if (result_value != v) { - std::cerr << "no match ? " << buffer << std::endl; - std::cout << "started with " << std::hexfloat << v << std::endl; - std::cout << "got back " << std::hexfloat << result_value << std::endl; - std::cout << std::dec; - errors++; - if (errors > 10) { - abort(); - } - } - } - } - std::cout << std::endl; -} - -int main() { - errors = 0; - size_t N = size_t(1) << (sizeof(size_t) * 4); // shift: 32 for 64bit, 16 for 32bit - random_values(N); - if (errors == 0) { - std::cout << std::endl; - std::cout << "all ok" << std::endl; - return EXIT_SUCCESS; - } - std::cerr << std::endl; - std::cerr << "errors were encountered" << std::endl; - return EXIT_FAILURE; -} diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/random_string.cpp b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/random_string.cpp deleted file mode 100644 index 8cabf5f4d..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/random_string.cpp +++ /dev/null @@ -1,240 +0,0 @@ -#include "fast_float/fast_float.h" - -#include -#include -#include -#include -#include -#include - -#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun) -// Anything at all that is related to cygwin, msys and so forth will -// always use this fallback because we cannot rely on it behaving as normal -// gcc. -#include -#include -// workaround for CYGWIN -double cygwin_strtod_l(const char* start, char** end) { - double d; - std::stringstream ss; - ss.imbue(std::locale::classic()); - ss << start; - ss >> d; - if(ss.fail()) { *end = nullptr; } - if(ss.eof()) { ss.clear(); } - auto nread = ss.tellg(); - *end = const_cast(start) + nread; - return d; -} -float cygwin_strtof_l(const char* start, char** end) { - float d; - std::stringstream ss; - ss.imbue(std::locale::classic()); - ss << start; - ss >> d; - if(ss.fail()) { *end = nullptr; } - if(ss.eof()) { ss.clear(); } - auto nread = ss.tellg(); - *end = const_cast(start) + nread; - return d; -} -#endif - -class RandomEngine { -public: - RandomEngine() = delete; - RandomEngine(uint64_t new_seed) : wyhash64_x_(new_seed) {}; - uint64_t next() { - // Adapted from https://github.com/wangyi-fudan/wyhash/blob/master/wyhash.h - // Inspired from - // https://github.com/lemire/testingRNG/blob/master/source/wyhash.h - wyhash64_x_ += UINT64_C(0x60bee2bee120fc15); - fast_float::value128 tmp = fast_float::full_multiplication(wyhash64_x_, UINT64_C(0xa3b195354a39b70d)); - uint64_t m1 = (tmp.high) ^ tmp.low; - tmp = fast_float::full_multiplication(m1, UINT64_C(0x1b03738712fad5c9)); - uint64_t m2 = (tmp.high) ^ tmp.low; - return m2; - } - bool next_bool() { return (next() & 1) == 1; } - int next_int() { return static_cast(next()); } - char next_char() { return static_cast(next()); } - double next_double() { return static_cast(next()); } - - int next_ranged_int(int min, int max) { // min and max are included - // Adapted from - // https://lemire.me/blog/2019/06/06/nearly-divisionless-random-integer-generation-on-various-systems/ - /* if (min == max) { - return min; - }*/ - uint64_t s = uint64_t(max - min + 1); - uint64_t x = next(); - fast_float::value128 m = fast_float::full_multiplication(x, s); - uint64_t l = m.low; - if (l < s) { - uint64_t t = -s % s; - while (l < t) { - x = next(); - m = fast_float::full_multiplication(x, s); - l = m.low; - } - } - return int(m.high) + min; - } - int next_digit() { return next_ranged_int(0, 9); } - -private: - uint64_t wyhash64_x_; -}; - -size_t build_random_string(RandomEngine &rand, char *buffer) { - size_t pos{0}; - if (rand.next_bool()) { - buffer[pos++] = '-'; - } - int number_of_digits = rand.next_ranged_int(1, 100); - if(number_of_digits == 100) { - // With low probability, we want to allow very long strings just to stress the system. - number_of_digits = rand.next_ranged_int(1, 2000); - } - int location_of_decimal_separator = rand.next_ranged_int(1, number_of_digits); - for (size_t i = 0; i < size_t(number_of_digits); i++) { - if (i == size_t(location_of_decimal_separator)) { - buffer[pos++] = '.'; - } - buffer[pos++] = char(rand.next_digit() + '0'); - } - if (rand.next_bool()) { - if (rand.next_bool()) { - buffer[pos++] = 'e'; - } else { - buffer[pos++] = 'E'; - } - if (rand.next_bool()) { - buffer[pos++] = '-'; - } else { - if (rand.next_bool()) { - buffer[pos++] = '+'; - } - } - number_of_digits = rand.next_ranged_int(1, 3); - for (size_t i = 0; i < size_t(number_of_digits); i++) { - buffer[pos++] = char(rand.next_digit() + '0'); - } - } - buffer[pos] = '\0'; // null termination - return pos; -} - -std::pair strtod_from_string(char *st) { - double d; - char *pr; -#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun) - d = cygwin_strtod_l(st, &pr); -#elif defined(_WIN32) - static _locale_t c_locale = _create_locale(LC_ALL, "C"); - d = _strtod_l(st, &pr, c_locale); -#else - static locale_t c_locale = newlocale(LC_ALL_MASK, "C", NULL); - d = strtod_l(st, &pr, c_locale); -#endif - if (st == pr) { - std::cerr << "strtod_l could not parse '" << st << std::endl; - return std::make_pair(0, false); - } - return std::make_pair(d, true); -} - -std::pair strtof_from_string(char *st) { - float d; - char *pr; -#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun) - d = cygwin_strtof_l(st, &pr); -#elif defined(_WIN32) - static _locale_t c_locale = _create_locale(LC_ALL, "C"); - d = _strtof_l(st, &pr, c_locale); -#else - static locale_t c_locale = newlocale(LC_ALL_MASK, "C", NULL); - d = strtof_l(st, &pr, c_locale); -#endif - if (st == pr) { - std::cerr << "strtof_l could not parse '" << st << std::endl; - return std::make_pair(0.0f, false); - } - return std::make_pair(d, true); -} - -/** - * We generate random strings and we try to parse them with both strtod/strtof, - * and we verify that we get the same answer with with fast_float::from_chars. - */ -bool tester(uint64_t seed, size_t volume) { - char buffer[4096]; // large buffer (can't overflow) - RandomEngine rand(seed); - for (size_t i = 0; i < volume; i++) { - if((i%100000) == 0) { std::cout << "."; std::cout.flush(); } - size_t length = build_random_string(rand, buffer); - std::pair expected_double = strtod_from_string(buffer); - if (expected_double.second) { - double result_value; - auto result = - fast_float::from_chars(buffer, buffer + length, result_value); - if (result.ec != std::errc()) { - printf("parsing %.*s\n", int(length), buffer); - std::cerr << " I could not parse " << std::endl; - return false; - } - if (result.ptr != buffer + length) { - printf("parsing %.*s\n", int(length), buffer); - std::cerr << " Did not get to the end " << std::endl; - return false; - } - if (result_value != expected_double.first) { - printf("parsing %.*s\n", int(length), buffer); - std::cerr << std::hexfloat << result_value << std::endl; - std::cerr << std::hexfloat << expected_double.first << std::endl; - std::cerr << " Mismatch " << std::endl; - return false; - } - } - std::pair expected_float = strtof_from_string(buffer); - if (expected_float.second) { - float result_value; - auto result = - fast_float::from_chars(buffer, buffer + length, result_value); - if (result.ec != std::errc()) { - printf("parsing %.*s\n", int(length), buffer); - std::cerr << " I could not parse " << std::endl; - return false; - } - if (result.ptr != buffer + length) { - printf("parsing %.*s\n", int(length), buffer); - std::cerr << " Did not get to the end " << std::endl; - return false; - } - if (result_value != expected_float.first) { - printf("parsing %.*s\n", int(length), buffer); - std::cerr << std::hexfloat << result_value << std::endl; - std::cerr << std::hexfloat << expected_float.first << std::endl; - std::cerr << " Mismatch " << std::endl; - return false; - } - } - } - return true; -} - -int main() { - -#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun) - std::cout << "Warning: msys/cygwin or solaris detected." << std::endl; - return EXIT_SUCCESS; -#else - if (tester(1234344, 100000000)) { - std::cout << "All tests ok." << std::endl; - return EXIT_SUCCESS; - } - std::cout << "Failure." << std::endl; - return EXIT_FAILURE; - -#endif -} diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/short_random_string.cpp b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/short_random_string.cpp deleted file mode 100644 index 3051b749d..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/short_random_string.cpp +++ /dev/null @@ -1,234 +0,0 @@ -#include "fast_float/fast_float.h" - -#include -#include -#include -#include -#include -#include - -#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun) -// Anything at all that is related to cygwin, msys and so forth will -// always use this fallback because we cannot rely on it behaving as normal -// gcc. -#include -#include -// workaround for CYGWIN -double cygwin_strtod_l(const char* start, char** end) { - double d; - std::stringstream ss; - ss.imbue(std::locale::classic()); - ss << start; - ss >> d; - if(ss.fail()) { *end = nullptr; } - if(ss.eof()) { ss.clear(); } - auto nread = ss.tellg(); - *end = const_cast(start) + nread; - return d; -} -float cygwin_strtof_l(const char* start, char** end) { - float d; - std::stringstream ss; - ss.imbue(std::locale::classic()); - ss << start; - ss >> d; - if(ss.fail()) { *end = nullptr; } - if(ss.eof()) { ss.clear(); } - auto nread = ss.tellg(); - *end = const_cast(start) + nread; - return d; -} -#endif - -class RandomEngine { -public: - RandomEngine() = delete; - RandomEngine(uint64_t new_seed) : wyhash64_x_(new_seed) { }; - uint64_t next() { - // Adapted from https://github.com/wangyi-fudan/wyhash/blob/master/wyhash.h - // Inspired from - // https://github.com/lemire/testingRNG/blob/master/source/wyhash.h - wyhash64_x_ += UINT64_C(0x60bee2bee120fc15); - fast_float::value128 tmp = fast_float::full_multiplication(wyhash64_x_, UINT64_C(0xa3b195354a39b70d)); - uint64_t m1 = (tmp.high) ^ tmp.low; - tmp = fast_float::full_multiplication(m1, UINT64_C(0x1b03738712fad5c9)); - uint64_t m2 = (tmp.high) ^ tmp.low; - return m2; - } - bool next_bool() { return (next() & 1) == 1; } - int next_int() { return static_cast(next()); } - char next_char() { return static_cast(next()); } - double next_double() { return static_cast(next()); } - - int next_ranged_int(int min, int max) { // min and max are included - // Adapted from - // https://lemire.me/blog/2019/06/06/nearly-divisionless-random-integer-generation-on-various-systems/ - /* if (min == max) { - return min; - }*/ - uint64_t s = uint64_t(max - min + 1); - uint64_t x = next(); - fast_float::value128 m = fast_float::full_multiplication(x, s); - uint64_t l = m.low; - if (l < s) { - uint64_t t = -s % s; - while (l < t) { - x = next(); - m = fast_float::full_multiplication(x, s); - l = m.low; - } - } - return int(m.high) + min; - } - int next_digit() { return next_ranged_int(0, 9); } - -private: - uint64_t wyhash64_x_; -}; - -size_t build_random_string(RandomEngine &rand, char *buffer) { - size_t pos{0}; - if (rand.next_bool()) { - buffer[pos++] = '-'; - } - int number_of_digits = rand.next_ranged_int(1, 19); - int location_of_decimal_separator = rand.next_ranged_int(1, number_of_digits); - for (size_t i = 0; i < size_t(number_of_digits); i++) { - if (i == size_t(location_of_decimal_separator)) { - buffer[pos++] = '.'; - } - buffer[pos++] = char(rand.next_digit() + '0'); - } - if (rand.next_bool()) { - if (rand.next_bool()) { - buffer[pos++] = 'e'; - } else { - buffer[pos++] = 'E'; - } - if (rand.next_bool()) { - buffer[pos++] = '-'; - } else { - if (rand.next_bool()) { - buffer[pos++] = '+'; - } - } - number_of_digits = rand.next_ranged_int(1, 3); - for (size_t i = 0; i < size_t(number_of_digits); i++) { - buffer[pos++] = char(rand.next_digit() + '0'); - } - } - buffer[pos] = '\0'; // null termination - return pos; -} - -std::pair strtod_from_string(char *st) { - double d; - char *pr; -#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun) - d = cygwin_strtod_l(st, &pr); -#elif defined(_WIN32) - static _locale_t c_locale = _create_locale(LC_ALL, "C"); - d = _strtod_l(st, &pr, c_locale); -#else - static locale_t c_locale = newlocale(LC_ALL_MASK, "C", NULL); - d = strtod_l(st, &pr, c_locale); -#endif - if (st == pr) { - std::cerr << "strtod_l could not parse '" << st << std::endl; - return std::make_pair(0, false); - } - return std::make_pair(d, true); -} - -std::pair strtof_from_string(char *st) { - float d; - char *pr; -#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun) - d = cygwin_strtof_l(st, &pr); -#elif defined(_WIN32) - static _locale_t c_locale = _create_locale(LC_ALL, "C"); - d = _strtof_l(st, &pr, c_locale); -#else - static locale_t c_locale = newlocale(LC_ALL_MASK, "C", NULL); - d = strtof_l(st, &pr, c_locale); -#endif - if (st == pr) { - std::cerr << "strtof_l could not parse '" << st << std::endl; - return std::make_pair(0.0f, false); - } - return std::make_pair(d, true); -} - -/** - * We generate random strings and we try to parse them with both strtod/strtof, - * and we verify that we get the same answer with with fast_float::from_chars. - */ -bool tester(uint64_t seed, size_t volume) { - char buffer[4096]; // large buffer (can't overflow) - RandomEngine rand(seed); - for (size_t i = 0; i < volume; i++) { - if((i%1000000) == 0) { std::cout << "."; std::cout.flush(); } - size_t length = build_random_string(rand, buffer); - std::pair expected_double = strtod_from_string(buffer); - if (expected_double.second) { - double result_value; - auto result = - fast_float::from_chars(buffer, buffer + length, result_value); - if (result.ec != std::errc()) { - printf("parsing %.*s\n", int(length), buffer); - std::cerr << " I could not parse " << std::endl; - return false; - } - if (result.ptr != buffer + length) { - printf("parsing %.*s\n", int(length), buffer); - std::cerr << " Did not get to the end " << std::endl; - return false; - } - if (result_value != expected_double.first) { - printf("parsing %.*s\n", int(length), buffer); - std::cerr << std::hexfloat << result_value << std::endl; - std::cerr << std::hexfloat << expected_double.first << std::endl; - std::cerr << " Mismatch " << std::endl; - return false; - } - } - std::pair expected_float = strtof_from_string(buffer); - if (expected_float.second) { - float result_value; - auto result = - fast_float::from_chars(buffer, buffer + length, result_value); - if (result.ec != std::errc()) { - printf("parsing %.*s\n", int(length), buffer); - std::cerr << " I could not parse " << std::endl; - return false; - } - if (result.ptr != buffer + length) { - printf("parsing %.*s\n", int(length), buffer); - std::cerr << " Did not get to the end " << std::endl; - return false; - } - if (result_value != expected_float.first) { - printf("parsing %.*s\n", int(length), buffer); - std::cerr << std::hexfloat << result_value << std::endl; - std::cerr << std::hexfloat << expected_float.first << std::endl; - std::cerr << " Mismatch " << std::endl; - return false; - } - } - } - return true; -} - -int main() { -#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun) - std::cout << "Warning: msys/cygwin detected. This particular test is likely to generate false failures due to our reliance on the underlying runtime library." << std::endl; - return EXIT_SUCCESS; -#else - if (tester(1234344, 100000000)) { - std::cout << "All tests ok." << std::endl; - return EXIT_SUCCESS; - } - return EXIT_FAILURE; - -#endif -} diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/string_test.cpp b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/string_test.cpp deleted file mode 100644 index 05871dbe3..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float/tests/string_test.cpp +++ /dev/null @@ -1,279 +0,0 @@ -#include "fast_float/fast_float.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun) -// Anything at all that is related to cygwin, msys and so forth will -// always use this fallback because we cannot rely on it behaving as normal -// gcc. -#include -#include -// workaround for CYGWIN -double cygwin_strtod_l(const char* start, char** end) { - double d; - std::stringstream ss; - ss.imbue(std::locale::classic()); - ss << start; - ss >> d; - if(ss.fail()) { *end = nullptr; } - if(ss.eof()) { ss.clear(); } - auto nread = ss.tellg(); - *end = const_cast(start) + nread; - return d; -} -float cygwin_strtof_l(const char* start, char** end) { - float d; - std::stringstream ss; - ss.imbue(std::locale::classic()); - ss << start; - ss >> d; - if(ss.fail()) { *end = nullptr; } - if(ss.eof()) { ss.clear(); } - auto nread = ss.tellg(); - *end = const_cast(start) + nread; - return d; -} -#endif - -inline void Assert(bool Assertion) { -#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun) - if (!Assertion) { std::cerr << "Omitting hard falure on msys/cygwin/sun systems."; } -#else - if (!Assertion) { throw std::runtime_error("bug"); } -#endif -} - -template std::string to_string(T d) { - std::string s(64, '\0'); - auto written = std::snprintf(&s[0], s.size(), "%.*e", - std::numeric_limits::max_digits10 - 1, d); - s.resize(size_t(written)); - return s; -} - -template -bool test() { - std::string input = "0.1 1e1000 100000 3.14159265359 -1e-500 001 1e01 1e0000001 -inf"; - std::vector answers = {T(0.1), std::numeric_limits::infinity(), 100000, T(3.14159265359), -0.0, 1, 10, 10, -std::numeric_limits::infinity()}; - const char * begin = input.data(); - const char * end = input.data() + input.size(); - for(size_t i = 0; i < answers.size(); i++) { - T result_value; - while((begin < end) && (std::isspace(*begin))) { begin++; } - auto result = fast_float::from_chars(begin, end, - result_value); - if (result.ec != std::errc()) { - printf("parsing %.*s\n", int(end - begin), begin); - std::cerr << " I could not parse " << std::endl; - return false; - } - if(result_value != answers[i]) { - printf("parsing %.*s\n", int(end - begin), begin); - std::cerr << " Mismatch " << std::endl; - return false; - - } - begin = result.ptr; - } - if(begin != end) { - std::cerr << " bad ending " << std::endl; - return false; - } - return true; -} - -template -void strtod_from_string(const std::string &st, T& d); - -template <> -void strtod_from_string(const std::string &st, double& d) { - char *pr = (char *)st.c_str(); -#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun) - d = cygwin_strtod_l(pr, &pr); -#elif defined(_WIN32) - static _locale_t c_locale = _create_locale(LC_ALL, "C"); - d = _strtod_l(st.c_str(), &pr, c_locale); -#else - static locale_t c_locale = newlocale(LC_ALL_MASK, "C", NULL); - d = strtod_l(st.c_str(), &pr, c_locale); -#endif - if (pr == st.c_str()) { - throw std::runtime_error("bug in strtod_from_string"); - } -} - -template <> -void strtod_from_string(const std::string &st, float& d) { - char *pr = (char *)st.c_str(); -#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun) - d = cygwin_strtof_l(st.c_str(), &pr); -#elif defined(_WIN32) - static _locale_t c_locale = _create_locale(LC_ALL, "C"); - d = _strtof_l(st.c_str(), &pr, c_locale); -#else - static locale_t c_locale = newlocale(LC_ALL_MASK, "C", NULL); - d = strtof_l(st.c_str(), &pr, c_locale); -#endif - if (pr == st.c_str()) { - throw std::runtime_error("bug in strtod_from_string"); - } -} - -template -bool partow_test() { - // credit: https://github.com/ArashPartow/strtk/blob/master/strtk_tokenizer_cmp.cpp#L568 - // MIT license - const std::string strint_list[] = { "9007199254740993", "9007199254740994", "9007199254740995" , - "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", - "917049", "4931205", "6768064", "6884243", "5647132", "7371203", "-8629878", "4941840", "4543268", "1075600", - "290", "823", "111", "715", "-866", "367", "666", "-706", "850", "-161", - "9922547", "6960207", "1883152", "2300759", "-279294", "4187292", "3699841", "8386395", "-1441129", "-887892", - "-635422", "9742573", "2326186", "-5903851", "5648486", "3057647", "2980079", "2957468", "7929158", "1925615", - "879", "130", "292", "705", "817", "446", "576", "750", "523", "-527", - "4365041", "5624958", "8990205", "2652177", "3993588", "-298316", "2901599", "3887387", "-5202979", "1196268", - "5968501", "7619928", "3565643", "1885272", "-749485", "2961381", "2982579", "2387454", "4250081", "5958205", - "00000", "00001", "00002", "00003", "00004", "00005", "00006", "00007", "00008", "00009", - "4907034", "2592882", "3269234", "549815", "6256292", "9721039", "-595225", "5587491", "4596297", "-3885009", - "673", "-899", "174", "354", "870", "147", "898", "-510", "369", "859", - "6518423", "5149762", "8834164", "-8085586", "3233120", "8166948", "4172345", "6735549", "-934295", "9481935", - "-430406", "6932717", "4087292", "4047263", "3236400", "-3863050", "4312079", "6956261", "5689446", "3871332", - "535", "691", "326", "-409", "704", "-568", "301", "951", "121", "384", - "4969414", "9378599", "7971781", "5380630", "5001363", "1715827", "6044615", "9118925", "9956168", "-8865496", - "5962464", "7408980", "6646513", "-634564", "4188330", "9805948", "5625691", "7641113", "-4212929", "7802447", - "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", - "2174248", "7449361", "9896659", "-25961", "1706598", "2412368", "-4617035", "6314554", "2225957", "7521434", - "-9530566", "3914164", "2394759", "7157744", "9919392", "6406949", "-744004", "9899789", "8380325", "-1416284", - "3402833", "2150043", "5191009", "8979538", "9565778", "3750211", "7304823", "2829359", "6544236", "-615740", - "363", "-627", "129", "656", "135", "113", "381", "646", "198", "38", - "8060564", "-176752", "1184717", "-666343", "-1273292", "-485827", "6241066", "6579411", "8093119", "7481306", - "-4924485", "7467889", "9813178", "7927100", "3614859", "7293354", "9232973", "4323115", "1133911", "9511638", - "4443188", "2289448", "5639726", "9073898", "8540394", "5389992", "1397726", "-589230", "1017086", "1852330", - "-840", "267", "201", "533", "-675", "494", "315", "706", "-920", "784", - "9097353", "6002251", "-308780", "-3830169", "4340467", "2235284", "3314444", "1085967", "4152107", "5431117", - "-0000", "-0001", "-0002", "-0003", "-0004", "-0005", "-0006", "-0007", "-0008", "-0009", - "-444999", "2136400", "6925907", "6990614", "3588271", "8422028", "-4034772", "5804039", "-6740545", "9381873", - "-924923", "1652367", "2302616", "6776663", "2567821", "-248935", "2587688", "7076742", "-6461467", "1562896", - "-768116", "2338768", "9887307", "9992184", "2045182", "2797589", "9784597", "9696554", "5113329", "1067216", - "-76247763", "58169007", "29408062", "85342511", "42092201", "-95817703", "-1912517", "-26275135", "54656606", "-58188878", - "473", "74", "374", "-64", "266", "715", "937", "-249", "249", "780", - "3907360", "-23063423", "59062754", "83711047", "-95221044", "34894840", "-38562139", "-82018330", "14226223", "-10799717", - "8529722", "88961903", "25608618", "-39988247", "33228241", "38598533", "21161480", "-33723784", "8873948", "96505557", - "-47385048", "-79413272", "-85904404", "87791158", "49194195", "13051222", "57773302", "31904423", "3142966", "27846156", - "7420011", "-72376922", "-68873971", "23765361", "4040725", "-22359806", "85777219", "10099223", "-90364256", "-40158172", - "-7948696", "-64344821", "34404238", "84037448", "-85084788", "-42078409", "-56550310", "96898389", "-595829", "-73166703", - "-0", "-1", "-2", "-3", "-4", "-5", "-6", "-7", "-8", "-9", - "2147483647", "31", "2147483610", "33", "2147483573", "37", "2147483536", - "-82838342", "64441808", "43641062", "-64419642", "-44421934", "75232413", "-75773725", "-89139509", "12812089", "-97633526", - "36090916", "-57706234", "17804655", "4189936", "-4100124", "38803710", "-39735126", "-62397437", "75801648", "51302332", - "73433906", "13015224", "-12624818", "91360377", "11576319", "-54467535", "8892431", "36319780", "38832042", "50172572", - "-317", "109", "-888", "302", "-463", "716", "916", "665", "826", "513", - "42423473", "41078812", "40445652", "-76722281", "95092224", "12075234", "-4045888", "-74396490", "-57304222", "-21726885", - "92038121", "-31899682", "21589254", "-30260046", "56000244", "69686659", "93327838", "96882881", "-91419389", "77529147", - "43288506", "1192435", "-74095920", "76756590", "-31184683", "-35716724", "9451980", "-63168350", "62864002", "26283194", - "37188395", "29151634", "99343471", "-69450330", "-55680090", "-64957599", "47577948", "47107924", "2490477", "48633003", - "-82740809", "-24122215", "67301713", "-63649610", "75499016", "82746620", "17052193", "4602244", "-32721165", "20837836", - "674", "467", "706", "889", "172", "282", "-795", "188", "87", "153", - "64501793", "53146328", "5152287", "-9674493", "68105580", "57245637", "39740229", "-74071854", "86777268", "86484437", - "-86962508", "12644427", "-62944073", "59539680", "43340539", "30661534", "20143968", "-68183731", "-48250926", "42669063", - "000", "001", "002", "003", "004", "005", "006", "007", "008", "009", - "2147483499", "71", "2147483462", "73", "2147483425", "77", "2147483388", - "87736852", "-4444906", "-48094147", "54774735", "54571890", "-22473078", "95053418", "393654", "-33229960", "32276798", - "-48361110", "44295939", "-79813406", "11630865", "38544571", "70972830", "-9821748", "-60965384", "-13096675", "-24569041", - "708", "-467", "-794", "610", "929", "766", "152", "482", "397", "-191", - "97233152", "51028396", "-13796948", "95437272", "71352512", "-83233730", "-68517318", "61832742", "-42667174", "-18002395", - "-92239407", "12701336", "-63830875", "41514172", "-5726049", "18668677", "69555144", "-13737009", "-22626233", "-55078143", - "00", "11", "22", "33", "44", "-00", "-11", "-22", "-33", "-44", - "000", "111", "222", "333", "444", "-000", "-111", "-222", "-333", "-444", - "0000", "1111", "2222", "3333", "4444", "-0000", "-1111", "-2222", "-3333", "-4444", - "00000", "11111", "22222", "33333", "44444", "-00000", "-11111", "-22222", "-33333", "-44444", - "000000", "111111", "222222", "333333", "444444", "-000000", "-111111", "-222222", "-333333", "-444444", - "0000000", "1111111", "2222222", "3333333", "4444444", "-0000000", "-1111111", "-2222222", "-3333333", "-4444444", - "00000000", "11111111", "22222222", "33333333", "44444444", "-00000000", "-11111111", "-22222222", "-33333333", "-44444444", - "000000000", "111111111", "222222222", "333333333", "444444444","-000000000","-111111111","-222222222","-333333333","-444444444", - "2147483351", "51", "2147483314", "53", "-2147483648", "57", "-2147483611", - "55", "66", "77", "88", "99", "-55", "-66", "-77", "-88", "-99", - "555", "666", "777", "888", "999", "-555", "-666", "-777", "-888", "-999", - "5555", "6666", "7777", "8888", "9999", "-5555", "-6666", "-7777", "-8888", "-9999", - "55555", "66666", "77777", "88888", "99999", "-55555", "-66666", "-77777", "-88888", "-99999", - "555555", "666666", "777777", "888888", "999999", "-555555", "-666666", "-777777", "-888888", "-999999", - "5555555", "6666666", "7777777", "8888888", "9999999", "-5555555", "-6666666", "-7777777", "-8888888", "-9999999", - "55555555", "66666666", "77777777", "88888888", "99999999", "-55555555", "-66666666", "-77777777", "-88888888", "-99999999", - "555555555", "666666666", "777777777", "888888888", "999999999","-555555555","-666666666","-777777777","-888888888","-999999999", - "-2147483574", "91", "-2147483537", "93", "-2147483500", "97", "-2147483463", - "0000000011", "0000000022", "0000000033", "0000000044", "-000000011", "-000000022", "-000000033", "-000000044", "-000000088", - "0000000111", "0000000222", "0000000333", "0000000444", "-000000111", "-000000222", "-000000333", "-000000444", "-000000888", - "0000001111", "0000002222", "0000003333", "0000004444", "-000001111", "-000002222", "-000003333", "-000004444", "-000008888", - "0000011111", "0000022222", "0000033333", "0000044444", "-000011111", "-000022222", "-000033333", "-000044444", "-000088888", - "0000111111", "0000222222", "0000333333", "0000444444", "-000111111", "-000222222", "-000333333", "-000444444", "-000888888", - "0001111111", "0002222222", "0003333333", "0004444444", "-001111111", "-002222222", "-003333333", "-004444444", "-008888888", - "0011111111", "0022222222", "0033333333", "0044444444", "-011111111", "-022222222", "-033333333", "-044444444", "-088888888", - "0111111111", "0222222222", "0333333333", "0444444444", "-111111111", "-222222222", "-333333333", "-444444444", "-888888888", - "0000000055", "0000000066", "0000000077", "0000000088", "0000000099", "-000000055", "-000000066", "-000000077", "-000000099", - "0000000555", "0000000666", "0000000777", "0000000888", "0000000999", "-000000555", "-000000666", "-000000777", "-000000999", - "0000005555", "0000006666", "0000007777", "0000008888", "0000009999", "-000005555", "-000006666", "-000007777", "-000009999", - "0000055555", "0000066666", "0000077777", "0000088888", "0000099999", "-000055555", "-000066666", "-000077777", "-000099999", - "0000555555", "0000666666", "0000777777", "0000888888", "0000999999", "-000555555", "-000666666", "-000777777", "-000999999", - "0005555555", "0006666666", "0007777777", "0008888888", "0009999999", "-005555555", "-006666666", "-007777777", "-009999999", - "0055555555", "0066666666", "0077777777", "0088888888", "0099999999", "-055555555", "-066666666", "-077777777", "-099999999", - "0555555555", "0666666666", "0777777777", "0888888888", "0999999999", "-555555555", "-666666666", "-777777777", "-999999999", - "-2147483426", "101", "-2147483389", "103", "-2147483352", "105", "-2147483315", - "0000001234567890", "0000001234567890", "-0000001234567890", - "000001234567890", "000001234567890", "-000001234567890", - "00001234567890", "00001234567890", "-00001234567890", - "0001234567890", "0001234567890", "-0001234567890", - "001234567890", "001234567890", "-001234567890", - "01234567890", "01234567890", "-01234567890", - "1234567890", "1234567890", "-1234567890", - }; - for(const std::string& st : strint_list) { - T expected_value; - strtod_from_string(st, expected_value); - T result_value; - auto result = fast_float::from_chars(st.data(), st.data() + st.size(), - result_value); - if (result.ec != std::errc()) { - printf("parsing %.*s\n", int(st.size()), st.data()); - std::cerr << " I could not parse " << std::endl; - return false; - } - if(result.ptr != st.data() + st.size()) { - printf("parsing %.*s\n", int(st.size()), st.data()); - std::cerr << " Did not get to the end " << std::endl; - return false; - } - if(result_value != expected_value) { - printf("parsing %.*s\n", int(st.size()), st.data()); - std::cerr << "expected value : " << to_string(expected_value) << std::endl; - std::cerr << "result value : " << to_string(result_value) << std::endl; - std::cerr << " Mismatch " << std::endl; - return false; - } - - } - return true; - -} - - -int main() { -#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) || defined(sun) || defined(__sun) - std::cout << "Warning: msys/cygwin or solaris detected." << std::endl; -#endif - std::cout << "32 bits checks" << std::endl; - Assert(partow_test()); - Assert(test()); - - std::cout << "64 bits checks" << std::endl; - Assert(partow_test()); - Assert(test()); - - std::cout << "All ok" << std::endl; - return EXIT_SUCCESS; -} diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float_all.h b/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float_all.h deleted file mode 100644 index 098aa17ab..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/fast_float_all.h +++ /dev/null @@ -1,2947 +0,0 @@ -// fast_float by Daniel Lemire -// fast_float by João Paulo Magalhaes - - -// with contributions from Eugene Golushkov -// with contributions from Maksim Kita -// with contributions from Marcin Wojdyr -// with contributions from Neal Richardson -// with contributions from Tim Paine -// with contributions from Fabio Pellacini - - -// Permission is hereby granted, free of charge, to any -// person obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the -// Software without restriction, including without -// limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software -// is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice -// shall be included in all copies or substantial portions -// of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - - -#ifndef FASTFLOAT_FAST_FLOAT_H -#define FASTFLOAT_FAST_FLOAT_H - -#include - -namespace fast_float { -enum chars_format { - scientific = 1<<0, - fixed = 1<<2, - hex = 1<<3, - general = fixed | scientific -}; - - -struct from_chars_result { - const char *ptr; - std::errc ec; -}; - -struct parse_options { - constexpr explicit parse_options(chars_format fmt = chars_format::general, - char dot = '.') - : format(fmt), decimal_point(dot) {} - - /** Which number formats are accepted */ - chars_format format; - /** The character used as decimal point */ - char decimal_point; -}; - -/** - * This function parses the character sequence [first,last) for a number. It parses floating-point numbers expecting - * a locale-indepent format equivalent to what is used by std::strtod in the default ("C") locale. - * The resulting floating-point value is the closest floating-point values (using either float or double), - * using the "round to even" convention for values that would otherwise fall right in-between two values. - * That is, we provide exact parsing according to the IEEE standard. - * - * Given a successful parse, the pointer (`ptr`) in the returned value is set to point right after the - * parsed number, and the `value` referenced is set to the parsed value. In case of error, the returned - * `ec` contains a representative error, otherwise the default (`std::errc()`) value is stored. - * - * The implementation does not throw and does not allocate memory (e.g., with `new` or `malloc`). - * - * Like the C++17 standard, the `fast_float::from_chars` functions take an optional last argument of - * the type `fast_float::chars_format`. It is a bitset value: we check whether - * `fmt & fast_float::chars_format::fixed` and `fmt & fast_float::chars_format::scientific` are set - * to determine whether we allowe the fixed point and scientific notation respectively. - * The default is `fast_float::chars_format::general` which allows both `fixed` and `scientific`. - */ -template -from_chars_result from_chars(const char *first, const char *last, - T &value, chars_format fmt = chars_format::general) noexcept; - -/** - * Like from_chars, but accepts an `options` argument to govern number parsing. - */ -template -from_chars_result from_chars_advanced(const char *first, const char *last, - T &value, parse_options options) noexcept; - -} -#endif // FASTFLOAT_FAST_FLOAT_H - - -#ifndef FASTFLOAT_FLOAT_COMMON_H -#define FASTFLOAT_FLOAT_COMMON_H - -#include -#include -#include -#include - -#if (defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) \ - || defined(__amd64) || defined(__aarch64__) || defined(_M_ARM64) \ - || defined(__MINGW64__) \ - || defined(__s390x__) \ - || (defined(__ppc64__) || defined(__PPC64__) || defined(__ppc64le__) || defined(__PPC64LE__)) \ - || defined(__EMSCRIPTEN__)) -#define FASTFLOAT_64BIT -#elif (defined(__i386) || defined(__i386__) || defined(_M_IX86) \ - || defined(__arm__) || defined(_M_ARM) \ - || defined(__MINGW32__)) -#define FASTFLOAT_32BIT -#else - // Need to check incrementally, since SIZE_MAX is a size_t, avoid overflow. - // We can never tell the register width, but the SIZE_MAX is a good approximation. - // UINTPTR_MAX and INTPTR_MAX are optional, so avoid them for max portability. - #if SIZE_MAX == 0xffff - #error Unknown platform (16-bit, unsupported) - #elif SIZE_MAX == 0xffffffff - #define FASTFLOAT_32BIT - #elif SIZE_MAX == 0xffffffffffffffff - #define FASTFLOAT_64BIT - #else - #error Unknown platform (not 32-bit, not 64-bit?) - #endif -#endif - -#if ((defined(_WIN32) || defined(_WIN64)) && !defined(__clang__)) -#include -#endif - -#if defined(_MSC_VER) && !defined(__clang__) -#define FASTFLOAT_VISUAL_STUDIO 1 -#endif - -#ifdef _WIN32 -#define FASTFLOAT_IS_BIG_ENDIAN 0 -#else -#if defined(__APPLE__) || defined(__FreeBSD__) -#include -#elif defined(sun) || defined(__sun) -#include -#else -#include -#endif -# -#ifndef __BYTE_ORDER__ -// safe choice -#define FASTFLOAT_IS_BIG_ENDIAN 0 -#endif -# -#ifndef __ORDER_LITTLE_ENDIAN__ -// safe choice -#define FASTFLOAT_IS_BIG_ENDIAN 0 -#endif -# -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -#define FASTFLOAT_IS_BIG_ENDIAN 0 -#else -#define FASTFLOAT_IS_BIG_ENDIAN 1 -#endif -#endif - -#ifdef FASTFLOAT_VISUAL_STUDIO -#define fastfloat_really_inline __forceinline -#else -#define fastfloat_really_inline inline __attribute__((always_inline)) -#endif - -#ifndef FASTFLOAT_ASSERT -#define FASTFLOAT_ASSERT(x) { if (!(x)) abort(); } -#endif - -#ifndef FASTFLOAT_DEBUG_ASSERT -#include -#define FASTFLOAT_DEBUG_ASSERT(x) assert(x) -#endif - -// rust style `try!()` macro, or `?` operator -#define FASTFLOAT_TRY(x) { if (!(x)) return false; } - -namespace fast_float { - -// Compares two ASCII strings in a case insensitive manner. -inline bool fastfloat_strncasecmp(const char *input1, const char *input2, - size_t length) { - char running_diff{0}; - for (size_t i = 0; i < length; i++) { - running_diff |= (input1[i] ^ input2[i]); - } - return (running_diff == 0) || (running_diff == 32); -} - -#ifndef FLT_EVAL_METHOD -#error "FLT_EVAL_METHOD should be defined, please include cfloat." -#endif - -// a pointer and a length to a contiguous block of memory -template -struct span { - const T* ptr; - size_t length; - span(const T* _ptr, size_t _length) : ptr(_ptr), length(_length) {} - span() : ptr(nullptr), length(0) {} - - constexpr size_t len() const noexcept { - return length; - } - - const T& operator[](size_t index) const noexcept { - FASTFLOAT_DEBUG_ASSERT(index < length); - return ptr[index]; - } -}; - -struct value128 { - uint64_t low; - uint64_t high; - value128(uint64_t _low, uint64_t _high) : low(_low), high(_high) {} - value128() : low(0), high(0) {} -}; - -/* result might be undefined when input_num is zero */ -fastfloat_really_inline int leading_zeroes(uint64_t input_num) { - assert(input_num > 0); -#ifdef FASTFLOAT_VISUAL_STUDIO - #if defined(_M_X64) || defined(_M_ARM64) - unsigned long leading_zero = 0; - // Search the mask data from most significant bit (MSB) - // to least significant bit (LSB) for a set bit (1). - _BitScanReverse64(&leading_zero, input_num); - return (int)(63 - leading_zero); - #else - int last_bit = 0; - if(input_num & uint64_t(0xffffffff00000000)) input_num >>= 32, last_bit |= 32; - if(input_num & uint64_t( 0xffff0000)) input_num >>= 16, last_bit |= 16; - if(input_num & uint64_t( 0xff00)) input_num >>= 8, last_bit |= 8; - if(input_num & uint64_t( 0xf0)) input_num >>= 4, last_bit |= 4; - if(input_num & uint64_t( 0xc)) input_num >>= 2, last_bit |= 2; - if(input_num & uint64_t( 0x2)) input_num >>= 1, last_bit |= 1; - return 63 - last_bit; - #endif -#else - return __builtin_clzll(input_num); -#endif -} - -#ifdef FASTFLOAT_32BIT - -// slow emulation routine for 32-bit -fastfloat_really_inline uint64_t emulu(uint32_t x, uint32_t y) { - return x * (uint64_t)y; -} - -// slow emulation routine for 32-bit -#if !defined(__MINGW64__) -fastfloat_really_inline uint64_t _umul128(uint64_t ab, uint64_t cd, - uint64_t *hi) { - uint64_t ad = emulu((uint32_t)(ab >> 32), (uint32_t)cd); - uint64_t bd = emulu((uint32_t)ab, (uint32_t)cd); - uint64_t adbc = ad + emulu((uint32_t)ab, (uint32_t)(cd >> 32)); - uint64_t adbc_carry = !!(adbc < ad); - uint64_t lo = bd + (adbc << 32); - *hi = emulu((uint32_t)(ab >> 32), (uint32_t)(cd >> 32)) + (adbc >> 32) + - (adbc_carry << 32) + !!(lo < bd); - return lo; -} -#endif // !__MINGW64__ - -#endif // FASTFLOAT_32BIT - - -// compute 64-bit a*b -fastfloat_really_inline value128 full_multiplication(uint64_t a, - uint64_t b) { - value128 answer; -#ifdef _M_ARM64 - // ARM64 has native support for 64-bit multiplications, no need to emulate - answer.high = __umulh(a, b); - answer.low = a * b; -#elif defined(FASTFLOAT_32BIT) || (defined(_WIN64) && !defined(__clang__)) - answer.low = _umul128(a, b, &answer.high); // _umul128 not available on ARM64 -#elif defined(FASTFLOAT_64BIT) - __uint128_t r = ((__uint128_t)a) * b; - answer.low = uint64_t(r); - answer.high = uint64_t(r >> 64); -#else - #error Not implemented -#endif - return answer; -} - -struct adjusted_mantissa { - uint64_t mantissa{0}; - int32_t power2{0}; // a negative value indicates an invalid result - adjusted_mantissa() = default; - bool operator==(const adjusted_mantissa &o) const { - return mantissa == o.mantissa && power2 == o.power2; - } - bool operator!=(const adjusted_mantissa &o) const { - return mantissa != o.mantissa || power2 != o.power2; - } -}; - -// Bias so we can get the real exponent with an invalid adjusted_mantissa. -constexpr static int32_t invalid_am_bias = -0x8000; - -constexpr static double powers_of_ten_double[] = { - 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, - 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22}; -constexpr static float powers_of_ten_float[] = {1e0, 1e1, 1e2, 1e3, 1e4, 1e5, - 1e6, 1e7, 1e8, 1e9, 1e10}; - -template struct binary_format { - static inline constexpr int mantissa_explicit_bits(); - static inline constexpr int minimum_exponent(); - static inline constexpr int infinite_power(); - static inline constexpr int sign_index(); - static inline constexpr int min_exponent_fast_path(); - static inline constexpr int max_exponent_fast_path(); - static inline constexpr int max_exponent_round_to_even(); - static inline constexpr int min_exponent_round_to_even(); - static inline constexpr uint64_t max_mantissa_fast_path(); - static inline constexpr int largest_power_of_ten(); - static inline constexpr int smallest_power_of_ten(); - static inline constexpr T exact_power_of_ten(int64_t power); - static inline constexpr size_t max_digits(); -}; - -template <> inline constexpr int binary_format::mantissa_explicit_bits() { - return 52; -} -template <> inline constexpr int binary_format::mantissa_explicit_bits() { - return 23; -} - -template <> inline constexpr int binary_format::max_exponent_round_to_even() { - return 23; -} - -template <> inline constexpr int binary_format::max_exponent_round_to_even() { - return 10; -} - -template <> inline constexpr int binary_format::min_exponent_round_to_even() { - return -4; -} - -template <> inline constexpr int binary_format::min_exponent_round_to_even() { - return -17; -} - -template <> inline constexpr int binary_format::minimum_exponent() { - return -1023; -} -template <> inline constexpr int binary_format::minimum_exponent() { - return -127; -} - -template <> inline constexpr int binary_format::infinite_power() { - return 0x7FF; -} -template <> inline constexpr int binary_format::infinite_power() { - return 0xFF; -} - -template <> inline constexpr int binary_format::sign_index() { return 63; } -template <> inline constexpr int binary_format::sign_index() { return 31; } - -template <> inline constexpr int binary_format::min_exponent_fast_path() { -#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0) - return 0; -#else - return -22; -#endif -} -template <> inline constexpr int binary_format::min_exponent_fast_path() { -#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0) - return 0; -#else - return -10; -#endif -} - -template <> inline constexpr int binary_format::max_exponent_fast_path() { - return 22; -} -template <> inline constexpr int binary_format::max_exponent_fast_path() { - return 10; -} - -template <> inline constexpr uint64_t binary_format::max_mantissa_fast_path() { - return uint64_t(2) << mantissa_explicit_bits(); -} -template <> inline constexpr uint64_t binary_format::max_mantissa_fast_path() { - return uint64_t(2) << mantissa_explicit_bits(); -} - -template <> -inline constexpr double binary_format::exact_power_of_ten(int64_t power) { - return powers_of_ten_double[power]; -} -template <> -inline constexpr float binary_format::exact_power_of_ten(int64_t power) { - - return powers_of_ten_float[power]; -} - - -template <> -inline constexpr int binary_format::largest_power_of_ten() { - return 308; -} -template <> -inline constexpr int binary_format::largest_power_of_ten() { - return 38; -} - -template <> -inline constexpr int binary_format::smallest_power_of_ten() { - return -342; -} -template <> -inline constexpr int binary_format::smallest_power_of_ten() { - return -65; -} - -template <> inline constexpr size_t binary_format::max_digits() { - return 769; -} -template <> inline constexpr size_t binary_format::max_digits() { - return 114; -} - -template -fastfloat_really_inline void to_float(bool negative, adjusted_mantissa am, T &value) { - uint64_t word = am.mantissa; - word |= uint64_t(am.power2) << binary_format::mantissa_explicit_bits(); - word = negative - ? word | (uint64_t(1) << binary_format::sign_index()) : word; -#if FASTFLOAT_IS_BIG_ENDIAN == 1 - if (std::is_same::value) { - ::memcpy(&value, (char *)&word + 4, sizeof(T)); // extract value at offset 4-7 if float on big-endian - } else { - ::memcpy(&value, &word, sizeof(T)); - } -#else - // For little-endian systems: - ::memcpy(&value, &word, sizeof(T)); -#endif -} - -} // namespace fast_float - -#endif - - -#ifndef FASTFLOAT_ASCII_NUMBER_H -#define FASTFLOAT_ASCII_NUMBER_H - -#include -#include -#include -#include - - -namespace fast_float { - -// Next function can be micro-optimized, but compilers are entirely -// able to optimize it well. -fastfloat_really_inline bool is_integer(char c) noexcept { return c >= '0' && c <= '9'; } - -fastfloat_really_inline uint64_t byteswap(uint64_t val) { - return (val & 0xFF00000000000000) >> 56 - | (val & 0x00FF000000000000) >> 40 - | (val & 0x0000FF0000000000) >> 24 - | (val & 0x000000FF00000000) >> 8 - | (val & 0x00000000FF000000) << 8 - | (val & 0x0000000000FF0000) << 24 - | (val & 0x000000000000FF00) << 40 - | (val & 0x00000000000000FF) << 56; -} - -fastfloat_really_inline uint64_t read_u64(const char *chars) { - uint64_t val; - ::memcpy(&val, chars, sizeof(uint64_t)); -#if FASTFLOAT_IS_BIG_ENDIAN == 1 - // Need to read as-if the number was in little-endian order. - val = byteswap(val); -#endif - return val; -} - -fastfloat_really_inline void write_u64(uint8_t *chars, uint64_t val) { -#if FASTFLOAT_IS_BIG_ENDIAN == 1 - // Need to read as-if the number was in little-endian order. - val = byteswap(val); -#endif - ::memcpy(chars, &val, sizeof(uint64_t)); -} - -// credit @aqrit -fastfloat_really_inline uint32_t parse_eight_digits_unrolled(uint64_t val) { - const uint64_t mask = 0x000000FF000000FF; - const uint64_t mul1 = 0x000F424000000064; // 100 + (1000000ULL << 32) - const uint64_t mul2 = 0x0000271000000001; // 1 + (10000ULL << 32) - val -= 0x3030303030303030; - val = (val * 10) + (val >> 8); // val = (val * 2561) >> 8; - val = (((val & mask) * mul1) + (((val >> 16) & mask) * mul2)) >> 32; - return uint32_t(val); -} - -fastfloat_really_inline uint32_t parse_eight_digits_unrolled(const char *chars) noexcept { - return parse_eight_digits_unrolled(read_u64(chars)); -} - -// credit @aqrit -fastfloat_really_inline bool is_made_of_eight_digits_fast(uint64_t val) noexcept { - return !((((val + 0x4646464646464646) | (val - 0x3030303030303030)) & - 0x8080808080808080)); -} - -fastfloat_really_inline bool is_made_of_eight_digits_fast(const char *chars) noexcept { - return is_made_of_eight_digits_fast(read_u64(chars)); -} - -typedef span byte_span; - -struct parsed_number_string { - int64_t exponent{0}; - uint64_t mantissa{0}; - const char *lastmatch{nullptr}; - bool negative{false}; - bool valid{false}; - bool too_many_digits{false}; - // contains the range of the significant digits - byte_span integer{}; // non-nullable - byte_span fraction{}; // nullable -}; - -// Assuming that you use no more than 19 digits, this will -// parse an ASCII string. -fastfloat_really_inline -parsed_number_string parse_number_string(const char *p, const char *pend, parse_options options) noexcept { - const chars_format fmt = options.format; - const char decimal_point = options.decimal_point; - - parsed_number_string answer; - answer.valid = false; - answer.too_many_digits = false; - answer.negative = (*p == '-'); - if (*p == '-') { // C++17 20.19.3.(7.1) explicitly forbids '+' sign here - ++p; - if (p == pend) { - return answer; - } - if (!is_integer(*p) && (*p != decimal_point)) { // a sign must be followed by an integer or the dot - return answer; - } - } - const char *const start_digits = p; - - uint64_t i = 0; // an unsigned int avoids signed overflows (which are bad) - - while ((std::distance(p, pend) >= 8) && is_made_of_eight_digits_fast(p)) { - i = i * 100000000 + parse_eight_digits_unrolled(p); // in rare cases, this will overflow, but that's ok - p += 8; - } - while ((p != pend) && is_integer(*p)) { - // a multiplication by 10 is cheaper than an arbitrary integer - // multiplication - i = 10 * i + - uint64_t(*p - '0'); // might overflow, we will handle the overflow later - ++p; - } - const char *const end_of_integer_part = p; - int64_t digit_count = int64_t(end_of_integer_part - start_digits); - answer.integer = byte_span(start_digits, size_t(digit_count)); - int64_t exponent = 0; - if ((p != pend) && (*p == decimal_point)) { - ++p; - const char* before = p; - // can occur at most twice without overflowing, but let it occur more, since - // for integers with many digits, digit parsing is the primary bottleneck. - while ((std::distance(p, pend) >= 8) && is_made_of_eight_digits_fast(p)) { - i = i * 100000000 + parse_eight_digits_unrolled(p); // in rare cases, this will overflow, but that's ok - p += 8; - } - while ((p != pend) && is_integer(*p)) { - uint8_t digit = uint8_t(*p - '0'); - ++p; - i = i * 10 + digit; // in rare cases, this will overflow, but that's ok - } - exponent = before - p; - answer.fraction = byte_span(before, size_t(p - before)); - digit_count -= exponent; - } - // we must have encountered at least one integer! - if (digit_count == 0) { - return answer; - } - int64_t exp_number = 0; // explicit exponential part - if ((fmt & chars_format::scientific) && (p != pend) && (('e' == *p) || ('E' == *p))) { - const char * location_of_e = p; - ++p; - bool neg_exp = false; - if ((p != pend) && ('-' == *p)) { - neg_exp = true; - ++p; - } else if ((p != pend) && ('+' == *p)) { // '+' on exponent is allowed by C++17 20.19.3.(7.1) - ++p; - } - if ((p == pend) || !is_integer(*p)) { - if(!(fmt & chars_format::fixed)) { - // We are in error. - return answer; - } - // Otherwise, we will be ignoring the 'e'. - p = location_of_e; - } else { - while ((p != pend) && is_integer(*p)) { - uint8_t digit = uint8_t(*p - '0'); - if (exp_number < 0x10000000) { - exp_number = 10 * exp_number + digit; - } - ++p; - } - if(neg_exp) { exp_number = - exp_number; } - exponent += exp_number; - } - } else { - // If it scientific and not fixed, we have to bail out. - if((fmt & chars_format::scientific) && !(fmt & chars_format::fixed)) { return answer; } - } - answer.lastmatch = p; - answer.valid = true; - - // If we frequently had to deal with long strings of digits, - // we could extend our code by using a 128-bit integer instead - // of a 64-bit integer. However, this is uncommon. - // - // We can deal with up to 19 digits. - if (digit_count > 19) { // this is uncommon - // It is possible that the integer had an overflow. - // We have to handle the case where we have 0.0000somenumber. - // We need to be mindful of the case where we only have zeroes... - // E.g., 0.000000000...000. - const char *start = start_digits; - while ((start != pend) && (*start == '0' || *start == decimal_point)) { - if(*start == '0') { digit_count --; } - start++; - } - if (digit_count > 19) { - answer.too_many_digits = true; - // Let us start again, this time, avoiding overflows. - // We don't need to check if is_integer, since we use the - // pre-tokenized spans from above. - i = 0; - p = answer.integer.ptr; - const char* int_end = p + answer.integer.len(); - const uint64_t minimal_nineteen_digit_integer{1000000000000000000}; - while((i < minimal_nineteen_digit_integer) && (p != int_end)) { - i = i * 10 + uint64_t(*p - '0'); - ++p; - } - if (i >= minimal_nineteen_digit_integer) { // We have a big integers - exponent = end_of_integer_part - p + exp_number; - } else { // We have a value with a fractional component. - p = answer.fraction.ptr; - const char* frac_end = p + answer.fraction.len(); - while((i < minimal_nineteen_digit_integer) && (p != frac_end)) { - i = i * 10 + uint64_t(*p - '0'); - ++p; - } - exponent = answer.fraction.ptr - p + exp_number; - } - // We have now corrected both exponent and i, to a truncated value - } - } - answer.exponent = exponent; - answer.mantissa = i; - return answer; -} - -} // namespace fast_float - -#endif - - -#ifndef FASTFLOAT_FAST_TABLE_H -#define FASTFLOAT_FAST_TABLE_H - -#include - -namespace fast_float { - -/** - * When mapping numbers from decimal to binary, - * we go from w * 10^q to m * 2^p but we have - * 10^q = 5^q * 2^q, so effectively - * we are trying to match - * w * 2^q * 5^q to m * 2^p. Thus the powers of two - * are not a concern since they can be represented - * exactly using the binary notation, only the powers of five - * affect the binary significand. - */ - -/** - * The smallest non-zero float (binary64) is 2^−1074. - * We take as input numbers of the form w x 10^q where w < 2^64. - * We have that w * 10^-343 < 2^(64-344) 5^-343 < 2^-1076. - * However, we have that - * (2^64-1) * 10^-342 = (2^64-1) * 2^-342 * 5^-342 > 2^−1074. - * Thus it is possible for a number of the form w * 10^-342 where - * w is a 64-bit value to be a non-zero floating-point number. - ********* - * Any number of form w * 10^309 where w>= 1 is going to be - * infinite in binary64 so we never need to worry about powers - * of 5 greater than 308. - */ -template -struct powers_template { - -constexpr static int smallest_power_of_five = binary_format::smallest_power_of_ten(); -constexpr static int largest_power_of_five = binary_format::largest_power_of_ten(); -constexpr static int number_of_entries = 2 * (largest_power_of_five - smallest_power_of_five + 1); -// Powers of five from 5^-342 all the way to 5^308 rounded toward one. -static const uint64_t power_of_five_128[number_of_entries]; -}; - -template -const uint64_t powers_template::power_of_five_128[number_of_entries] = { - 0xeef453d6923bd65a,0x113faa2906a13b3f, - 0x9558b4661b6565f8,0x4ac7ca59a424c507, - 0xbaaee17fa23ebf76,0x5d79bcf00d2df649, - 0xe95a99df8ace6f53,0xf4d82c2c107973dc, - 0x91d8a02bb6c10594,0x79071b9b8a4be869, - 0xb64ec836a47146f9,0x9748e2826cdee284, - 0xe3e27a444d8d98b7,0xfd1b1b2308169b25, - 0x8e6d8c6ab0787f72,0xfe30f0f5e50e20f7, - 0xb208ef855c969f4f,0xbdbd2d335e51a935, - 0xde8b2b66b3bc4723,0xad2c788035e61382, - 0x8b16fb203055ac76,0x4c3bcb5021afcc31, - 0xaddcb9e83c6b1793,0xdf4abe242a1bbf3d, - 0xd953e8624b85dd78,0xd71d6dad34a2af0d, - 0x87d4713d6f33aa6b,0x8672648c40e5ad68, - 0xa9c98d8ccb009506,0x680efdaf511f18c2, - 0xd43bf0effdc0ba48,0x212bd1b2566def2, - 0x84a57695fe98746d,0x14bb630f7604b57, - 0xa5ced43b7e3e9188,0x419ea3bd35385e2d, - 0xcf42894a5dce35ea,0x52064cac828675b9, - 0x818995ce7aa0e1b2,0x7343efebd1940993, - 0xa1ebfb4219491a1f,0x1014ebe6c5f90bf8, - 0xca66fa129f9b60a6,0xd41a26e077774ef6, - 0xfd00b897478238d0,0x8920b098955522b4, - 0x9e20735e8cb16382,0x55b46e5f5d5535b0, - 0xc5a890362fddbc62,0xeb2189f734aa831d, - 0xf712b443bbd52b7b,0xa5e9ec7501d523e4, - 0x9a6bb0aa55653b2d,0x47b233c92125366e, - 0xc1069cd4eabe89f8,0x999ec0bb696e840a, - 0xf148440a256e2c76,0xc00670ea43ca250d, - 0x96cd2a865764dbca,0x380406926a5e5728, - 0xbc807527ed3e12bc,0xc605083704f5ecf2, - 0xeba09271e88d976b,0xf7864a44c633682e, - 0x93445b8731587ea3,0x7ab3ee6afbe0211d, - 0xb8157268fdae9e4c,0x5960ea05bad82964, - 0xe61acf033d1a45df,0x6fb92487298e33bd, - 0x8fd0c16206306bab,0xa5d3b6d479f8e056, - 0xb3c4f1ba87bc8696,0x8f48a4899877186c, - 0xe0b62e2929aba83c,0x331acdabfe94de87, - 0x8c71dcd9ba0b4925,0x9ff0c08b7f1d0b14, - 0xaf8e5410288e1b6f,0x7ecf0ae5ee44dd9, - 0xdb71e91432b1a24a,0xc9e82cd9f69d6150, - 0x892731ac9faf056e,0xbe311c083a225cd2, - 0xab70fe17c79ac6ca,0x6dbd630a48aaf406, - 0xd64d3d9db981787d,0x92cbbccdad5b108, - 0x85f0468293f0eb4e,0x25bbf56008c58ea5, - 0xa76c582338ed2621,0xaf2af2b80af6f24e, - 0xd1476e2c07286faa,0x1af5af660db4aee1, - 0x82cca4db847945ca,0x50d98d9fc890ed4d, - 0xa37fce126597973c,0xe50ff107bab528a0, - 0xcc5fc196fefd7d0c,0x1e53ed49a96272c8, - 0xff77b1fcbebcdc4f,0x25e8e89c13bb0f7a, - 0x9faacf3df73609b1,0x77b191618c54e9ac, - 0xc795830d75038c1d,0xd59df5b9ef6a2417, - 0xf97ae3d0d2446f25,0x4b0573286b44ad1d, - 0x9becce62836ac577,0x4ee367f9430aec32, - 0xc2e801fb244576d5,0x229c41f793cda73f, - 0xf3a20279ed56d48a,0x6b43527578c1110f, - 0x9845418c345644d6,0x830a13896b78aaa9, - 0xbe5691ef416bd60c,0x23cc986bc656d553, - 0xedec366b11c6cb8f,0x2cbfbe86b7ec8aa8, - 0x94b3a202eb1c3f39,0x7bf7d71432f3d6a9, - 0xb9e08a83a5e34f07,0xdaf5ccd93fb0cc53, - 0xe858ad248f5c22c9,0xd1b3400f8f9cff68, - 0x91376c36d99995be,0x23100809b9c21fa1, - 0xb58547448ffffb2d,0xabd40a0c2832a78a, - 0xe2e69915b3fff9f9,0x16c90c8f323f516c, - 0x8dd01fad907ffc3b,0xae3da7d97f6792e3, - 0xb1442798f49ffb4a,0x99cd11cfdf41779c, - 0xdd95317f31c7fa1d,0x40405643d711d583, - 0x8a7d3eef7f1cfc52,0x482835ea666b2572, - 0xad1c8eab5ee43b66,0xda3243650005eecf, - 0xd863b256369d4a40,0x90bed43e40076a82, - 0x873e4f75e2224e68,0x5a7744a6e804a291, - 0xa90de3535aaae202,0x711515d0a205cb36, - 0xd3515c2831559a83,0xd5a5b44ca873e03, - 0x8412d9991ed58091,0xe858790afe9486c2, - 0xa5178fff668ae0b6,0x626e974dbe39a872, - 0xce5d73ff402d98e3,0xfb0a3d212dc8128f, - 0x80fa687f881c7f8e,0x7ce66634bc9d0b99, - 0xa139029f6a239f72,0x1c1fffc1ebc44e80, - 0xc987434744ac874e,0xa327ffb266b56220, - 0xfbe9141915d7a922,0x4bf1ff9f0062baa8, - 0x9d71ac8fada6c9b5,0x6f773fc3603db4a9, - 0xc4ce17b399107c22,0xcb550fb4384d21d3, - 0xf6019da07f549b2b,0x7e2a53a146606a48, - 0x99c102844f94e0fb,0x2eda7444cbfc426d, - 0xc0314325637a1939,0xfa911155fefb5308, - 0xf03d93eebc589f88,0x793555ab7eba27ca, - 0x96267c7535b763b5,0x4bc1558b2f3458de, - 0xbbb01b9283253ca2,0x9eb1aaedfb016f16, - 0xea9c227723ee8bcb,0x465e15a979c1cadc, - 0x92a1958a7675175f,0xbfacd89ec191ec9, - 0xb749faed14125d36,0xcef980ec671f667b, - 0xe51c79a85916f484,0x82b7e12780e7401a, - 0x8f31cc0937ae58d2,0xd1b2ecb8b0908810, - 0xb2fe3f0b8599ef07,0x861fa7e6dcb4aa15, - 0xdfbdcece67006ac9,0x67a791e093e1d49a, - 0x8bd6a141006042bd,0xe0c8bb2c5c6d24e0, - 0xaecc49914078536d,0x58fae9f773886e18, - 0xda7f5bf590966848,0xaf39a475506a899e, - 0x888f99797a5e012d,0x6d8406c952429603, - 0xaab37fd7d8f58178,0xc8e5087ba6d33b83, - 0xd5605fcdcf32e1d6,0xfb1e4a9a90880a64, - 0x855c3be0a17fcd26,0x5cf2eea09a55067f, - 0xa6b34ad8c9dfc06f,0xf42faa48c0ea481e, - 0xd0601d8efc57b08b,0xf13b94daf124da26, - 0x823c12795db6ce57,0x76c53d08d6b70858, - 0xa2cb1717b52481ed,0x54768c4b0c64ca6e, - 0xcb7ddcdda26da268,0xa9942f5dcf7dfd09, - 0xfe5d54150b090b02,0xd3f93b35435d7c4c, - 0x9efa548d26e5a6e1,0xc47bc5014a1a6daf, - 0xc6b8e9b0709f109a,0x359ab6419ca1091b, - 0xf867241c8cc6d4c0,0xc30163d203c94b62, - 0x9b407691d7fc44f8,0x79e0de63425dcf1d, - 0xc21094364dfb5636,0x985915fc12f542e4, - 0xf294b943e17a2bc4,0x3e6f5b7b17b2939d, - 0x979cf3ca6cec5b5a,0xa705992ceecf9c42, - 0xbd8430bd08277231,0x50c6ff782a838353, - 0xece53cec4a314ebd,0xa4f8bf5635246428, - 0x940f4613ae5ed136,0x871b7795e136be99, - 0xb913179899f68584,0x28e2557b59846e3f, - 0xe757dd7ec07426e5,0x331aeada2fe589cf, - 0x9096ea6f3848984f,0x3ff0d2c85def7621, - 0xb4bca50b065abe63,0xfed077a756b53a9, - 0xe1ebce4dc7f16dfb,0xd3e8495912c62894, - 0x8d3360f09cf6e4bd,0x64712dd7abbbd95c, - 0xb080392cc4349dec,0xbd8d794d96aacfb3, - 0xdca04777f541c567,0xecf0d7a0fc5583a0, - 0x89e42caaf9491b60,0xf41686c49db57244, - 0xac5d37d5b79b6239,0x311c2875c522ced5, - 0xd77485cb25823ac7,0x7d633293366b828b, - 0x86a8d39ef77164bc,0xae5dff9c02033197, - 0xa8530886b54dbdeb,0xd9f57f830283fdfc, - 0xd267caa862a12d66,0xd072df63c324fd7b, - 0x8380dea93da4bc60,0x4247cb9e59f71e6d, - 0xa46116538d0deb78,0x52d9be85f074e608, - 0xcd795be870516656,0x67902e276c921f8b, - 0x806bd9714632dff6,0xba1cd8a3db53b6, - 0xa086cfcd97bf97f3,0x80e8a40eccd228a4, - 0xc8a883c0fdaf7df0,0x6122cd128006b2cd, - 0xfad2a4b13d1b5d6c,0x796b805720085f81, - 0x9cc3a6eec6311a63,0xcbe3303674053bb0, - 0xc3f490aa77bd60fc,0xbedbfc4411068a9c, - 0xf4f1b4d515acb93b,0xee92fb5515482d44, - 0x991711052d8bf3c5,0x751bdd152d4d1c4a, - 0xbf5cd54678eef0b6,0xd262d45a78a0635d, - 0xef340a98172aace4,0x86fb897116c87c34, - 0x9580869f0e7aac0e,0xd45d35e6ae3d4da0, - 0xbae0a846d2195712,0x8974836059cca109, - 0xe998d258869facd7,0x2bd1a438703fc94b, - 0x91ff83775423cc06,0x7b6306a34627ddcf, - 0xb67f6455292cbf08,0x1a3bc84c17b1d542, - 0xe41f3d6a7377eeca,0x20caba5f1d9e4a93, - 0x8e938662882af53e,0x547eb47b7282ee9c, - 0xb23867fb2a35b28d,0xe99e619a4f23aa43, - 0xdec681f9f4c31f31,0x6405fa00e2ec94d4, - 0x8b3c113c38f9f37e,0xde83bc408dd3dd04, - 0xae0b158b4738705e,0x9624ab50b148d445, - 0xd98ddaee19068c76,0x3badd624dd9b0957, - 0x87f8a8d4cfa417c9,0xe54ca5d70a80e5d6, - 0xa9f6d30a038d1dbc,0x5e9fcf4ccd211f4c, - 0xd47487cc8470652b,0x7647c3200069671f, - 0x84c8d4dfd2c63f3b,0x29ecd9f40041e073, - 0xa5fb0a17c777cf09,0xf468107100525890, - 0xcf79cc9db955c2cc,0x7182148d4066eeb4, - 0x81ac1fe293d599bf,0xc6f14cd848405530, - 0xa21727db38cb002f,0xb8ada00e5a506a7c, - 0xca9cf1d206fdc03b,0xa6d90811f0e4851c, - 0xfd442e4688bd304a,0x908f4a166d1da663, - 0x9e4a9cec15763e2e,0x9a598e4e043287fe, - 0xc5dd44271ad3cdba,0x40eff1e1853f29fd, - 0xf7549530e188c128,0xd12bee59e68ef47c, - 0x9a94dd3e8cf578b9,0x82bb74f8301958ce, - 0xc13a148e3032d6e7,0xe36a52363c1faf01, - 0xf18899b1bc3f8ca1,0xdc44e6c3cb279ac1, - 0x96f5600f15a7b7e5,0x29ab103a5ef8c0b9, - 0xbcb2b812db11a5de,0x7415d448f6b6f0e7, - 0xebdf661791d60f56,0x111b495b3464ad21, - 0x936b9fcebb25c995,0xcab10dd900beec34, - 0xb84687c269ef3bfb,0x3d5d514f40eea742, - 0xe65829b3046b0afa,0xcb4a5a3112a5112, - 0x8ff71a0fe2c2e6dc,0x47f0e785eaba72ab, - 0xb3f4e093db73a093,0x59ed216765690f56, - 0xe0f218b8d25088b8,0x306869c13ec3532c, - 0x8c974f7383725573,0x1e414218c73a13fb, - 0xafbd2350644eeacf,0xe5d1929ef90898fa, - 0xdbac6c247d62a583,0xdf45f746b74abf39, - 0x894bc396ce5da772,0x6b8bba8c328eb783, - 0xab9eb47c81f5114f,0x66ea92f3f326564, - 0xd686619ba27255a2,0xc80a537b0efefebd, - 0x8613fd0145877585,0xbd06742ce95f5f36, - 0xa798fc4196e952e7,0x2c48113823b73704, - 0xd17f3b51fca3a7a0,0xf75a15862ca504c5, - 0x82ef85133de648c4,0x9a984d73dbe722fb, - 0xa3ab66580d5fdaf5,0xc13e60d0d2e0ebba, - 0xcc963fee10b7d1b3,0x318df905079926a8, - 0xffbbcfe994e5c61f,0xfdf17746497f7052, - 0x9fd561f1fd0f9bd3,0xfeb6ea8bedefa633, - 0xc7caba6e7c5382c8,0xfe64a52ee96b8fc0, - 0xf9bd690a1b68637b,0x3dfdce7aa3c673b0, - 0x9c1661a651213e2d,0x6bea10ca65c084e, - 0xc31bfa0fe5698db8,0x486e494fcff30a62, - 0xf3e2f893dec3f126,0x5a89dba3c3efccfa, - 0x986ddb5c6b3a76b7,0xf89629465a75e01c, - 0xbe89523386091465,0xf6bbb397f1135823, - 0xee2ba6c0678b597f,0x746aa07ded582e2c, - 0x94db483840b717ef,0xa8c2a44eb4571cdc, - 0xba121a4650e4ddeb,0x92f34d62616ce413, - 0xe896a0d7e51e1566,0x77b020baf9c81d17, - 0x915e2486ef32cd60,0xace1474dc1d122e, - 0xb5b5ada8aaff80b8,0xd819992132456ba, - 0xe3231912d5bf60e6,0x10e1fff697ed6c69, - 0x8df5efabc5979c8f,0xca8d3ffa1ef463c1, - 0xb1736b96b6fd83b3,0xbd308ff8a6b17cb2, - 0xddd0467c64bce4a0,0xac7cb3f6d05ddbde, - 0x8aa22c0dbef60ee4,0x6bcdf07a423aa96b, - 0xad4ab7112eb3929d,0x86c16c98d2c953c6, - 0xd89d64d57a607744,0xe871c7bf077ba8b7, - 0x87625f056c7c4a8b,0x11471cd764ad4972, - 0xa93af6c6c79b5d2d,0xd598e40d3dd89bcf, - 0xd389b47879823479,0x4aff1d108d4ec2c3, - 0x843610cb4bf160cb,0xcedf722a585139ba, - 0xa54394fe1eedb8fe,0xc2974eb4ee658828, - 0xce947a3da6a9273e,0x733d226229feea32, - 0x811ccc668829b887,0x806357d5a3f525f, - 0xa163ff802a3426a8,0xca07c2dcb0cf26f7, - 0xc9bcff6034c13052,0xfc89b393dd02f0b5, - 0xfc2c3f3841f17c67,0xbbac2078d443ace2, - 0x9d9ba7832936edc0,0xd54b944b84aa4c0d, - 0xc5029163f384a931,0xa9e795e65d4df11, - 0xf64335bcf065d37d,0x4d4617b5ff4a16d5, - 0x99ea0196163fa42e,0x504bced1bf8e4e45, - 0xc06481fb9bcf8d39,0xe45ec2862f71e1d6, - 0xf07da27a82c37088,0x5d767327bb4e5a4c, - 0x964e858c91ba2655,0x3a6a07f8d510f86f, - 0xbbe226efb628afea,0x890489f70a55368b, - 0xeadab0aba3b2dbe5,0x2b45ac74ccea842e, - 0x92c8ae6b464fc96f,0x3b0b8bc90012929d, - 0xb77ada0617e3bbcb,0x9ce6ebb40173744, - 0xe55990879ddcaabd,0xcc420a6a101d0515, - 0x8f57fa54c2a9eab6,0x9fa946824a12232d, - 0xb32df8e9f3546564,0x47939822dc96abf9, - 0xdff9772470297ebd,0x59787e2b93bc56f7, - 0x8bfbea76c619ef36,0x57eb4edb3c55b65a, - 0xaefae51477a06b03,0xede622920b6b23f1, - 0xdab99e59958885c4,0xe95fab368e45eced, - 0x88b402f7fd75539b,0x11dbcb0218ebb414, - 0xaae103b5fcd2a881,0xd652bdc29f26a119, - 0xd59944a37c0752a2,0x4be76d3346f0495f, - 0x857fcae62d8493a5,0x6f70a4400c562ddb, - 0xa6dfbd9fb8e5b88e,0xcb4ccd500f6bb952, - 0xd097ad07a71f26b2,0x7e2000a41346a7a7, - 0x825ecc24c873782f,0x8ed400668c0c28c8, - 0xa2f67f2dfa90563b,0x728900802f0f32fa, - 0xcbb41ef979346bca,0x4f2b40a03ad2ffb9, - 0xfea126b7d78186bc,0xe2f610c84987bfa8, - 0x9f24b832e6b0f436,0xdd9ca7d2df4d7c9, - 0xc6ede63fa05d3143,0x91503d1c79720dbb, - 0xf8a95fcf88747d94,0x75a44c6397ce912a, - 0x9b69dbe1b548ce7c,0xc986afbe3ee11aba, - 0xc24452da229b021b,0xfbe85badce996168, - 0xf2d56790ab41c2a2,0xfae27299423fb9c3, - 0x97c560ba6b0919a5,0xdccd879fc967d41a, - 0xbdb6b8e905cb600f,0x5400e987bbc1c920, - 0xed246723473e3813,0x290123e9aab23b68, - 0x9436c0760c86e30b,0xf9a0b6720aaf6521, - 0xb94470938fa89bce,0xf808e40e8d5b3e69, - 0xe7958cb87392c2c2,0xb60b1d1230b20e04, - 0x90bd77f3483bb9b9,0xb1c6f22b5e6f48c2, - 0xb4ecd5f01a4aa828,0x1e38aeb6360b1af3, - 0xe2280b6c20dd5232,0x25c6da63c38de1b0, - 0x8d590723948a535f,0x579c487e5a38ad0e, - 0xb0af48ec79ace837,0x2d835a9df0c6d851, - 0xdcdb1b2798182244,0xf8e431456cf88e65, - 0x8a08f0f8bf0f156b,0x1b8e9ecb641b58ff, - 0xac8b2d36eed2dac5,0xe272467e3d222f3f, - 0xd7adf884aa879177,0x5b0ed81dcc6abb0f, - 0x86ccbb52ea94baea,0x98e947129fc2b4e9, - 0xa87fea27a539e9a5,0x3f2398d747b36224, - 0xd29fe4b18e88640e,0x8eec7f0d19a03aad, - 0x83a3eeeef9153e89,0x1953cf68300424ac, - 0xa48ceaaab75a8e2b,0x5fa8c3423c052dd7, - 0xcdb02555653131b6,0x3792f412cb06794d, - 0x808e17555f3ebf11,0xe2bbd88bbee40bd0, - 0xa0b19d2ab70e6ed6,0x5b6aceaeae9d0ec4, - 0xc8de047564d20a8b,0xf245825a5a445275, - 0xfb158592be068d2e,0xeed6e2f0f0d56712, - 0x9ced737bb6c4183d,0x55464dd69685606b, - 0xc428d05aa4751e4c,0xaa97e14c3c26b886, - 0xf53304714d9265df,0xd53dd99f4b3066a8, - 0x993fe2c6d07b7fab,0xe546a8038efe4029, - 0xbf8fdb78849a5f96,0xde98520472bdd033, - 0xef73d256a5c0f77c,0x963e66858f6d4440, - 0x95a8637627989aad,0xdde7001379a44aa8, - 0xbb127c53b17ec159,0x5560c018580d5d52, - 0xe9d71b689dde71af,0xaab8f01e6e10b4a6, - 0x9226712162ab070d,0xcab3961304ca70e8, - 0xb6b00d69bb55c8d1,0x3d607b97c5fd0d22, - 0xe45c10c42a2b3b05,0x8cb89a7db77c506a, - 0x8eb98a7a9a5b04e3,0x77f3608e92adb242, - 0xb267ed1940f1c61c,0x55f038b237591ed3, - 0xdf01e85f912e37a3,0x6b6c46dec52f6688, - 0x8b61313bbabce2c6,0x2323ac4b3b3da015, - 0xae397d8aa96c1b77,0xabec975e0a0d081a, - 0xd9c7dced53c72255,0x96e7bd358c904a21, - 0x881cea14545c7575,0x7e50d64177da2e54, - 0xaa242499697392d2,0xdde50bd1d5d0b9e9, - 0xd4ad2dbfc3d07787,0x955e4ec64b44e864, - 0x84ec3c97da624ab4,0xbd5af13bef0b113e, - 0xa6274bbdd0fadd61,0xecb1ad8aeacdd58e, - 0xcfb11ead453994ba,0x67de18eda5814af2, - 0x81ceb32c4b43fcf4,0x80eacf948770ced7, - 0xa2425ff75e14fc31,0xa1258379a94d028d, - 0xcad2f7f5359a3b3e,0x96ee45813a04330, - 0xfd87b5f28300ca0d,0x8bca9d6e188853fc, - 0x9e74d1b791e07e48,0x775ea264cf55347e, - 0xc612062576589dda,0x95364afe032a819e, - 0xf79687aed3eec551,0x3a83ddbd83f52205, - 0x9abe14cd44753b52,0xc4926a9672793543, - 0xc16d9a0095928a27,0x75b7053c0f178294, - 0xf1c90080baf72cb1,0x5324c68b12dd6339, - 0x971da05074da7bee,0xd3f6fc16ebca5e04, - 0xbce5086492111aea,0x88f4bb1ca6bcf585, - 0xec1e4a7db69561a5,0x2b31e9e3d06c32e6, - 0x9392ee8e921d5d07,0x3aff322e62439fd0, - 0xb877aa3236a4b449,0x9befeb9fad487c3, - 0xe69594bec44de15b,0x4c2ebe687989a9b4, - 0x901d7cf73ab0acd9,0xf9d37014bf60a11, - 0xb424dc35095cd80f,0x538484c19ef38c95, - 0xe12e13424bb40e13,0x2865a5f206b06fba, - 0x8cbccc096f5088cb,0xf93f87b7442e45d4, - 0xafebff0bcb24aafe,0xf78f69a51539d749, - 0xdbe6fecebdedd5be,0xb573440e5a884d1c, - 0x89705f4136b4a597,0x31680a88f8953031, - 0xabcc77118461cefc,0xfdc20d2b36ba7c3e, - 0xd6bf94d5e57a42bc,0x3d32907604691b4d, - 0x8637bd05af6c69b5,0xa63f9a49c2c1b110, - 0xa7c5ac471b478423,0xfcf80dc33721d54, - 0xd1b71758e219652b,0xd3c36113404ea4a9, - 0x83126e978d4fdf3b,0x645a1cac083126ea, - 0xa3d70a3d70a3d70a,0x3d70a3d70a3d70a4, - 0xcccccccccccccccc,0xcccccccccccccccd, - 0x8000000000000000,0x0, - 0xa000000000000000,0x0, - 0xc800000000000000,0x0, - 0xfa00000000000000,0x0, - 0x9c40000000000000,0x0, - 0xc350000000000000,0x0, - 0xf424000000000000,0x0, - 0x9896800000000000,0x0, - 0xbebc200000000000,0x0, - 0xee6b280000000000,0x0, - 0x9502f90000000000,0x0, - 0xba43b74000000000,0x0, - 0xe8d4a51000000000,0x0, - 0x9184e72a00000000,0x0, - 0xb5e620f480000000,0x0, - 0xe35fa931a0000000,0x0, - 0x8e1bc9bf04000000,0x0, - 0xb1a2bc2ec5000000,0x0, - 0xde0b6b3a76400000,0x0, - 0x8ac7230489e80000,0x0, - 0xad78ebc5ac620000,0x0, - 0xd8d726b7177a8000,0x0, - 0x878678326eac9000,0x0, - 0xa968163f0a57b400,0x0, - 0xd3c21bcecceda100,0x0, - 0x84595161401484a0,0x0, - 0xa56fa5b99019a5c8,0x0, - 0xcecb8f27f4200f3a,0x0, - 0x813f3978f8940984,0x4000000000000000, - 0xa18f07d736b90be5,0x5000000000000000, - 0xc9f2c9cd04674ede,0xa400000000000000, - 0xfc6f7c4045812296,0x4d00000000000000, - 0x9dc5ada82b70b59d,0xf020000000000000, - 0xc5371912364ce305,0x6c28000000000000, - 0xf684df56c3e01bc6,0xc732000000000000, - 0x9a130b963a6c115c,0x3c7f400000000000, - 0xc097ce7bc90715b3,0x4b9f100000000000, - 0xf0bdc21abb48db20,0x1e86d40000000000, - 0x96769950b50d88f4,0x1314448000000000, - 0xbc143fa4e250eb31,0x17d955a000000000, - 0xeb194f8e1ae525fd,0x5dcfab0800000000, - 0x92efd1b8d0cf37be,0x5aa1cae500000000, - 0xb7abc627050305ad,0xf14a3d9e40000000, - 0xe596b7b0c643c719,0x6d9ccd05d0000000, - 0x8f7e32ce7bea5c6f,0xe4820023a2000000, - 0xb35dbf821ae4f38b,0xdda2802c8a800000, - 0xe0352f62a19e306e,0xd50b2037ad200000, - 0x8c213d9da502de45,0x4526f422cc340000, - 0xaf298d050e4395d6,0x9670b12b7f410000, - 0xdaf3f04651d47b4c,0x3c0cdd765f114000, - 0x88d8762bf324cd0f,0xa5880a69fb6ac800, - 0xab0e93b6efee0053,0x8eea0d047a457a00, - 0xd5d238a4abe98068,0x72a4904598d6d880, - 0x85a36366eb71f041,0x47a6da2b7f864750, - 0xa70c3c40a64e6c51,0x999090b65f67d924, - 0xd0cf4b50cfe20765,0xfff4b4e3f741cf6d, - 0x82818f1281ed449f,0xbff8f10e7a8921a4, - 0xa321f2d7226895c7,0xaff72d52192b6a0d, - 0xcbea6f8ceb02bb39,0x9bf4f8a69f764490, - 0xfee50b7025c36a08,0x2f236d04753d5b4, - 0x9f4f2726179a2245,0x1d762422c946590, - 0xc722f0ef9d80aad6,0x424d3ad2b7b97ef5, - 0xf8ebad2b84e0d58b,0xd2e0898765a7deb2, - 0x9b934c3b330c8577,0x63cc55f49f88eb2f, - 0xc2781f49ffcfa6d5,0x3cbf6b71c76b25fb, - 0xf316271c7fc3908a,0x8bef464e3945ef7a, - 0x97edd871cfda3a56,0x97758bf0e3cbb5ac, - 0xbde94e8e43d0c8ec,0x3d52eeed1cbea317, - 0xed63a231d4c4fb27,0x4ca7aaa863ee4bdd, - 0x945e455f24fb1cf8,0x8fe8caa93e74ef6a, - 0xb975d6b6ee39e436,0xb3e2fd538e122b44, - 0xe7d34c64a9c85d44,0x60dbbca87196b616, - 0x90e40fbeea1d3a4a,0xbc8955e946fe31cd, - 0xb51d13aea4a488dd,0x6babab6398bdbe41, - 0xe264589a4dcdab14,0xc696963c7eed2dd1, - 0x8d7eb76070a08aec,0xfc1e1de5cf543ca2, - 0xb0de65388cc8ada8,0x3b25a55f43294bcb, - 0xdd15fe86affad912,0x49ef0eb713f39ebe, - 0x8a2dbf142dfcc7ab,0x6e3569326c784337, - 0xacb92ed9397bf996,0x49c2c37f07965404, - 0xd7e77a8f87daf7fb,0xdc33745ec97be906, - 0x86f0ac99b4e8dafd,0x69a028bb3ded71a3, - 0xa8acd7c0222311bc,0xc40832ea0d68ce0c, - 0xd2d80db02aabd62b,0xf50a3fa490c30190, - 0x83c7088e1aab65db,0x792667c6da79e0fa, - 0xa4b8cab1a1563f52,0x577001b891185938, - 0xcde6fd5e09abcf26,0xed4c0226b55e6f86, - 0x80b05e5ac60b6178,0x544f8158315b05b4, - 0xa0dc75f1778e39d6,0x696361ae3db1c721, - 0xc913936dd571c84c,0x3bc3a19cd1e38e9, - 0xfb5878494ace3a5f,0x4ab48a04065c723, - 0x9d174b2dcec0e47b,0x62eb0d64283f9c76, - 0xc45d1df942711d9a,0x3ba5d0bd324f8394, - 0xf5746577930d6500,0xca8f44ec7ee36479, - 0x9968bf6abbe85f20,0x7e998b13cf4e1ecb, - 0xbfc2ef456ae276e8,0x9e3fedd8c321a67e, - 0xefb3ab16c59b14a2,0xc5cfe94ef3ea101e, - 0x95d04aee3b80ece5,0xbba1f1d158724a12, - 0xbb445da9ca61281f,0x2a8a6e45ae8edc97, - 0xea1575143cf97226,0xf52d09d71a3293bd, - 0x924d692ca61be758,0x593c2626705f9c56, - 0xb6e0c377cfa2e12e,0x6f8b2fb00c77836c, - 0xe498f455c38b997a,0xb6dfb9c0f956447, - 0x8edf98b59a373fec,0x4724bd4189bd5eac, - 0xb2977ee300c50fe7,0x58edec91ec2cb657, - 0xdf3d5e9bc0f653e1,0x2f2967b66737e3ed, - 0x8b865b215899f46c,0xbd79e0d20082ee74, - 0xae67f1e9aec07187,0xecd8590680a3aa11, - 0xda01ee641a708de9,0xe80e6f4820cc9495, - 0x884134fe908658b2,0x3109058d147fdcdd, - 0xaa51823e34a7eede,0xbd4b46f0599fd415, - 0xd4e5e2cdc1d1ea96,0x6c9e18ac7007c91a, - 0x850fadc09923329e,0x3e2cf6bc604ddb0, - 0xa6539930bf6bff45,0x84db8346b786151c, - 0xcfe87f7cef46ff16,0xe612641865679a63, - 0x81f14fae158c5f6e,0x4fcb7e8f3f60c07e, - 0xa26da3999aef7749,0xe3be5e330f38f09d, - 0xcb090c8001ab551c,0x5cadf5bfd3072cc5, - 0xfdcb4fa002162a63,0x73d9732fc7c8f7f6, - 0x9e9f11c4014dda7e,0x2867e7fddcdd9afa, - 0xc646d63501a1511d,0xb281e1fd541501b8, - 0xf7d88bc24209a565,0x1f225a7ca91a4226, - 0x9ae757596946075f,0x3375788de9b06958, - 0xc1a12d2fc3978937,0x52d6b1641c83ae, - 0xf209787bb47d6b84,0xc0678c5dbd23a49a, - 0x9745eb4d50ce6332,0xf840b7ba963646e0, - 0xbd176620a501fbff,0xb650e5a93bc3d898, - 0xec5d3fa8ce427aff,0xa3e51f138ab4cebe, - 0x93ba47c980e98cdf,0xc66f336c36b10137, - 0xb8a8d9bbe123f017,0xb80b0047445d4184, - 0xe6d3102ad96cec1d,0xa60dc059157491e5, - 0x9043ea1ac7e41392,0x87c89837ad68db2f, - 0xb454e4a179dd1877,0x29babe4598c311fb, - 0xe16a1dc9d8545e94,0xf4296dd6fef3d67a, - 0x8ce2529e2734bb1d,0x1899e4a65f58660c, - 0xb01ae745b101e9e4,0x5ec05dcff72e7f8f, - 0xdc21a1171d42645d,0x76707543f4fa1f73, - 0x899504ae72497eba,0x6a06494a791c53a8, - 0xabfa45da0edbde69,0x487db9d17636892, - 0xd6f8d7509292d603,0x45a9d2845d3c42b6, - 0x865b86925b9bc5c2,0xb8a2392ba45a9b2, - 0xa7f26836f282b732,0x8e6cac7768d7141e, - 0xd1ef0244af2364ff,0x3207d795430cd926, - 0x8335616aed761f1f,0x7f44e6bd49e807b8, - 0xa402b9c5a8d3a6e7,0x5f16206c9c6209a6, - 0xcd036837130890a1,0x36dba887c37a8c0f, - 0x802221226be55a64,0xc2494954da2c9789, - 0xa02aa96b06deb0fd,0xf2db9baa10b7bd6c, - 0xc83553c5c8965d3d,0x6f92829494e5acc7, - 0xfa42a8b73abbf48c,0xcb772339ba1f17f9, - 0x9c69a97284b578d7,0xff2a760414536efb, - 0xc38413cf25e2d70d,0xfef5138519684aba, - 0xf46518c2ef5b8cd1,0x7eb258665fc25d69, - 0x98bf2f79d5993802,0xef2f773ffbd97a61, - 0xbeeefb584aff8603,0xaafb550ffacfd8fa, - 0xeeaaba2e5dbf6784,0x95ba2a53f983cf38, - 0x952ab45cfa97a0b2,0xdd945a747bf26183, - 0xba756174393d88df,0x94f971119aeef9e4, - 0xe912b9d1478ceb17,0x7a37cd5601aab85d, - 0x91abb422ccb812ee,0xac62e055c10ab33a, - 0xb616a12b7fe617aa,0x577b986b314d6009, - 0xe39c49765fdf9d94,0xed5a7e85fda0b80b, - 0x8e41ade9fbebc27d,0x14588f13be847307, - 0xb1d219647ae6b31c,0x596eb2d8ae258fc8, - 0xde469fbd99a05fe3,0x6fca5f8ed9aef3bb, - 0x8aec23d680043bee,0x25de7bb9480d5854, - 0xada72ccc20054ae9,0xaf561aa79a10ae6a, - 0xd910f7ff28069da4,0x1b2ba1518094da04, - 0x87aa9aff79042286,0x90fb44d2f05d0842, - 0xa99541bf57452b28,0x353a1607ac744a53, - 0xd3fa922f2d1675f2,0x42889b8997915ce8, - 0x847c9b5d7c2e09b7,0x69956135febada11, - 0xa59bc234db398c25,0x43fab9837e699095, - 0xcf02b2c21207ef2e,0x94f967e45e03f4bb, - 0x8161afb94b44f57d,0x1d1be0eebac278f5, - 0xa1ba1ba79e1632dc,0x6462d92a69731732, - 0xca28a291859bbf93,0x7d7b8f7503cfdcfe, - 0xfcb2cb35e702af78,0x5cda735244c3d43e, - 0x9defbf01b061adab,0x3a0888136afa64a7, - 0xc56baec21c7a1916,0x88aaa1845b8fdd0, - 0xf6c69a72a3989f5b,0x8aad549e57273d45, - 0x9a3c2087a63f6399,0x36ac54e2f678864b, - 0xc0cb28a98fcf3c7f,0x84576a1bb416a7dd, - 0xf0fdf2d3f3c30b9f,0x656d44a2a11c51d5, - 0x969eb7c47859e743,0x9f644ae5a4b1b325, - 0xbc4665b596706114,0x873d5d9f0dde1fee, - 0xeb57ff22fc0c7959,0xa90cb506d155a7ea, - 0x9316ff75dd87cbd8,0x9a7f12442d588f2, - 0xb7dcbf5354e9bece,0xc11ed6d538aeb2f, - 0xe5d3ef282a242e81,0x8f1668c8a86da5fa, - 0x8fa475791a569d10,0xf96e017d694487bc, - 0xb38d92d760ec4455,0x37c981dcc395a9ac, - 0xe070f78d3927556a,0x85bbe253f47b1417, - 0x8c469ab843b89562,0x93956d7478ccec8e, - 0xaf58416654a6babb,0x387ac8d1970027b2, - 0xdb2e51bfe9d0696a,0x6997b05fcc0319e, - 0x88fcf317f22241e2,0x441fece3bdf81f03, - 0xab3c2fddeeaad25a,0xd527e81cad7626c3, - 0xd60b3bd56a5586f1,0x8a71e223d8d3b074, - 0x85c7056562757456,0xf6872d5667844e49, - 0xa738c6bebb12d16c,0xb428f8ac016561db, - 0xd106f86e69d785c7,0xe13336d701beba52, - 0x82a45b450226b39c,0xecc0024661173473, - 0xa34d721642b06084,0x27f002d7f95d0190, - 0xcc20ce9bd35c78a5,0x31ec038df7b441f4, - 0xff290242c83396ce,0x7e67047175a15271, - 0x9f79a169bd203e41,0xf0062c6e984d386, - 0xc75809c42c684dd1,0x52c07b78a3e60868, - 0xf92e0c3537826145,0xa7709a56ccdf8a82, - 0x9bbcc7a142b17ccb,0x88a66076400bb691, - 0xc2abf989935ddbfe,0x6acff893d00ea435, - 0xf356f7ebf83552fe,0x583f6b8c4124d43, - 0x98165af37b2153de,0xc3727a337a8b704a, - 0xbe1bf1b059e9a8d6,0x744f18c0592e4c5c, - 0xeda2ee1c7064130c,0x1162def06f79df73, - 0x9485d4d1c63e8be7,0x8addcb5645ac2ba8, - 0xb9a74a0637ce2ee1,0x6d953e2bd7173692, - 0xe8111c87c5c1ba99,0xc8fa8db6ccdd0437, - 0x910ab1d4db9914a0,0x1d9c9892400a22a2, - 0xb54d5e4a127f59c8,0x2503beb6d00cab4b, - 0xe2a0b5dc971f303a,0x2e44ae64840fd61d, - 0x8da471a9de737e24,0x5ceaecfed289e5d2, - 0xb10d8e1456105dad,0x7425a83e872c5f47, - 0xdd50f1996b947518,0xd12f124e28f77719, - 0x8a5296ffe33cc92f,0x82bd6b70d99aaa6f, - 0xace73cbfdc0bfb7b,0x636cc64d1001550b, - 0xd8210befd30efa5a,0x3c47f7e05401aa4e, - 0x8714a775e3e95c78,0x65acfaec34810a71, - 0xa8d9d1535ce3b396,0x7f1839a741a14d0d, - 0xd31045a8341ca07c,0x1ede48111209a050, - 0x83ea2b892091e44d,0x934aed0aab460432, - 0xa4e4b66b68b65d60,0xf81da84d5617853f, - 0xce1de40642e3f4b9,0x36251260ab9d668e, - 0x80d2ae83e9ce78f3,0xc1d72b7c6b426019, - 0xa1075a24e4421730,0xb24cf65b8612f81f, - 0xc94930ae1d529cfc,0xdee033f26797b627, - 0xfb9b7cd9a4a7443c,0x169840ef017da3b1, - 0x9d412e0806e88aa5,0x8e1f289560ee864e, - 0xc491798a08a2ad4e,0xf1a6f2bab92a27e2, - 0xf5b5d7ec8acb58a2,0xae10af696774b1db, - 0x9991a6f3d6bf1765,0xacca6da1e0a8ef29, - 0xbff610b0cc6edd3f,0x17fd090a58d32af3, - 0xeff394dcff8a948e,0xddfc4b4cef07f5b0, - 0x95f83d0a1fb69cd9,0x4abdaf101564f98e, - 0xbb764c4ca7a4440f,0x9d6d1ad41abe37f1, - 0xea53df5fd18d5513,0x84c86189216dc5ed, - 0x92746b9be2f8552c,0x32fd3cf5b4e49bb4, - 0xb7118682dbb66a77,0x3fbc8c33221dc2a1, - 0xe4d5e82392a40515,0xfabaf3feaa5334a, - 0x8f05b1163ba6832d,0x29cb4d87f2a7400e, - 0xb2c71d5bca9023f8,0x743e20e9ef511012, - 0xdf78e4b2bd342cf6,0x914da9246b255416, - 0x8bab8eefb6409c1a,0x1ad089b6c2f7548e, - 0xae9672aba3d0c320,0xa184ac2473b529b1, - 0xda3c0f568cc4f3e8,0xc9e5d72d90a2741e, - 0x8865899617fb1871,0x7e2fa67c7a658892, - 0xaa7eebfb9df9de8d,0xddbb901b98feeab7, - 0xd51ea6fa85785631,0x552a74227f3ea565, - 0x8533285c936b35de,0xd53a88958f87275f, - 0xa67ff273b8460356,0x8a892abaf368f137, - 0xd01fef10a657842c,0x2d2b7569b0432d85, - 0x8213f56a67f6b29b,0x9c3b29620e29fc73, - 0xa298f2c501f45f42,0x8349f3ba91b47b8f, - 0xcb3f2f7642717713,0x241c70a936219a73, - 0xfe0efb53d30dd4d7,0xed238cd383aa0110, - 0x9ec95d1463e8a506,0xf4363804324a40aa, - 0xc67bb4597ce2ce48,0xb143c6053edcd0d5, - 0xf81aa16fdc1b81da,0xdd94b7868e94050a, - 0x9b10a4e5e9913128,0xca7cf2b4191c8326, - 0xc1d4ce1f63f57d72,0xfd1c2f611f63a3f0, - 0xf24a01a73cf2dccf,0xbc633b39673c8cec, - 0x976e41088617ca01,0xd5be0503e085d813, - 0xbd49d14aa79dbc82,0x4b2d8644d8a74e18, - 0xec9c459d51852ba2,0xddf8e7d60ed1219e, - 0x93e1ab8252f33b45,0xcabb90e5c942b503, - 0xb8da1662e7b00a17,0x3d6a751f3b936243, - 0xe7109bfba19c0c9d,0xcc512670a783ad4, - 0x906a617d450187e2,0x27fb2b80668b24c5, - 0xb484f9dc9641e9da,0xb1f9f660802dedf6, - 0xe1a63853bbd26451,0x5e7873f8a0396973, - 0x8d07e33455637eb2,0xdb0b487b6423e1e8, - 0xb049dc016abc5e5f,0x91ce1a9a3d2cda62, - 0xdc5c5301c56b75f7,0x7641a140cc7810fb, - 0x89b9b3e11b6329ba,0xa9e904c87fcb0a9d, - 0xac2820d9623bf429,0x546345fa9fbdcd44, - 0xd732290fbacaf133,0xa97c177947ad4095, - 0x867f59a9d4bed6c0,0x49ed8eabcccc485d, - 0xa81f301449ee8c70,0x5c68f256bfff5a74, - 0xd226fc195c6a2f8c,0x73832eec6fff3111, - 0x83585d8fd9c25db7,0xc831fd53c5ff7eab, - 0xa42e74f3d032f525,0xba3e7ca8b77f5e55, - 0xcd3a1230c43fb26f,0x28ce1bd2e55f35eb, - 0x80444b5e7aa7cf85,0x7980d163cf5b81b3, - 0xa0555e361951c366,0xd7e105bcc332621f, - 0xc86ab5c39fa63440,0x8dd9472bf3fefaa7, - 0xfa856334878fc150,0xb14f98f6f0feb951, - 0x9c935e00d4b9d8d2,0x6ed1bf9a569f33d3, - 0xc3b8358109e84f07,0xa862f80ec4700c8, - 0xf4a642e14c6262c8,0xcd27bb612758c0fa, - 0x98e7e9cccfbd7dbd,0x8038d51cb897789c, - 0xbf21e44003acdd2c,0xe0470a63e6bd56c3, - 0xeeea5d5004981478,0x1858ccfce06cac74, - 0x95527a5202df0ccb,0xf37801e0c43ebc8, - 0xbaa718e68396cffd,0xd30560258f54e6ba, - 0xe950df20247c83fd,0x47c6b82ef32a2069, - 0x91d28b7416cdd27e,0x4cdc331d57fa5441, - 0xb6472e511c81471d,0xe0133fe4adf8e952, - 0xe3d8f9e563a198e5,0x58180fddd97723a6, - 0x8e679c2f5e44ff8f,0x570f09eaa7ea7648,}; -using powers = powers_template<>; - -} - -#endif - - -#ifndef FASTFLOAT_DECIMAL_TO_BINARY_H -#define FASTFLOAT_DECIMAL_TO_BINARY_H - -#include -#include -#include -#include -#include -#include - -namespace fast_float { - -// This will compute or rather approximate w * 5**q and return a pair of 64-bit words approximating -// the result, with the "high" part corresponding to the most significant bits and the -// low part corresponding to the least significant bits. -// -template -fastfloat_really_inline -value128 compute_product_approximation(int64_t q, uint64_t w) { - const int index = 2 * int(q - powers::smallest_power_of_five); - // For small values of q, e.g., q in [0,27], the answer is always exact because - // The line value128 firstproduct = full_multiplication(w, power_of_five_128[index]); - // gives the exact answer. - value128 firstproduct = full_multiplication(w, powers::power_of_five_128[index]); - static_assert((bit_precision >= 0) && (bit_precision <= 64), " precision should be in (0,64]"); - constexpr uint64_t precision_mask = (bit_precision < 64) ? - (uint64_t(0xFFFFFFFFFFFFFFFF) >> bit_precision) - : uint64_t(0xFFFFFFFFFFFFFFFF); - if((firstproduct.high & precision_mask) == precision_mask) { // could further guard with (lower + w < lower) - // regarding the second product, we only need secondproduct.high, but our expectation is that the compiler will optimize this extra work away if needed. - value128 secondproduct = full_multiplication(w, powers::power_of_five_128[index + 1]); - firstproduct.low += secondproduct.high; - if(secondproduct.high > firstproduct.low) { - firstproduct.high++; - } - } - return firstproduct; -} - -namespace detail { -/** - * For q in (0,350), we have that - * f = (((152170 + 65536) * q ) >> 16); - * is equal to - * floor(p) + q - * where - * p = log(5**q)/log(2) = q * log(5)/log(2) - * - * For negative values of q in (-400,0), we have that - * f = (((152170 + 65536) * q ) >> 16); - * is equal to - * -ceil(p) + q - * where - * p = log(5**-q)/log(2) = -q * log(5)/log(2) - */ - constexpr fastfloat_really_inline int32_t power(int32_t q) noexcept { - return (((152170 + 65536) * q) >> 16) + 63; - } -} // namespace detail - -// create an adjusted mantissa, biased by the invalid power2 -// for significant digits already multiplied by 10 ** q. -template -fastfloat_really_inline -adjusted_mantissa compute_error_scaled(int64_t q, uint64_t w, int lz) noexcept { - int hilz = int(w >> 63) ^ 1; - adjusted_mantissa answer; - answer.mantissa = w << hilz; - int bias = binary::mantissa_explicit_bits() - binary::minimum_exponent(); - answer.power2 = int32_t(detail::power(int32_t(q)) + bias - hilz - lz - 62 + invalid_am_bias); - return answer; -} - -// w * 10 ** q, without rounding the representation up. -// the power2 in the exponent will be adjusted by invalid_am_bias. -template -fastfloat_really_inline -adjusted_mantissa compute_error(int64_t q, uint64_t w) noexcept { - int lz = leading_zeroes(w); - w <<= lz; - value128 product = compute_product_approximation(q, w); - return compute_error_scaled(q, product.high, lz); -} - -// w * 10 ** q -// The returned value should be a valid ieee64 number that simply need to be packed. -// However, in some very rare cases, the computation will fail. In such cases, we -// return an adjusted_mantissa with a negative power of 2: the caller should recompute -// in such cases. -template -fastfloat_really_inline -adjusted_mantissa compute_float(int64_t q, uint64_t w) noexcept { - adjusted_mantissa answer; - if ((w == 0) || (q < binary::smallest_power_of_ten())) { - answer.power2 = 0; - answer.mantissa = 0; - // result should be zero - return answer; - } - if (q > binary::largest_power_of_ten()) { - // we want to get infinity: - answer.power2 = binary::infinite_power(); - answer.mantissa = 0; - return answer; - } - // At this point in time q is in [powers::smallest_power_of_five, powers::largest_power_of_five]. - - // We want the most significant bit of i to be 1. Shift if needed. - int lz = leading_zeroes(w); - w <<= lz; - - // The required precision is binary::mantissa_explicit_bits() + 3 because - // 1. We need the implicit bit - // 2. We need an extra bit for rounding purposes - // 3. We might lose a bit due to the "upperbit" routine (result too small, requiring a shift) - - value128 product = compute_product_approximation(q, w); - if(product.low == 0xFFFFFFFFFFFFFFFF) { // could guard it further - // In some very rare cases, this could happen, in which case we might need a more accurate - // computation that what we can provide cheaply. This is very, very unlikely. - // - const bool inside_safe_exponent = (q >= -27) && (q <= 55); // always good because 5**q <2**128 when q>=0, - // and otherwise, for q<0, we have 5**-q<2**64 and the 128-bit reciprocal allows for exact computation. - if(!inside_safe_exponent) { - return compute_error_scaled(q, product.high, lz); - } - } - // The "compute_product_approximation" function can be slightly slower than a branchless approach: - // value128 product = compute_product(q, w); - // but in practice, we can win big with the compute_product_approximation if its additional branch - // is easily predicted. Which is best is data specific. - int upperbit = int(product.high >> 63); - - answer.mantissa = product.high >> (upperbit + 64 - binary::mantissa_explicit_bits() - 3); - - answer.power2 = int32_t(detail::power(int32_t(q)) + upperbit - lz - binary::minimum_exponent()); - if (answer.power2 <= 0) { // we have a subnormal? - // Here have that answer.power2 <= 0 so -answer.power2 >= 0 - if(-answer.power2 + 1 >= 64) { // if we have more than 64 bits below the minimum exponent, you have a zero for sure. - answer.power2 = 0; - answer.mantissa = 0; - // result should be zero - return answer; - } - // next line is safe because -answer.power2 + 1 < 64 - answer.mantissa >>= -answer.power2 + 1; - // Thankfully, we can't have both "round-to-even" and subnormals because - // "round-to-even" only occurs for powers close to 0. - answer.mantissa += (answer.mantissa & 1); // round up - answer.mantissa >>= 1; - // There is a weird scenario where we don't have a subnormal but just. - // Suppose we start with 2.2250738585072013e-308, we end up - // with 0x3fffffffffffff x 2^-1023-53 which is technically subnormal - // whereas 0x40000000000000 x 2^-1023-53 is normal. Now, we need to round - // up 0x3fffffffffffff x 2^-1023-53 and once we do, we are no longer - // subnormal, but we can only know this after rounding. - // So we only declare a subnormal if we are smaller than the threshold. - answer.power2 = (answer.mantissa < (uint64_t(1) << binary::mantissa_explicit_bits())) ? 0 : 1; - return answer; - } - - // usually, we round *up*, but if we fall right in between and and we have an - // even basis, we need to round down - // We are only concerned with the cases where 5**q fits in single 64-bit word. - if ((product.low <= 1) && (q >= binary::min_exponent_round_to_even()) && (q <= binary::max_exponent_round_to_even()) && - ((answer.mantissa & 3) == 1) ) { // we may fall between two floats! - // To be in-between two floats we need that in doing - // answer.mantissa = product.high >> (upperbit + 64 - binary::mantissa_explicit_bits() - 3); - // ... we dropped out only zeroes. But if this happened, then we can go back!!! - if((answer.mantissa << (upperbit + 64 - binary::mantissa_explicit_bits() - 3)) == product.high) { - answer.mantissa &= ~uint64_t(1); // flip it so that we do not round up - } - } - - answer.mantissa += (answer.mantissa & 1); // round up - answer.mantissa >>= 1; - if (answer.mantissa >= (uint64_t(2) << binary::mantissa_explicit_bits())) { - answer.mantissa = (uint64_t(1) << binary::mantissa_explicit_bits()); - answer.power2++; // undo previous addition - } - - answer.mantissa &= ~(uint64_t(1) << binary::mantissa_explicit_bits()); - if (answer.power2 >= binary::infinite_power()) { // infinity - answer.power2 = binary::infinite_power(); - answer.mantissa = 0; - } - return answer; -} - -} // namespace fast_float - -#endif - - -#ifndef FASTFLOAT_BIGINT_H -#define FASTFLOAT_BIGINT_H - -#include -#include -#include -#include - - -namespace fast_float { - -// the limb width: we want efficient multiplication of double the bits in -// limb, or for 64-bit limbs, at least 64-bit multiplication where we can -// extract the high and low parts efficiently. this is every 64-bit -// architecture except for sparc, which emulates 128-bit multiplication. -// we might have platforms where `CHAR_BIT` is not 8, so let's avoid -// doing `8 * sizeof(limb)`. -#if defined(FASTFLOAT_64BIT) && !defined(__sparc) -#define FASTFLOAT_64BIT_LIMB -typedef uint64_t limb; -constexpr size_t limb_bits = 64; -#else -#define FASTFLOAT_32BIT_LIMB -typedef uint32_t limb; -constexpr size_t limb_bits = 32; -#endif - -typedef span limb_span; - -// number of bits in a bigint. this needs to be at least the number -// of bits required to store the largest bigint, which is -// `log2(10**(digits + max_exp))`, or `log2(10**(767 + 342))`, or -// ~3600 bits, so we round to 4000. -constexpr size_t bigint_bits = 4000; -constexpr size_t bigint_limbs = bigint_bits / limb_bits; - -// vector-like type that is allocated on the stack. the entire -// buffer is pre-allocated, and only the length changes. -template -struct stackvec { - limb data[size]; - // we never need more than 150 limbs - uint16_t length{0}; - - stackvec() = default; - stackvec(const stackvec &) = delete; - stackvec &operator=(const stackvec &) = delete; - stackvec(stackvec &&) = delete; - stackvec &operator=(stackvec &&other) = delete; - - // create stack vector from existing limb span. - stackvec(limb_span s) { - FASTFLOAT_ASSERT(try_extend(s)); - } - - limb& operator[](size_t index) noexcept { - FASTFLOAT_DEBUG_ASSERT(index < length); - return data[index]; - } - const limb& operator[](size_t index) const noexcept { - FASTFLOAT_DEBUG_ASSERT(index < length); - return data[index]; - } - // index from the end of the container - const limb& rindex(size_t index) const noexcept { - FASTFLOAT_DEBUG_ASSERT(index < length); - size_t rindex = length - index - 1; - return data[rindex]; - } - - // set the length, without bounds checking. - void set_len(size_t len) noexcept { - length = uint16_t(len); - } - constexpr size_t len() const noexcept { - return length; - } - constexpr bool is_empty() const noexcept { - return length == 0; - } - constexpr size_t capacity() const noexcept { - return size; - } - // append item to vector, without bounds checking - void push_unchecked(limb value) noexcept { - data[length] = value; - length++; - } - // append item to vector, returning if item was added - bool try_push(limb value) noexcept { - if (len() < capacity()) { - push_unchecked(value); - return true; - } else { - return false; - } - } - // add items to the vector, from a span, without bounds checking - void extend_unchecked(limb_span s) noexcept { - limb* ptr = data + length; - ::memcpy((void*)ptr, (const void*)s.ptr, sizeof(limb) * s.len()); - set_len(len() + s.len()); - } - // try to add items to the vector, returning if items were added - bool try_extend(limb_span s) noexcept { - if (len() + s.len() <= capacity()) { - extend_unchecked(s); - return true; - } else { - return false; - } - } - // resize the vector, without bounds checking - // if the new size is longer than the vector, assign value to each - // appended item. - void resize_unchecked(size_t new_len, limb value) noexcept { - if (new_len > len()) { - size_t count = new_len - len(); - limb* first = data + len(); - limb* last = first + count; - ::std::fill(first, last, value); - set_len(new_len); - } else { - set_len(new_len); - } - } - // try to resize the vector, returning if the vector was resized. - bool try_resize(size_t new_len, limb value) noexcept { - if (new_len > capacity()) { - return false; - } else { - resize_unchecked(new_len, value); - return true; - } - } - // check if any limbs are non-zero after the given index. - // this needs to be done in reverse order, since the index - // is relative to the most significant limbs. - bool nonzero(size_t index) const noexcept { - while (index < len()) { - if (rindex(index) != 0) { - return true; - } - index++; - } - return false; - } - // normalize the big integer, so most-significant zero limbs are removed. - void normalize() noexcept { - while (len() > 0 && rindex(0) == 0) { - length--; - } - } -}; - -fastfloat_really_inline -uint64_t empty_hi64(bool& truncated) noexcept { - truncated = false; - return 0; -} - -fastfloat_really_inline -uint64_t uint64_hi64(uint64_t r0, bool& truncated) noexcept { - truncated = false; - int shl = leading_zeroes(r0); - return r0 << shl; -} - -fastfloat_really_inline -uint64_t uint64_hi64(uint64_t r0, uint64_t r1, bool& truncated) noexcept { - int shl = leading_zeroes(r0); - if (shl == 0) { - truncated = r1 != 0; - return r0; - } else { - int shr = 64 - shl; - truncated = (r1 << shl) != 0; - return (r0 << shl) | (r1 >> shr); - } -} - -fastfloat_really_inline -uint64_t uint32_hi64(uint32_t r0, bool& truncated) noexcept { - return uint64_hi64(r0, truncated); -} - -fastfloat_really_inline -uint64_t uint32_hi64(uint32_t r0, uint32_t r1, bool& truncated) noexcept { - uint64_t x0 = r0; - uint64_t x1 = r1; - return uint64_hi64((x0 << 32) | x1, truncated); -} - -fastfloat_really_inline -uint64_t uint32_hi64(uint32_t r0, uint32_t r1, uint32_t r2, bool& truncated) noexcept { - uint64_t x0 = r0; - uint64_t x1 = r1; - uint64_t x2 = r2; - return uint64_hi64(x0, (x1 << 32) | x2, truncated); -} - -// add two small integers, checking for overflow. -// we want an efficient operation. for msvc, where -// we don't have built-in intrinsics, this is still -// pretty fast. -fastfloat_really_inline -limb scalar_add(limb x, limb y, bool& overflow) noexcept { - limb z; - -// gcc and clang -#if defined(__has_builtin) - #if __has_builtin(__builtin_add_overflow) - overflow = __builtin_add_overflow(x, y, &z); - return z; - #endif -#endif - - // generic, this still optimizes correctly on MSVC. - z = x + y; - overflow = z < x; - return z; -} - -// multiply two small integers, getting both the high and low bits. -fastfloat_really_inline -limb scalar_mul(limb x, limb y, limb& carry) noexcept { -#ifdef FASTFLOAT_64BIT_LIMB - #if defined(__SIZEOF_INT128__) - // GCC and clang both define it as an extension. - __uint128_t z = __uint128_t(x) * __uint128_t(y) + __uint128_t(carry); - carry = limb(z >> limb_bits); - return limb(z); - #else - // fallback, no native 128-bit integer multiplication with carry. - // on msvc, this optimizes identically, somehow. - value128 z = full_multiplication(x, y); - bool overflow; - z.low = scalar_add(z.low, carry, overflow); - z.high += uint64_t(overflow); // cannot overflow - carry = z.high; - return z.low; - #endif -#else - uint64_t z = uint64_t(x) * uint64_t(y) + uint64_t(carry); - carry = limb(z >> limb_bits); - return limb(z); -#endif -} - -// add scalar value to bigint starting from offset. -// used in grade school multiplication -template -inline bool small_add_from(stackvec& vec, limb y, size_t start) noexcept { - size_t index = start; - limb carry = y; - bool overflow; - while (carry != 0 && index < vec.len()) { - vec[index] = scalar_add(vec[index], carry, overflow); - carry = limb(overflow); - index += 1; - } - if (carry != 0) { - FASTFLOAT_TRY(vec.try_push(carry)); - } - return true; -} - -// add scalar value to bigint. -template -fastfloat_really_inline bool small_add(stackvec& vec, limb y) noexcept { - return small_add_from(vec, y, 0); -} - -// multiply bigint by scalar value. -template -inline bool small_mul(stackvec& vec, limb y) noexcept { - limb carry = 0; - for (size_t index = 0; index < vec.len(); index++) { - vec[index] = scalar_mul(vec[index], y, carry); - } - if (carry != 0) { - FASTFLOAT_TRY(vec.try_push(carry)); - } - return true; -} - -// add bigint to bigint starting from index. -// used in grade school multiplication -template -bool large_add_from(stackvec& x, limb_span y, size_t start) noexcept { - // the effective x buffer is from `xstart..x.len()`, so exit early - // if we can't get that current range. - if (x.len() < start || y.len() > x.len() - start) { - FASTFLOAT_TRY(x.try_resize(y.len() + start, 0)); - } - - bool carry = false; - for (size_t index = 0; index < y.len(); index++) { - limb xi = x[index + start]; - limb yi = y[index]; - bool c1 = false; - bool c2 = false; - xi = scalar_add(xi, yi, c1); - if (carry) { - xi = scalar_add(xi, 1, c2); - } - x[index + start] = xi; - carry = c1 | c2; - } - - // handle overflow - if (carry) { - FASTFLOAT_TRY(small_add_from(x, 1, y.len() + start)); - } - return true; -} - -// add bigint to bigint. -template -fastfloat_really_inline bool large_add_from(stackvec& x, limb_span y) noexcept { - return large_add_from(x, y, 0); -} - -// grade-school multiplication algorithm -template -bool long_mul(stackvec& x, limb_span y) noexcept { - limb_span xs = limb_span(x.data, x.len()); - stackvec z(xs); - limb_span zs = limb_span(z.data, z.len()); - - if (y.len() != 0) { - limb y0 = y[0]; - FASTFLOAT_TRY(small_mul(x, y0)); - for (size_t index = 1; index < y.len(); index++) { - limb yi = y[index]; - stackvec zi; - if (yi != 0) { - // re-use the same buffer throughout - zi.set_len(0); - FASTFLOAT_TRY(zi.try_extend(zs)); - FASTFLOAT_TRY(small_mul(zi, yi)); - limb_span zis = limb_span(zi.data, zi.len()); - FASTFLOAT_TRY(large_add_from(x, zis, index)); - } - } - } - - x.normalize(); - return true; -} - -// grade-school multiplication algorithm -template -bool large_mul(stackvec& x, limb_span y) noexcept { - if (y.len() == 1) { - FASTFLOAT_TRY(small_mul(x, y[0])); - } else { - FASTFLOAT_TRY(long_mul(x, y)); - } - return true; -} - -// big integer type. implements a small subset of big integer -// arithmetic, using simple algorithms since asymptotically -// faster algorithms are slower for a small number of limbs. -// all operations assume the big-integer is normalized. -struct bigint { - // storage of the limbs, in little-endian order. - stackvec vec; - - bigint(): vec() {} - bigint(const bigint &) = delete; - bigint &operator=(const bigint &) = delete; - bigint(bigint &&) = delete; - bigint &operator=(bigint &&other) = delete; - - bigint(uint64_t value): vec() { -#ifdef FASTFLOAT_64BIT_LIMB - vec.push_unchecked(value); -#else - vec.push_unchecked(uint32_t(value)); - vec.push_unchecked(uint32_t(value >> 32)); -#endif - vec.normalize(); - } - - // get the high 64 bits from the vector, and if bits were truncated. - // this is to get the significant digits for the float. - uint64_t hi64(bool& truncated) const noexcept { -#ifdef FASTFLOAT_64BIT_LIMB - if (vec.len() == 0) { - return empty_hi64(truncated); - } else if (vec.len() == 1) { - return uint64_hi64(vec.rindex(0), truncated); - } else { - uint64_t result = uint64_hi64(vec.rindex(0), vec.rindex(1), truncated); - truncated |= vec.nonzero(2); - return result; - } -#else - if (vec.len() == 0) { - return empty_hi64(truncated); - } else if (vec.len() == 1) { - return uint32_hi64(vec.rindex(0), truncated); - } else if (vec.len() == 2) { - return uint32_hi64(vec.rindex(0), vec.rindex(1), truncated); - } else { - uint64_t result = uint32_hi64(vec.rindex(0), vec.rindex(1), vec.rindex(2), truncated); - truncated |= vec.nonzero(3); - return result; - } -#endif - } - - // compare two big integers, returning the large value. - // assumes both are normalized. if the return value is - // negative, other is larger, if the return value is - // positive, this is larger, otherwise they are equal. - // the limbs are stored in little-endian order, so we - // must compare the limbs in ever order. - int compare(const bigint& other) const noexcept { - if (vec.len() > other.vec.len()) { - return 1; - } else if (vec.len() < other.vec.len()) { - return -1; - } else { - for (size_t index = vec.len(); index > 0; index--) { - limb xi = vec[index - 1]; - limb yi = other.vec[index - 1]; - if (xi > yi) { - return 1; - } else if (xi < yi) { - return -1; - } - } - return 0; - } - } - - // shift left each limb n bits, carrying over to the new limb - // returns true if we were able to shift all the digits. - bool shl_bits(size_t n) noexcept { - // Internally, for each item, we shift left by n, and add the previous - // right shifted limb-bits. - // For example, we transform (for u8) shifted left 2, to: - // b10100100 b01000010 - // b10 b10010001 b00001000 - FASTFLOAT_DEBUG_ASSERT(n != 0); - FASTFLOAT_DEBUG_ASSERT(n < sizeof(limb) * 8); - - size_t shl = n; - size_t shr = limb_bits - shl; - limb prev = 0; - for (size_t index = 0; index < vec.len(); index++) { - limb xi = vec[index]; - vec[index] = (xi << shl) | (prev >> shr); - prev = xi; - } - - limb carry = prev >> shr; - if (carry != 0) { - return vec.try_push(carry); - } - return true; - } - - // move the limbs left by `n` limbs. - bool shl_limbs(size_t n) noexcept { - FASTFLOAT_DEBUG_ASSERT(n != 0); - if (n + vec.len() > vec.capacity()) { - return false; - } else if (!vec.is_empty()) { - // move limbs - limb* dst = vec.data + n; - const limb* src = vec.data; - ::memmove(dst, src, sizeof(limb) * vec.len()); - // fill in empty limbs - limb* first = vec.data; - limb* last = first + n; - ::std::fill(first, last, 0); - vec.set_len(n + vec.len()); - return true; - } else { - return true; - } - } - - // move the limbs left by `n` bits. - bool shl(size_t n) noexcept { - size_t rem = n % limb_bits; - size_t div = n / limb_bits; - if (rem != 0) { - FASTFLOAT_TRY(shl_bits(rem)); - } - if (div != 0) { - FASTFLOAT_TRY(shl_limbs(div)); - } - return true; - } - - // get the number of leading zeros in the bigint. - int ctlz() const noexcept { - if (vec.is_empty()) { - return 0; - } else { -#ifdef FASTFLOAT_64BIT_LIMB - return leading_zeroes(vec.rindex(0)); -#else - // no use defining a specialized leading_zeroes for a 32-bit type. - uint64_t r0 = vec.rindex(0); - return leading_zeroes(r0 << 32); -#endif - } - } - - // get the number of bits in the bigint. - int bit_length() const noexcept { - int lz = ctlz(); - return int(limb_bits * vec.len()) - lz; - } - - bool mul(limb y) noexcept { - return small_mul(vec, y); - } - - bool add(limb y) noexcept { - return small_add(vec, y); - } - - // multiply as if by 2 raised to a power. - bool pow2(uint32_t exp) noexcept { - return shl(exp); - } - - // multiply as if by 5 raised to a power. - bool pow5(uint32_t exp) noexcept { - // multiply by a power of 5 - static constexpr uint32_t large_step = 135; - static constexpr uint64_t small_power_of_5[] = { - 1UL, 5UL, 25UL, 125UL, 625UL, 3125UL, 15625UL, 78125UL, 390625UL, - 1953125UL, 9765625UL, 48828125UL, 244140625UL, 1220703125UL, - 6103515625UL, 30517578125UL, 152587890625UL, 762939453125UL, - 3814697265625UL, 19073486328125UL, 95367431640625UL, 476837158203125UL, - 2384185791015625UL, 11920928955078125UL, 59604644775390625UL, - 298023223876953125UL, 1490116119384765625UL, 7450580596923828125UL, - }; -#ifdef FASTFLOAT_64BIT_LIMB - constexpr static limb large_power_of_5[] = { - 1414648277510068013UL, 9180637584431281687UL, 4539964771860779200UL, - 10482974169319127550UL, 198276706040285095UL}; -#else - constexpr static limb large_power_of_5[] = { - 4279965485U, 329373468U, 4020270615U, 2137533757U, 4287402176U, - 1057042919U, 1071430142U, 2440757623U, 381945767U, 46164893U}; -#endif - size_t large_length = sizeof(large_power_of_5) / sizeof(limb); - limb_span large = limb_span(large_power_of_5, large_length); - while (exp >= large_step) { - FASTFLOAT_TRY(large_mul(vec, large)); - exp -= large_step; - } -#ifdef FASTFLOAT_64BIT_LIMB - uint32_t small_step = 27; - limb max_native = 7450580596923828125UL; -#else - uint32_t small_step = 13; - limb max_native = 1220703125U; -#endif - while (exp >= small_step) { - FASTFLOAT_TRY(small_mul(vec, max_native)); - exp -= small_step; - } - if (exp != 0) { - FASTFLOAT_TRY(small_mul(vec, limb(small_power_of_5[exp]))); - } - - return true; - } - - // multiply as if by 10 raised to a power. - bool pow10(uint32_t exp) noexcept { - FASTFLOAT_TRY(pow5(exp)); - return pow2(exp); - } -}; - -} // namespace fast_float - -#endif - - -#ifndef FASTFLOAT_ASCII_NUMBER_H -#define FASTFLOAT_ASCII_NUMBER_H - -#include -#include -#include -#include - - -namespace fast_float { - -// Next function can be micro-optimized, but compilers are entirely -// able to optimize it well. -fastfloat_really_inline bool is_integer(char c) noexcept { return c >= '0' && c <= '9'; } - -fastfloat_really_inline uint64_t byteswap(uint64_t val) { - return (val & 0xFF00000000000000) >> 56 - | (val & 0x00FF000000000000) >> 40 - | (val & 0x0000FF0000000000) >> 24 - | (val & 0x000000FF00000000) >> 8 - | (val & 0x00000000FF000000) << 8 - | (val & 0x0000000000FF0000) << 24 - | (val & 0x000000000000FF00) << 40 - | (val & 0x00000000000000FF) << 56; -} - -fastfloat_really_inline uint64_t read_u64(const char *chars) { - uint64_t val; - ::memcpy(&val, chars, sizeof(uint64_t)); -#if FASTFLOAT_IS_BIG_ENDIAN == 1 - // Need to read as-if the number was in little-endian order. - val = byteswap(val); -#endif - return val; -} - -fastfloat_really_inline void write_u64(uint8_t *chars, uint64_t val) { -#if FASTFLOAT_IS_BIG_ENDIAN == 1 - // Need to read as-if the number was in little-endian order. - val = byteswap(val); -#endif - ::memcpy(chars, &val, sizeof(uint64_t)); -} - -// credit @aqrit -fastfloat_really_inline uint32_t parse_eight_digits_unrolled(uint64_t val) { - const uint64_t mask = 0x000000FF000000FF; - const uint64_t mul1 = 0x000F424000000064; // 100 + (1000000ULL << 32) - const uint64_t mul2 = 0x0000271000000001; // 1 + (10000ULL << 32) - val -= 0x3030303030303030; - val = (val * 10) + (val >> 8); // val = (val * 2561) >> 8; - val = (((val & mask) * mul1) + (((val >> 16) & mask) * mul2)) >> 32; - return uint32_t(val); -} - -fastfloat_really_inline uint32_t parse_eight_digits_unrolled(const char *chars) noexcept { - return parse_eight_digits_unrolled(read_u64(chars)); -} - -// credit @aqrit -fastfloat_really_inline bool is_made_of_eight_digits_fast(uint64_t val) noexcept { - return !((((val + 0x4646464646464646) | (val - 0x3030303030303030)) & - 0x8080808080808080)); -} - -fastfloat_really_inline bool is_made_of_eight_digits_fast(const char *chars) noexcept { - return is_made_of_eight_digits_fast(read_u64(chars)); -} - -typedef span byte_span; - -struct parsed_number_string { - int64_t exponent{0}; - uint64_t mantissa{0}; - const char *lastmatch{nullptr}; - bool negative{false}; - bool valid{false}; - bool too_many_digits{false}; - // contains the range of the significant digits - byte_span integer{}; // non-nullable - byte_span fraction{}; // nullable -}; - -// Assuming that you use no more than 19 digits, this will -// parse an ASCII string. -fastfloat_really_inline -parsed_number_string parse_number_string(const char *p, const char *pend, parse_options options) noexcept { - const chars_format fmt = options.format; - const char decimal_point = options.decimal_point; - - parsed_number_string answer; - answer.valid = false; - answer.too_many_digits = false; - answer.negative = (*p == '-'); - if (*p == '-') { // C++17 20.19.3.(7.1) explicitly forbids '+' sign here - ++p; - if (p == pend) { - return answer; - } - if (!is_integer(*p) && (*p != decimal_point)) { // a sign must be followed by an integer or the dot - return answer; - } - } - const char *const start_digits = p; - - uint64_t i = 0; // an unsigned int avoids signed overflows (which are bad) - - while ((std::distance(p, pend) >= 8) && is_made_of_eight_digits_fast(p)) { - i = i * 100000000 + parse_eight_digits_unrolled(p); // in rare cases, this will overflow, but that's ok - p += 8; - } - while ((p != pend) && is_integer(*p)) { - // a multiplication by 10 is cheaper than an arbitrary integer - // multiplication - i = 10 * i + - uint64_t(*p - '0'); // might overflow, we will handle the overflow later - ++p; - } - const char *const end_of_integer_part = p; - int64_t digit_count = int64_t(end_of_integer_part - start_digits); - answer.integer = byte_span(start_digits, size_t(digit_count)); - int64_t exponent = 0; - if ((p != pend) && (*p == decimal_point)) { - ++p; - const char* before = p; - // can occur at most twice without overflowing, but let it occur more, since - // for integers with many digits, digit parsing is the primary bottleneck. - while ((std::distance(p, pend) >= 8) && is_made_of_eight_digits_fast(p)) { - i = i * 100000000 + parse_eight_digits_unrolled(p); // in rare cases, this will overflow, but that's ok - p += 8; - } - while ((p != pend) && is_integer(*p)) { - uint8_t digit = uint8_t(*p - '0'); - ++p; - i = i * 10 + digit; // in rare cases, this will overflow, but that's ok - } - exponent = before - p; - answer.fraction = byte_span(before, size_t(p - before)); - digit_count -= exponent; - } - // we must have encountered at least one integer! - if (digit_count == 0) { - return answer; - } - int64_t exp_number = 0; // explicit exponential part - if ((fmt & chars_format::scientific) && (p != pend) && (('e' == *p) || ('E' == *p))) { - const char * location_of_e = p; - ++p; - bool neg_exp = false; - if ((p != pend) && ('-' == *p)) { - neg_exp = true; - ++p; - } else if ((p != pend) && ('+' == *p)) { // '+' on exponent is allowed by C++17 20.19.3.(7.1) - ++p; - } - if ((p == pend) || !is_integer(*p)) { - if(!(fmt & chars_format::fixed)) { - // We are in error. - return answer; - } - // Otherwise, we will be ignoring the 'e'. - p = location_of_e; - } else { - while ((p != pend) && is_integer(*p)) { - uint8_t digit = uint8_t(*p - '0'); - if (exp_number < 0x10000000) { - exp_number = 10 * exp_number + digit; - } - ++p; - } - if(neg_exp) { exp_number = - exp_number; } - exponent += exp_number; - } - } else { - // If it scientific and not fixed, we have to bail out. - if((fmt & chars_format::scientific) && !(fmt & chars_format::fixed)) { return answer; } - } - answer.lastmatch = p; - answer.valid = true; - - // If we frequently had to deal with long strings of digits, - // we could extend our code by using a 128-bit integer instead - // of a 64-bit integer. However, this is uncommon. - // - // We can deal with up to 19 digits. - if (digit_count > 19) { // this is uncommon - // It is possible that the integer had an overflow. - // We have to handle the case where we have 0.0000somenumber. - // We need to be mindful of the case where we only have zeroes... - // E.g., 0.000000000...000. - const char *start = start_digits; - while ((start != pend) && (*start == '0' || *start == decimal_point)) { - if(*start == '0') { digit_count --; } - start++; - } - if (digit_count > 19) { - answer.too_many_digits = true; - // Let us start again, this time, avoiding overflows. - // We don't need to check if is_integer, since we use the - // pre-tokenized spans from above. - i = 0; - p = answer.integer.ptr; - const char* int_end = p + answer.integer.len(); - const uint64_t minimal_nineteen_digit_integer{1000000000000000000}; - while((i < minimal_nineteen_digit_integer) && (p != int_end)) { - i = i * 10 + uint64_t(*p - '0'); - ++p; - } - if (i >= minimal_nineteen_digit_integer) { // We have a big integers - exponent = end_of_integer_part - p + exp_number; - } else { // We have a value with a fractional component. - p = answer.fraction.ptr; - const char* frac_end = p + answer.fraction.len(); - while((i < minimal_nineteen_digit_integer) && (p != frac_end)) { - i = i * 10 + uint64_t(*p - '0'); - ++p; - } - exponent = answer.fraction.ptr - p + exp_number; - } - // We have now corrected both exponent and i, to a truncated value - } - } - answer.exponent = exponent; - answer.mantissa = i; - return answer; -} - -} // namespace fast_float - -#endif - - -#ifndef FASTFLOAT_DIGIT_COMPARISON_H -#define FASTFLOAT_DIGIT_COMPARISON_H - -#include -#include -#include -#include - - -namespace fast_float { - -// 1e0 to 1e19 -constexpr static uint64_t powers_of_ten_uint64[] = { - 1UL, 10UL, 100UL, 1000UL, 10000UL, 100000UL, 1000000UL, 10000000UL, 100000000UL, - 1000000000UL, 10000000000UL, 100000000000UL, 1000000000000UL, 10000000000000UL, - 100000000000000UL, 1000000000000000UL, 10000000000000000UL, 100000000000000000UL, - 1000000000000000000UL, 10000000000000000000UL}; - -// calculate the exponent, in scientific notation, of the number. -// this algorithm is not even close to optimized, but it has no practical -// effect on performance: in order to have a faster algorithm, we'd need -// to slow down performance for faster algorithms, and this is still fast. -fastfloat_really_inline int32_t scientific_exponent(parsed_number_string& num) noexcept { - uint64_t mantissa = num.mantissa; - int32_t exponent = int32_t(num.exponent); - while (mantissa >= 10000) { - mantissa /= 10000; - exponent += 4; - } - while (mantissa >= 100) { - mantissa /= 100; - exponent += 2; - } - while (mantissa >= 10) { - mantissa /= 10; - exponent += 1; - } - return exponent; -} - -// this converts a native floating-point number to an extended-precision float. -template -fastfloat_really_inline adjusted_mantissa to_extended(T value) noexcept { - adjusted_mantissa am; - int32_t bias = binary_format::mantissa_explicit_bits() - binary_format::minimum_exponent(); - if (std::is_same::value) { - constexpr uint32_t exponent_mask = 0x7F800000; - constexpr uint32_t mantissa_mask = 0x007FFFFF; - constexpr uint64_t hidden_bit_mask = 0x00800000; - uint32_t bits; - ::memcpy(&bits, &value, sizeof(T)); - if ((bits & exponent_mask) == 0) { - // denormal - am.power2 = 1 - bias; - am.mantissa = bits & mantissa_mask; - } else { - // normal - am.power2 = int32_t((bits & exponent_mask) >> binary_format::mantissa_explicit_bits()); - am.power2 -= bias; - am.mantissa = (bits & mantissa_mask) | hidden_bit_mask; - } - } else { - constexpr uint64_t exponent_mask = 0x7FF0000000000000; - constexpr uint64_t mantissa_mask = 0x000FFFFFFFFFFFFF; - constexpr uint64_t hidden_bit_mask = 0x0010000000000000; - uint64_t bits; - ::memcpy(&bits, &value, sizeof(T)); - if ((bits & exponent_mask) == 0) { - // denormal - am.power2 = 1 - bias; - am.mantissa = bits & mantissa_mask; - } else { - // normal - am.power2 = int32_t((bits & exponent_mask) >> binary_format::mantissa_explicit_bits()); - am.power2 -= bias; - am.mantissa = (bits & mantissa_mask) | hidden_bit_mask; - } - } - - return am; -} - -// get the extended precision value of the halfway point between b and b+u. -// we are given a native float that represents b, so we need to adjust it -// halfway between b and b+u. -template -fastfloat_really_inline adjusted_mantissa to_extended_halfway(T value) noexcept { - adjusted_mantissa am = to_extended(value); - am.mantissa <<= 1; - am.mantissa += 1; - am.power2 -= 1; - return am; -} - -// round an extended-precision float to the nearest machine float. -template -fastfloat_really_inline void round(adjusted_mantissa& am, callback cb) noexcept { - int32_t mantissa_shift = 64 - binary_format::mantissa_explicit_bits() - 1; - if (-am.power2 >= mantissa_shift) { - // have a denormal float - int32_t shift = -am.power2 + 1; - cb(am, std::min(shift, 64)); - // check for round-up: if rounding-nearest carried us to the hidden bit. - am.power2 = (am.mantissa < (uint64_t(1) << binary_format::mantissa_explicit_bits())) ? 0 : 1; - return; - } - - // have a normal float, use the default shift. - cb(am, mantissa_shift); - - // check for carry - if (am.mantissa >= (uint64_t(2) << binary_format::mantissa_explicit_bits())) { - am.mantissa = (uint64_t(1) << binary_format::mantissa_explicit_bits()); - am.power2++; - } - - // check for infinite: we could have carried to an infinite power - am.mantissa &= ~(uint64_t(1) << binary_format::mantissa_explicit_bits()); - if (am.power2 >= binary_format::infinite_power()) { - am.power2 = binary_format::infinite_power(); - am.mantissa = 0; - } -} - -template -fastfloat_really_inline -void round_nearest_tie_even(adjusted_mantissa& am, int32_t shift, callback cb) noexcept { - uint64_t mask; - uint64_t halfway; - if (shift == 64) { - mask = UINT64_MAX; - } else { - mask = (uint64_t(1) << shift) - 1; - } - if (shift == 0) { - halfway = 0; - } else { - halfway = uint64_t(1) << (shift - 1); - } - uint64_t truncated_bits = am.mantissa & mask; - uint64_t is_above = truncated_bits > halfway; - uint64_t is_halfway = truncated_bits == halfway; - - // shift digits into position - if (shift == 64) { - am.mantissa = 0; - } else { - am.mantissa >>= shift; - } - am.power2 += shift; - - bool is_odd = (am.mantissa & 1) == 1; - am.mantissa += uint64_t(cb(is_odd, is_halfway, is_above)); -} - -fastfloat_really_inline void round_down(adjusted_mantissa& am, int32_t shift) noexcept { - if (shift == 64) { - am.mantissa = 0; - } else { - am.mantissa >>= shift; - } - am.power2 += shift; -} - -fastfloat_really_inline void skip_zeros(const char*& first, const char* last) noexcept { - uint64_t val; - while (std::distance(first, last) >= 8) { - ::memcpy(&val, first, sizeof(uint64_t)); - if (val != 0x3030303030303030) { - break; - } - first += 8; - } - while (first != last) { - if (*first != '0') { - break; - } - first++; - } -} - -// determine if any non-zero digits were truncated. -// all characters must be valid digits. -fastfloat_really_inline bool is_truncated(const char* first, const char* last) noexcept { - // do 8-bit optimizations, can just compare to 8 literal 0s. - uint64_t val; - while (std::distance(first, last) >= 8) { - ::memcpy(&val, first, sizeof(uint64_t)); - if (val != 0x3030303030303030) { - return true; - } - first += 8; - } - while (first != last) { - if (*first != '0') { - return true; - } - first++; - } - return false; -} - -fastfloat_really_inline bool is_truncated(byte_span s) noexcept { - return is_truncated(s.ptr, s.ptr + s.len()); -} - -fastfloat_really_inline -void parse_eight_digits(const char*& p, limb& value, size_t& counter, size_t& count) noexcept { - value = value * 100000000 + parse_eight_digits_unrolled(p); - p += 8; - counter += 8; - count += 8; -} - -fastfloat_really_inline -void parse_one_digit(const char*& p, limb& value, size_t& counter, size_t& count) noexcept { - value = value * 10 + limb(*p - '0'); - p++; - counter++; - count++; -} - -fastfloat_really_inline -void add_native(bigint& big, limb power, limb value) noexcept { - big.mul(power); - big.add(value); -} - -fastfloat_really_inline void round_up_bigint(bigint& big, size_t& count) noexcept { - // need to round-up the digits, but need to avoid rounding - // ....9999 to ...10000, which could cause a false halfway point. - add_native(big, 10, 1); - count++; -} - -// parse the significant digits into a big integer -inline void parse_mantissa(bigint& result, parsed_number_string& num, size_t max_digits, size_t& digits) noexcept { - // try to minimize the number of big integer and scalar multiplication. - // therefore, try to parse 8 digits at a time, and multiply by the largest - // scalar value (9 or 19 digits) for each step. - size_t counter = 0; - digits = 0; - limb value = 0; -#ifdef FASTFLOAT_64BIT_LIMB - size_t step = 19; -#else - size_t step = 9; -#endif - - // process all integer digits. - const char* p = num.integer.ptr; - const char* pend = p + num.integer.len(); - skip_zeros(p, pend); - // process all digits, in increments of step per loop - while (p != pend) { - while ((std::distance(p, pend) >= 8) && (step - counter >= 8) && (max_digits - digits >= 8)) { - parse_eight_digits(p, value, counter, digits); - } - while (counter < step && p != pend && digits < max_digits) { - parse_one_digit(p, value, counter, digits); - } - if (digits == max_digits) { - // add the temporary value, then check if we've truncated any digits - add_native(result, limb(powers_of_ten_uint64[counter]), value); - bool truncated = is_truncated(p, pend); - if (num.fraction.ptr != nullptr) { - truncated |= is_truncated(num.fraction); - } - if (truncated) { - round_up_bigint(result, digits); - } - return; - } else { - add_native(result, limb(powers_of_ten_uint64[counter]), value); - counter = 0; - value = 0; - } - } - - // add our fraction digits, if they're available. - if (num.fraction.ptr != nullptr) { - p = num.fraction.ptr; - pend = p + num.fraction.len(); - if (digits == 0) { - skip_zeros(p, pend); - } - // process all digits, in increments of step per loop - while (p != pend) { - while ((std::distance(p, pend) >= 8) && (step - counter >= 8) && (max_digits - digits >= 8)) { - parse_eight_digits(p, value, counter, digits); - } - while (counter < step && p != pend && digits < max_digits) { - parse_one_digit(p, value, counter, digits); - } - if (digits == max_digits) { - // add the temporary value, then check if we've truncated any digits - add_native(result, limb(powers_of_ten_uint64[counter]), value); - bool truncated = is_truncated(p, pend); - if (truncated) { - round_up_bigint(result, digits); - } - return; - } else { - add_native(result, limb(powers_of_ten_uint64[counter]), value); - counter = 0; - value = 0; - } - } - } - - if (counter != 0) { - add_native(result, limb(powers_of_ten_uint64[counter]), value); - } -} - -template -inline adjusted_mantissa positive_digit_comp(bigint& bigmant, int32_t exponent) noexcept { - FASTFLOAT_ASSERT(bigmant.pow10(uint32_t(exponent))); - adjusted_mantissa answer; - bool truncated; - answer.mantissa = bigmant.hi64(truncated); - int bias = binary_format::mantissa_explicit_bits() - binary_format::minimum_exponent(); - answer.power2 = bigmant.bit_length() - 64 + bias; - - round(answer, [truncated](adjusted_mantissa& a, int32_t shift) { - round_nearest_tie_even(a, shift, [truncated](bool is_odd, bool is_halfway, bool is_above) -> bool { - return is_above || (is_halfway && truncated) || (is_odd && is_halfway); - }); - }); - - return answer; -} - -// the scaling here is quite simple: we have, for the real digits `m * 10^e`, -// and for the theoretical digits `n * 2^f`. Since `e` is always negative, -// to scale them identically, we do `n * 2^f * 5^-f`, so we now have `m * 2^e`. -// we then need to scale by `2^(f- e)`, and then the two significant digits -// are of the same magnitude. -template -inline adjusted_mantissa negative_digit_comp(bigint& bigmant, adjusted_mantissa am, int32_t exponent) noexcept { - bigint& real_digits = bigmant; - int32_t real_exp = exponent; - - // get the value of `b`, rounded down, and get a bigint representation of b+h - adjusted_mantissa am_b = am; - // gcc7 buf: use a lambda to remove the noexcept qualifier bug with -Wnoexcept-type. - round(am_b, [](adjusted_mantissa&a, int32_t shift) { round_down(a, shift); }); - T b; - to_float(false, am_b, b); - adjusted_mantissa theor = to_extended_halfway(b); - bigint theor_digits(theor.mantissa); - int32_t theor_exp = theor.power2; - - // scale real digits and theor digits to be same power. - int32_t pow2_exp = theor_exp - real_exp; - uint32_t pow5_exp = uint32_t(-real_exp); - if (pow5_exp != 0) { - FASTFLOAT_ASSERT(theor_digits.pow5(pow5_exp)); - } - if (pow2_exp > 0) { - FASTFLOAT_ASSERT(theor_digits.pow2(uint32_t(pow2_exp))); - } else if (pow2_exp < 0) { - FASTFLOAT_ASSERT(real_digits.pow2(uint32_t(-pow2_exp))); - } - - // compare digits, and use it to director rounding - int ord = real_digits.compare(theor_digits); - adjusted_mantissa answer = am; - round(answer, [ord](adjusted_mantissa& a, int32_t shift) { - round_nearest_tie_even(a, shift, [ord](bool is_odd, bool _, bool __) -> bool { - (void)_; // not needed, since we've done our comparison - (void)__; // not needed, since we've done our comparison - if (ord > 0) { - return true; - } else if (ord < 0) { - return false; - } else { - return is_odd; - } - }); - }); - - return answer; -} - -// parse the significant digits as a big integer to unambiguously round the -// the significant digits. here, we are trying to determine how to round -// an extended float representation close to `b+h`, halfway between `b` -// (the float rounded-down) and `b+u`, the next positive float. this -// algorithm is always correct, and uses one of two approaches. when -// the exponent is positive relative to the significant digits (such as -// 1234), we create a big-integer representation, get the high 64-bits, -// determine if any lower bits are truncated, and use that to direct -// rounding. in case of a negative exponent relative to the significant -// digits (such as 1.2345), we create a theoretical representation of -// `b` as a big-integer type, scaled to the same binary exponent as -// the actual digits. we then compare the big integer representations -// of both, and use that to direct rounding. -template -inline adjusted_mantissa digit_comp(parsed_number_string& num, adjusted_mantissa am) noexcept { - // remove the invalid exponent bias - am.power2 -= invalid_am_bias; - - int32_t sci_exp = scientific_exponent(num); - size_t max_digits = binary_format::max_digits(); - size_t digits = 0; - bigint bigmant; - parse_mantissa(bigmant, num, max_digits, digits); - // can't underflow, since digits is at most max_digits. - int32_t exponent = sci_exp + 1 - int32_t(digits); - if (exponent >= 0) { - return positive_digit_comp(bigmant, exponent); - } else { - return negative_digit_comp(bigmant, am, exponent); - } -} - -} // namespace fast_float - -#endif - - -#ifndef FASTFLOAT_PARSE_NUMBER_H -#define FASTFLOAT_PARSE_NUMBER_H - - -#include -#include -#include -#include - -namespace fast_float { - - -namespace detail { -/** - * Special case +inf, -inf, nan, infinity, -infinity. - * The case comparisons could be made much faster given that we know that the - * strings a null-free and fixed. - **/ -template -from_chars_result parse_infnan(const char *first, const char *last, T &value) noexcept { - from_chars_result answer; - answer.ptr = first; - answer.ec = std::errc(); // be optimistic - bool minusSign = false; - if (*first == '-') { // assume first < last, so dereference without checks; C++17 20.19.3.(7.1) explicitly forbids '+' here - minusSign = true; - ++first; - } - if (last - first >= 3) { - if (fastfloat_strncasecmp(first, "nan", 3)) { - answer.ptr = (first += 3); - value = minusSign ? -std::numeric_limits::quiet_NaN() : std::numeric_limits::quiet_NaN(); - // Check for possible nan(n-char-seq-opt), C++17 20.19.3.7, C11 7.20.1.3.3. At least MSVC produces nan(ind) and nan(snan). - if(first != last && *first == '(') { - for(const char* ptr = first + 1; ptr != last; ++ptr) { - if (*ptr == ')') { - answer.ptr = ptr + 1; // valid nan(n-char-seq-opt) - break; - } - else if(!(('a' <= *ptr && *ptr <= 'z') || ('A' <= *ptr && *ptr <= 'Z') || ('0' <= *ptr && *ptr <= '9') || *ptr == '_')) - break; // forbidden char, not nan(n-char-seq-opt) - } - } - return answer; - } - if (fastfloat_strncasecmp(first, "inf", 3)) { - if ((last - first >= 8) && fastfloat_strncasecmp(first + 3, "inity", 5)) { - answer.ptr = first + 8; - } else { - answer.ptr = first + 3; - } - value = minusSign ? -std::numeric_limits::infinity() : std::numeric_limits::infinity(); - return answer; - } - } - answer.ec = std::errc::invalid_argument; - return answer; -} - -} // namespace detail - -template -from_chars_result from_chars(const char *first, const char *last, - T &value, chars_format fmt /*= chars_format::general*/) noexcept { - return from_chars_advanced(first, last, value, parse_options{fmt}); -} - -template -from_chars_result from_chars_advanced(const char *first, const char *last, - T &value, parse_options options) noexcept { - - static_assert (std::is_same::value || std::is_same::value, "only float and double are supported"); - - - from_chars_result answer; - if (first == last) { - answer.ec = std::errc::invalid_argument; - answer.ptr = first; - return answer; - } - parsed_number_string pns = parse_number_string(first, last, options); - if (!pns.valid) { - return detail::parse_infnan(first, last, value); - } - answer.ec = std::errc(); // be optimistic - answer.ptr = pns.lastmatch; - // Next is Clinger's fast path. - if (binary_format::min_exponent_fast_path() <= pns.exponent && pns.exponent <= binary_format::max_exponent_fast_path() && pns.mantissa <=binary_format::max_mantissa_fast_path() && !pns.too_many_digits) { - value = T(pns.mantissa); - if (pns.exponent < 0) { value = value / binary_format::exact_power_of_ten(-pns.exponent); } - else { value = value * binary_format::exact_power_of_ten(pns.exponent); } - if (pns.negative) { value = -value; } - return answer; - } - adjusted_mantissa am = compute_float>(pns.exponent, pns.mantissa); - if(pns.too_many_digits && am.power2 >= 0) { - if(am != compute_float>(pns.exponent, pns.mantissa + 1)) { - am = compute_error>(pns.exponent, pns.mantissa); - } - } - // If we called compute_float>(pns.exponent, pns.mantissa) and we have an invalid power (am.power2 < 0), - // then we need to go the long way around again. This is very uncommon. - if(am.power2 < 0) { am = digit_comp(pns, am); } - to_float(pns.negative, am, value); - return answer; -} - -} // namespace fast_float - -#endif diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/rng/rng.hpp b/thirdparty/ryml/ext/c4core/src/c4/ext/rng/rng.hpp deleted file mode 100644 index 63af09008..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/rng/rng.hpp +++ /dev/null @@ -1,192 +0,0 @@ -/* Copyright (c) 2018 Arvid Gerstmann. - * - * https://arvid.io/2018/07/02/better-cxx-prng/ - * - * This code is licensed under MIT license. */ -#ifndef AG_RANDOM_H -#define AG_RANDOM_H - -#include -#include - - -namespace c4 { -namespace rng { - - -class splitmix -{ -public: - using result_type = uint32_t; - static constexpr result_type (min)() { return 0; } - static constexpr result_type (max)() { return UINT32_MAX; } - friend bool operator==(splitmix const &, splitmix const &); - friend bool operator!=(splitmix const &, splitmix const &); - - splitmix() : m_seed(1) {} - explicit splitmix(uint64_t s) : m_seed(s) {} - explicit splitmix(std::random_device &rd) - { - seed(rd); - } - - void seed(uint64_t s) { m_seed = s; } - void seed(std::random_device &rd) - { - m_seed = uint64_t(rd()) << 31 | uint64_t(rd()); - } - - result_type operator()() - { - uint64_t z = (m_seed += UINT64_C(0x9E3779B97F4A7C15)); - z = (z ^ (z >> 30)) * UINT64_C(0xBF58476D1CE4E5B9); - z = (z ^ (z >> 27)) * UINT64_C(0x94D049BB133111EB); - return result_type((z ^ (z >> 31)) >> 31); - } - - void discard(unsigned long long n) - { - for (unsigned long long i = 0; i < n; ++i) - operator()(); - } - -private: - uint64_t m_seed; -}; - -inline bool operator==(splitmix const &lhs, splitmix const &rhs) -{ - return lhs.m_seed == rhs.m_seed; -} -inline bool operator!=(splitmix const &lhs, splitmix const &rhs) -{ - return lhs.m_seed != rhs.m_seed; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -class xorshift -{ -public: - using result_type = uint32_t; - static constexpr result_type (min)() { return 0; } - static constexpr result_type (max)() { return UINT32_MAX; } - friend bool operator==(xorshift const &, xorshift const &); - friend bool operator!=(xorshift const &, xorshift const &); - - xorshift() : m_seed(0xc1f651c67c62c6e0ull) {} - explicit xorshift(std::random_device &rd) - { - seed(rd); - } - - void seed(uint64_t s) { m_seed = s; } - void seed(std::random_device &rd) - { - m_seed = uint64_t(rd()) << 31 | uint64_t(rd()); - } - - result_type operator()() - { - uint64_t result = m_seed * 0xd989bcacc137dcd5ull; - m_seed ^= m_seed >> 11; - m_seed ^= m_seed << 31; - m_seed ^= m_seed >> 18; - return uint32_t(result >> 32ull); - } - - void discard(unsigned long long n) - { - for (unsigned long long i = 0; i < n; ++i) - operator()(); - } - -private: - uint64_t m_seed; -}; - -inline bool operator==(xorshift const &lhs, xorshift const &rhs) -{ - return lhs.m_seed == rhs.m_seed; -} -inline bool operator!=(xorshift const &lhs, xorshift const &rhs) -{ - return lhs.m_seed != rhs.m_seed; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -class pcg -{ -public: - using result_type = uint32_t; - static constexpr result_type (min)() { return 0; } - static constexpr result_type (max)() { return UINT32_MAX; } - friend bool operator==(pcg const &, pcg const &); - friend bool operator!=(pcg const &, pcg const &); - - pcg() - : m_state(0x853c49e6748fea9bULL) - , m_inc(0xda3e39cb94b95bdbULL) - {} - explicit pcg(uint64_t s) { m_state = s; m_inc = m_state << 1; } - explicit pcg(std::random_device &rd) - { - seed(rd); - } - - void seed(uint64_t s) { m_state = s; } - void seed(std::random_device &rd) - { - uint64_t s0 = uint64_t(rd()) << 31 | uint64_t(rd()); - uint64_t s1 = uint64_t(rd()) << 31 | uint64_t(rd()); - - m_state = 0; - m_inc = (s1 << 1) | 1; - (void)operator()(); - m_state += s0; - (void)operator()(); - } - - result_type operator()() - { - uint64_t oldstate = m_state; - m_state = oldstate * 6364136223846793005ULL + m_inc; - uint32_t xorshifted = uint32_t(((oldstate >> 18u) ^ oldstate) >> 27u); - //int rot = oldstate >> 59u; // the original. error? - int64_t rot = (int64_t)oldstate >> 59u; // error? - return (xorshifted >> rot) | (xorshifted << ((uint64_t)(-rot) & 31)); - } - - void discard(unsigned long long n) - { - for (unsigned long long i = 0; i < n; ++i) - operator()(); - } - -private: - uint64_t m_state; - uint64_t m_inc; -}; - -inline bool operator==(pcg const &lhs, pcg const &rhs) -{ - return lhs.m_state == rhs.m_state - && lhs.m_inc == rhs.m_inc; -} -inline bool operator!=(pcg const &lhs, pcg const &rhs) -{ - return lhs.m_state != rhs.m_state - || lhs.m_inc != rhs.m_inc; -} - -} // namespace rng -} // namespace c4 - -#endif /* AG_RANDOM_H */ diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/sg14/README.md b/thirdparty/ryml/ext/c4core/src/c4/ext/sg14/README.md deleted file mode 100644 index 11d0f94a0..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/sg14/README.md +++ /dev/null @@ -1 +0,0 @@ -https://github.com/WG21-SG14/SG14/blob/master/SG14/inplace_function.h diff --git a/thirdparty/ryml/ext/c4core/src/c4/ext/sg14/inplace_function.h b/thirdparty/ryml/ext/c4core/src/c4/ext/sg14/inplace_function.h deleted file mode 100644 index af3e83054..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/ext/sg14/inplace_function.h +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Boost Software License - Version 1.0 - August 17th, 2003 - * - * Permission is hereby granted, free of charge, to any person or organization - * obtaining a copy of the software and accompanying documentation covered by - * this license (the "Software") to use, reproduce, display, distribute, - * execute, and transmit the Software, and to prepare derivative works of the - * Software, and to permit third-parties to whom the Software is furnished to - * do so, all subject to the following: - * - * The copyright notices in the Software and this entire statement, including - * the above license grant, this restriction and the following disclaimer, - * must be included in all copies of the Software, in whole or in part, and - * all derivative works of the Software, unless such copies or derivative - * works are solely in the form of machine-executable object code generated by - * a source language processor. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT - * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE - * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ -#ifndef _C4_EXT_SG14_INPLACE_FUNCTION_H_ -#define _C4_EXT_SG14_INPLACE_FUNCTION_H_ - -#include -#include -#include - -namespace stdext { - -namespace inplace_function_detail { - -static constexpr size_t InplaceFunctionDefaultCapacity = 32; - -#if defined(__GLIBCXX__) // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61458 -template -union aligned_storage_helper { - struct double1 { double a; }; - struct double4 { double a[4]; }; - template using maybe = typename std::conditional<(Cap >= sizeof(T)), T, char>::type; - char real_data[Cap]; - maybe a; - maybe b; - maybe c; - maybe d; - maybe e; - maybe f; - maybe g; - maybe h; -}; - -template>::value> -struct aligned_storage { - using type = typename std::aligned_storage::type; -}; -#else -using std::aligned_storage; -#endif - -template struct wrapper -{ - using type = T; -}; - -template struct vtable -{ - using storage_ptr_t = void*; - - using invoke_ptr_t = R(*)(storage_ptr_t, Args&&...); - using process_ptr_t = void(*)(storage_ptr_t, storage_ptr_t); - using destructor_ptr_t = void(*)(storage_ptr_t); - - const invoke_ptr_t invoke_ptr; - const process_ptr_t copy_ptr; - const process_ptr_t move_ptr; - const destructor_ptr_t destructor_ptr; - - explicit constexpr vtable() noexcept : - invoke_ptr{ [](storage_ptr_t, Args&&...) -> R - { throw std::bad_function_call(); } - }, - copy_ptr{ [](storage_ptr_t, storage_ptr_t) noexcept -> void {} }, - move_ptr{ [](storage_ptr_t, storage_ptr_t) noexcept -> void {} }, - destructor_ptr{ [](storage_ptr_t) noexcept -> void {} } - {} - - template explicit constexpr vtable(wrapper) noexcept : - invoke_ptr{ [](storage_ptr_t storage_ptr, Args&&... args) - noexcept(noexcept(std::declval()(args...))) -> R - { return (*static_cast(storage_ptr))( - std::forward(args)... - ); } - }, - copy_ptr{ [](storage_ptr_t dst_ptr, storage_ptr_t src_ptr) - noexcept(std::is_nothrow_copy_constructible::value) -> void - { new (dst_ptr) C{ (*static_cast(src_ptr)) }; } - }, - move_ptr{ [](storage_ptr_t dst_ptr, storage_ptr_t src_ptr) - noexcept(std::is_nothrow_move_constructible::value) -> void - { new (dst_ptr) C{ std::move(*static_cast(src_ptr)) }; } - }, - destructor_ptr{ [](storage_ptr_t storage_ptr) - noexcept -> void - { static_cast(storage_ptr)->~C(); } - } - {} - - vtable(const vtable&) = delete; - vtable(vtable&&) = delete; - - vtable& operator= (const vtable&) = delete; - vtable& operator= (vtable&&) = delete; - - ~vtable() = default; -}; - -template -struct is_valid_inplace_dst : std::true_type -{ - static_assert(DstCap >= SrcCap, - "Can't squeeze larger inplace_function into a smaller one" - ); - - static_assert(DstAlign % SrcAlign == 0, - "Incompatible inplace_function alignments" - ); -}; - -} // namespace inplace_function_detail - -template< - typename Signature, - size_t Capacity = inplace_function_detail::InplaceFunctionDefaultCapacity, - size_t Alignment = std::alignment_of::type>::value -> -class inplace_function; // unspecified - -template< - typename R, - typename... Args, - size_t Capacity, - size_t Alignment -> -class inplace_function -{ - static const constexpr inplace_function_detail::vtable empty_vtable{}; -public: - using capacity = std::integral_constant; - using alignment = std::integral_constant; - - using storage_t = typename inplace_function_detail::aligned_storage::type; - using vtable_t = inplace_function_detail::vtable; - using vtable_ptr_t = const vtable_t*; - - template friend class inplace_function; - - inplace_function() noexcept : - vtable_ptr_{std::addressof(empty_vtable)} - {} - - template< - typename T, - typename C = typename std::decay::type, - typename = typename std::enable_if< - !(std::is_same::value - || std::is_convertible::value) - >::type - > - inplace_function(T&& closure) - { -#if __cplusplus >= 201703L - static_assert(std::is_invocable_r::value, - "inplace_function cannot be constructed from non-callable type" - ); -#endif - static_assert(std::is_copy_constructible::value, - "inplace_function cannot be constructed from non-copyable type" - ); - - static_assert(sizeof(C) <= Capacity, - "inplace_function cannot be constructed from object with this (large) size" - ); - - static_assert(Alignment % std::alignment_of::value == 0, - "inplace_function cannot be constructed from object with this (large) alignment" - ); - - static const vtable_t vt{inplace_function_detail::wrapper{}}; - vtable_ptr_ = std::addressof(vt); - - new (std::addressof(storage_)) C{std::forward(closure)}; - } - - inplace_function(std::nullptr_t) noexcept : - vtable_ptr_{std::addressof(empty_vtable)} - {} - - inplace_function(const inplace_function& other) : - vtable_ptr_{other.vtable_ptr_} - { - vtable_ptr_->copy_ptr( - std::addressof(storage_), - std::addressof(other.storage_) - ); - } - - inplace_function(inplace_function&& other) : - vtable_ptr_{other.vtable_ptr_} - { - vtable_ptr_->move_ptr( - std::addressof(storage_), - std::addressof(other.storage_) - ); - } - - inplace_function& operator= (std::nullptr_t) noexcept - { - vtable_ptr_->destructor_ptr(std::addressof(storage_)); - vtable_ptr_ = std::addressof(empty_vtable); - return *this; - } - - inplace_function& operator= (const inplace_function& other) - { - if(this != std::addressof(other)) - { - vtable_ptr_->destructor_ptr(std::addressof(storage_)); - - vtable_ptr_ = other.vtable_ptr_; - vtable_ptr_->copy_ptr( - std::addressof(storage_), - std::addressof(other.storage_) - ); - } - return *this; - } - - inplace_function& operator= (inplace_function&& other) - { - if(this != std::addressof(other)) - { - vtable_ptr_->destructor_ptr(std::addressof(storage_)); - - vtable_ptr_ = other.vtable_ptr_; - vtable_ptr_->move_ptr( - std::addressof(storage_), - std::addressof(other.storage_) - ); - } - return *this; - } - - ~inplace_function() - { - vtable_ptr_->destructor_ptr(std::addressof(storage_)); - } - - R operator() (Args... args) const - { - return vtable_ptr_->invoke_ptr( - std::addressof(storage_), - std::forward(args)... - ); - } - - constexpr bool operator== (std::nullptr_t) const noexcept - { - return !operator bool(); - } - - constexpr bool operator!= (std::nullptr_t) const noexcept - { - return operator bool(); - } - - explicit constexpr operator bool() const noexcept - { - return vtable_ptr_ != std::addressof(empty_vtable); - } - - template - operator inplace_function() const& - { - static_assert(inplace_function_detail::is_valid_inplace_dst< - Cap, Align, Capacity, Alignment - >::value, "conversion not allowed"); - - return {vtable_ptr_, vtable_ptr_->copy_ptr, std::addressof(storage_)}; - } - - template - operator inplace_function() && - { - static_assert(inplace_function_detail::is_valid_inplace_dst< - Cap, Align, Capacity, Alignment - >::value, "conversion not allowed"); - - return {vtable_ptr_, vtable_ptr_->move_ptr, std::addressof(storage_)}; - } - - void swap(inplace_function& other) - { - if (this == std::addressof(other)) return; - - storage_t tmp; - vtable_ptr_->move_ptr( - std::addressof(tmp), - std::addressof(storage_) - ); - vtable_ptr_->destructor_ptr(std::addressof(storage_)); - - other.vtable_ptr_->move_ptr( - std::addressof(storage_), - std::addressof(other.storage_) - ); - other.vtable_ptr_->destructor_ptr(std::addressof(other.storage_)); - - vtable_ptr_->move_ptr( - std::addressof(other.storage_), - std::addressof(tmp) - ); - vtable_ptr_->destructor_ptr(std::addressof(tmp)); - - std::swap(vtable_ptr_, other.vtable_ptr_); - } - -private: - vtable_ptr_t vtable_ptr_; - mutable storage_t storage_; - - inplace_function( - vtable_ptr_t vtable_ptr, - typename vtable_t::process_ptr_t process_ptr, - typename vtable_t::storage_ptr_t storage_ptr - ) : vtable_ptr_{vtable_ptr} - { - process_ptr(std::addressof(storage_), storage_ptr); - } -}; - -} // namespace stdext - -#endif /* _C4_EXT_SG14_INPLACE_FUNCTION_H_ */ diff --git a/thirdparty/ryml/ext/c4core/src/c4/format.cpp b/thirdparty/ryml/ext/c4core/src/c4/format.cpp deleted file mode 100644 index cc058c311..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/format.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include "c4/format.hpp" - -#include // for std::align - -#ifdef __clang__ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wformat-nonliteral" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wformat-nonliteral" -#endif - -namespace c4 { - - -size_t to_chars(substr buf, fmt::const_raw_wrapper r) -{ - void * vptr = buf.str; - size_t space = buf.len; - auto ptr = (decltype(buf.str)) std::align(r.alignment, r.len, vptr, space); - if(ptr == nullptr) - { - // if it was not possible to align, return a conservative estimate - // of the required space - return r.alignment + r.len; - } - C4_CHECK(ptr >= buf.begin() && ptr <= buf.end()); - size_t sz = static_cast(ptr - buf.str) + r.len; - if(sz <= buf.len) - { - memcpy(ptr, r.buf, r.len); - } - return sz; -} - - -bool from_chars(csubstr buf, fmt::raw_wrapper *r) -{ - void * vptr = (void*)buf.str; - size_t space = buf.len; - auto ptr = (decltype(buf.str)) std::align(r->alignment, r->len, vptr, space); - C4_CHECK(ptr != nullptr); - C4_CHECK(ptr >= buf.begin() && ptr <= buf.end()); - //size_t dim = (ptr - buf.str) + r->len; - memcpy(r->buf, ptr, r->len); - return true; -} - - -} // namespace c4 - -#ifdef __clang__ -# pragma clang diagnostic pop -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#endif diff --git a/thirdparty/ryml/ext/c4core/src/c4/format.hpp b/thirdparty/ryml/ext/c4core/src/c4/format.hpp deleted file mode 100644 index 589bd9842..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/format.hpp +++ /dev/null @@ -1,900 +0,0 @@ -#ifndef _C4_FORMAT_HPP_ -#define _C4_FORMAT_HPP_ - -/** @file format.hpp provides type-safe facilities for formatting arguments - * to string buffers */ - -#include "c4/charconv.hpp" -#include "c4/blob.hpp" - - -#ifdef _MSC_VER -# pragma warning(push) -# if C4_MSVC_VERSION != C4_MSVC_VERSION_2017 -# pragma warning(disable: 4800) // forcing value to bool 'true' or 'false' (performance warning) -# endif -# pragma warning(disable: 4996) // snprintf/scanf: this function or variable may be unsafe -#elif defined(__clang__) -# pragma clang diagnostic push -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wuseless-cast" -#endif - -namespace c4 { - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// formatting truthy types as booleans - -namespace fmt { - -/** write a variable as an alphabetic boolean, ie as either true or false - * @param strict_read */ -template -struct boolalpha_ -{ - boolalpha_(T val_, bool strict_read_=false) : val(val_ ? true : false), strict_read(strict_read_) {} - bool val; - bool strict_read; -}; - -template -boolalpha_ boolalpha(T const& val, bool strict_read=false) -{ - return boolalpha_(val, strict_read); -} - -} // namespace fmt - -/** write a variable as an alphabetic boolean, ie as either true or false */ -template -inline size_t to_chars(substr buf, fmt::boolalpha_ fmt) -{ - return to_chars(buf, fmt.val ? "true" : "false"); -} - - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// formatting integral types - -namespace fmt { - -/** format an integral type with a custom radix */ -template -struct integral_ -{ - T val; - T radix; - C4_ALWAYS_INLINE integral_(T val_, T radix_) : val(val_), radix(radix_) {} -}; - -/** format an integral type with a custom radix, and pad with zeroes on the left */ -template -struct integral_padded_ -{ - T val; - T radix; - size_t num_digits; - C4_ALWAYS_INLINE integral_padded_(T val_, T radix_, size_t nd) : val(val_), radix(radix_), num_digits(nd) {} -}; - -/** format an integral type with a custom radix */ -template -C4_ALWAYS_INLINE integral_ integral(T val, T radix=10) -{ - return integral_(val, radix); -} -/** format an integral type with a custom radix */ -template -C4_ALWAYS_INLINE integral_ integral(T const* val, T radix=10) -{ - return integral_(reinterpret_cast(val), static_cast(radix)); -} -/** format an integral type with a custom radix */ -template -C4_ALWAYS_INLINE integral_ integral(std::nullptr_t, T radix=10) -{ - return integral_(intptr_t(0), static_cast(radix)); -} -/** pad the argument with zeroes on the left, with decimal radix */ -template -C4_ALWAYS_INLINE integral_padded_ zpad(T val, size_t num_digits) -{ - return integral_padded_(val, T(10), num_digits); -} -/** pad the argument with zeroes on the left */ -template -C4_ALWAYS_INLINE integral_padded_ zpad(integral_ val, size_t num_digits) -{ - return integral_padded_(val.val, val.radix, num_digits); -} -/** pad the argument with zeroes on the left */ -C4_ALWAYS_INLINE integral_padded_ zpad(std::nullptr_t, size_t num_digits) -{ - return integral_padded_(0, 16, num_digits); -} -/** pad the argument with zeroes on the left */ -template -C4_ALWAYS_INLINE integral_padded_ zpad(T const* val, size_t num_digits) -{ - return integral_padded_(reinterpret_cast(val), 16, num_digits); -} -template -C4_ALWAYS_INLINE integral_padded_ zpad(T * val, size_t num_digits) -{ - return integral_padded_(reinterpret_cast(val), 16, num_digits); -} - - -/** format the pointer as an hexadecimal value */ -template -inline integral_ hex(T * v) -{ - return integral_(reinterpret_cast(v), intptr_t(16)); -} -/** format the pointer as an hexadecimal value */ -template -inline integral_ hex(T const* v) -{ - return integral_(reinterpret_cast(v), intptr_t(16)); -} -/** format null as an hexadecimal value - * @overload hex */ -inline integral_ hex(std::nullptr_t) -{ - return integral_(0, intptr_t(16)); -} -/** format the integral_ argument as an hexadecimal value - * @overload hex */ -template -inline integral_ hex(T v) -{ - return integral_(v, T(16)); -} - -/** format the pointer as an octal value */ -template -inline integral_ oct(T const* v) -{ - return integral_(reinterpret_cast(v), intptr_t(8)); -} -/** format the pointer as an octal value */ -template -inline integral_ oct(T * v) -{ - return integral_(reinterpret_cast(v), intptr_t(8)); -} -/** format null as an octal value */ -inline integral_ oct(std::nullptr_t) -{ - return integral_(intptr_t(0), intptr_t(8)); -} -/** format the integral_ argument as an octal value */ -template -inline integral_ oct(T v) -{ - return integral_(v, T(8)); -} - -/** format the pointer as a binary 0-1 value - * @see c4::raw() if you want to use a binary memcpy instead of 0-1 formatting */ -template -inline integral_ bin(T const* v) -{ - return integral_(reinterpret_cast(v), intptr_t(2)); -} -/** format the pointer as a binary 0-1 value - * @see c4::raw() if you want to use a binary memcpy instead of 0-1 formatting */ -template -inline integral_ bin(T * v) -{ - return integral_(reinterpret_cast(v), intptr_t(2)); -} -/** format null as a binary 0-1 value - * @see c4::raw() if you want to use a binary memcpy instead of 0-1 formatting */ -inline integral_ bin(std::nullptr_t) -{ - return integral_(intptr_t(0), intptr_t(2)); -} -/** format the integral_ argument as a binary 0-1 value - * @see c4::raw() if you want to use a raw memcpy-based binary dump instead of 0-1 formatting */ -template -inline integral_ bin(T v) -{ - return integral_(v, T(2)); -} - - -template -struct overflow_checked_ -{ - static_assert(std::is_integral::value, "range checking only for integral types"); - C4_ALWAYS_INLINE overflow_checked_(T &val_) : val(&val_) {} - T *val; -}; -template -C4_ALWAYS_INLINE overflow_checked_ overflow_checked(T &val) -{ - return overflow_checked_(val); -} - -} // namespace fmt - -/** format an integral_ signed type */ -template -C4_ALWAYS_INLINE -typename std::enable_if::value, size_t>::type -to_chars(substr buf, fmt::integral_ fmt) -{ - return itoa(buf, fmt.val, fmt.radix); -} -/** format an integral_ signed type, pad with zeroes */ -template -C4_ALWAYS_INLINE -typename std::enable_if::value, size_t>::type -to_chars(substr buf, fmt::integral_padded_ fmt) -{ - return itoa(buf, fmt.val, fmt.radix, fmt.num_digits); -} - -/** format an integral_ unsigned type */ -template -C4_ALWAYS_INLINE -typename std::enable_if::value, size_t>::type -to_chars(substr buf, fmt::integral_ fmt) -{ - return utoa(buf, fmt.val, fmt.radix); -} -/** format an integral_ unsigned type, pad with zeroes */ -template -C4_ALWAYS_INLINE -typename std::enable_if::value, size_t>::type -to_chars(substr buf, fmt::integral_padded_ fmt) -{ - return utoa(buf, fmt.val, fmt.radix, fmt.num_digits); -} - -template -C4_ALWAYS_INLINE bool from_chars(csubstr s, fmt::overflow_checked_ wrapper) -{ - if(C4_LIKELY(!overflows(s))) - return atox(s, wrapper.val); - return false; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// formatting real types - -namespace fmt { - -template -struct real_ -{ - T val; - int precision; - RealFormat_e fmt; - real_(T v, int prec=-1, RealFormat_e f=FTOA_FLOAT) : val(v), precision(prec), fmt(f) {} -}; - -template -real_ real(T val, int precision, RealFormat_e fmt=FTOA_FLOAT) -{ - return real_(val, precision, fmt); -} - -} // namespace fmt - -inline size_t to_chars(substr buf, fmt::real_< float> fmt) { return ftoa(buf, fmt.val, fmt.precision, fmt.fmt); } -inline size_t to_chars(substr buf, fmt::real_ fmt) { return dtoa(buf, fmt.val, fmt.precision, fmt.fmt); } - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// writing raw binary data - -namespace fmt { - -/** @see blob_ */ -template -struct raw_wrapper_ : public blob_ -{ - size_t alignment; - - C4_ALWAYS_INLINE raw_wrapper_(blob_ data, size_t alignment_) noexcept - : - blob_(data), - alignment(alignment_) - { - C4_ASSERT_MSG(alignment > 0 && (alignment & (alignment - 1)) == 0, "alignment must be a power of two"); - } -}; - -using const_raw_wrapper = raw_wrapper_; -using raw_wrapper = raw_wrapper_; - -/** mark a variable to be written in raw binary format, using memcpy - * @see blob_ */ -inline const_raw_wrapper craw(cblob data, size_t alignment=alignof(max_align_t)) -{ - return const_raw_wrapper(data, alignment); -} -/** mark a variable to be written in raw binary format, using memcpy - * @see blob_ */ -inline const_raw_wrapper raw(cblob data, size_t alignment=alignof(max_align_t)) -{ - return const_raw_wrapper(data, alignment); -} -/** mark a variable to be written in raw binary format, using memcpy - * @see blob_ */ -template -inline const_raw_wrapper craw(T const& C4_RESTRICT data, size_t alignment=alignof(T)) -{ - return const_raw_wrapper(cblob(data), alignment); -} -/** mark a variable to be written in raw binary format, using memcpy - * @see blob_ */ -template -inline const_raw_wrapper raw(T const& C4_RESTRICT data, size_t alignment=alignof(T)) -{ - return const_raw_wrapper(cblob(data), alignment); -} - -/** mark a variable to be read in raw binary format, using memcpy */ -inline raw_wrapper raw(blob data, size_t alignment=alignof(max_align_t)) -{ - return raw_wrapper(data, alignment); -} -/** mark a variable to be read in raw binary format, using memcpy */ -template -inline raw_wrapper raw(T & C4_RESTRICT data, size_t alignment=alignof(T)) -{ - return raw_wrapper(blob(data), alignment); -} - -} // namespace fmt - - -/** write a variable in raw binary format, using memcpy */ -C4CORE_EXPORT size_t to_chars(substr buf, fmt::const_raw_wrapper r); - -/** read a variable in raw binary format, using memcpy */ -C4CORE_EXPORT bool from_chars(csubstr buf, fmt::raw_wrapper *r); -/** read a variable in raw binary format, using memcpy */ -inline bool from_chars(csubstr buf, fmt::raw_wrapper r) -{ - return from_chars(buf, &r); -} - -/** read a variable in raw binary format, using memcpy */ -inline size_t from_chars_first(csubstr buf, fmt::raw_wrapper *r) -{ - return from_chars(buf, r); -} -/** read a variable in raw binary format, using memcpy */ -inline size_t from_chars_first(csubstr buf, fmt::raw_wrapper r) -{ - return from_chars(buf, &r); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// formatting aligned to left/right - -namespace fmt { - -template -struct left_ -{ - T val; - size_t width; - char pad; - left_(T v, size_t w, char p) : val(v), width(w), pad(p) {} -}; - -template -struct right_ -{ - T val; - size_t width; - char pad; - right_(T v, size_t w, char p) : val(v), width(w), pad(p) {} -}; - -/** mark an argument to be aligned left */ -template -left_ left(T val, size_t width, char padchar=' ') -{ - return left_(val, width, padchar); -} - -/** mark an argument to be aligned right */ -template -right_ right(T val, size_t width, char padchar=' ') -{ - return right_(val, width, padchar); -} - -} // namespace fmt - - -template -size_t to_chars(substr buf, fmt::left_ const& C4_RESTRICT align) -{ - size_t ret = to_chars(buf, align.val); - if(ret >= buf.len || ret >= align.width) - return ret > align.width ? ret : align.width; - buf.first(align.width).sub(ret).fill(align.pad); - to_chars(buf, align.val); - return align.width; -} - -template -size_t to_chars(substr buf, fmt::right_ const& C4_RESTRICT align) -{ - size_t ret = to_chars(buf, align.val); - if(ret >= buf.len || ret >= align.width) - return ret > align.width ? ret : align.width; - size_t rem = static_cast(align.width - ret); - buf.first(rem).fill(align.pad); - to_chars(buf.sub(rem), align.val); - return align.width; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -/// @cond dev -// terminates the variadic recursion -inline size_t cat(substr /*buf*/) -{ - return 0; -} -/// @endcond - - -/** serialize the arguments, concatenating them to the given fixed-size buffer. - * The buffer size is strictly respected: no writes will occur beyond its end. - * @return the number of characters needed to write all the arguments into the buffer. - * @see c4::catrs() if instead of a fixed-size buffer, a resizeable container is desired - * @see c4::uncat() for the inverse function - * @see c4::catsep() if a separator between each argument is to be used - * @see c4::format() if a format string is desired */ -template -size_t cat(substr buf, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more) -{ - size_t num = to_chars(buf, a); - buf = buf.len >= num ? buf.sub(num) : substr{}; - num += cat(buf, more...); - return num; -} - -/** like c4::cat() but return a substr instead of a size */ -template -substr cat_sub(substr buf, Args && ...args) -{ - size_t sz = cat(buf, std::forward(args)...); - C4_CHECK(sz <= buf.len); - return {buf.str, sz <= buf.len ? sz : buf.len}; -} - - -//----------------------------------------------------------------------------- - -/// @cond dev -// terminates the variadic recursion -inline size_t uncat(csubstr /*buf*/) -{ - return 0; -} -/// @endcond - - -/** deserialize the arguments from the given buffer. - * - * @return the number of characters read from the buffer, or csubstr::npos - * if a conversion was not successful. - * @see c4::cat(). c4::uncat() is the inverse of c4::cat(). */ -template -size_t uncat(csubstr buf, Arg & C4_RESTRICT a, Args & C4_RESTRICT ...more) -{ - size_t out = from_chars_first(buf, &a); - if(C4_UNLIKELY(out == csubstr::npos)) - return csubstr::npos; - buf = buf.len >= out ? buf.sub(out) : substr{}; - size_t num = uncat(buf, more...); - if(C4_UNLIKELY(num == csubstr::npos)) - return csubstr::npos; - return out + num; -} - - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -namespace detail { - -template -inline size_t catsep_more(substr /*buf*/, Sep const& C4_RESTRICT /*sep*/) -{ - return 0; -} - -template -size_t catsep_more(substr buf, Sep const& C4_RESTRICT sep, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more) -{ - size_t ret = to_chars(buf, sep), num = ret; - buf = buf.len >= ret ? buf.sub(ret) : substr{}; - ret = to_chars(buf, a); - num += ret; - buf = buf.len >= ret ? buf.sub(ret) : substr{}; - ret = catsep_more(buf, sep, more...); - num += ret; - return num; -} - -template -inline size_t uncatsep_more(csubstr /*buf*/, Sep & /*sep*/) -{ - return 0; -} - -template -size_t uncatsep_more(csubstr buf, Sep & C4_RESTRICT sep, Arg & C4_RESTRICT a, Args & C4_RESTRICT ...more) -{ - size_t ret = from_chars_first(buf, &sep), num = ret; - if(C4_UNLIKELY(ret == csubstr::npos)) - return csubstr::npos; - buf = buf.len >= ret ? buf.sub(ret) : substr{}; - ret = from_chars_first(buf, &a); - if(C4_UNLIKELY(ret == csubstr::npos)) - return csubstr::npos; - num += ret; - buf = buf.len >= ret ? buf.sub(ret) : substr{}; - ret = uncatsep_more(buf, sep, more...); - if(C4_UNLIKELY(ret == csubstr::npos)) - return csubstr::npos; - num += ret; - return num; -} - -} // namespace detail - - -/** serialize the arguments, concatenating them to the given fixed-size - * buffer, using a separator between each argument. - * The buffer size is strictly respected: no writes will occur beyond its end. - * @return the number of characters needed to write all the arguments into the buffer. - * @see c4::catseprs() if instead of a fixed-size buffer, a resizeable container is desired - * @see c4::uncatsep() for the inverse function (ie, reading instead of writing) - * @see c4::cat() if no separator is needed - * @see c4::format() if a format string is desired */ -template -size_t catsep(substr buf, Sep const& C4_RESTRICT sep, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more) -{ - size_t num = to_chars(buf, a); - buf = buf.len >= num ? buf.sub(num) : substr{}; - num += detail::catsep_more(buf, sep, more...); - return num; -} - -/** like c4::catsep() but return a substr instead of a size - * @see c4::catsep(). c4::uncatsep() is the inverse of c4::catsep(). */ -template -substr catsep_sub(substr buf, Args && ...args) -{ - size_t sz = catsep(buf, std::forward(args)...); - C4_CHECK(sz <= buf.len); - return {buf.str, sz <= buf.len ? sz : buf.len}; -} - -/** deserialize the arguments from the given buffer, using a separator. - * - * @return the number of characters read from the buffer, or csubstr::npos - * if a conversion was not successful - * @see c4::catsep(). c4::uncatsep() is the inverse of c4::catsep(). */ -template -size_t uncatsep(csubstr buf, Sep & C4_RESTRICT sep, Arg & C4_RESTRICT a, Args & C4_RESTRICT ...more) -{ - size_t ret = from_chars_first(buf, &a), num = ret; - if(C4_UNLIKELY(ret == csubstr::npos)) - return csubstr::npos; - buf = buf.len >= ret ? buf.sub(ret) : substr{}; - ret = detail::uncatsep_more(buf, sep, more...); - if(C4_UNLIKELY(ret == csubstr::npos)) - return csubstr::npos; - num += ret; - return num; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -/// @cond dev -// terminates the variadic recursion -inline size_t format(substr buf, csubstr fmt) -{ - return to_chars(buf, fmt); -} -/// @endcond - - -/** using a format string, serialize the arguments into the given - * fixed-size buffer. - * The buffer size is strictly respected: no writes will occur beyond its end. - * In the format string, each argument is marked with a compact - * curly-bracket pair: {}. Arguments beyond the last curly bracket pair - * are silently ignored. For example: - * @code{.cpp} - * c4::format(buf, "the {} drank {} {}", "partier", 5, "beers"); // the partier drank 5 beers - * c4::format(buf, "the {} drank {} {}", "programmer", 6, "coffees"); // the programmer drank 6 coffees - * @endcode - * @return the number of characters needed to write into the buffer. - * @see c4::formatrs() if instead of a fixed-size buffer, a resizeable container is desired - * @see c4::unformat() for the inverse function - * @see c4::cat() if no format or separator is needed - * @see c4::catsep() if no format is needed, but a separator must be used */ -template -size_t format(substr buf, csubstr fmt, Arg const& C4_RESTRICT a, Args const& C4_RESTRICT ...more) -{ - size_t pos = fmt.find("{}"); // @todo use _find_fmt() - if(C4_UNLIKELY(pos == csubstr::npos)) - return to_chars(buf, fmt); - size_t num = to_chars(buf, fmt.sub(0, pos)); - size_t out = num; - buf = buf.len >= num ? buf.sub(num) : substr{}; - num = to_chars(buf, a); - out += num; - buf = buf.len >= num ? buf.sub(num) : substr{}; - num = format(buf, fmt.sub(pos + 2), more...); - out += num; - return out; -} - -/** like c4::format() but return a substr instead of a size - * @see c4::format() - * @see c4::catsep(). uncatsep() is the inverse of catsep(). */ -template -substr format_sub(substr buf, csubstr fmt, Args const& C4_RESTRICT ...args) -{ - size_t sz = c4::format(buf, fmt, args...); - C4_CHECK(sz <= buf.len); - return {buf.str, sz <= buf.len ? sz : buf.len}; -} - - -//----------------------------------------------------------------------------- - -/// @cond dev -// terminates the variadic recursion -inline size_t unformat(csubstr /*buf*/, csubstr fmt) -{ - return fmt.len; -} -/// @endcond - - -/** using a format string, deserialize the arguments from the given - * buffer. - * @return the number of characters read from the buffer, or npos if a conversion failed. - * @see c4::format(). c4::unformat() is the inverse function to format(). */ -template -size_t unformat(csubstr buf, csubstr fmt, Arg & C4_RESTRICT a, Args & C4_RESTRICT ...more) -{ - const size_t pos = fmt.find("{}"); - if(C4_UNLIKELY(pos == csubstr::npos)) - return unformat(buf, fmt); - size_t num = pos; - size_t out = num; - buf = buf.len >= num ? buf.sub(num) : substr{}; - num = from_chars_first(buf, &a); - if(C4_UNLIKELY(num == csubstr::npos)) - return csubstr::npos; - out += num; - buf = buf.len >= num ? buf.sub(num) : substr{}; - num = unformat(buf, fmt.sub(pos + 2), more...); - if(C4_UNLIKELY(num == csubstr::npos)) - return csubstr::npos; - out += num; - return out; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -/** a tag type for marking append to container - * @see c4::catrs() */ -struct append_t {}; - -/** a tag variable - * @see c4::catrs() */ -constexpr const append_t append = {}; - - -//----------------------------------------------------------------------------- - -/** like c4::cat(), but receives a container, and resizes it as needed to contain - * the result. The container is overwritten. To append to it, use the append - * overload. - * @see c4::cat() */ -template -inline void catrs(CharOwningContainer * C4_RESTRICT cont, Args const& C4_RESTRICT ...args) -{ -retry: - substr buf = to_substr(*cont); - size_t ret = cat(buf, args...); - cont->resize(ret); - if(ret > buf.len) - goto retry; -} - -/** like c4::cat(), but creates and returns a new container sized as needed to contain - * the result. - * @see c4::cat() */ -template -inline CharOwningContainer catrs(Args const& C4_RESTRICT ...args) -{ - CharOwningContainer cont; - catrs(&cont, args...); - return cont; -} - -/** like c4::cat(), but receives a container, and appends to it instead of - * overwriting it. The container is resized as needed to contain the result. - * @return the region newly appended to the original container - * @see c4::cat() - * @see c4::catrs() */ -template -inline csubstr catrs(append_t, CharOwningContainer * C4_RESTRICT cont, Args const& C4_RESTRICT ...args) -{ - const size_t pos = cont->size(); -retry: - substr buf = to_substr(*cont).sub(pos); - size_t ret = cat(buf, args...); - cont->resize(pos + ret); - if(ret > buf.len) - goto retry; - return to_csubstr(*cont).range(pos, cont->size()); -} - - -//----------------------------------------------------------------------------- - -/// @cond dev -// terminates the recursion -template -inline void catseprs(CharOwningContainer * C4_RESTRICT, Sep const& C4_RESTRICT) -{ - return; -} -/// @end cond - - -/** like c4::catsep(), but receives a container, and resizes it as needed to contain the result. - * The container is overwritten. To append to the container use the append overload. - * @see c4::catsep() */ -template -inline void catseprs(CharOwningContainer * C4_RESTRICT cont, Sep const& C4_RESTRICT sep, Args const& C4_RESTRICT ...args) -{ -retry: - substr buf = to_substr(*cont); - size_t ret = catsep(buf, sep, args...); - cont->resize(ret); - if(ret > buf.len) - goto retry; -} - -/** like c4::catsep(), but create a new container with the result. - * @return the requested container */ -template -inline CharOwningContainer catseprs(Sep const& C4_RESTRICT sep, Args const& C4_RESTRICT ...args) -{ - CharOwningContainer cont; - catseprs(&cont, sep, args...); - return cont; -} - - -/// @cond dev -// terminates the recursion -template -inline csubstr catseprs(append_t, CharOwningContainer * C4_RESTRICT, Sep const& C4_RESTRICT) -{ - csubstr s; - return s; -} -/// @endcond - -/** like catsep(), but receives a container, and appends the arguments, resizing the - * container as needed to contain the result. The buffer is appended to. - * @return a csubstr of the appended part - * @ingroup formatting_functions */ -template -inline csubstr catseprs(append_t, CharOwningContainer * C4_RESTRICT cont, Sep const& C4_RESTRICT sep, Args const& C4_RESTRICT ...args) -{ - const size_t pos = cont->size(); -retry: - substr buf = to_substr(*cont).sub(pos); - size_t ret = catsep(buf, sep, args...); - cont->resize(pos + ret); - if(ret > buf.len) - goto retry; - return to_csubstr(*cont).range(pos, cont->size()); -} - - -//----------------------------------------------------------------------------- - -/** like c4::format(), but receives a container, and resizes it as needed - * to contain the result. The container is overwritten. To append to - * the container use the append overload. - * @see c4::format() */ -template -inline void formatrs(CharOwningContainer * C4_RESTRICT cont, csubstr fmt, Args const& C4_RESTRICT ...args) -{ -retry: - substr buf = to_substr(*cont); - size_t ret = format(buf, fmt, args...); - cont->resize(ret); - if(ret > buf.len) - goto retry; -} - -/** like c4::format(), but create a new container with the result. - * @return the requested container */ -template -inline CharOwningContainer formatrs(csubstr fmt, Args const& C4_RESTRICT ...args) -{ - CharOwningContainer cont; - formatrs(&cont, fmt, args...); - return cont; -} - -/** like format(), but receives a container, and appends the - * arguments, resizing the container as needed to contain the - * result. The buffer is appended to. - * @return the region newly appended to the original container - * @ingroup formatting_functions */ -template -inline csubstr formatrs(append_t, CharOwningContainer * C4_RESTRICT cont, csubstr fmt, Args const& C4_RESTRICT ...args) -{ - const size_t pos = cont->size(); -retry: - substr buf = to_substr(*cont).sub(pos); - size_t ret = format(buf, fmt, args...); - cont->resize(pos + ret); - if(ret > buf.len) - goto retry; - return to_csubstr(*cont).range(pos, cont->size()); -} - -} // namespace c4 - -#ifdef _MSC_VER -# pragma warning(pop) -#elif defined(__clang__) -# pragma clang diagnostic pop -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#endif - -#endif /* _C4_FORMAT_HPP_ */ diff --git a/thirdparty/ryml/ext/c4core/src/c4/hash.hpp b/thirdparty/ryml/ext/c4core/src/c4/hash.hpp deleted file mode 100644 index 635bc1544..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/hash.hpp +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef _C4_HASH_HPP_ -#define _C4_HASH_HPP_ - -#include "c4/config.hpp" -#include - -/** @file hash.hpp */ - -/** @defgroup hash Hash utils - * @see http://aras-p.info/blog/2016/08/02/Hash-Functions-all-the-way-down/ */ - -namespace c4 { - -namespace detail { - -/** @internal - * @ingroup hash - * @see this was taken a great answer in stackoverflow: - * https://stackoverflow.com/a/34597785/5875572 - * @see http://aras-p.info/blog/2016/08/02/Hash-Functions-all-the-way-down/ */ -template -class basic_fnv1a final -{ - - static_assert(std::is_unsigned::value, "need unsigned integer"); - -public: - - using result_type = ResultT; - -private: - - result_type state_ {}; - -public: - - C4_CONSTEXPR14 basic_fnv1a() noexcept : state_ {OffsetBasis} {} - - C4_CONSTEXPR14 void update(const void *const data, const size_t size) noexcept - { - auto cdata = static_cast(data); - auto acc = this->state_; - for(size_t i = 0; i < size; ++i) - { - const auto next = size_t(cdata[i]); - acc = (acc ^ next) * Prime; - } - this->state_ = acc; - } - - C4_CONSTEXPR14 result_type digest() const noexcept - { - return this->state_; - } - -}; - -using fnv1a_32 = basic_fnv1a; -using fnv1a_64 = basic_fnv1a; - -template struct fnv1a; -template<> struct fnv1a<32> { using type = fnv1a_32; }; -template<> struct fnv1a<64> { using type = fnv1a_64; }; - -} // namespace detail - - -/** @ingroup hash */ -template -using fnv1a_t = typename detail::fnv1a::type; - - -/** @ingroup hash */ -C4_CONSTEXPR14 inline size_t hash_bytes(const void *const data, const size_t size) noexcept -{ - fnv1a_t fn{}; - fn.update(data, size); - return fn.digest(); -} - -/** - * @overload hash_bytes - * @ingroup hash */ -template -C4_CONSTEXPR14 inline size_t hash_bytes(const char (&str)[N]) noexcept -{ - fnv1a_t fn{}; - fn.update(str, N); - return fn.digest(); -} - -} // namespace c4 - - -#endif // _C4_HASH_HPP_ diff --git a/thirdparty/ryml/ext/c4core/src/c4/language.cpp b/thirdparty/ryml/ext/c4core/src/c4/language.cpp deleted file mode 100644 index d1b569741..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/language.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "c4/language.hpp" - -namespace c4 { -namespace detail { - -#ifndef __GNUC__ -void use_char_pointer(char const volatile* v) -{ - C4_UNUSED(v); -} -#else -void foo() {} // to avoid empty file warning from the linker -#endif - -} // namespace detail -} // namespace c4 diff --git a/thirdparty/ryml/ext/c4core/src/c4/language.hpp b/thirdparty/ryml/ext/c4core/src/c4/language.hpp deleted file mode 100644 index 90ff9bab5..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/language.hpp +++ /dev/null @@ -1,275 +0,0 @@ -#ifndef _C4_LANGUAGE_HPP_ -#define _C4_LANGUAGE_HPP_ - -/** @file language.hpp Provides language standard information macros and - * compiler agnostic utility macros: namespace facilities, function attributes, - * variable attributes, etc. - * @ingroup basic_headers */ - -#include "c4/preprocessor.hpp" -#include "c4/compiler.hpp" - -/* Detect C++ standard. - * @see http://stackoverflow.com/a/7132549/5875572 */ -#ifndef C4_CPP -# ifdef _MSC_VER -# if _MSC_VER >= 1910 // >VS2015: VS2017, VS2019 -# if (!defined(_MSVC_LANG)) -# error _MSVC not defined -# endif -# if _MSVC_LANG >= 201705L -# define C4_CPP 20 -# define C4_CPP20 -# elif _MSVC_LANG == 201703L -# define C4_CPP 17 -# define C4_CPP17 -# elif _MSVC_LANG >= 201402L -# define C4_CPP 14 -# define C4_CPP14 -# elif _MSVC_LANG >= 201103L -# define C4_CPP 11 -# define C4_CPP11 -# else -# error C++ lesser than C++11 not supported -# endif -# else -# if _MSC_VER == 1900 -# define C4_CPP 14 // VS2015 is c++14 https://devblogs.microsoft.com/cppblog/c111417-features-in-vs-2015-rtm/ -# define C4_CPP14 -# elif _MSC_VER == 1800 // VS2013 -# define C4_CPP 11 -# define C4_CPP11 -# else -# error C++ lesser than C++11 not supported -# endif -# endif -# elif defined(__INTEL_COMPILER) // https://software.intel.com/en-us/node/524490 -# ifdef __INTEL_CXX20_MODE__ // not sure about this -# define C4_CPP 20 -# define C4_CPP20 -# elif defined __INTEL_CXX17_MODE__ // not sure about this -# define C4_CPP 17 -# define C4_CPP17 -# elif defined __INTEL_CXX14_MODE__ // not sure about this -# define C4_CPP 14 -# define C4_CPP14 -# elif defined __INTEL_CXX11_MODE__ -# define C4_CPP 11 -# define C4_CPP11 -# else -# error C++ lesser than C++11 not supported -# endif -# else -# ifndef __cplusplus -# error __cplusplus is not defined? -# endif -# if __cplusplus == 1 -# error cannot handle __cplusplus==1 -# elif __cplusplus >= 201709L -# define C4_CPP 20 -# define C4_CPP20 -# elif __cplusplus >= 201703L -# define C4_CPP 17 -# define C4_CPP17 -# elif __cplusplus >= 201402L -# define C4_CPP 14 -# define C4_CPP14 -# elif __cplusplus >= 201103L -# define C4_CPP 11 -# define C4_CPP11 -# elif __cplusplus >= 199711L -# error C++ lesser than C++11 not supported -# endif -# endif -#else -# ifdef C4_CPP == 20 -# define C4_CPP20 -# elif C4_CPP == 17 -# define C4_CPP17 -# elif C4_CPP == 14 -# define C4_CPP14 -# elif C4_CPP == 11 -# define C4_CPP11 -# elif C4_CPP == 98 -# define C4_CPP98 -# error C++ lesser than C++11 not supported -# else -# error C4_CPP must be one of 20, 17, 14, 11, 98 -# endif -#endif - -#ifdef C4_CPP20 -# define C4_CPP17 -# define C4_CPP14 -# define C4_CPP11 -#elif defined(C4_CPP17) -# define C4_CPP14 -# define C4_CPP11 -#elif defined(C4_CPP14) -# define C4_CPP11 -#endif - -/** lifted from this answer: http://stackoverflow.com/a/20170989/5875572 */ -#ifndef _MSC_VER -# if __cplusplus < 201103 -# define C4_CONSTEXPR11 -# define C4_CONSTEXPR14 -//# define C4_NOEXCEPT -# elif __cplusplus == 201103 -# define C4_CONSTEXPR11 constexpr -# define C4_CONSTEXPR14 -//# define C4_NOEXCEPT noexcept -# else -# define C4_CONSTEXPR11 constexpr -# define C4_CONSTEXPR14 constexpr -//# define C4_NOEXCEPT noexcept -# endif -#else // _MSC_VER -# if _MSC_VER < 1900 -# define C4_CONSTEXPR11 -# define C4_CONSTEXPR14 -//# define C4_NOEXCEPT -# elif _MSC_VER < 2000 -# define C4_CONSTEXPR11 constexpr -# define C4_CONSTEXPR14 -//# define C4_NOEXCEPT noexcept -# else -# define C4_CONSTEXPR11 constexpr -# define C4_CONSTEXPR14 constexpr -//# define C4_NOEXCEPT noexcept -# endif -#endif // _MSC_VER - - -#if C4_CPP < 17 -#define C4_IF_CONSTEXPR -#define C4_INLINE_CONSTEXPR constexpr -#else -#define C4_IF_CONSTEXPR constexpr -#define C4_INLINE_CONSTEXPR inline constexpr -#endif - - -//------------------------------------------------------------ - -#define _C4_BEGIN_NAMESPACE(ns) namespace ns { -#define _C4_END_NAMESPACE(ns) } - -// MSVC cant handle the C4_FOR_EACH macro... need to fix this -//#define C4_BEGIN_NAMESPACE(...) C4_FOR_EACH_SEP(_C4_BEGIN_NAMESPACE, , __VA_ARGS__) -//#define C4_END_NAMESPACE(...) C4_FOR_EACH_SEP(_C4_END_NAMESPACE, , __VA_ARGS__) -#define C4_BEGIN_NAMESPACE(ns) namespace ns { -#define C4_END_NAMESPACE(ns) } - -#define C4_BEGIN_HIDDEN_NAMESPACE namespace /*hidden*/ { -#define C4_END_HIDDEN_NAMESPACE } /* namespace hidden */ - -//------------------------------------------------------------ - -#ifndef C4_API -# if defined(_MSC_VER) -# if defined(C4_EXPORT) -# define C4_API __declspec(dllexport) -# elif defined(C4_IMPORT) -# define C4_API __declspec(dllimport) -# else -# define C4_API -# endif -# else -# define C4_API -# endif -#endif - -#ifndef _MSC_VER ///< @todo assuming gcc-like compiler. check it is actually so. -/** for function attributes in GCC, - * @see https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes */ -/** for __builtin functions in GCC, - * @see https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html */ -# define C4_RESTRICT __restrict__ -# define C4_RESTRICT_FN __attribute__((restrict)) -# define C4_NO_INLINE __attribute__((noinline)) -# define C4_ALWAYS_INLINE inline __attribute__((always_inline)) -# define C4_CONST __attribute__((const)) -# define C4_PURE __attribute__((pure)) -/** force inlining of every callee function */ -# define C4_FLATTEN __atribute__((flatten)) -/** mark a function as hot, ie as having a visible impact in CPU time - * thus making it more likely to inline, etc - * @see http://stackoverflow.com/questions/15028990/semantics-of-gcc-hot-attribute */ -# define C4_HOT __attribute__((hot)) -/** mark a function as cold, ie as NOT having a visible impact in CPU time - * @see http://stackoverflow.com/questions/15028990/semantics-of-gcc-hot-attribute */ -# define C4_COLD __attribute__((cold)) -# define C4_EXPECT(x, y) __builtin_expect(x, y) ///< @see https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html -# define C4_LIKELY(x) __builtin_expect(x, 1) -# define C4_UNLIKELY(x) __builtin_expect(x, 0) -# define C4_UNREACHABLE() __builtin_unreachable() -# define C4_ATTR_FORMAT(...) //__attribute__((format (__VA_ARGS__))) ///< @see https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes -# define C4_NORETURN __attribute__((noreturn)) -#else -# define C4_RESTRICT __restrict -# define C4_RESTRICT_FN __declspec(restrict) -# define C4_NO_INLINE __declspec(noinline) -# define C4_ALWAYS_INLINE inline __forceinline -/** these are not available in VS AFAIK */ -# define C4_CONST -# define C4_PURE -# define C4_FLATTEN -# define C4_HOT /** @todo */ -# define C4_COLD /** @todo */ -# define C4_EXPECT(x, y) x /** @todo */ -# define C4_LIKELY(x) x /** @todo */ -# define C4_UNLIKELY(x) x /** @todo */ -# define C4_UNREACHABLE() /** @todo */ -# define C4_ATTR_FORMAT(...) /** */ -# define C4_NORETURN /** @todo */ -#endif - -#ifndef _MSC_VER -# define C4_FUNC __FUNCTION__ -# define C4_PRETTY_FUNC __PRETTY_FUNCTION__ -#else /// @todo assuming gcc-like compiler. check it is actually so. -# define C4_FUNC __FUNCTION__ -# define C4_PRETTY_FUNC __FUNCSIG__ -#endif - -/** prevent compiler warnings about a specific var being unused */ -#define C4_UNUSED(var) (void)var - -#if C4_CPP >= 17 -#define C4_STATIC_ASSERT(cond) static_assert(cond) -#else -#define C4_STATIC_ASSERT(cond) static_assert((cond), #cond) -#endif -#define C4_STATIC_ASSERT_MSG(cond, msg) static_assert((cond), #cond ": " msg) - -/** @def C4_DONT_OPTIMIZE idea lifted from GoogleBenchmark. - * @see https://github.com/google/benchmark/blob/master/include/benchmark/benchmark_api.h */ -namespace c4 { -namespace detail { -#ifdef __GNUC__ -# define C4_DONT_OPTIMIZE(var) c4::detail::dont_optimize(var) -template< class T > -C4_ALWAYS_INLINE void dont_optimize(T const& value) { asm volatile("" : : "g"(value) : "memory"); } -#else -# define C4_DONT_OPTIMIZE(var) c4::detail::use_char_pointer(reinterpret_cast< const char* >(&var)) -void use_char_pointer(char const volatile*); -#endif -} // namespace detail -} // namespace c4 - -/** @def C4_KEEP_EMPTY_LOOP prevent an empty loop from being optimized out. - * @see http://stackoverflow.com/a/7084193/5875572 */ -#ifndef _MSC_VER -# define C4_KEEP_EMPTY_LOOP { asm(""); } -#else -# define C4_KEEP_EMPTY_LOOP { char c; C4_DONT_OPTIMIZE(c); } -#endif - -/** @def C4_VA_LIST_REUSE_MUST_COPY - * @todo I strongly suspect that this is actually only in UNIX platforms. revisit this. */ -#ifdef __GNUC__ -# define C4_VA_LIST_REUSE_MUST_COPY -#endif - -#endif /* _C4_LANGUAGE_HPP_ */ diff --git a/thirdparty/ryml/ext/c4core/src/c4/memory_resource.cpp b/thirdparty/ryml/ext/c4core/src/c4/memory_resource.cpp deleted file mode 100644 index 647d26736..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/memory_resource.cpp +++ /dev/null @@ -1,338 +0,0 @@ -#include "c4/memory_resource.hpp" -#include "c4/memory_util.hpp" - -#include -#include -#if defined(C4_POSIX) || defined(C4_IOS) || defined(C4_MACOS) || defined(C4_ARM) -# include -#endif -#if defined(C4_ARM) -# include -#endif - -#include - -namespace c4 { - -namespace detail { - - -#ifdef C4_NO_ALLOC_DEFAULTS -aalloc_pfn s_aalloc = nullptr; -free_pfn s_afree = nullptr; -arealloc_pfn s_arealloc = nullptr; -#else - - -void afree_impl(void *ptr) -{ -#if defined(C4_WIN) || defined(C4_XBOX) - ::_aligned_free(ptr); -#else - ::free(ptr); -#endif -} - - -void* aalloc_impl(size_t size, size_t alignment) -{ - void *mem; -#if defined(C4_WIN) || defined(C4_XBOX) - mem = ::_aligned_malloc(size, alignment); - C4_CHECK(mem != nullptr || size == 0); -#elif defined(C4_ARM) - // https://stackoverflow.com/questions/53614538/undefined-reference-to-posix-memalign-in-arm-gcc - // https://electronics.stackexchange.com/questions/467382/e2-studio-undefined-reference-to-posix-memalign/467753 - mem = memalign(alignment, size); - C4_CHECK(mem != nullptr || size == 0); -#elif defined(C4_POSIX) || defined(C4_IOS) || defined(C4_MACOS) - // NOTE: alignment needs to be sized in multiples of sizeof(void*) - size_t amult = alignment; - if(C4_UNLIKELY(alignment < sizeof(void*))) - { - amult = sizeof(void*); - } - int ret = ::posix_memalign(&mem, amult, size); - if(C4_UNLIKELY(ret)) - { - if(ret == EINVAL) - { - C4_ERROR("The alignment argument %zu was not a power of two, " - "or was not a multiple of sizeof(void*)", alignment); - } - else if(ret == ENOMEM) - { - C4_ERROR("There was insufficient memory to fulfill the " - "allocation request of %zu bytes (alignment=%lu)", size, size); - } - return nullptr; - } -#else - C4_NOT_IMPLEMENTED_MSG("need to implement an aligned allocation for this platform"); -#endif - C4_ASSERT_MSG((uintptr_t(mem) & (alignment-1)) == 0, "address %p is not aligned to %zu boundary", mem, alignment); - return mem; -} - - -void* arealloc_impl(void* ptr, size_t oldsz, size_t newsz, size_t alignment) -{ - /** @todo make this more efficient - * @see https://stackoverflow.com/questions/9078259/does-realloc-keep-the-memory-alignment-of-posix-memalign - * @see look for qReallocAligned() in http://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/global/qmalloc.cpp - */ - void *tmp = aalloc(newsz, alignment); - size_t min = newsz < oldsz ? newsz : oldsz; - if(mem_overlaps(ptr, tmp, oldsz, newsz)) - { - ::memmove(tmp, ptr, min); - } - else - { - ::memcpy(tmp, ptr, min); - } - afree(ptr); - return tmp; -} - -aalloc_pfn s_aalloc = aalloc_impl; -afree_pfn s_afree = afree_impl; -arealloc_pfn s_arealloc = arealloc_impl; - -#endif // C4_NO_ALLOC_DEFAULTS - -} // namespace detail - - -aalloc_pfn get_aalloc() -{ - return detail::s_aalloc; -} -void set_aalloc(aalloc_pfn fn) -{ - detail::s_aalloc = fn; -} - -afree_pfn get_afree() -{ - return detail::s_afree; -} -void set_afree(afree_pfn fn) -{ - detail::s_afree = fn; -} - -arealloc_pfn get_arealloc() -{ - return detail::s_arealloc; -} -void set_arealloc(arealloc_pfn fn) -{ - detail::s_arealloc = fn; -} - - -void* aalloc(size_t sz, size_t alignment) -{ - C4_ASSERT_MSG(c4::get_aalloc() != nullptr, "did you forget to call set_aalloc()?"); - auto fn = c4::get_aalloc(); - void* ptr = fn(sz, alignment); - return ptr; -} - -void afree(void* ptr) -{ - C4_ASSERT_MSG(c4::get_afree() != nullptr, "did you forget to call set_afree()?"); - auto fn = c4::get_afree(); - fn(ptr); -} - -void* arealloc(void *ptr, size_t oldsz, size_t newsz, size_t alignment) -{ - C4_ASSERT_MSG(c4::get_arealloc() != nullptr, "did you forget to call set_arealloc()?"); - auto fn = c4::get_arealloc(); - void* nptr = fn(ptr, oldsz, newsz, alignment); - return nptr; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -void detail::_MemoryResourceSingleChunk::release() -{ - if(m_mem && m_owner) - { - impl_type::deallocate(m_mem, m_size); - } - m_mem = nullptr; - m_size = 0; - m_owner = false; - m_pos = 0; -} - -void detail::_MemoryResourceSingleChunk::acquire(size_t sz) -{ - clear(); - m_owner = true; - m_mem = (char*) impl_type::allocate(sz, alignof(max_align_t)); - m_size = sz; - m_pos = 0; -} - -void detail::_MemoryResourceSingleChunk::acquire(void *mem, size_t sz) -{ - clear(); - m_owner = false; - m_mem = (char*) mem; - m_size = sz; - m_pos = 0; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -void* MemoryResourceLinear::do_allocate(size_t sz, size_t alignment, void *hint) -{ - C4_UNUSED(hint); - if(sz == 0) return nullptr; - // make sure there's enough room to allocate - if(m_pos + sz > m_size) - { - C4_ERROR("out of memory"); - return nullptr; - } - void *mem = m_mem + m_pos; - size_t space = m_size - m_pos; - if(std::align(alignment, sz, mem, space)) - { - C4_ASSERT(m_pos <= m_size); - C4_ASSERT(m_size - m_pos >= space); - m_pos += (m_size - m_pos) - space; - m_pos += sz; - C4_ASSERT(m_pos <= m_size); - } - else - { - C4_ERROR("could not align memory"); - mem = nullptr; - } - return mem; -} - -void MemoryResourceLinear::do_deallocate(void* ptr, size_t sz, size_t alignment) -{ - C4_UNUSED(ptr); - C4_UNUSED(sz); - C4_UNUSED(alignment); - // nothing to do!! -} - -void* MemoryResourceLinear::do_reallocate(void* ptr, size_t oldsz, size_t newsz, size_t alignment) -{ - if(newsz == oldsz) return ptr; - // is ptr the most recently allocated (MRA) block? - char *cptr = (char*)ptr; - bool same_pos = (m_mem + m_pos == cptr + oldsz); - // no need to get more memory when shrinking - if(newsz < oldsz) - { - // if this is the MRA, we can safely shrink the position - if(same_pos) - { - m_pos -= oldsz - newsz; - } - return ptr; - } - // we're growing the block, and it fits in size - else if(same_pos && cptr + newsz <= m_mem + m_size) - { - // if this is the MRA, we can safely shrink the position - m_pos += newsz - oldsz; - return ptr; - } - // we're growing the block or it doesn't fit - - // delegate any of these situations to do_deallocate() - return do_allocate(newsz, alignment, ptr); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -/** @todo add a free list allocator. A good candidate because of its - * small size is TLSF. - * - * @see https://github.com/mattconte/tlsf - * - * Comparisons: - * - * @see https://www.researchgate.net/publication/262375150_A_Comparative_Study_on_Memory_Allocators_in_Multicore_and_Multithreaded_Applications_-_SBESC_2011_-_Presentation_Slides - * @see http://webkit.sed.hu/blog/20100324/war-allocators-tlsf-action - * @see https://github.com/emeryberger/Malloc-Implementations/tree/master/allocators - * - * */ - -} // namespace c4 - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -#ifdef C4_REDEFINE_CPPNEW -#include -void* operator new(size_t size) -{ - auto *mr = ::c4::get_memory_resource(); - return mr->allocate(size); -} -void operator delete(void *p) noexcept -{ - C4_NEVER_REACH(); -} -void operator delete(void *p, size_t size) -{ - auto *mr = ::c4::get_memory_resource(); - mr->deallocate(p, size); -} -void* operator new[](size_t size) -{ - return operator new(size); -} -void operator delete[](void *p) noexcept -{ - operator delete(p); -} -void operator delete[](void *p, size_t size) -{ - operator delete(p, size); -} -void* operator new(size_t size, std::nothrow_t) -{ - return operator new(size); -} -void operator delete(void *p, std::nothrow_t) -{ - operator delete(p); -} -void operator delete(void *p, size_t size, std::nothrow_t) -{ - operator delete(p, size); -} -void* operator new[](size_t size, std::nothrow_t) -{ - return operator new(size); -} -void operator delete[](void *p, std::nothrow_t) -{ - operator delete(p); -} -void operator delete[](void *p, size_t, std::nothrow_t) -{ - operator delete(p, size); -} -#endif // C4_REDEFINE_CPPNEW diff --git a/thirdparty/ryml/ext/c4core/src/c4/memory_resource.hpp b/thirdparty/ryml/ext/c4core/src/c4/memory_resource.hpp deleted file mode 100644 index 0818f5874..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/memory_resource.hpp +++ /dev/null @@ -1,568 +0,0 @@ -#ifndef _C4_MEMORY_RESOURCE_HPP_ -#define _C4_MEMORY_RESOURCE_HPP_ - -/** @file memory_resource.hpp Provides facilities to allocate typeless - * memory, via the memory resource model consecrated with C++17. */ - -/** @defgroup memory memory utilities */ - -/** @defgroup raw_memory_alloc Raw memory allocation - * @ingroup memory - */ - -/** @defgroup memory_resources Memory resources - * @ingroup memory - */ - -#include "c4/config.hpp" -#include "c4/error.hpp" - -namespace c4 { - -// need these forward decls here -struct MemoryResource; -struct MemoryResourceMalloc; -struct MemoryResourceStack; -MemoryResourceMalloc* get_memory_resource_malloc(); -MemoryResourceStack* get_memory_resource_stack(); -namespace detail { MemoryResource*& get_memory_resource(); } - - -// c-style allocation --------------------------------------------------------- - -// this API provides aligned allocation functions. -// These functions forward the call to a user-modifiable function. - - -// aligned allocation. - -/** Aligned allocation. Merely calls the current get_aalloc() function. - * @see get_aalloc() - * @ingroup raw_memory_alloc */ -void* aalloc(size_t sz, size_t alignment); - -/** Aligned free. Merely calls the current get_afree() function. - * @see get_afree() - * @ingroup raw_memory_alloc */ -void afree(void* ptr); - -/** Aligned reallocation. Merely calls the current get_arealloc() function. - * @see get_arealloc() - * @ingroup raw_memory_alloc */ -void* arealloc(void* ptr, size_t oldsz, size_t newsz, size_t alignment); - - -// allocation setup facilities. - -/** Function pointer type for aligned allocation - * @see set_aalloc() - * @ingroup raw_memory_alloc */ -using aalloc_pfn = void* (*)(size_t size, size_t alignment); - -/** Function pointer type for aligned deallocation - * @see set_afree() - * @ingroup raw_memory_alloc */ -using afree_pfn = void (*)(void *ptr); - -/** Function pointer type for aligned reallocation - * @see set_arealloc() - * @ingroup raw_memory_alloc */ -using arealloc_pfn = void* (*)(void *ptr, size_t oldsz, size_t newsz, size_t alignment); - - -// allocation function pointer setters/getters - -/** Set the global aligned allocation function. - * @see aalloc() - * @see get_aalloc() - * @ingroup raw_memory_alloc */ -void set_aalloc(aalloc_pfn fn); - -/** Set the global aligned deallocation function. - * @see afree() - * @see get_afree() - * @ingroup raw_memory_alloc */ -void set_afree(afree_pfn fn); - -/** Set the global aligned reallocation function. - * @see arealloc() - * @see get_arealloc() - * @ingroup raw_memory_alloc */ -void set_arealloc(arealloc_pfn fn); - - -/** Get the global aligned reallocation function. - * @see arealloc() - * @ingroup raw_memory_alloc */ -aalloc_pfn get_aalloc(); - -/** Get the global aligned deallocation function. - * @see afree() - * @ingroup raw_memory_alloc */ -afree_pfn get_afree(); - -/** Get the global aligned reallocation function. - * @see arealloc() - * @ingroup raw_memory_alloc */ -arealloc_pfn get_arealloc(); - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// c++-style allocation ------------------------------------------------------- - -/** C++17-style memory_resource base class. See http://en.cppreference.com/w/cpp/experimental/memory_resource - * @ingroup memory_resources */ -struct MemoryResource -{ - const char *name = nullptr; - virtual ~MemoryResource() {} - - void* allocate(size_t sz, size_t alignment=alignof(max_align_t), void *hint=nullptr) - { - void *mem = this->do_allocate(sz, alignment, hint); - C4_CHECK_MSG(mem != nullptr, "could not allocate %lu bytes", sz); - return mem; - } - - void* reallocate(void* ptr, size_t oldsz, size_t newsz, size_t alignment=alignof(max_align_t)) - { - void *mem = this->do_reallocate(ptr, oldsz, newsz, alignment); - C4_CHECK_MSG(mem != nullptr, "could not reallocate from %lu to %lu bytes", oldsz, newsz); - return mem; - } - - void deallocate(void* ptr, size_t sz, size_t alignment=alignof(max_align_t)) - { - this->do_deallocate(ptr, sz, alignment); - } - -protected: - - virtual void* do_allocate(size_t sz, size_t alignment, void* hint) = 0; - virtual void* do_reallocate(void* ptr, size_t oldsz, size_t newsz, size_t alignment) = 0; - virtual void do_deallocate(void* ptr, size_t sz, size_t alignment) = 0; - -}; - -/** get the current global memory resource. To avoid static initialization - * order problems, this is implemented using a function call to ensure - * that it is available when first used. - * @ingroup memory_resources */ -C4_ALWAYS_INLINE MemoryResource* get_memory_resource() -{ - return detail::get_memory_resource(); -} - -/** set the global memory resource - * @ingroup memory_resources */ -C4_ALWAYS_INLINE void set_memory_resource(MemoryResource* mr) -{ - C4_ASSERT(mr != nullptr); - detail::get_memory_resource() = mr; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -/** A c4::aalloc-based memory resource. Thread-safe if the implementation - * called by c4::aalloc() is safe. - * @ingroup memory_resources */ -struct MemoryResourceMalloc : public MemoryResource -{ - - MemoryResourceMalloc() { name = "malloc"; } - virtual ~MemoryResourceMalloc() override {} - -protected: - - virtual void* do_allocate(size_t sz, size_t alignment, void *hint) override - { - C4_UNUSED(hint); - return c4::aalloc(sz, alignment); - } - - virtual void do_deallocate(void* ptr, size_t sz, size_t alignment) override - { - C4_UNUSED(sz); - C4_UNUSED(alignment); - c4::afree(ptr); - } - - virtual void* do_reallocate(void* ptr, size_t oldsz, size_t newsz, size_t alignment) override - { - return c4::arealloc(ptr, oldsz, newsz, alignment); - } - -}; - -/** returns a malloc-based memory resource - * @ingroup memory_resources */ -C4_ALWAYS_INLINE MemoryResourceMalloc* get_memory_resource_malloc() -{ - /** @todo use a nifty counter: - * https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Nifty_Counter */ - static MemoryResourceMalloc mr; - return &mr; -} - -namespace detail { -C4_ALWAYS_INLINE MemoryResource* & get_memory_resource() -{ - /** @todo use a nifty counter: - * https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Nifty_Counter */ - thread_local static MemoryResource* mr = get_memory_resource_malloc(); - return mr; -} -} // namespace detail - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -namespace detail { - -/** Allows a memory resource to obtain its memory from another memory resource. - * @ingroup memory_resources */ -struct DerivedMemoryResource : public MemoryResource -{ -public: - - DerivedMemoryResource(MemoryResource *mr_=nullptr) : m_local(mr_ ? mr_ : get_memory_resource()) {} - -private: - - MemoryResource *m_local; - -protected: - - virtual void* do_allocate(size_t sz, size_t alignment, void* hint) override - { - return m_local->allocate(sz, alignment, hint); - } - - virtual void* do_reallocate(void* ptr, size_t oldsz, size_t newsz, size_t alignment) override - { - return m_local->reallocate(ptr, oldsz, newsz, alignment); - } - - virtual void do_deallocate(void* ptr, size_t sz, size_t alignment) override - { - return m_local->deallocate(ptr, sz, alignment); - } -}; - -/** Provides common facilities for memory resource consisting of a single memory block - * @ingroup memory_resources */ -struct _MemoryResourceSingleChunk : public DerivedMemoryResource -{ - - C4_NO_COPY_OR_MOVE(_MemoryResourceSingleChunk); - - using impl_type = DerivedMemoryResource; - -public: - - _MemoryResourceSingleChunk(MemoryResource *impl=nullptr) : DerivedMemoryResource(impl) { name = "linear_malloc"; } - - /** initialize with owned memory, allocated from the given (or the global) memory resource */ - _MemoryResourceSingleChunk(size_t sz, MemoryResource *impl=nullptr) : _MemoryResourceSingleChunk(impl) { acquire(sz); } - /** initialize with borrowed memory */ - _MemoryResourceSingleChunk(void *mem, size_t sz) : _MemoryResourceSingleChunk() { acquire(mem, sz); } - - virtual ~_MemoryResourceSingleChunk() override { release(); } - -public: - - void const* mem() const { return m_mem; } - - size_t capacity() const { return m_size; } - size_t size() const { return m_pos; } - size_t slack() const { C4_ASSERT(m_size >= m_pos); return m_size - m_pos; } - -public: - - char *m_mem{nullptr}; - size_t m_size{0}; - size_t m_pos{0}; - bool m_owner; - -public: - - /** set the internal pointer to the beginning of the linear buffer */ - void clear() { m_pos = 0; } - - /** initialize with owned memory, allocated from the global memory resource */ - void acquire(size_t sz); - /** initialize with borrowed memory */ - void acquire(void *mem, size_t sz); - /** release the memory */ - void release(); - -}; - -} // namespace detail - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -/** provides a linear memory resource. Allocates incrementally from a linear - * buffer, without ever deallocating. Deallocations are a no-op, and the - * memory is freed only when the resource is release()d. The memory used by - * this object can be either owned or borrowed. When borrowed, no calls to - * malloc/free take place. - * - * @ingroup memory_resources */ -struct MemoryResourceLinear : public detail::_MemoryResourceSingleChunk -{ - - C4_NO_COPY_OR_MOVE(MemoryResourceLinear); - -public: - - using detail::_MemoryResourceSingleChunk::_MemoryResourceSingleChunk; - -protected: - - virtual void* do_allocate(size_t sz, size_t alignment, void *hint) override; - virtual void do_deallocate(void* ptr, size_t sz, size_t alignment) override; - virtual void* do_reallocate(void* ptr, size_t oldsz, size_t newsz, size_t alignment) override; -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -/** provides a stack-type malloc-based memory resource. - * @ingroup memory_resources */ -struct MemoryResourceStack : public detail::_MemoryResourceSingleChunk -{ - - C4_NO_COPY_OR_MOVE(MemoryResourceStack); - -public: - - using detail::_MemoryResourceSingleChunk::_MemoryResourceSingleChunk; - -protected: - - virtual void* do_allocate(size_t sz, size_t alignment, void *hint) override; - virtual void do_deallocate(void* ptr, size_t sz, size_t alignment) override; - virtual void* do_reallocate(void* ptr, size_t oldsz, size_t newsz, size_t alignment) override; -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -/** provides a linear array-based memory resource. - * @see MemoryResourceLinear - * @ingroup memory_resources */ -template -struct MemoryResourceLinearArr : public MemoryResourceLinear -{ - #ifdef _MSC_VER - #pragma warning(push) - #pragma warning(disable: 4324) // structure was padded due to alignment specifier - #endif - alignas(alignof(max_align_t)) char m_arr[N]; - #ifdef _MSC_VER - #pragma warning(pop) - #endif - MemoryResourceLinearArr() : MemoryResourceLinear(m_arr, N) { name = "linear_arr"; } -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -struct AllocationCounts -{ - struct Item - { - ssize_t allocs; - ssize_t size; - - void add(size_t sz) - { - ++allocs; - size += static_cast(sz); - } - void rem(size_t sz) - { - --allocs; - size -= static_cast(sz); - } - Item max(Item const& that) const - { - Item r(*this); - r.allocs = r.allocs > that.allocs ? r.allocs : that.allocs; - r.size = r.size > that.size ? r.size : that.size; - return r; - } - }; - - Item curr = {0, 0}; - Item total = {0, 0}; - Item max = {0, 0}; - - void clear_counts() - { - curr = {0, 0}; - total = {0, 0}; - max = {0, 0}; - } - - void update(AllocationCounts const& that) - { - curr.allocs += that.curr.allocs; - curr.size += that.curr.size; - total.allocs += that.total.allocs; - total.size += that.total.size; - max.allocs += that.max.allocs; - max.size += that.max.size; - } - - void add_counts(void* ptr, size_t sz) - { - if(ptr == nullptr) return; - curr.add(sz); - total.add(sz); - max = max.max(curr); - } - - void rem_counts(void *ptr, size_t sz) - { - if(ptr == nullptr) return; - curr.rem(sz); - } - - AllocationCounts operator- (AllocationCounts const& that) const - { - AllocationCounts r(*this); - r.curr.allocs -= that.curr.allocs; - r.curr.size -= that.curr.size; - r.total.allocs -= that.total.allocs; - r.total.size -= that.total.size; - r.max.allocs -= that.max.allocs; - r.max.size -= that.max.size; - return r; - } - - AllocationCounts operator+ (AllocationCounts const& that) const - { - AllocationCounts r(*this); - r.curr.allocs += that.curr.allocs; - r.curr.size += that.curr.size; - r.total.allocs += that.total.allocs; - r.total.size += that.total.size; - r.max.allocs += that.max.allocs; - r.max.size += that.max.size; - return r; - } -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -/** a MemoryResource which latches onto another MemoryResource - * and counts allocations and sizes. - * @ingroup memory_resources */ -class MemoryResourceCounts : public MemoryResource -{ -public: - - MemoryResourceCounts() : m_resource(get_memory_resource()) - { - C4_ASSERT(m_resource != this); - name = "MemoryResourceCounts"; - } - MemoryResourceCounts(MemoryResource *res) : m_resource(res) - { - C4_ASSERT(m_resource != this); - name = "MemoryResourceCounts"; - } - - MemoryResource *resource() { return m_resource; } - AllocationCounts const& counts() const { return m_counts; } - -protected: - - MemoryResource *m_resource; - AllocationCounts m_counts; - -protected: - - virtual void* do_allocate(size_t sz, size_t alignment, void * /*hint*/) override - { - void *ptr = m_resource->allocate(sz, alignment); - m_counts.add_counts(ptr, sz); - return ptr; - } - - virtual void do_deallocate(void* ptr, size_t sz, size_t alignment) override - { - m_counts.rem_counts(ptr, sz); - m_resource->deallocate(ptr, sz, alignment); - } - - virtual void* do_reallocate(void* ptr, size_t oldsz, size_t newsz, size_t alignment) override - { - m_counts.rem_counts(ptr, oldsz); - void* nptr = m_resource->reallocate(ptr, oldsz, newsz, alignment); - m_counts.add_counts(nptr, newsz); - return nptr; - } - -}; - -//----------------------------------------------------------------------------- -/** RAII class which binds a memory resource with a scope duration. - * @ingroup memory_resources */ -struct ScopedMemoryResource -{ - MemoryResource *m_original; - - ScopedMemoryResource(MemoryResource *r) - : - m_original(get_memory_resource()) - { - set_memory_resource(r); - } - - ~ScopedMemoryResource() - { - set_memory_resource(m_original); - } -}; - -//----------------------------------------------------------------------------- -/** RAII class which counts allocations and frees inside a scope. Can - * optionally set also the memory resource to be used. - * @ingroup memory_resources */ -struct ScopedMemoryResourceCounts -{ - MemoryResourceCounts mr; - - ScopedMemoryResourceCounts() : mr() - { - set_memory_resource(&mr); - } - ScopedMemoryResourceCounts(MemoryResource *m) : mr(m) - { - set_memory_resource(&mr); - } - ~ScopedMemoryResourceCounts() - { - set_memory_resource(mr.resource()); - } -}; - -} // namespace c4 - -#endif /* _C4_MEMORY_RESOURCE_HPP_ */ diff --git a/thirdparty/ryml/ext/c4core/src/c4/memory_util.cpp b/thirdparty/ryml/ext/c4core/src/c4/memory_util.cpp deleted file mode 100644 index 981c62bb1..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/memory_util.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include "c4/memory_util.hpp" -#include "c4/error.hpp" - -namespace c4 { - -/** Fills 'dest' with the first 'pattern_size' bytes at 'pattern', 'num_times'. */ -void mem_repeat(void* dest, void const* pattern, size_t pattern_size, size_t num_times) -{ - if(C4_UNLIKELY(num_times == 0)) - return; - C4_ASSERT( ! mem_overlaps(dest, pattern, num_times*pattern_size, pattern_size)); - char *begin = (char*)dest; - char *end = begin + num_times * pattern_size; - // copy the pattern once - ::memcpy(begin, pattern, pattern_size); - // now copy from dest to itself, doubling up every time - size_t n = pattern_size; - while(begin + 2*n < end) - { - ::memcpy(begin + n, begin, n); - n <<= 1; // double n - } - // copy the missing part - if(begin + n < end) - { - ::memcpy(begin + n, begin, static_cast(end - (begin + n))); - } -} - -} // namespace c4 diff --git a/thirdparty/ryml/ext/c4core/src/c4/memory_util.hpp b/thirdparty/ryml/ext/c4core/src/c4/memory_util.hpp deleted file mode 100644 index 7dfb263ba..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/memory_util.hpp +++ /dev/null @@ -1,774 +0,0 @@ -#ifndef _C4_MEMORY_UTIL_HPP_ -#define _C4_MEMORY_UTIL_HPP_ - -#include "c4/config.hpp" -#include "c4/error.hpp" -#include "c4/compiler.hpp" -#include "c4/cpu.hpp" -#ifdef C4_MSVC -#include -#endif -#include - -#if (defined(__GNUC__) && __GNUC__ >= 10) || defined(__has_builtin) -#define _C4_USE_LSB_INTRINSIC(which) __has_builtin(which) -#define _C4_USE_MSB_INTRINSIC(which) __has_builtin(which) -#elif defined(C4_MSVC) -#define _C4_USE_LSB_INTRINSIC(which) true -#define _C4_USE_MSB_INTRINSIC(which) true -#else -// let's try our luck -#define _C4_USE_LSB_INTRINSIC(which) true -#define _C4_USE_MSB_INTRINSIC(which) true -#endif - - -/** @file memory_util.hpp Some memory utilities. */ - -namespace c4 { - -/** set the given memory to zero */ -C4_ALWAYS_INLINE void mem_zero(void* mem, size_t num_bytes) -{ - memset(mem, 0, num_bytes); -} -/** set the given memory to zero */ -template -C4_ALWAYS_INLINE void mem_zero(T* mem, size_t num_elms) -{ - memset(mem, 0, sizeof(T) * num_elms); -} -/** set the given memory to zero */ -template -C4_ALWAYS_INLINE void mem_zero(T* mem) -{ - memset(mem, 0, sizeof(T)); -} - -C4_ALWAYS_INLINE C4_CONST bool mem_overlaps(void const* a, void const* b, size_t sza, size_t szb) -{ - // thanks @timwynants - return (((const char*)b + szb) > a && b < ((const char*)a+sza)); -} - -void mem_repeat(void* dest, void const* pattern, size_t pattern_size, size_t num_times); - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -template -C4_ALWAYS_INLINE C4_CONST bool is_aligned(T *ptr, uintptr_t alignment=alignof(T)) -{ - return (uintptr_t(ptr) & (alignment - uintptr_t(1))) == uintptr_t(0); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// least significant bit - -/** @name msb Compute the least significant bit - * @note the input value must be nonzero - * @note the input type must be unsigned - */ -/** @{ */ - -// https://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightLinear -#define _c4_lsb_fallback \ - unsigned c = 0; \ - v = (v ^ (v - 1)) >> 1; /* Set v's trailing 0s to 1s and zero rest */ \ - for(; v; ++c) \ - v >>= 1; \ - return (unsigned) c - -// u8 -template -C4_CONSTEXPR14 -auto lsb(I v) noexcept - -> typename std::enable_if::type -{ - C4_STATIC_ASSERT(std::is_unsigned::value); - C4_ASSERT(v != 0); - #if _C4_USE_LSB_INTRINSIC(__builtin_ctz) - // upcast to use the intrinsic, it's cheaper. - #ifdef C4_MSVC - #if !defined(C4_CPU_ARM64) && !defined(C4_CPU_ARM) - unsigned long bit; - _BitScanForward(&bit, (unsigned long)v); - return bit; - #else - _c4_lsb_fallback; - #endif - #else - return (unsigned)__builtin_ctz((unsigned)v); - #endif - #else - _c4_lsb_fallback; - #endif -} - -// u16 -template -C4_CONSTEXPR14 -auto lsb(I v) noexcept - -> typename std::enable_if::type -{ - C4_STATIC_ASSERT(std::is_unsigned::value); - C4_ASSERT(v != 0); - #if _C4_USE_LSB_INTRINSIC(__builtin_ctz) - // upcast to use the intrinsic, it's cheaper. - // Then remember that the upcast makes it to 31bits - #ifdef C4_MSVC - #if !defined(C4_CPU_ARM64) && !defined(C4_CPU_ARM) - unsigned long bit; - _BitScanForward(&bit, (unsigned long)v); - return bit; - #else - _c4_lsb_fallback; - #endif - #else - return (unsigned)__builtin_ctz((unsigned)v); - #endif - #else - _c4_lsb_fallback; - #endif -} - -// u32 -template -C4_CONSTEXPR14 -auto lsb(I v) noexcept - -> typename std::enable_if::type -{ - C4_STATIC_ASSERT(std::is_unsigned::value); - C4_ASSERT(v != 0); - #if _C4_USE_LSB_INTRINSIC(__builtin_ctz) - #ifdef C4_MSVC - #if !defined(C4_CPU_ARM64) && !defined(C4_CPU_ARM) - unsigned long bit; - _BitScanForward(&bit, v); - return bit; - #else - _c4_lsb_fallback; - #endif - #else - return (unsigned)__builtin_ctz((unsigned)v); - #endif - #else - _c4_lsb_fallback; - #endif -} - -// u64 in 64bits -template -C4_CONSTEXPR14 -auto lsb(I v) noexcept - -> typename std::enable_if::type -{ - C4_STATIC_ASSERT(std::is_unsigned::value); - C4_ASSERT(v != 0); - #if _C4_USE_LSB_INTRINSIC(__builtin_ctzl) - #if defined(C4_MSVC) - #if !defined(C4_CPU_ARM64) && !defined(C4_CPU_ARM) - unsigned long bit; - _BitScanForward64(&bit, v); - return bit; - #else - _c4_lsb_fallback; - #endif - #else - return (unsigned)__builtin_ctzl((unsigned long)v); - #endif - #else - _c4_lsb_fallback; - #endif -} - -// u64 in 32bits -template -C4_CONSTEXPR14 -auto lsb(I v) noexcept - -> typename std::enable_if::type -{ - C4_STATIC_ASSERT(std::is_unsigned::value); - C4_ASSERT(v != 0); - #if _C4_USE_LSB_INTRINSIC(__builtin_ctzll) - #if defined(C4_MSVC) - #if !defined(C4_CPU_X86) && !defined(C4_CPU_ARM64) && !defined(C4_CPU_ARM) - unsigned long bit; - _BitScanForward64(&bit, v); - return bit; - #else - _c4_lsb_fallback; - #endif - #else - return (unsigned)__builtin_ctzll((unsigned long long)v); - #endif - #else - _c4_lsb_fallback; - #endif -} - -#undef _c4_lsb_fallback - -/** @} */ - - -namespace detail { -template struct _lsb11; -template -struct _lsb11 -{ - enum : unsigned { num = _lsb11>1), num_bits+I(1), (((val>>1)&I(1))!=I(0))>::num }; -}; -template -struct _lsb11 -{ - enum : unsigned { num = num_bits }; -}; -} // namespace detail - - -/** TMP version of lsb(); this needs to be implemented with template - * meta-programming because C++11 cannot use a constexpr function with - * local variables - * @see lsb */ -template -struct lsb11 -{ - static_assert(number != 0, "lsb: number must be nonzero"); - enum : unsigned { value = detail::_lsb11::num}; -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// most significant bit - - -/** @name msb Compute the most significant bit - * @note the input value must be nonzero - * @note the input type must be unsigned - */ -/** @{ */ - - -#define _c4_msb8_fallback \ - unsigned n = 0; \ - if(v & I(0xf0)) v >>= 4, n |= I(4); \ - if(v & I(0x0c)) v >>= 2, n |= I(2); \ - if(v & I(0x02)) v >>= 1, n |= I(1); \ - return n - -#define _c4_msb16_fallback \ - unsigned n = 0; \ - if(v & I(0xff00)) v >>= 8, n |= I(8); \ - if(v & I(0x00f0)) v >>= 4, n |= I(4); \ - if(v & I(0x000c)) v >>= 2, n |= I(2); \ - if(v & I(0x0002)) v >>= 1, n |= I(1); \ - return n - -#define _c4_msb32_fallback \ - unsigned n = 0; \ - if(v & I(0xffff0000)) v >>= 16, n |= 16; \ - if(v & I(0x0000ff00)) v >>= 8, n |= 8; \ - if(v & I(0x000000f0)) v >>= 4, n |= 4; \ - if(v & I(0x0000000c)) v >>= 2, n |= 2; \ - if(v & I(0x00000002)) v >>= 1, n |= 1; \ - return n - -#define _c4_msb64_fallback \ - unsigned n = 0; \ - if(v & I(0xffffffff00000000)) v >>= 32, n |= I(32); \ - if(v & I(0x00000000ffff0000)) v >>= 16, n |= I(16); \ - if(v & I(0x000000000000ff00)) v >>= 8, n |= I(8); \ - if(v & I(0x00000000000000f0)) v >>= 4, n |= I(4); \ - if(v & I(0x000000000000000c)) v >>= 2, n |= I(2); \ - if(v & I(0x0000000000000002)) v >>= 1, n |= I(1); \ - return n - - -// u8 -template -C4_CONSTEXPR14 -auto msb(I v) noexcept - -> typename std::enable_if::type -{ - C4_STATIC_ASSERT(std::is_unsigned::value); - C4_ASSERT(v != 0); - #if _C4_USE_MSB_INTRINSIC(__builtin_clz) - // upcast to use the intrinsic, it's cheaper. - // Then remember that the upcast makes it to 31bits - #ifdef C4_MSVC - #if !defined(C4_CPU_ARM64) && !defined(C4_CPU_ARM) - unsigned long bit; - _BitScanReverse(&bit, (unsigned long)v); - return bit; - #else - _c4_msb8_fallback; - #endif - #else - return 31u - (unsigned)__builtin_clz((unsigned)v); - #endif - #else - _c4_msb8_fallback; - #endif -} - -// u16 -template -C4_CONSTEXPR14 -auto msb(I v) noexcept - -> typename std::enable_if::type -{ - C4_STATIC_ASSERT(std::is_unsigned::value); - C4_ASSERT(v != 0); - #if _C4_USE_MSB_INTRINSIC(__builtin_clz) - // upcast to use the intrinsic, it's cheaper. - // Then remember that the upcast makes it to 31bits - #ifdef C4_MSVC - #if !defined(C4_CPU_ARM64) && !defined(C4_CPU_ARM) - unsigned long bit; - _BitScanReverse(&bit, (unsigned long)v); - return bit; - #else - _c4_msb16_fallback; - #endif - #else - return 31u - (unsigned)__builtin_clz((unsigned)v); - #endif - #else - _c4_msb16_fallback; - #endif -} - -// u32 -template -C4_CONSTEXPR14 -auto msb(I v) noexcept - -> typename std::enable_if::type -{ - C4_STATIC_ASSERT(std::is_unsigned::value); - C4_ASSERT(v != 0); - #if _C4_USE_MSB_INTRINSIC(__builtin_clz) - #ifdef C4_MSVC - #if !defined(C4_CPU_ARM64) && !defined(C4_CPU_ARM) - unsigned long bit; - _BitScanReverse(&bit, v); - return bit; - #else - _c4_msb32_fallback; - #endif - #else - return 31u - (unsigned)__builtin_clz((unsigned)v); - #endif - #else - _c4_msb32_fallback; - #endif -} - -// u64 in 64bits -template -C4_CONSTEXPR14 -auto msb(I v) noexcept - -> typename std::enable_if::type -{ - C4_STATIC_ASSERT(std::is_unsigned::value); - C4_ASSERT(v != 0); - #if _C4_USE_MSB_INTRINSIC(__builtin_clzl) - #ifdef C4_MSVC - #if !defined(C4_CPU_ARM64) && !defined(C4_CPU_ARM) - unsigned long bit; - _BitScanReverse64(&bit, v); - return bit; - #else - _c4_msb64_fallback; - #endif - #else - return 63u - (unsigned)__builtin_clzl((unsigned long)v); - #endif - #else - _c4_msb64_fallback; - #endif -} - -// u64 in 32bits -template -C4_CONSTEXPR14 -auto msb(I v) noexcept - -> typename std::enable_if::type -{ - C4_STATIC_ASSERT(std::is_unsigned::value); - C4_ASSERT(v != 0); - #if _C4_USE_MSB_INTRINSIC(__builtin_clzll) - #ifdef C4_MSVC - #if !defined(C4_CPU_X86) && !defined(C4_CPU_ARM64) && !defined(C4_CPU_ARM) - unsigned long bit; - _BitScanReverse64(&bit, v); - return bit; - #else - _c4_msb64_fallback; - #endif - #else - return 63u - (unsigned)__builtin_clzll((unsigned long long)v); - #endif - #else - _c4_msb64_fallback; - #endif -} - -#undef _c4_msb8_fallback -#undef _c4_msb16_fallback -#undef _c4_msb32_fallback -#undef _c4_msb64_fallback - -/** @} */ - - -namespace detail { -template struct _msb11; -template -struct _msb11< I, val, num_bits, false> -{ - enum : unsigned { num = _msb11>1), num_bits+I(1), ((val>>1)==I(0))>::num }; -}; -template -struct _msb11 -{ - static_assert(val == 0, "bad implementation"); - enum : unsigned { num = (unsigned)(num_bits-1) }; -}; -} // namespace detail - - -/** TMP version of msb(); this needs to be implemented with template - * meta-programming because C++11 cannot use a constexpr function with - * local variables - * @see msb */ -template -struct msb11 -{ - enum : unsigned { value = detail::_msb11::num }; -}; - - - -#undef _C4_USE_LSB_INTRINSIC -#undef _C4_USE_MSB_INTRINSIC - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -// there is an implicit conversion below; it happens when E or B are -// narrower than int, and thus any operation will upcast the result to -// int, and then downcast to assign -C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH("-Wconversion") - -/** integer power; this function is constexpr-14 because of the local - * variables */ -template -C4_CONSTEXPR14 C4_CONST auto ipow(B base, E exponent) noexcept -> typename std::enable_if::value, B>::type -{ - C4_STATIC_ASSERT(std::is_integral::value); - B r = B(1); - if(exponent >= 0) - { - for(E e = 0; e < exponent; ++e) - r *= base; - } - else - { - exponent *= E(-1); - for(E e = 0; e < exponent; ++e) - r /= base; - } - return r; -} - -/** integer power; this function is constexpr-14 because of the local - * variables */ -template -C4_CONSTEXPR14 C4_CONST auto ipow(E exponent) noexcept -> typename std::enable_if::value, B>::type -{ - C4_STATIC_ASSERT(std::is_integral::value); - B r = B(1); - if(exponent >= 0) - { - for(E e = 0; e < exponent; ++e) - r *= base; - } - else - { - exponent *= E(-1); - for(E e = 0; e < exponent; ++e) - r /= base; - } - return r; -} - -/** integer power; this function is constexpr-14 because of the local - * variables */ -template -C4_CONSTEXPR14 C4_CONST auto ipow(E exponent) noexcept -> typename std::enable_if::value, B>::type -{ - C4_STATIC_ASSERT(std::is_integral::value); - B r = B(1); - B bbase = B(base); - if(exponent >= 0) - { - for(E e = 0; e < exponent; ++e) - r *= bbase; - } - else - { - exponent *= E(-1); - for(E e = 0; e < exponent; ++e) - r /= bbase; - } - return r; -} - -/** integer power; this function is constexpr-14 because of the local - * variables */ -template -C4_CONSTEXPR14 C4_CONST auto ipow(B base, E exponent) noexcept -> typename std::enable_if::value, B>::type -{ - C4_STATIC_ASSERT(std::is_integral::value); - B r = B(1); - for(E e = 0; e < exponent; ++e) - r *= base; - return r; -} - -/** integer power; this function is constexpr-14 because of the local - * variables */ -template -C4_CONSTEXPR14 C4_CONST auto ipow(E exponent) noexcept -> typename std::enable_if::value, B>::type -{ - C4_STATIC_ASSERT(std::is_integral::value); - B r = B(1); - for(E e = 0; e < exponent; ++e) - r *= base; - return r; -} -/** integer power; this function is constexpr-14 because of the local - * variables */ -template -C4_CONSTEXPR14 C4_CONST auto ipow(E exponent) noexcept -> typename std::enable_if::value, B>::type -{ - C4_STATIC_ASSERT(std::is_integral::value); - B r = B(1); - B bbase = B(base); - for(E e = 0; e < exponent; ++e) - r *= bbase; - return r; -} - -C4_SUPPRESS_WARNING_GCC_CLANG_POP - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -/** return a mask with all bits set [first_bit,last_bit[; this function - * is constexpr-14 because of the local variables */ -template -C4_CONSTEXPR14 I contiguous_mask(I first_bit, I last_bit) -{ - I r = 0; - for(I i = first_bit; i < last_bit; ++i) - { - r |= (I(1) << i); - } - return r; -} - - -namespace detail { - -template -struct _ctgmsk11; - -template -struct _ctgmsk11< I, val, first, last, true> -{ - enum : I { value = _ctgmsk11::value }; -}; - -template -struct _ctgmsk11< I, val, first, last, false> -{ - enum : I { value = val }; -}; - -} // namespace detail - - -/** TMP version of contiguous_mask(); this needs to be implemented with template - * meta-programming because C++11 cannot use a constexpr function with - * local variables - * @see contiguous_mask */ -template -struct contiguous_mask11 -{ - enum : I { value = detail::_ctgmsk11::value }; -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -/** use Empty Base Class Optimization to reduce the size of a pair of - * potentially empty types*/ - -namespace detail { -typedef enum { - tpc_same, - tpc_same_empty, - tpc_both_empty, - tpc_first_empty, - tpc_second_empty, - tpc_general -} TightPairCase_e; - -template -constexpr TightPairCase_e tpc_which_case() -{ - return std::is_same::value ? - std::is_empty::value ? - tpc_same_empty - : - tpc_same - : - std::is_empty::value && std::is_empty::value ? - tpc_both_empty - : - std::is_empty::value ? - tpc_first_empty - : - std::is_empty::value ? - tpc_second_empty - : - tpc_general - ; -} - -template -struct tight_pair -{ -private: - - First m_first; - Second m_second; - -public: - - using first_type = First; - using second_type = Second; - - tight_pair() : m_first(), m_second() {} - tight_pair(First const& f, Second const& s) : m_first(f), m_second(s) {} - - C4_ALWAYS_INLINE C4_CONSTEXPR14 First & first () { return m_first; } - C4_ALWAYS_INLINE C4_CONSTEXPR14 First const& first () const { return m_first; } - C4_ALWAYS_INLINE C4_CONSTEXPR14 Second & second() { return m_second; } - C4_ALWAYS_INLINE C4_CONSTEXPR14 Second const& second() const { return m_second; } -}; - -template -struct tight_pair : public First -{ - static_assert(std::is_same::value, "bad implementation"); - - using first_type = First; - using second_type = Second; - - tight_pair() : First() {} - tight_pair(First const& f, Second const& /*s*/) : First(f) {} - - C4_ALWAYS_INLINE C4_CONSTEXPR14 First & first () { return static_cast(*this); } - C4_ALWAYS_INLINE C4_CONSTEXPR14 First const& first () const { return static_cast(*this); } - C4_ALWAYS_INLINE C4_CONSTEXPR14 Second & second() { return reinterpret_cast(*this); } - C4_ALWAYS_INLINE C4_CONSTEXPR14 Second const& second() const { return reinterpret_cast(*this); } -}; - -template -struct tight_pair : public First, public Second -{ - using first_type = First; - using second_type = Second; - - tight_pair() : First(), Second() {} - tight_pair(First const& f, Second const& s) : First(f), Second(s) {} - - C4_ALWAYS_INLINE C4_CONSTEXPR14 First & first () { return static_cast(*this); } - C4_ALWAYS_INLINE C4_CONSTEXPR14 First const& first () const { return static_cast(*this); } - C4_ALWAYS_INLINE C4_CONSTEXPR14 Second & second() { return static_cast(*this); } - C4_ALWAYS_INLINE C4_CONSTEXPR14 Second const& second() const { return static_cast(*this); } -}; - -template -struct tight_pair : public First -{ - Second m_second; - - using first_type = First; - using second_type = Second; - - tight_pair() : First() {} - tight_pair(First const& f, Second const& s) : First(f), m_second(s) {} - - C4_ALWAYS_INLINE C4_CONSTEXPR14 First & first () { return static_cast(*this); } - C4_ALWAYS_INLINE C4_CONSTEXPR14 First const& first () const { return static_cast(*this); } - C4_ALWAYS_INLINE C4_CONSTEXPR14 Second & second() { return m_second; } - C4_ALWAYS_INLINE C4_CONSTEXPR14 Second const& second() const { return m_second; } -}; - -template -struct tight_pair : public First -{ - Second m_second; - - using first_type = First; - using second_type = Second; - - tight_pair() : First(), m_second() {} - tight_pair(First const& f, Second const& s) : First(f), m_second(s) {} - - C4_ALWAYS_INLINE C4_CONSTEXPR14 First & first () { return static_cast(*this); } - C4_ALWAYS_INLINE C4_CONSTEXPR14 First const& first () const { return static_cast(*this); } - C4_ALWAYS_INLINE C4_CONSTEXPR14 Second & second() { return m_second; } - C4_ALWAYS_INLINE C4_CONSTEXPR14 Second const& second() const { return m_second; } -}; - -template -struct tight_pair : public Second -{ - First m_first; - - using first_type = First; - using second_type = Second; - - tight_pair() : Second(), m_first() {} - tight_pair(First const& f, Second const& s) : Second(s), m_first(f) {} - - C4_ALWAYS_INLINE C4_CONSTEXPR14 First & first () { return m_first; } - C4_ALWAYS_INLINE C4_CONSTEXPR14 First const& first () const { return m_first; } - C4_ALWAYS_INLINE C4_CONSTEXPR14 Second & second() { return static_cast(*this); } - C4_ALWAYS_INLINE C4_CONSTEXPR14 Second const& second() const { return static_cast(*this); } -}; - -} // namespace detail - -template -using tight_pair = detail::tight_pair()>; - -} // namespace c4 - -#endif /* _C4_MEMORY_UTIL_HPP_ */ diff --git a/thirdparty/ryml/ext/c4core/src/c4/platform.hpp b/thirdparty/ryml/ext/c4core/src/c4/platform.hpp deleted file mode 100644 index 8f9a61f0f..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/platform.hpp +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef _C4_PLATFORM_HPP_ -#define _C4_PLATFORM_HPP_ - -/** @file platform.hpp Provides platform information macros - * @ingroup basic_headers */ - -// see also https://sourceforge.net/p/predef/wiki/OperatingSystems/ - -#if defined(_WIN64) -# define C4_WIN -# define C4_WIN64 -#elif defined(_WIN32) -# define C4_WIN -# define C4_WIN32 -#elif defined(__ANDROID__) -# define C4_ANDROID -#elif defined(__APPLE__) -# include "TargetConditionals.h" -# if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR -# define C4_IOS -# elif TARGET_OS_MAC || TARGET_OS_OSX -# define C4_MACOS -# else -# error "Unknown Apple platform" -# endif -#elif defined(__linux__) || defined(__linux) -# define C4_UNIX -# define C4_LINUX -#elif defined(__unix__) || defined(__unix) -# define C4_UNIX -#elif defined(__arm__) || defined(__aarch64__) -# define C4_ARM -#elif defined(SWIG) -# define C4_SWIG -#else -# error "unknown platform" -#endif - -#if defined(__posix) || defined(C4_UNIX) || defined(C4_LINUX) -# define C4_POSIX -#endif - - -#endif /* _C4_PLATFORM_HPP_ */ diff --git a/thirdparty/ryml/ext/c4core/src/c4/preprocessor.hpp b/thirdparty/ryml/ext/c4core/src/c4/preprocessor.hpp deleted file mode 100644 index a55482540..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/preprocessor.hpp +++ /dev/null @@ -1,123 +0,0 @@ -#ifndef _C4_PREPROCESSOR_HPP_ -#define _C4_PREPROCESSOR_HPP_ - -/** @file preprocessor.hpp Contains basic macros and preprocessor utilities. - * @ingroup basic_headers */ - -#ifdef __clang__ - /* NOTE: using , ## __VA_ARGS__ to deal with zero-args calls to - * variadic macros is not portable, but works in clang, gcc, msvc, icc. - * clang requires switching off compiler warnings for pedantic mode. - * @see http://stackoverflow.com/questions/32047685/variadic-macro-without-arguments */ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" // warning: token pasting of ',' and __VA_ARGS__ is a GNU extension -#elif defined(__GNUC__) - /* GCC also issues a warning for zero-args calls to variadic macros. - * This warning is switched on with -pedantic and apparently there is no - * easy way to turn it off as with clang. But marking this as a system - * header works. - * @see https://gcc.gnu.org/onlinedocs/cpp/System-Headers.html - * @see http://stackoverflow.com/questions/35587137/ */ -# pragma GCC system_header -#endif - -#define C4_WIDEN(str) L"" str - -#define C4_COUNTOF(arr) (sizeof(arr)/sizeof((arr)[0])) - -#define C4_EXPAND(arg) arg - -/** useful in some macro calls with template arguments */ -#define C4_COMMA , -/** useful in some macro calls with template arguments - * @see C4_COMMA */ -#define C4_COMMA_X C4_COMMA - -/** expand and quote */ -#define C4_XQUOTE(arg) _C4_XQUOTE(arg) -#define _C4_XQUOTE(arg) C4_QUOTE(arg) -#define C4_QUOTE(arg) #arg - -/** expand and concatenate */ -#define C4_XCAT(arg1, arg2) _C4_XCAT(arg1, arg2) -#define _C4_XCAT(arg1, arg2) C4_CAT(arg1, arg2) -#define C4_CAT(arg1, arg2) arg1##arg2 - -#define C4_VERSION_CAT(major, minor, patch) ((major)*10000 + (minor)*100 + (patch)) - -/** A preprocessor foreach. Spectacular trick taken from: - * http://stackoverflow.com/a/1872506/5875572 - * The first argument is for a macro receiving a single argument, - * which will be called with every subsequent argument. There is - * currently a limit of 32 arguments, and at least 1 must be provided. - * -Example: -@code{.cpp} -struct Example { - int a; - int b; - int c; -}; -// define a one-arg macro to be called -#define PRN_STRUCT_OFFSETS(field) PRN_STRUCT_OFFSETS_(Example, field) -#define PRN_STRUCT_OFFSETS_(structure, field) printf(C4_XQUOTE(structure) ":" C4_XQUOTE(field)" - offset=%zu\n", offsetof(structure, field)); - -// now call the macro for a, b and c -C4_FOR_EACH(PRN_STRUCT_OFFSETS, a, b, c); -@endcode */ -#define C4_FOR_EACH(what, ...) C4_FOR_EACH_SEP(what, ;, __VA_ARGS__) - -/** same as C4_FOR_EACH(), but use a custom separator between statements. - * If a comma is needed as the separator, use the C4_COMMA macro. - * @see C4_FOR_EACH - * @see C4_COMMA - */ -#define C4_FOR_EACH_SEP(what, sep, ...) _C4_FOR_EACH_(_C4_FOR_EACH_NARG(__VA_ARGS__), what, sep, __VA_ARGS__) - -/// @cond dev - -#define _C4_FOR_EACH_01(what, sep, x) what(x) sep -#define _C4_FOR_EACH_02(what, sep, x, ...) what(x) sep _C4_FOR_EACH_01(what, sep, __VA_ARGS__) -#define _C4_FOR_EACH_03(what, sep, x, ...) what(x) sep _C4_FOR_EACH_02(what, sep, __VA_ARGS__) -#define _C4_FOR_EACH_04(what, sep, x, ...) what(x) sep _C4_FOR_EACH_03(what, sep, __VA_ARGS__) -#define _C4_FOR_EACH_05(what, sep, x, ...) what(x) sep _C4_FOR_EACH_04(what, sep, __VA_ARGS__) -#define _C4_FOR_EACH_06(what, sep, x, ...) what(x) sep _C4_FOR_EACH_05(what, sep, __VA_ARGS__) -#define _C4_FOR_EACH_07(what, sep, x, ...) what(x) sep _C4_FOR_EACH_06(what, sep, __VA_ARGS__) -#define _C4_FOR_EACH_08(what, sep, x, ...) what(x) sep _C4_FOR_EACH_07(what, sep, __VA_ARGS__) -#define _C4_FOR_EACH_09(what, sep, x, ...) what(x) sep _C4_FOR_EACH_08(what, sep, __VA_ARGS__) -#define _C4_FOR_EACH_10(what, sep, x, ...) what(x) sep _C4_FOR_EACH_09(what, sep, __VA_ARGS__) -#define _C4_FOR_EACH_11(what, sep, x, ...) what(x) sep _C4_FOR_EACH_10(what, sep, __VA_ARGS__) -#define _C4_FOR_EACH_12(what, sep, x, ...) what(x) sep _C4_FOR_EACH_11(what, sep, __VA_ARGS__) -#define _C4_FOR_EACH_13(what, sep, x, ...) what(x) sep _C4_FOR_EACH_12(what, sep, __VA_ARGS__) -#define _C4_FOR_EACH_14(what, sep, x, ...) what(x) sep _C4_FOR_EACH_13(what, sep, __VA_ARGS__) -#define _C4_FOR_EACH_15(what, sep, x, ...) what(x) sep _C4_FOR_EACH_14(what, sep, __VA_ARGS__) -#define _C4_FOR_EACH_16(what, sep, x, ...) what(x) sep _C4_FOR_EACH_15(what, sep, __VA_ARGS__) -#define _C4_FOR_EACH_17(what, sep, x, ...) what(x) sep _C4_FOR_EACH_16(what, sep, __VA_ARGS__) -#define _C4_FOR_EACH_18(what, sep, x, ...) what(x) sep _C4_FOR_EACH_17(what, sep, __VA_ARGS__) -#define _C4_FOR_EACH_19(what, sep, x, ...) what(x) sep _C4_FOR_EACH_18(what, sep, __VA_ARGS__) -#define _C4_FOR_EACH_20(what, sep, x, ...) what(x) sep _C4_FOR_EACH_19(what, sep, __VA_ARGS__) -#define _C4_FOR_EACH_21(what, sep, x, ...) what(x) sep _C4_FOR_EACH_20(what, sep, __VA_ARGS__) -#define _C4_FOR_EACH_22(what, sep, x, ...) what(x) sep _C4_FOR_EACH_21(what, sep, __VA_ARGS__) -#define _C4_FOR_EACH_23(what, sep, x, ...) what(x) sep _C4_FOR_EACH_22(what, sep, __VA_ARGS__) -#define _C4_FOR_EACH_24(what, sep, x, ...) what(x) sep _C4_FOR_EACH_23(what, sep, __VA_ARGS__) -#define _C4_FOR_EACH_25(what, sep, x, ...) what(x) sep _C4_FOR_EACH_24(what, sep, __VA_ARGS__) -#define _C4_FOR_EACH_26(what, sep, x, ...) what(x) sep _C4_FOR_EACH_25(what, sep, __VA_ARGS__) -#define _C4_FOR_EACH_27(what, sep, x, ...) what(x) sep _C4_FOR_EACH_26(what, sep, __VA_ARGS__) -#define _C4_FOR_EACH_28(what, sep, x, ...) what(x) sep _C4_FOR_EACH_27(what, sep, __VA_ARGS__) -#define _C4_FOR_EACH_29(what, sep, x, ...) what(x) sep _C4_FOR_EACH_28(what, sep, __VA_ARGS__) -#define _C4_FOR_EACH_30(what, sep, x, ...) what(x) sep _C4_FOR_EACH_29(what, sep, __VA_ARGS__) -#define _C4_FOR_EACH_31(what, sep, x, ...) what(x) sep _C4_FOR_EACH_30(what, sep, __VA_ARGS__) -#define _C4_FOR_EACH_32(what, sep, x, ...) what(x) sep _C4_FOR_EACH_31(what, sep, __VA_ARGS__) -#define _C4_FOR_EACH_NARG(...) _C4_FOR_EACH_NARG_(__VA_ARGS__, _C4_FOR_EACH_RSEQ_N()) -#define _C4_FOR_EACH_NARG_(...) _C4_FOR_EACH_ARG_N(__VA_ARGS__) -#define _C4_FOR_EACH_ARG_N(_01, _02, _03, _04, _05, _06, _07, _08, _09, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, N, ...) N -#define _C4_FOR_EACH_RSEQ_N() 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 09, 08, 07, 06, 05, 04, 03, 02, 01 -#define _C4_FOR_EACH_(N, what, sep, ...) C4_XCAT(_C4_FOR_EACH_, N)(what, sep, __VA_ARGS__) - -/// @endcond - -#ifdef __clang__ -# pragma clang diagnostic pop -#endif - -#endif /* _C4_PREPROCESSOR_HPP_ */ diff --git a/thirdparty/ryml/ext/c4core/src/c4/restrict.hpp b/thirdparty/ryml/ext/c4core/src/c4/restrict.hpp deleted file mode 100644 index a8a59301b..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/restrict.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef _C4_RESTRICT_HPP_ -#define _C4_RESTRICT_HPP_ - -/** @file restrict.hpp macros defining shorthand symbols for restricted - * pointers and references - * @see unrestrict.hpp - * @see restrict - */ - -/** @defgroup restrict Restrict utilities - * macros defining shorthand symbols for restricted - * pointers and references - * ```cpp - * void sum_arrays(size_t sz, float const* C4_RESTRICT a, float const *C4_RESTRICT b, float *result); - * float * C4_RESTRICT ptr; - * float & C4_RESTRICT ref = *ptr; - * float const* C4_RESTRICT cptr; - * float const& C4_RESTRICT cref = *cptr; - * - * // becomes this: - * #include - * void sum_arrays(size_t sz, float c$ a, float c$ b, float * result); - * float $ ptr; - * float $$ ref = *ptr; - * float c$ cptr; - * float c$$ cref = *cptr; - * ``` - * @ingroup types - * @{ */ - -/** @def \$ a restricted pointer */ -/** @def c\$ a restricted pointer to const data */ - -/** @def \$\$ a restricted reference */ -/** @def c\$\$ a restricted reference to const data */ - -#ifdef __clang__ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdollar-in-identifier-extension" -#elif defined(__GNUC__) -#endif - -#define $ * C4_RESTRICT // a restricted pointer -#define c$ const* C4_RESTRICT // a restricted pointer to const data - -#define $$ & C4_RESTRICT // restricted reference -#define c$$ const& C4_RESTRICT // restricted reference to const data - -/** @} */ - -#endif /* _C4_RESTRICT_HPP_ */ diff --git a/thirdparty/ryml/ext/c4core/src/c4/span.hpp b/thirdparty/ryml/ext/c4core/src/c4/span.hpp deleted file mode 100644 index cc6e463dc..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/span.hpp +++ /dev/null @@ -1,517 +0,0 @@ -#ifndef _C4_SPAN_HPP_ -#define _C4_SPAN_HPP_ - -/** @file span.hpp Provides span classes. */ - -#include "c4/config.hpp" -#include "c4/error.hpp" -#include "c4/szconv.hpp" - -#include - -namespace c4 { - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -/** a crtp base for implementing span classes - * - * A span is a non-owning range of elements contiguously stored in memory. - * Unlike STL's array_view, the span allows write-access to its members. - * - * To obtain subspans from a span, the following const member functions - * are available: - * - subspan(first, num) - * - range(first, last) - * - first(num) - * - last(num) - * - * A span can also be resized via the following non-const member functions: - * - resize(sz) - * - ltrim(num) - * - rtrim(num) - * - * @see span - * @see cspan - * @see spanrs - * @see cspanrs - * @see spanrsl - * @see cspanrsl - */ -template -class span_crtp -{ -// some utility defines, undefined at the end of this class -#define _c4this ((SpanImpl *)this) -#define _c4cthis ((SpanImpl const*)this) -#define _c4ptr ((SpanImpl *)this)->m_ptr -#define _c4cptr ((SpanImpl const*)this)->m_ptr -#define _c4sz ((SpanImpl *)this)->m_size -#define _c4csz ((SpanImpl const*)this)->m_size - -public: - - _c4_DEFINE_ARRAY_TYPES(T, I); - -public: - - C4_ALWAYS_INLINE constexpr I value_size() const noexcept { return sizeof(T); } - C4_ALWAYS_INLINE constexpr I elm_size () const noexcept { return sizeof(T); } - C4_ALWAYS_INLINE constexpr I type_size () const noexcept { return sizeof(T); } - C4_ALWAYS_INLINE I byte_size () const noexcept { return _c4csz*sizeof(T); } - - C4_ALWAYS_INLINE bool empty() const noexcept { return _c4csz == 0; } - C4_ALWAYS_INLINE I size() const noexcept { return _c4csz; } - //C4_ALWAYS_INLINE I capacity() const noexcept { return _c4sz; } // this must be defined by impl classes - - C4_ALWAYS_INLINE void clear() noexcept { _c4sz = 0; } - - C4_ALWAYS_INLINE T * data() noexcept { return _c4ptr; } - C4_ALWAYS_INLINE T const* data() const noexcept { return _c4cptr; } - - C4_ALWAYS_INLINE iterator begin() noexcept { return _c4ptr; } - C4_ALWAYS_INLINE const_iterator begin() const noexcept { return _c4cptr; } - C4_ALWAYS_INLINE const_iterator cbegin() const noexcept { return _c4cptr; } - - C4_ALWAYS_INLINE iterator end() noexcept { return _c4ptr + _c4sz; } - C4_ALWAYS_INLINE const_iterator end() const noexcept { return _c4cptr + _c4csz; } - C4_ALWAYS_INLINE const_iterator cend() const noexcept { return _c4cptr + _c4csz; } - - C4_ALWAYS_INLINE reverse_iterator rbegin() noexcept { return reverse_iterator(_c4ptr + _c4sz); } - C4_ALWAYS_INLINE const_reverse_iterator rbegin() const noexcept { return reverse_iterator(_c4cptr + _c4sz); } - C4_ALWAYS_INLINE const_reverse_iterator crbegin() const noexcept { return reverse_iterator(_c4cptr + _c4sz); } - - C4_ALWAYS_INLINE reverse_iterator rend() noexcept { return const_reverse_iterator(_c4ptr); } - C4_ALWAYS_INLINE const_reverse_iterator rend() const noexcept { return const_reverse_iterator(_c4cptr); } - C4_ALWAYS_INLINE const_reverse_iterator crend() const noexcept { return const_reverse_iterator(_c4cptr); } - - C4_ALWAYS_INLINE T & front() C4_NOEXCEPT_X { C4_XASSERT(!empty()); return _c4ptr [0]; } - C4_ALWAYS_INLINE T const& front() const C4_NOEXCEPT_X { C4_XASSERT(!empty()); return _c4cptr[0]; } - - C4_ALWAYS_INLINE T & back() C4_NOEXCEPT_X { C4_XASSERT(!empty()); return _c4ptr [_c4sz - 1]; } - C4_ALWAYS_INLINE T const& back() const C4_NOEXCEPT_X { C4_XASSERT(!empty()); return _c4cptr[_c4csz - 1]; } - - C4_ALWAYS_INLINE T & operator[] (I i) C4_NOEXCEPT_X { C4_XASSERT(i >= 0 && i < _c4sz ); return _c4ptr [i]; } - C4_ALWAYS_INLINE T const& operator[] (I i) const C4_NOEXCEPT_X { C4_XASSERT(i >= 0 && i < _c4csz); return _c4cptr[i]; } - - C4_ALWAYS_INLINE SpanImpl subspan(I first, I num) const C4_NOEXCEPT_X - { - C4_XASSERT((first >= 0 && first < _c4csz) || (first == _c4csz && num == 0)); - C4_XASSERT((first + num >= 0) && (first + num <= _c4csz)); - return _c4cthis->_select(_c4cptr + first, num); - } - C4_ALWAYS_INLINE SpanImpl subspan(I first) const C4_NOEXCEPT_X ///< goes up until the end of the span - { - C4_XASSERT(first >= 0 && first <= _c4csz); - return _c4cthis->_select(_c4cptr + first, _c4csz - first); - } - - C4_ALWAYS_INLINE SpanImpl range(I first, I last) const C4_NOEXCEPT_X ///< last element is NOT included - { - C4_XASSERT(((first >= 0) && (first < _c4csz)) || (first == _c4csz && first == last)); - C4_XASSERT((last >= 0) && (last <= _c4csz)); - C4_XASSERT(last >= first); - return _c4cthis->_select(_c4cptr + first, last - first); - } - C4_ALWAYS_INLINE SpanImpl range(I first) const C4_NOEXCEPT_X ///< goes up until the end of the span - { - C4_XASSERT(((first >= 0) && (first <= _c4csz))); - return _c4cthis->_select(_c4cptr + first, _c4csz - first); - } - - C4_ALWAYS_INLINE SpanImpl first(I num) const C4_NOEXCEPT_X ///< get the first num elements, starting at 0 - { - C4_XASSERT((num >= 0) && (num <= _c4csz)); - return _c4cthis->_select(_c4cptr, num); - } - C4_ALWAYS_INLINE SpanImpl last(I num) const C4_NOEXCEPT_X ///< get the last num elements, starting at size()-num - { - C4_XASSERT((num >= 0) && (num <= _c4csz)); - return _c4cthis->_select(_c4cptr + _c4csz - num, num); - } - - bool is_subspan(span_crtp const& ss) const noexcept - { - if(_c4cptr == nullptr) return false; - auto *b = begin(), *e = end(); - auto *ssb = ss.begin(), *sse = ss.end(); - if(ssb >= b && sse <= e) - { - return true; - } - else - { - return false; - } - } - - /** COMPLement Left: return the complement to the left of the beginning of the given subspan. - * If ss does not begin inside this, returns an empty substring. */ - SpanImpl compll(span_crtp const& ss) const C4_NOEXCEPT_X - { - auto ssb = ss.begin(); - auto b = begin(); - auto e = end(); - if(ssb >= b && ssb <= e) - { - return subspan(0, static_cast(ssb - b)); - } - else - { - return subspan(0, 0); - } - } - - /** COMPLement Right: return the complement to the right of the end of the given subspan. - * If ss does not end inside this, returns an empty substring. */ - SpanImpl complr(span_crtp const& ss) const C4_NOEXCEPT_X - { - auto sse = ss.end(); - auto b = begin(); - auto e = end(); - if(sse >= b && sse <= e) - { - return subspan(static_cast(sse - b), static_cast(e - sse)); - } - else - { - return subspan(0, 0); - } - } - - C4_ALWAYS_INLINE bool same_span(span_crtp const& that) const noexcept - { - return size() == that.size() && data() == that.data(); - } - template - C4_ALWAYS_INLINE bool same_span(span_crtp const& that) const C4_NOEXCEPT_X - { - I tsz = szconv(that.size()); // x-asserts that the size does not overflow - return size() == tsz && data() == that.data(); - } - -#undef _c4this -#undef _c4cthis -#undef _c4ptr -#undef _c4cptr -#undef _c4sz -#undef _c4csz -}; - -//----------------------------------------------------------------------------- -template -inline constexpr bool operator== -( - span_crtp const& l, - span_crtp const& r -) -{ -#if C4_CPP >= 14 - return std::equal(l.begin(), l.end(), r.begin(), r.end()); -#else - return l.same_span(r) || std::equal(l.begin(), l.end(), r.begin()); -#endif -} - -template -inline constexpr bool operator!= -( - span_crtp const& l, - span_crtp const& r -) -{ - return ! (l == r); -} - -//----------------------------------------------------------------------------- -template -inline constexpr bool operator< -( - span_crtp const& l, - span_crtp const& r -) -{ - return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end()); -} - -template -inline constexpr bool operator<= -( - span_crtp const& l, - span_crtp const& r -) -{ - return ! (l > r); -} - -//----------------------------------------------------------------------------- -template -inline constexpr bool operator> -( - span_crtp const& l, - span_crtp const& r -) -{ - return r < l; -} - -//----------------------------------------------------------------------------- -template -inline constexpr bool operator>= -( - span_crtp const& l, - span_crtp const& r -) -{ - return ! (l < r); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -/** A non-owning span of elements contiguously stored in memory. */ -template -class span : public span_crtp> -{ - friend class span_crtp>; - - T * C4_RESTRICT m_ptr; - I m_size; - - C4_ALWAYS_INLINE span _select(T *p, I sz) const { return span(p, sz); } - -public: - - _c4_DEFINE_ARRAY_TYPES(T, I); - using NCT = typename std::remove_const::type; //!< NCT=non const type - using CT = typename std::add_const::type; //!< CT=const type - using const_type = span; - - /// convert automatically to span of const T - operator span () const { span s(m_ptr, m_size); return s; } - -public: - - C4_ALWAYS_INLINE C4_CONSTEXPR14 span() noexcept : m_ptr{nullptr}, m_size{0} {} - - span(span const&) = default; - span(span &&) = default; - - span& operator= (span const&) = default; - span& operator= (span &&) = default; - -public: - - /** @name Construction and assignment from same type */ - /** @{ */ - - template C4_ALWAYS_INLINE C4_CONSTEXPR14 span (T (&arr)[N]) noexcept : m_ptr{arr}, m_size{N} {} - template C4_ALWAYS_INLINE C4_CONSTEXPR14 void assign(T (&arr)[N]) noexcept { m_ptr = arr; m_size = N; } - - C4_ALWAYS_INLINE C4_CONSTEXPR14 span(T *p, I sz) noexcept : m_ptr{p}, m_size{sz} {} - C4_ALWAYS_INLINE C4_CONSTEXPR14 void assign(T *p, I sz) noexcept { m_ptr = p; m_size = sz; } - - C4_ALWAYS_INLINE C4_CONSTEXPR14 span (c4::aggregate_t, std::initializer_list il) noexcept : m_ptr{&*il.begin()}, m_size{il.size()} {} - C4_ALWAYS_INLINE C4_CONSTEXPR14 void assign(c4::aggregate_t, std::initializer_list il) noexcept { m_ptr = &*il.begin(); m_size = il.size(); } - - /** @} */ - -public: - - C4_ALWAYS_INLINE I capacity() const noexcept { return m_size; } - - C4_ALWAYS_INLINE void resize(I sz) C4_NOEXCEPT_A { C4_ASSERT(sz <= m_size); m_size = sz; } - C4_ALWAYS_INLINE void rtrim (I n ) C4_NOEXCEPT_A { C4_ASSERT(n >= 0 && n < m_size); m_size -= n; } - C4_ALWAYS_INLINE void ltrim (I n ) C4_NOEXCEPT_A { C4_ASSERT(n >= 0 && n < m_size); m_size -= n; m_ptr += n; } - -}; -template using cspan = span; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -/** A non-owning span resizeable up to a capacity. Subselection or resizing - * will keep the original provided it starts at begin(). If subselection or - * resizing change the pointer, then the original capacity information will - * be lost. - * - * Thus, resizing via resize() and ltrim() and subselecting via first() - * or any of subspan() or range() when starting from the beginning will keep - * the original capacity. OTOH, using last(), or any of subspan() or range() - * with an offset from the start will remove from capacity (shifting the - * pointer) by the corresponding offset. If this is undesired, then consider - * using spanrsl. - * - * @see spanrs for a span resizeable on the right - * @see spanrsl for a span resizeable on the right and left - */ - -template -class spanrs : public span_crtp> -{ - friend class span_crtp>; - - T * C4_RESTRICT m_ptr; - I m_size; - I m_capacity; - - C4_ALWAYS_INLINE spanrs _select(T *p, I sz) const noexcept - { - C4_ASSERT(p >= m_ptr); - size_t delta = static_cast(p - m_ptr); - C4_ASSERT(m_capacity >= delta); - return spanrs(p, sz, static_cast(m_capacity - delta)); - } - -public: - - _c4_DEFINE_ARRAY_TYPES(T, I); - using NCT = typename std::remove_const::type; //!< NCT=non const type - using CT = typename std::add_const::type; //!< CT=const type - using const_type = spanrs; - - /// convert automatically to span of T - C4_ALWAYS_INLINE operator span () const noexcept { return span(m_ptr, m_size); } - /// convert automatically to span of const T - //C4_ALWAYS_INLINE operator span () const noexcept { span s(m_ptr, m_size); return s; } - /// convert automatically to spanrs of const T - C4_ALWAYS_INLINE operator spanrs () const noexcept { spanrs s(m_ptr, m_size, m_capacity); return s; } - -public: - - C4_ALWAYS_INLINE spanrs() noexcept : m_ptr{nullptr}, m_size{0}, m_capacity{0} {} - - spanrs(spanrs const&) = default; - spanrs(spanrs &&) = default; - - spanrs& operator= (spanrs const&) = default; - spanrs& operator= (spanrs &&) = default; - -public: - - /** @name Construction and assignment from same type */ - /** @{ */ - - C4_ALWAYS_INLINE spanrs(T *p, I sz) noexcept : m_ptr{p}, m_size{sz}, m_capacity{sz} {} - /** @warning will reset the capacity to sz */ - C4_ALWAYS_INLINE void assign(T *p, I sz) noexcept { m_ptr = p; m_size = sz; m_capacity = sz; } - - C4_ALWAYS_INLINE spanrs(T *p, I sz, I cap) noexcept : m_ptr{p}, m_size{sz}, m_capacity{cap} {} - C4_ALWAYS_INLINE void assign(T *p, I sz, I cap) noexcept { m_ptr = p; m_size = sz; m_capacity = cap; } - - template C4_ALWAYS_INLINE spanrs(T (&arr)[N]) noexcept : m_ptr{arr}, m_size{N}, m_capacity{N} {} - template C4_ALWAYS_INLINE void assign(T (&arr)[N]) noexcept { m_ptr = arr; m_size = N; m_capacity = N; } - - C4_ALWAYS_INLINE spanrs(c4::aggregate_t, std::initializer_list il) noexcept : m_ptr{il.begin()}, m_size{il.size()}, m_capacity{il.size()} {} - C4_ALWAYS_INLINE void assign(c4::aggregate_t, std::initializer_list il) noexcept { m_ptr = il.begin(); m_size = il.size(); m_capacity = il.size(); } - - /** @} */ - -public: - - C4_ALWAYS_INLINE I capacity() const noexcept { return m_capacity; } - - C4_ALWAYS_INLINE void resize(I sz) C4_NOEXCEPT_A { C4_ASSERT(sz <= m_capacity); m_size = sz; } - C4_ALWAYS_INLINE void rtrim (I n ) C4_NOEXCEPT_A { C4_ASSERT(n >= 0 && n < m_size); m_size -= n; } - C4_ALWAYS_INLINE void ltrim (I n ) C4_NOEXCEPT_A { C4_ASSERT(n >= 0 && n < m_size); m_size -= n; m_ptr += n; m_capacity -= n; } - -}; -template using cspanrs = spanrs; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -/** A non-owning span which always retains the capacity of the original - * range it was taken from (though it may loose its original size). - * The resizing methods resize(), ltrim(), rtrim() as well - * as the subselection methods subspan(), range(), first() and last() can be - * used at will without loosing the original capacity; the full capacity span - * can always be recovered by calling original(). - */ -template -class spanrsl : public span_crtp> -{ - friend class span_crtp>; - - T *C4_RESTRICT m_ptr; ///< the current ptr. the original ptr is (m_ptr - m_offset). - I m_size; ///< the current size. the original size is unrecoverable. - I m_capacity; ///< the current capacity. the original capacity is (m_capacity + m_offset). - I m_offset; ///< the offset of the current m_ptr to the start of the original memory block. - - C4_ALWAYS_INLINE spanrsl _select(T *p, I sz) const noexcept - { - C4_ASSERT(p >= m_ptr); - I delta = static_cast(p - m_ptr); - C4_ASSERT(m_capacity >= delta); - return spanrsl(p, sz, static_cast(m_capacity - delta), m_offset + delta); - } - -public: - - _c4_DEFINE_ARRAY_TYPES(T, I); - using NCT = typename std::remove_const::type; //!< NCT=non const type - using CT = typename std::add_const::type; //!< CT=const type - using const_type = spanrsl; - - C4_ALWAYS_INLINE operator span () const noexcept { return span(m_ptr, m_size); } - C4_ALWAYS_INLINE operator spanrs () const noexcept { return spanrs(m_ptr, m_size, m_capacity); } - C4_ALWAYS_INLINE operator spanrsl () const noexcept { return spanrsl(m_ptr, m_size, m_capacity, m_offset); } - -public: - - C4_ALWAYS_INLINE spanrsl() noexcept : m_ptr{nullptr}, m_size{0}, m_capacity{0}, m_offset{0} {} - - spanrsl(spanrsl const&) = default; - spanrsl(spanrsl &&) = default; - - spanrsl& operator= (spanrsl const&) = default; - spanrsl& operator= (spanrsl &&) = default; - -public: - - C4_ALWAYS_INLINE spanrsl(T *p, I sz) noexcept : m_ptr{p}, m_size{sz}, m_capacity{sz}, m_offset{0} {} - C4_ALWAYS_INLINE void assign(T *p, I sz) noexcept { m_ptr = p; m_size = sz; m_capacity = sz; m_offset = 0; } - - C4_ALWAYS_INLINE spanrsl(T *p, I sz, I cap) noexcept : m_ptr{p}, m_size{sz}, m_capacity{cap}, m_offset{0} {} - C4_ALWAYS_INLINE void assign(T *p, I sz, I cap) noexcept { m_ptr = p; m_size = sz; m_capacity = cap; m_offset = 0; } - - C4_ALWAYS_INLINE spanrsl(T *p, I sz, I cap, I offs) noexcept : m_ptr{p}, m_size{sz}, m_capacity{cap}, m_offset{offs} {} - C4_ALWAYS_INLINE void assign(T *p, I sz, I cap, I offs) noexcept { m_ptr = p; m_size = sz; m_capacity = cap; m_offset = offs; } - - template C4_ALWAYS_INLINE spanrsl(T (&arr)[N]) noexcept : m_ptr{arr}, m_size{N}, m_capacity{N}, m_offset{0} {} - template C4_ALWAYS_INLINE void assign(T (&arr)[N]) noexcept { m_ptr = arr; m_size = N; m_capacity = N; m_offset = 0; } - - C4_ALWAYS_INLINE spanrsl(c4::aggregate_t, std::initializer_list il) noexcept : m_ptr{il.begin()}, m_size{il.size()}, m_capacity{il.size()}, m_offset{0} {} - C4_ALWAYS_INLINE void assign (c4::aggregate_t, std::initializer_list il) noexcept { m_ptr = il.begin(); m_size = il.size(); m_capacity = il.size(); m_offset = 0; } - -public: - - C4_ALWAYS_INLINE I offset() const noexcept { return m_offset; } - C4_ALWAYS_INLINE I capacity() const noexcept { return m_capacity; } - - C4_ALWAYS_INLINE void resize(I sz) C4_NOEXCEPT_A { C4_ASSERT(sz <= m_capacity); m_size = sz; } - C4_ALWAYS_INLINE void rtrim (I n ) C4_NOEXCEPT_A { C4_ASSERT(n >= 0 && n < m_size); m_size -= n; } - C4_ALWAYS_INLINE void ltrim (I n ) C4_NOEXCEPT_A { C4_ASSERT(n >= 0 && n < m_size); m_size -= n; m_ptr += n; m_offset += n; m_capacity -= n; } - - /** recover the original span as an spanrsl */ - C4_ALWAYS_INLINE spanrsl original() const - { - return spanrsl(m_ptr - m_offset, m_capacity + m_offset, m_capacity + m_offset, 0); - } - /** recover the original span as a different span type. Example: spanrs<...> orig = s.original(); */ - template class OtherSpanType> - C4_ALWAYS_INLINE OtherSpanType original() - { - return OtherSpanType(m_ptr - m_offset, m_capacity + m_offset); - } -}; -template using cspanrsl = spanrsl; - - -} // namespace c4 - - -#endif /* _C4_SPAN_HPP_ */ diff --git a/thirdparty/ryml/ext/c4core/src/c4/std/std.hpp b/thirdparty/ryml/ext/c4core/src/c4/std/std.hpp deleted file mode 100644 index 3df8d1986..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/std/std.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _C4_STD_STD_HPP_ -#define _C4_STD_STD_HPP_ - -/** @file std.hpp includes all c4-std interop files */ - -#include "c4/std/vector.hpp" -#include "c4/std/string.hpp" -#include "c4/std/tuple.hpp" - -#endif // _C4_STD_STD_HPP_ diff --git a/thirdparty/ryml/ext/c4core/src/c4/std/std_fwd.hpp b/thirdparty/ryml/ext/c4core/src/c4/std/std_fwd.hpp deleted file mode 100644 index 8c42ce711..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/std/std_fwd.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _C4_STD_STD_FWD_HPP_ -#define _C4_STD_STD_FWD_HPP_ - -/** @file std_fwd.hpp includes all c4-std interop fwd files */ - -#include "c4/std/vector_fwd.hpp" -#include "c4/std/string_fwd.hpp" -//#include "c4/std/tuple_fwd.hpp" - -#endif // _C4_STD_STD_FWD_HPP_ diff --git a/thirdparty/ryml/ext/c4core/src/c4/std/string.hpp b/thirdparty/ryml/ext/c4core/src/c4/std/string.hpp deleted file mode 100644 index 5b9837ab4..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/std/string.hpp +++ /dev/null @@ -1,97 +0,0 @@ -#ifndef _C4_STD_STRING_HPP_ -#define _C4_STD_STRING_HPP_ - -/** @file string.hpp */ - -#ifndef C4CORE_SINGLE_HEADER -#include "c4/substr.hpp" -#endif - -#include - -namespace c4 { - -//----------------------------------------------------------------------------- - -/** get a writeable view to an existing std::string. - * When the string is empty, the returned view will be pointing - * at the character with value '\0', but the size will be zero. - * @see https://en.cppreference.com/w/cpp/string/basic_string/operator_at - */ -C4_ALWAYS_INLINE c4::substr to_substr(std::string &s) noexcept -{ - #if C4_CPP < 11 - #error this function will do undefined behavior - #endif - // since c++11 it is legal to call s[s.size()]. - return c4::substr(&s[0], s.size()); -} - -/** get a readonly view to an existing std::string. - * When the string is empty, the returned view will be pointing - * at the character with value '\0', but the size will be zero. - * @see https://en.cppreference.com/w/cpp/string/basic_string/operator_at - */ -C4_ALWAYS_INLINE c4::csubstr to_csubstr(std::string const& s) noexcept -{ - #if C4_CPP < 11 - #error this function will do undefined behavior - #endif - // since c++11 it is legal to call s[s.size()]. - return c4::csubstr(&s[0], s.size()); -} - -//----------------------------------------------------------------------------- - -C4_ALWAYS_INLINE bool operator== (c4::csubstr ss, std::string const& s) { return ss.compare(to_csubstr(s)) == 0; } -C4_ALWAYS_INLINE bool operator!= (c4::csubstr ss, std::string const& s) { return ss.compare(to_csubstr(s)) != 0; } -C4_ALWAYS_INLINE bool operator>= (c4::csubstr ss, std::string const& s) { return ss.compare(to_csubstr(s)) >= 0; } -C4_ALWAYS_INLINE bool operator> (c4::csubstr ss, std::string const& s) { return ss.compare(to_csubstr(s)) > 0; } -C4_ALWAYS_INLINE bool operator<= (c4::csubstr ss, std::string const& s) { return ss.compare(to_csubstr(s)) <= 0; } -C4_ALWAYS_INLINE bool operator< (c4::csubstr ss, std::string const& s) { return ss.compare(to_csubstr(s)) < 0; } - -C4_ALWAYS_INLINE bool operator== (std::string const& s, c4::csubstr ss) { return ss.compare(to_csubstr(s)) == 0; } -C4_ALWAYS_INLINE bool operator!= (std::string const& s, c4::csubstr ss) { return ss.compare(to_csubstr(s)) != 0; } -C4_ALWAYS_INLINE bool operator>= (std::string const& s, c4::csubstr ss) { return ss.compare(to_csubstr(s)) <= 0; } -C4_ALWAYS_INLINE bool operator> (std::string const& s, c4::csubstr ss) { return ss.compare(to_csubstr(s)) < 0; } -C4_ALWAYS_INLINE bool operator<= (std::string const& s, c4::csubstr ss) { return ss.compare(to_csubstr(s)) >= 0; } -C4_ALWAYS_INLINE bool operator< (std::string const& s, c4::csubstr ss) { return ss.compare(to_csubstr(s)) > 0; } - -//----------------------------------------------------------------------------- - -/** copy an std::string to a writeable string view */ -inline size_t to_chars(c4::substr buf, std::string const& s) -{ - C4_ASSERT(!buf.overlaps(to_csubstr(s))); - size_t len = buf.len < s.size() ? buf.len : s.size(); - // calling memcpy with null strings is undefined behavior - // and will wreak havoc in calling code's branches. - // see https://github.com/biojppm/rapidyaml/pull/264#issuecomment-1262133637 - if(len) - { - C4_ASSERT(s.data() != nullptr); - C4_ASSERT(buf.str != nullptr); - memcpy(buf.str, s.data(), len); - } - return s.size(); // return the number of needed chars -} - -/** copy a string view to an existing std::string */ -inline bool from_chars(c4::csubstr buf, std::string * s) -{ - s->resize(buf.len); - C4_ASSERT(!buf.overlaps(to_csubstr(*s))); - // calling memcpy with null strings is undefined behavior - // and will wreak havoc in calling code's branches. - // see https://github.com/biojppm/rapidyaml/pull/264#issuecomment-1262133637 - if(buf.len) - { - C4_ASSERT(buf.str != nullptr); - memcpy(&(*s)[0], buf.str, buf.len); - } - return true; -} - -} // namespace c4 - -#endif // _C4_STD_STRING_HPP_ diff --git a/thirdparty/ryml/ext/c4core/src/c4/std/string_fwd.hpp b/thirdparty/ryml/ext/c4core/src/c4/std/string_fwd.hpp deleted file mode 100644 index 6f6f42146..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/std/string_fwd.hpp +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef _C4_STD_STRING_FWD_HPP_ -#define _C4_STD_STRING_FWD_HPP_ - -/** @file string_fwd.hpp */ - -#ifndef DOXYGEN - -#ifndef C4CORE_SINGLE_HEADER -#include "c4/substr_fwd.hpp" -#endif - -#include - -// forward declarations for std::string -#if defined(__GLIBCXX__) || defined(__GLIBCPP__) -#include // use the fwd header in glibcxx -#elif defined(_LIBCPP_VERSION) || defined(__APPLE_CC__) -#include // use the fwd header in stdlibc++ -#elif defined(_MSC_VER) -//! @todo is there a fwd header in msvc? -namespace std { -template struct char_traits; -template class allocator; -template class basic_string; -using string = basic_string, allocator>; -} /* namespace std */ -#else -#error "unknown standard library" -#endif - -namespace c4 { - -C4_ALWAYS_INLINE c4::substr to_substr(std::string &s) noexcept; -C4_ALWAYS_INLINE c4::csubstr to_csubstr(std::string const& s) noexcept; - -bool operator== (c4::csubstr ss, std::string const& s); -bool operator!= (c4::csubstr ss, std::string const& s); -bool operator>= (c4::csubstr ss, std::string const& s); -bool operator> (c4::csubstr ss, std::string const& s); -bool operator<= (c4::csubstr ss, std::string const& s); -bool operator< (c4::csubstr ss, std::string const& s); - -bool operator== (std::string const& s, c4::csubstr ss); -bool operator!= (std::string const& s, c4::csubstr ss); -bool operator>= (std::string const& s, c4::csubstr ss); -bool operator> (std::string const& s, c4::csubstr ss); -bool operator<= (std::string const& s, c4::csubstr ss); -bool operator< (std::string const& s, c4::csubstr ss); - -size_t to_chars(c4::substr buf, std::string const& s); -bool from_chars(c4::csubstr buf, std::string * s); - -} // namespace c4 - -#endif // DOXYGEN -#endif // _C4_STD_STRING_FWD_HPP_ diff --git a/thirdparty/ryml/ext/c4core/src/c4/std/tuple.hpp b/thirdparty/ryml/ext/c4core/src/c4/std/tuple.hpp deleted file mode 100644 index 5edcd63da..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/std/tuple.hpp +++ /dev/null @@ -1,184 +0,0 @@ -#ifndef _C4_STD_TUPLE_HPP_ -#define _C4_STD_TUPLE_HPP_ - -/** @file tuple.hpp */ - -#ifndef C4CORE_SINGLE_HEADER -#include "c4/format.hpp" -#endif - -#include - -/** this is a work in progress */ -#undef C4_TUPLE_TO_CHARS - -namespace c4 { - -#ifdef C4_TUPLE_TO_CHARS -namespace detail { - -template< size_t Curr, class... Types > -struct tuple_helper -{ - static size_t do_cat(substr buf, std::tuple< Types... > const& tp) - { - size_t num = to_chars(buf, std::get(tp)); - buf = buf.len >= num ? buf.sub(num) : substr{}; - num += tuple_helper< Curr+1, Types... >::do_cat(buf, tp); - return num; - } - - static size_t do_uncat(csubstr buf, std::tuple< Types... > & tp) - { - size_t num = from_str_trim(buf, &std::get(tp)); - if(num == csubstr::npos) return csubstr::npos; - buf = buf.len >= num ? buf.sub(num) : substr{}; - num += tuple_helper< Curr+1, Types... >::do_uncat(buf, tp); - return num; - } - - template< class Sep > - static size_t do_catsep_more(substr buf, Sep const& sep, std::tuple< Types... > const& tp) - { - size_t ret = to_chars(buf, sep), num = ret; - buf = buf.len >= ret ? buf.sub(ret) : substr{}; - ret = to_chars(buf, std::get(tp)); - num += ret; - buf = buf.len >= ret ? buf.sub(ret) : substr{}; - ret = tuple_helper< Curr+1, Types... >::do_catsep_more(buf, sep, tp); - num += ret; - return num; - } - - template< class Sep > - static size_t do_uncatsep_more(csubstr buf, Sep & sep, std::tuple< Types... > & tp) - { - size_t ret = from_str_trim(buf, &sep), num = ret; - if(ret == csubstr::npos) return csubstr::npos; - buf = buf.len >= ret ? buf.sub(ret) : substr{}; - ret = from_str_trim(buf, &std::get(tp)); - if(ret == csubstr::npos) return csubstr::npos; - num += ret; - buf = buf.len >= ret ? buf.sub(ret) : substr{}; - ret = tuple_helper< Curr+1, Types... >::do_uncatsep_more(buf, sep, tp); - if(ret == csubstr::npos) return csubstr::npos; - num += ret; - return num; - } - - static size_t do_format(substr buf, csubstr fmt, std::tuple< Types... > const& tp) - { - auto pos = fmt.find("{}"); - if(pos != csubstr::npos) - { - size_t num = to_chars(buf, fmt.sub(0, pos)); - size_t out = num; - buf = buf.len >= num ? buf.sub(num) : substr{}; - num = to_chars(buf, std::get(tp)); - out += num; - buf = buf.len >= num ? buf.sub(num) : substr{}; - num = tuple_helper< Curr+1, Types... >::do_format(buf, fmt.sub(pos + 2), tp); - out += num; - return out; - } - else - { - return format(buf, fmt); - } - } - - static size_t do_unformat(csubstr buf, csubstr fmt, std::tuple< Types... > & tp) - { - auto pos = fmt.find("{}"); - if(pos != csubstr::npos) - { - size_t num = pos; - size_t out = num; - buf = buf.len >= num ? buf.sub(num) : substr{}; - num = from_str_trim(buf, &std::get(tp)); - out += num; - buf = buf.len >= num ? buf.sub(num) : substr{}; - num = tuple_helper< Curr+1, Types... >::do_unformat(buf, fmt.sub(pos + 2), tp); - out += num; - return out; - } - else - { - return tuple_helper< sizeof...(Types), Types... >::do_unformat(buf, fmt, tp); - } - } - -}; - -/** @todo VS compilation fails for this class */ -template< class... Types > -struct tuple_helper< sizeof...(Types), Types... > -{ - static size_t do_cat(substr /*buf*/, std::tuple const& /*tp*/) { return 0; } - static size_t do_uncat(csubstr /*buf*/, std::tuple & /*tp*/) { return 0; } - - template< class Sep > static size_t do_catsep_more(substr /*buf*/, Sep const& /*sep*/, std::tuple const& /*tp*/) { return 0; } - template< class Sep > static size_t do_uncatsep_more(csubstr /*buf*/, Sep & /*sep*/, std::tuple & /*tp*/) { return 0; } - - static size_t do_format(substr buf, csubstr fmt, std::tuple const& /*tp*/) - { - return to_chars(buf, fmt); - } - - static size_t do_unformat(csubstr buf, csubstr fmt, std::tuple const& /*tp*/) - { - return 0; - } -}; - -} // namespace detail - -template< class... Types > -inline size_t cat(substr buf, std::tuple< Types... > const& tp) -{ - return detail::tuple_helper< 0, Types... >::do_cat(buf, tp); -} - -template< class... Types > -inline size_t uncat(csubstr buf, std::tuple< Types... > & tp) -{ - return detail::tuple_helper< 0, Types... >::do_uncat(buf, tp); -} - -template< class Sep, class... Types > -inline size_t catsep(substr buf, Sep const& sep, std::tuple< Types... > const& tp) -{ - size_t num = to_chars(buf, std::cref(std::get<0>(tp))); - buf = buf.len >= num ? buf.sub(num) : substr{}; - num += detail::tuple_helper< 1, Types... >::do_catsep_more(buf, sep, tp); - return num; -} - -template< class Sep, class... Types > -inline size_t uncatsep(csubstr buf, Sep & sep, std::tuple< Types... > & tp) -{ - size_t ret = from_str_trim(buf, &std::get<0>(tp)), num = ret; - if(ret == csubstr::npos) return csubstr::npos; - buf = buf.len >= ret ? buf.sub(ret) : substr{}; - ret = detail::tuple_helper< 1, Types... >::do_uncatsep_more(buf, sep, tp); - if(ret == csubstr::npos) return csubstr::npos; - num += ret; - return num; -} - -template< class... Types > -inline size_t format(substr buf, csubstr fmt, std::tuple< Types... > const& tp) -{ - return detail::tuple_helper< 0, Types... >::do_format(buf, fmt, tp); -} - -template< class... Types > -inline size_t unformat(csubstr buf, csubstr fmt, std::tuple< Types... > & tp) -{ - return detail::tuple_helper< 0, Types... >::do_unformat(buf, fmt, tp); -} -#endif // C4_TUPLE_TO_CHARS - -} // namespace c4 - -#endif /* _C4_STD_TUPLE_HPP_ */ diff --git a/thirdparty/ryml/ext/c4core/src/c4/std/vector.hpp b/thirdparty/ryml/ext/c4core/src/c4/std/vector.hpp deleted file mode 100644 index baaa24223..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/std/vector.hpp +++ /dev/null @@ -1,88 +0,0 @@ -#ifndef _C4_STD_VECTOR_HPP_ -#define _C4_STD_VECTOR_HPP_ - -/** @file vector.hpp provides conversion and comparison facilities - * from/between std::vector to c4::substr and c4::csubstr. - * @todo add to_span() and friends - */ - -#ifndef C4CORE_SINGLE_HEADER -#include "c4/substr.hpp" -#endif - -#include - -namespace c4 { - -//----------------------------------------------------------------------------- - -/** get a substr (writeable string view) of an existing std::vector */ -template -c4::substr to_substr(std::vector &vec) -{ - char *data = vec.empty() ? nullptr : vec.data(); // data() may or may not return a null pointer. - return c4::substr(data, vec.size()); -} - -/** get a csubstr (read-only string) view of an existing std::vector */ -template -c4::csubstr to_csubstr(std::vector const& vec) -{ - const char *data = vec.empty() ? nullptr : vec.data(); // data() may or may not return a null pointer. - return c4::csubstr(data, vec.size()); -} - -//----------------------------------------------------------------------------- -// comparisons between substrings and std::vector - -template C4_ALWAYS_INLINE bool operator!= (c4::csubstr ss, std::vector const& s) { return ss != to_csubstr(s); } -template C4_ALWAYS_INLINE bool operator== (c4::csubstr ss, std::vector const& s) { return ss == to_csubstr(s); } -template C4_ALWAYS_INLINE bool operator>= (c4::csubstr ss, std::vector const& s) { return ss >= to_csubstr(s); } -template C4_ALWAYS_INLINE bool operator> (c4::csubstr ss, std::vector const& s) { return ss > to_csubstr(s); } -template C4_ALWAYS_INLINE bool operator<= (c4::csubstr ss, std::vector const& s) { return ss <= to_csubstr(s); } -template C4_ALWAYS_INLINE bool operator< (c4::csubstr ss, std::vector const& s) { return ss < to_csubstr(s); } - -template C4_ALWAYS_INLINE bool operator!= (std::vector const& s, c4::csubstr ss) { return ss != to_csubstr(s); } -template C4_ALWAYS_INLINE bool operator== (std::vector const& s, c4::csubstr ss) { return ss == to_csubstr(s); } -template C4_ALWAYS_INLINE bool operator>= (std::vector const& s, c4::csubstr ss) { return ss <= to_csubstr(s); } -template C4_ALWAYS_INLINE bool operator> (std::vector const& s, c4::csubstr ss) { return ss < to_csubstr(s); } -template C4_ALWAYS_INLINE bool operator<= (std::vector const& s, c4::csubstr ss) { return ss >= to_csubstr(s); } -template C4_ALWAYS_INLINE bool operator< (std::vector const& s, c4::csubstr ss) { return ss > to_csubstr(s); } - -//----------------------------------------------------------------------------- - -/** copy a std::vector to a writeable string view */ -template -inline size_t to_chars(c4::substr buf, std::vector const& s) -{ - C4_ASSERT(!buf.overlaps(to_csubstr(s))); - size_t len = buf.len < s.size() ? buf.len : s.size(); - // calling memcpy with null strings is undefined behavior - // and will wreak havoc in calling code's branches. - // see https://github.com/biojppm/rapidyaml/pull/264#issuecomment-1262133637 - if(len > 0) - { - memcpy(buf.str, s.data(), len); - } - return s.size(); // return the number of needed chars -} - -/** copy a string view to an existing std::vector */ -template -inline bool from_chars(c4::csubstr buf, std::vector * s) -{ - s->resize(buf.len); - C4_ASSERT(!buf.overlaps(to_csubstr(*s))); - // calling memcpy with null strings is undefined behavior - // and will wreak havoc in calling code's branches. - // see https://github.com/biojppm/rapidyaml/pull/264#issuecomment-1262133637 - if(buf.len > 0) - { - memcpy(&(*s)[0], buf.str, buf.len); - } - return true; -} - -} // namespace c4 - -#endif // _C4_STD_VECTOR_HPP_ diff --git a/thirdparty/ryml/ext/c4core/src/c4/std/vector_fwd.hpp b/thirdparty/ryml/ext/c4core/src/c4/std/vector_fwd.hpp deleted file mode 100644 index a739b7d28..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/std/vector_fwd.hpp +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef _C4_STD_VECTOR_FWD_HPP_ -#define _C4_STD_VECTOR_FWD_HPP_ - -/** @file vector_fwd.hpp */ - -#include - -// forward declarations for std::vector -#if defined(__GLIBCXX__) || defined(__GLIBCPP__) || defined(_MSC_VER) -#if defined(_MSC_VER) -__pragma(warning(push)) -__pragma(warning(disable : 4643)) -#endif -namespace std { -template class allocator; -template class vector; -} // namespace std -#if defined(_MSC_VER) -__pragma(warning(pop)) -#endif -#elif defined(_LIBCPP_ABI_NAMESPACE) -namespace std { -inline namespace _LIBCPP_ABI_NAMESPACE { -template class allocator; -template class vector; -} // namespace _LIBCPP_ABI_NAMESPACE -} // namespace std -#else -#error "unknown standard library" -#endif - -#ifndef C4CORE_SINGLE_HEADER -#include "c4/substr_fwd.hpp" -#endif - -namespace c4 { - -template c4::substr to_substr(std::vector &vec); -template c4::csubstr to_csubstr(std::vector const& vec); - -template bool operator!= (c4::csubstr ss, std::vector const& s); -template bool operator== (c4::csubstr ss, std::vector const& s); -template bool operator>= (c4::csubstr ss, std::vector const& s); -template bool operator> (c4::csubstr ss, std::vector const& s); -template bool operator<= (c4::csubstr ss, std::vector const& s); -template bool operator< (c4::csubstr ss, std::vector const& s); - -template bool operator!= (std::vector const& s, c4::csubstr ss); -template bool operator== (std::vector const& s, c4::csubstr ss); -template bool operator>= (std::vector const& s, c4::csubstr ss); -template bool operator> (std::vector const& s, c4::csubstr ss); -template bool operator<= (std::vector const& s, c4::csubstr ss); -template bool operator< (std::vector const& s, c4::csubstr ss); - -template size_t to_chars(c4::substr buf, std::vector const& s); -template bool from_chars(c4::csubstr buf, std::vector * s); - -} // namespace c4 - -#endif // _C4_STD_VECTOR_FWD_HPP_ diff --git a/thirdparty/ryml/ext/c4core/src/c4/substr.hpp b/thirdparty/ryml/ext/c4core/src/c4/substr.hpp deleted file mode 100644 index ead46727e..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/substr.hpp +++ /dev/null @@ -1,2246 +0,0 @@ -#ifndef _C4_SUBSTR_HPP_ -#define _C4_SUBSTR_HPP_ - -/** @file substr.hpp read+write string views */ - -#include -#include -#include - -#include "c4/config.hpp" -#include "c4/error.hpp" -#include "c4/substr_fwd.hpp" - -#ifdef __clang__ -# pragma clang diagnostic push -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wtype-limits" // disable warnings on size_t>=0, used heavily in assertions below. These assertions are a preparation step for providing the index type as a template parameter. -# pragma GCC diagnostic ignored "-Wuseless-cast" -#endif - - -namespace c4 { - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -namespace detail { - -template -static inline void _do_reverse(C *C4_RESTRICT first, C *C4_RESTRICT last) -{ - while(last > first) - { - C tmp = *last; - *last-- = *first; - *first++ = tmp; - } -} - -} // namespace detail - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -// utility macros to deuglify SFINAE code; undefined after the class. -// https://stackoverflow.com/questions/43051882/how-to-disable-a-class-member-funrtion-for-certain-template-types -#define C4_REQUIRE_RW(ret_type) \ - template \ - typename std::enable_if< ! std::is_const::value, ret_type>::type -// non-const-to-const -#define C4_NC2C(ty) \ - typename std::enable_if::value && ( ! std::is_const::value), ty>::type - - -/** a non-owning string-view, consisting of a character pointer - * and a length. - * - * @note The pointer is explicitly restricted. - * @note Because of a C++ limitation, there cannot coexist overloads for - * constructing from a char[N] and a char*; the latter will always be chosen - * by the compiler. To construct an object of this type, call to_substr() or - * to_csubstr(). For a more detailed explanation on why the overloads cannot - * coexist, see http://cplusplus.bordoon.com/specializeForCharacterArrays.html - * - * @see to_substr() - * @see to_csubstr() - */ -template -struct C4CORE_EXPORT basic_substring -{ -public: - - /** a restricted pointer to the first character of the substring */ - C * C4_RESTRICT str; - /** the length of the substring */ - size_t len; - -public: - - /** @name Types */ - /** @{ */ - - using CC = typename std::add_const::type; //!< CC=const char - using NCC_ = typename std::remove_const::type; //!< NCC_=non const char - - using ro_substr = basic_substring; - using rw_substr = basic_substring; - - using char_type = C; - using size_type = size_t; - - using iterator = C*; - using const_iterator = CC*; - - enum : size_t { npos = (size_t)-1, NONE = (size_t)-1 }; - - /// convert automatically to substring of const C - operator ro_substr () const { ro_substr s(str, len); return s; } - - /** @} */ - -public: - - /** @name Default construction and assignment */ - /** @{ */ - - constexpr basic_substring() : str(nullptr), len(0) {} - - constexpr basic_substring(basic_substring const&) = default; - constexpr basic_substring(basic_substring &&) = default; - constexpr basic_substring(std::nullptr_t) : str(nullptr), len(0) {} - - basic_substring& operator= (basic_substring const&) = default; - basic_substring& operator= (basic_substring &&) = default; - basic_substring& operator= (std::nullptr_t) { str = nullptr; len = 0; return *this; } - - /** @} */ - -public: - - /** @name Construction and assignment from characters with the same type */ - /** @{ */ - - //basic_substring(C *s_) : str(s_), len(s_ ? strlen(s_) : 0) {} - /** the overload for receiving a single C* pointer will always - * hide the array[N] overload. So it is disabled. If you want to - * construct a substr from a single pointer containing a C-style string, - * you can call c4::to_substr()/c4::to_csubstr(). - * @see c4::to_substr() - * @see c4::to_csubstr() */ - template - constexpr basic_substring(C (&s_)[N]) noexcept : str(s_), len(N-1) {} - basic_substring(C *s_, size_t len_) : str(s_), len(len_) { C4_ASSERT(str || !len_); } - basic_substring(C *beg_, C *end_) : str(beg_), len(static_cast(end_ - beg_)) { C4_ASSERT(end_ >= beg_); } - - //basic_substring& operator= (C *s_) { this->assign(s_); return *this; } - template - basic_substring& operator= (C (&s_)[N]) { this->assign(s_); return *this; } - - //void assign(C *s_) { str = (s_); len = (s_ ? strlen(s_) : 0); } - /** the overload for receiving a single C* pointer will always - * hide the array[N] overload. So it is disabled. If you want to - * construct a substr from a single pointer containing a C-style string, - * you can call c4::to_substr()/c4::to_csubstr(). - * @see c4::to_substr() - * @see c4::to_csubstr() */ - template - void assign(C (&s_)[N]) { str = (s_); len = (N-1); } - void assign(C *s_, size_t len_) { str = s_; len = len_; C4_ASSERT(str || !len_); } - void assign(C *beg_, C *end_) { C4_ASSERT(end_ >= beg_); str = (beg_); len = (end_ - beg_); } - - void clear() { str = nullptr; len = 0; } - - /** @} */ - -public: - - /** @name Construction from non-const characters */ - /** @{ */ - - // when the char type is const, allow construction and assignment from non-const chars - - /** only available when the char type is const */ - template explicit basic_substring(C4_NC2C(U) (&s_)[N]) { str = s_; len = N-1; } - /** only available when the char type is const */ - template< class U=NCC_> basic_substring(C4_NC2C(U) *s_, size_t len_) { str = s_; len = len_; } - /** only available when the char type is const */ - template< class U=NCC_> basic_substring(C4_NC2C(U) *beg_, C4_NC2C(U) *end_) { C4_ASSERT(end_ >= beg_); str = beg_; len = end_ - beg_; } - - /** only available when the char type is const */ - template void assign(C4_NC2C(U) (&s_)[N]) { str = s_; len = N-1; } - /** only available when the char type is const */ - template< class U=NCC_> void assign(C4_NC2C(U) *s_, size_t len_) { str = s_; len = len_; } - /** only available when the char type is const */ - template< class U=NCC_> void assign(C4_NC2C(U) *beg_, C4_NC2C(U) *end_) { C4_ASSERT(end_ >= beg_); str = beg_; len = end_ - beg_; } - - /** only available when the char type is const */ - template - basic_substring& operator=(C4_NC2C(U) (&s_)[N]) { str = s_; len = N-1; return *this; } - - /** @} */ - -public: - - /** @name Standard accessor methods */ - /** @{ */ - - C4_ALWAYS_INLINE C4_PURE bool has_str() const noexcept { return ! empty() && str[0] != C(0); } - C4_ALWAYS_INLINE C4_PURE bool empty() const noexcept { return (len == 0 || str == nullptr); } - C4_ALWAYS_INLINE C4_PURE bool not_empty() const noexcept { return (len != 0 && str != nullptr); } - C4_ALWAYS_INLINE C4_PURE size_t size() const noexcept { return len; } - - C4_ALWAYS_INLINE C4_PURE iterator begin() noexcept { return str; } - C4_ALWAYS_INLINE C4_PURE iterator end () noexcept { return str + len; } - - C4_ALWAYS_INLINE C4_PURE const_iterator begin() const noexcept { return str; } - C4_ALWAYS_INLINE C4_PURE const_iterator end () const noexcept { return str + len; } - - C4_ALWAYS_INLINE C4_PURE C * data() noexcept { return str; } - C4_ALWAYS_INLINE C4_PURE C const* data() const noexcept { return str; } - - C4_ALWAYS_INLINE C4_PURE C & operator[] (size_t i) noexcept { C4_ASSERT(i >= 0 && i < len); return str[i]; } - C4_ALWAYS_INLINE C4_PURE C const& operator[] (size_t i) const noexcept { C4_ASSERT(i >= 0 && i < len); return str[i]; } - - C4_ALWAYS_INLINE C4_PURE C & front() noexcept { C4_ASSERT(len > 0 && str != nullptr); return *str; } - C4_ALWAYS_INLINE C4_PURE C const& front() const noexcept { C4_ASSERT(len > 0 && str != nullptr); return *str; } - - C4_ALWAYS_INLINE C4_PURE C & back() noexcept { C4_ASSERT(len > 0 && str != nullptr); return *(str + len - 1); } - C4_ALWAYS_INLINE C4_PURE C const& back() const noexcept { C4_ASSERT(len > 0 && str != nullptr); return *(str + len - 1); } - - /** @} */ - -public: - - /** @name Comparison methods */ - /** @{ */ - - C4_PURE int compare(C const c) const noexcept - { - C4_XASSERT((str != nullptr) || len == 0); - if(C4_LIKELY(str != nullptr && len > 0)) - return (*str != c) ? *str - c : (static_cast(len) - 1); - else - return -1; - } - - C4_PURE int compare(const char *C4_RESTRICT that, size_t sz) const noexcept - { - C4_XASSERT(that || sz == 0); - C4_XASSERT(str || len == 0); - if(C4_LIKELY(str && that)) - { - { - const size_t min = len < sz ? len : sz; - for(size_t i = 0; i < min; ++i) - if(str[i] != that[i]) - return str[i] < that[i] ? -1 : 1; - } - if(len < sz) - return -1; - else if(len == sz) - return 0; - else - return 1; - } - else if(len == sz) - { - C4_XASSERT(len == 0 && sz == 0); - return 0; - } - return len < sz ? -1 : 1; - } - - C4_ALWAYS_INLINE C4_PURE int compare(ro_substr const that) const noexcept { return this->compare(that.str, that.len); } - - C4_ALWAYS_INLINE C4_PURE bool operator== (std::nullptr_t) const noexcept { return str == nullptr; } - C4_ALWAYS_INLINE C4_PURE bool operator!= (std::nullptr_t) const noexcept { return str != nullptr; } - - C4_ALWAYS_INLINE C4_PURE bool operator== (C const c) const noexcept { return this->compare(c) == 0; } - C4_ALWAYS_INLINE C4_PURE bool operator!= (C const c) const noexcept { return this->compare(c) != 0; } - C4_ALWAYS_INLINE C4_PURE bool operator< (C const c) const noexcept { return this->compare(c) < 0; } - C4_ALWAYS_INLINE C4_PURE bool operator> (C const c) const noexcept { return this->compare(c) > 0; } - C4_ALWAYS_INLINE C4_PURE bool operator<= (C const c) const noexcept { return this->compare(c) <= 0; } - C4_ALWAYS_INLINE C4_PURE bool operator>= (C const c) const noexcept { return this->compare(c) >= 0; } - - template C4_ALWAYS_INLINE C4_PURE bool operator== (basic_substring const that) const noexcept { return this->compare(that) == 0; } - template C4_ALWAYS_INLINE C4_PURE bool operator!= (basic_substring const that) const noexcept { return this->compare(that) != 0; } - template C4_ALWAYS_INLINE C4_PURE bool operator< (basic_substring const that) const noexcept { return this->compare(that) < 0; } - template C4_ALWAYS_INLINE C4_PURE bool operator> (basic_substring const that) const noexcept { return this->compare(that) > 0; } - template C4_ALWAYS_INLINE C4_PURE bool operator<= (basic_substring const that) const noexcept { return this->compare(that) <= 0; } - template C4_ALWAYS_INLINE C4_PURE bool operator>= (basic_substring const that) const noexcept { return this->compare(that) >= 0; } - - template C4_ALWAYS_INLINE C4_PURE bool operator== (const char (&that)[N]) const noexcept { return this->compare(that, N-1) == 0; } - template C4_ALWAYS_INLINE C4_PURE bool operator!= (const char (&that)[N]) const noexcept { return this->compare(that, N-1) != 0; } - template C4_ALWAYS_INLINE C4_PURE bool operator< (const char (&that)[N]) const noexcept { return this->compare(that, N-1) < 0; } - template C4_ALWAYS_INLINE C4_PURE bool operator> (const char (&that)[N]) const noexcept { return this->compare(that, N-1) > 0; } - template C4_ALWAYS_INLINE C4_PURE bool operator<= (const char (&that)[N]) const noexcept { return this->compare(that, N-1) <= 0; } - template C4_ALWAYS_INLINE C4_PURE bool operator>= (const char (&that)[N]) const noexcept { return this->compare(that, N-1) >= 0; } - - /** @} */ - -public: - - /** @name Sub-selection methods */ - /** @{ */ - - /** true if *this is a substring of that (ie, from the same buffer) */ - C4_ALWAYS_INLINE C4_PURE bool is_sub(ro_substr const that) const noexcept - { - return that.is_super(*this); - } - - /** true if that is a substring of *this (ie, from the same buffer) */ - C4_ALWAYS_INLINE C4_PURE bool is_super(ro_substr const that) const noexcept - { - if(C4_LIKELY(len > 0)) - return that.str >= str && that.str+that.len <= str+len; - else - return that.len == 0 && that.str == str && str != nullptr; - } - - /** true if there is overlap of at least one element between that and *this */ - C4_ALWAYS_INLINE C4_PURE bool overlaps(ro_substr const that) const noexcept - { - // thanks @timwynants - return that.str+that.len > str && that.str < str+len; - } - -public: - - /** return [first,len[ */ - C4_ALWAYS_INLINE C4_PURE basic_substring sub(size_t first) const noexcept - { - C4_ASSERT(first >= 0 && first <= len); - return basic_substring(str + first, len - first); - } - - /** return [first,first+num[. If num==npos, return [first,len[ */ - C4_ALWAYS_INLINE C4_PURE basic_substring sub(size_t first, size_t num) const noexcept - { - C4_ASSERT(first >= 0 && first <= len); - C4_ASSERT((num >= 0 && num <= len) || (num == npos)); - size_t rnum = num != npos ? num : len - first; - C4_ASSERT((first >= 0 && first + rnum <= len) || (num == 0)); - return basic_substring(str + first, rnum); - } - - /** return [first,last[. If last==npos, return [first,len[ */ - C4_ALWAYS_INLINE C4_PURE basic_substring range(size_t first, size_t last=npos) const noexcept - { - C4_ASSERT(first >= 0 && first <= len); - last = last != npos ? last : len; - C4_ASSERT(first <= last); - C4_ASSERT(last >= 0 && last <= len); - return basic_substring(str + first, last - first); - } - - /** return the first @p num elements: [0,num[*/ - C4_ALWAYS_INLINE C4_PURE basic_substring first(size_t num) const noexcept - { - C4_ASSERT(num <= len || num == npos); - return basic_substring(str, num != npos ? num : len); - } - - /** return the last @num elements: [len-num,len[*/ - C4_ALWAYS_INLINE C4_PURE basic_substring last(size_t num) const noexcept - { - C4_ASSERT(num <= len || num == npos); - return num != npos ? - basic_substring(str + len - num, num) : - *this; - } - - /** offset from the ends: return [left,len-right[ ; ie, trim a - number of characters from the left and right. This is - equivalent to python's negative list indices. */ - C4_ALWAYS_INLINE C4_PURE basic_substring offs(size_t left, size_t right) const noexcept - { - C4_ASSERT(left >= 0 && left <= len); - C4_ASSERT(right >= 0 && right <= len); - C4_ASSERT(left <= len - right + 1); - return basic_substring(str + left, len - right - left); - } - - /** return [0, pos[ . Same as .first(pos), but provided for compatibility with .right_of() */ - C4_ALWAYS_INLINE C4_PURE basic_substring left_of(size_t pos) const noexcept - { - C4_ASSERT(pos <= len || pos == npos); - return (pos != npos) ? - basic_substring(str, pos) : - *this; - } - - /** return [0, pos+include_pos[ . Same as .first(pos+1), but provided for compatibility with .right_of() */ - C4_ALWAYS_INLINE C4_PURE basic_substring left_of(size_t pos, bool include_pos) const noexcept - { - C4_ASSERT(pos <= len || pos == npos); - return (pos != npos) ? - basic_substring(str, pos+include_pos) : - *this; - } - - /** return [pos+1, len[ */ - C4_ALWAYS_INLINE C4_PURE basic_substring right_of(size_t pos) const noexcept - { - C4_ASSERT(pos <= len || pos == npos); - return (pos != npos) ? - basic_substring(str + (pos + 1), len - (pos + 1)) : - basic_substring(str + len, size_t(0)); - } - - /** return [pos+!include_pos, len[ */ - C4_ALWAYS_INLINE C4_PURE basic_substring right_of(size_t pos, bool include_pos) const noexcept - { - C4_ASSERT(pos <= len || pos == npos); - return (pos != npos) ? - basic_substring(str + (pos + !include_pos), len - (pos + !include_pos)) : - basic_substring(str + len, size_t(0)); - } - -public: - - /** given @p subs a substring of the current string, get the - * portion of the current string to the left of it */ - C4_ALWAYS_INLINE C4_PURE basic_substring left_of(ro_substr const subs) const noexcept - { - C4_ASSERT(is_super(subs) || subs.empty()); - auto ssb = subs.begin(); - auto b = begin(); - auto e = end(); - if(ssb >= b && ssb <= e) - return sub(0, static_cast(ssb - b)); - else - return sub(0, 0); - } - - /** given @p subs a substring of the current string, get the - * portion of the current string to the right of it */ - C4_ALWAYS_INLINE C4_PURE basic_substring right_of(ro_substr const subs) const noexcept - { - C4_ASSERT(is_super(subs) || subs.empty()); - auto sse = subs.end(); - auto b = begin(); - auto e = end(); - if(sse >= b && sse <= e) - return sub(static_cast(sse - b), static_cast(e - sse)); - else - return sub(0, 0); - } - - /** @} */ - -public: - - /** @name Removing characters (trim()) / patterns (strip()) from the tips of the string */ - /** @{ */ - - /** trim left */ - basic_substring triml(const C c) const - { - if( ! empty()) - { - size_t pos = first_not_of(c); - if(pos != npos) - return sub(pos); - } - return sub(0, 0); - } - /** trim left ANY of the characters. - * @see stripl() to remove a pattern from the left */ - basic_substring triml(ro_substr chars) const - { - if( ! empty()) - { - size_t pos = first_not_of(chars); - if(pos != npos) - return sub(pos); - } - return sub(0, 0); - } - - /** trim the character c from the right */ - basic_substring trimr(const C c) const - { - if( ! empty()) - { - size_t pos = last_not_of(c, npos); - if(pos != npos) - return sub(0, pos+1); - } - return sub(0, 0); - } - /** trim right ANY of the characters - * @see stripr() to remove a pattern from the right */ - basic_substring trimr(ro_substr chars) const - { - if( ! empty()) - { - size_t pos = last_not_of(chars, npos); - if(pos != npos) - return sub(0, pos+1); - } - return sub(0, 0); - } - - /** trim the character c left and right */ - basic_substring trim(const C c) const - { - return triml(c).trimr(c); - } - /** trim left and right ANY of the characters - * @see strip() to remove a pattern from the left and right */ - basic_substring trim(ro_substr const chars) const - { - return triml(chars).trimr(chars); - } - - /** remove a pattern from the left - * @see triml() to remove characters*/ - basic_substring stripl(ro_substr pattern) const - { - if( ! begins_with(pattern)) - return *this; - return sub(pattern.len < len ? pattern.len : len); - } - - /** remove a pattern from the right - * @see trimr() to remove characters*/ - basic_substring stripr(ro_substr pattern) const - { - if( ! ends_with(pattern)) - return *this; - return left_of(len - (pattern.len < len ? pattern.len : len)); - } - - /** @} */ - -public: - - /** @name Lookup methods */ - /** @{ */ - - inline size_t find(const C c, size_t start_pos=0) const - { - return first_of(c, start_pos); - } - inline size_t find(ro_substr pattern, size_t start_pos=0) const - { - C4_ASSERT(start_pos == npos || (start_pos >= 0 && start_pos <= len)); - if(len < pattern.len) return npos; - for(size_t i = start_pos, e = len - pattern.len + 1; i < e; ++i) - { - bool gotit = true; - for(size_t j = 0; j < pattern.len; ++j) - { - C4_ASSERT(i + j < len); - if(str[i + j] != pattern.str[j]) - { - gotit = false; - break; - } - } - if(gotit) - { - return i; - } - } - return npos; - } - -public: - - /** count the number of occurrences of c */ - inline size_t count(const C c, size_t pos=0) const - { - C4_ASSERT(pos >= 0 && pos <= len); - size_t num = 0; - pos = find(c, pos); - while(pos != npos) - { - ++num; - pos = find(c, pos + 1); - } - return num; - } - - /** count the number of occurrences of s */ - inline size_t count(ro_substr c, size_t pos=0) const - { - C4_ASSERT(pos >= 0 && pos <= len); - size_t num = 0; - pos = find(c, pos); - while(pos != npos) - { - ++num; - pos = find(c, pos + c.len); - } - return num; - } - - /** get the substr consisting of the first occurrence of @p c after @p pos, or an empty substr if none occurs */ - inline basic_substring select(const C c, size_t pos=0) const - { - pos = find(c, pos); - return pos != npos ? sub(pos, 1) : basic_substring(); - } - - /** get the substr consisting of the first occurrence of @p pattern after @p pos, or an empty substr if none occurs */ - inline basic_substring select(ro_substr pattern, size_t pos=0) const - { - pos = find(pattern, pos); - return pos != npos ? sub(pos, pattern.len) : basic_substring(); - } - -public: - - struct first_of_any_result - { - size_t which; - size_t pos; - inline operator bool() const { return which != NONE && pos != npos; } - }; - - first_of_any_result first_of_any(ro_substr s0, ro_substr s1) const - { - ro_substr s[2] = {s0, s1}; - return first_of_any_iter(&s[0], &s[0] + 2); - } - - first_of_any_result first_of_any(ro_substr s0, ro_substr s1, ro_substr s2) const - { - ro_substr s[3] = {s0, s1, s2}; - return first_of_any_iter(&s[0], &s[0] + 3); - } - - first_of_any_result first_of_any(ro_substr s0, ro_substr s1, ro_substr s2, ro_substr s3) const - { - ro_substr s[4] = {s0, s1, s2, s3}; - return first_of_any_iter(&s[0], &s[0] + 4); - } - - first_of_any_result first_of_any(ro_substr s0, ro_substr s1, ro_substr s2, ro_substr s3, ro_substr s4) const - { - ro_substr s[5] = {s0, s1, s2, s3, s4}; - return first_of_any_iter(&s[0], &s[0] + 5); - } - - template - first_of_any_result first_of_any_iter(It first_span, It last_span) const - { - for(size_t i = 0; i < len; ++i) - { - size_t curr = 0; - for(It it = first_span; it != last_span; ++curr, ++it) - { - auto const& chars = *it; - if((i + chars.len) > len) continue; - bool gotit = true; - for(size_t j = 0; j < chars.len; ++j) - { - C4_ASSERT(i + j < len); - if(str[i + j] != chars[j]) - { - gotit = false; - break; - } - } - if(gotit) - { - return {curr, i}; - } - } - } - return {NONE, npos}; - } - -public: - - /** true if the first character of the string is @p c */ - bool begins_with(const C c) const - { - return len > 0 ? str[0] == c : false; - } - - /** true if the first @p num characters of the string are @p c */ - bool begins_with(const C c, size_t num) const - { - if(len < num) - { - return false; - } - for(size_t i = 0; i < num; ++i) - { - if(str[i] != c) - { - return false; - } - } - return true; - } - - /** true if the string begins with the given @p pattern */ - bool begins_with(ro_substr pattern) const - { - if(len < pattern.len) - { - return false; - } - for(size_t i = 0; i < pattern.len; ++i) - { - if(str[i] != pattern[i]) - { - return false; - } - } - return true; - } - - /** true if the first character of the string is any of the given @p chars */ - bool begins_with_any(ro_substr chars) const - { - if(len == 0) - { - return false; - } - for(size_t i = 0; i < chars.len; ++i) - { - if(str[0] == chars.str[i]) - { - return true; - } - } - return false; - } - - /** true if the last character of the string is @p c */ - bool ends_with(const C c) const - { - return len > 0 ? str[len-1] == c : false; - } - - /** true if the last @p num characters of the string are @p c */ - bool ends_with(const C c, size_t num) const - { - if(len < num) - { - return false; - } - for(size_t i = len - num; i < len; ++i) - { - if(str[i] != c) - { - return false; - } - } - return true; - } - - /** true if the string ends with the given @p pattern */ - bool ends_with(ro_substr pattern) const - { - if(len < pattern.len) - { - return false; - } - for(size_t i = 0, s = len-pattern.len; i < pattern.len; ++i) - { - if(str[s+i] != pattern[i]) - { - return false; - } - } - return true; - } - - /** true if the last character of the string is any of the given @p chars */ - bool ends_with_any(ro_substr chars) const - { - if(len == 0) - { - return false; - } - for(size_t i = 0; i < chars.len; ++i) - { - if(str[len - 1] == chars[i]) - { - return true; - } - } - return false; - } - -public: - - /** @return the first position where c is found in the string, or npos if none is found */ - size_t first_of(const C c, size_t start=0) const - { - C4_ASSERT(start == npos || (start >= 0 && start <= len)); - for(size_t i = start; i < len; ++i) - { - if(str[i] == c) - return i; - } - return npos; - } - - /** @return the last position where c is found in the string, or npos if none is found */ - size_t last_of(const C c, size_t start=npos) const - { - C4_ASSERT(start == npos || (start >= 0 && start <= len)); - if(start == npos) - start = len; - for(size_t i = start-1; i != size_t(-1); --i) - { - if(str[i] == c) - return i; - } - return npos; - } - - /** @return the first position where ANY of the chars is found in the string, or npos if none is found */ - size_t first_of(ro_substr chars, size_t start=0) const - { - C4_ASSERT(start == npos || (start >= 0 && start <= len)); - for(size_t i = start; i < len; ++i) - { - for(size_t j = 0; j < chars.len; ++j) - { - if(str[i] == chars[j]) - return i; - } - } - return npos; - } - - /** @return the last position where ANY of the chars is found in the string, or npos if none is found */ - size_t last_of(ro_substr chars, size_t start=npos) const - { - C4_ASSERT(start == npos || (start >= 0 && start <= len)); - if(start == npos) - start = len; - for(size_t i = start-1; i != size_t(-1); --i) - { - for(size_t j = 0; j < chars.len; ++j) - { - if(str[i] == chars[j]) - return i; - } - } - return npos; - } - -public: - - size_t first_not_of(const C c, size_t start=0) const - { - C4_ASSERT((start >= 0 && start <= len) || (start == len && len == 0)); - for(size_t i = start; i < len; ++i) - { - if(str[i] != c) - return i; - } - return npos; - } - - size_t last_not_of(const C c, size_t start=npos) const - { - C4_ASSERT(start == npos || (start >= 0 && start <= len)); - if(start == npos) - start = len; - for(size_t i = start-1; i != size_t(-1); --i) - { - if(str[i] != c) - return i; - } - return npos; - } - - size_t first_not_of(ro_substr chars, size_t start=0) const - { - C4_ASSERT((start >= 0 && start <= len) || (start == len && len == 0)); - for(size_t i = start; i < len; ++i) - { - bool gotit = true; - for(size_t j = 0; j < chars.len; ++j) - { - if(str[i] == chars.str[j]) - { - gotit = false; - break; - } - } - if(gotit) - { - return i; - } - } - return npos; - } - - size_t last_not_of(ro_substr chars, size_t start=npos) const - { - C4_ASSERT(start == npos || (start >= 0 && start <= len)); - if(start == npos) - start = len; - for(size_t i = start-1; i != size_t(-1); --i) - { - bool gotit = true; - for(size_t j = 0; j < chars.len; ++j) - { - if(str[i] == chars.str[j]) - { - gotit = false; - break; - } - } - if(gotit) - { - return i; - } - } - return npos; - } - - /** @} */ - -public: - - /** @name Range lookup methods */ - /** @{ */ - - /** get the range delimited by an open-close pair of characters. - * @note There must be no nested pairs. - * @note No checks for escapes are performed. */ - basic_substring pair_range(CC open, CC close) const - { - size_t b = find(open); - if(b == npos) - return basic_substring(); - size_t e = find(close, b+1); - if(e == npos) - return basic_substring(); - basic_substring ret = range(b, e+1); - C4_ASSERT(ret.sub(1).find(open) == npos); - return ret; - } - - /** get the range delimited by a single open-close character (eg, quotes). - * @note The open-close character can be escaped. */ - basic_substring pair_range_esc(CC open_close, CC escape=CC('\\')) - { - size_t b = find(open_close); - if(b == npos) return basic_substring(); - for(size_t i = b+1; i < len; ++i) - { - CC c = str[i]; - if(c == open_close) - { - if(str[i-1] != escape) - { - return range(b, i+1); - } - } - } - return basic_substring(); - } - - /** get the range delimited by an open-close pair of characters, - * with possibly nested occurrences. No checks for escapes are - * performed. */ - basic_substring pair_range_nested(CC open, CC close) const - { - size_t b = find(open); - if(b == npos) return basic_substring(); - size_t e, curr = b+1, count = 0; - const char both[] = {open, close, '\0'}; - while((e = first_of(both, curr)) != npos) - { - if(str[e] == open) - { - ++count; - curr = e+1; - } - else if(str[e] == close) - { - if(count == 0) return range(b, e+1); - --count; - curr = e+1; - } - } - return basic_substring(); - } - - basic_substring unquoted() const - { - constexpr const C dq('"'), sq('\''); - if(len >= 2 && (str[len - 2] != C('\\')) && - ((begins_with(sq) && ends_with(sq)) - || - (begins_with(dq) && ends_with(dq)))) - { - return range(1, len -1); - } - return *this; - } - - /** @} */ - -public: - - /** @name Number-matching query methods */ - /** @{ */ - - /** @return true if the substring contents are a floating-point or integer number. - * @note any leading or trailing whitespace will return false. */ - bool is_number() const - { - if(empty() || (first_non_empty_span().empty())) - return false; - if(first_uint_span() == *this) - return true; - if(first_int_span() == *this) - return true; - if(first_real_span() == *this) - return true; - return false; - } - - /** @return true if the substring contents are a real number. - * @note any leading or trailing whitespace will return false. */ - bool is_real() const - { - if(empty() || (first_non_empty_span().empty())) - return false; - if(first_real_span() == *this) - return true; - return false; - } - - /** @return true if the substring contents are an integer number. - * @note any leading or trailing whitespace will return false. */ - bool is_integer() const - { - if(empty() || (first_non_empty_span().empty())) - return false; - if(first_uint_span() == *this) - return true; - if(first_int_span() == *this) - return true; - return false; - } - - /** @return true if the substring contents are an unsigned integer number. - * @note any leading or trailing whitespace will return false. */ - bool is_unsigned_integer() const - { - if(empty() || (first_non_empty_span().empty())) - return false; - if(first_uint_span() == *this) - return true; - return false; - } - - /** get the first span consisting exclusively of non-empty characters */ - basic_substring first_non_empty_span() const - { - constexpr const ro_substr empty_chars(" \n\r\t"); - size_t pos = first_not_of(empty_chars); - if(pos == npos) - return first(0); - auto ret = sub(pos); - pos = ret.first_of(empty_chars); - return ret.first(pos); - } - - /** get the first span which can be interpreted as an unsigned integer */ - basic_substring first_uint_span() const - { - basic_substring ne = first_non_empty_span(); - if(ne.empty()) - return ne; - if(ne.str[0] == '-') - return first(0); - size_t skip_start = (ne.str[0] == '+') ? 1 : 0; - return ne._first_integral_span(skip_start); - } - - /** get the first span which can be interpreted as a signed integer */ - basic_substring first_int_span() const - { - basic_substring ne = first_non_empty_span(); - if(ne.empty()) - return ne; - size_t skip_start = (ne.str[0] == '+' || ne.str[0] == '-') ? 1 : 0; - return ne._first_integral_span(skip_start); - } - - basic_substring _first_integral_span(size_t skip_start) const - { - C4_ASSERT(!empty()); - if(skip_start == len) - return first(0); - C4_ASSERT(skip_start < len); - if(len >= skip_start + 3) - { - if(str[skip_start] != '0') - { - for(size_t i = skip_start; i < len; ++i) - { - char c = str[i]; - if(c < '0' || c > '9') - return i > skip_start && _is_delim_char(c) ? first(i) : first(0); - } - } - else - { - char next = str[skip_start + 1]; - if(next == 'x' || next == 'X') - { - skip_start += 2; - for(size_t i = skip_start; i < len; ++i) - { - const char c = str[i]; - if( ! _is_hex_char(c)) - return i > skip_start && _is_delim_char(c) ? first(i) : first(0); - } - return *this; - } - else if(next == 'b' || next == 'B') - { - skip_start += 2; - for(size_t i = skip_start; i < len; ++i) - { - const char c = str[i]; - if(c != '0' && c != '1') - return i > skip_start && _is_delim_char(c) ? first(i) : first(0); - } - return *this; - } - else if(next == 'o' || next == 'O') - { - skip_start += 2; - for(size_t i = skip_start; i < len; ++i) - { - const char c = str[i]; - if(c < '0' || c > '7') - return i > skip_start && _is_delim_char(c) ? first(i) : first(0); - } - return *this; - } - } - } - // must be a decimal, or it is not a an number - for(size_t i = skip_start; i < len; ++i) - { - const char c = str[i]; - if(c < '0' || c > '9') - return i > skip_start && _is_delim_char(c) ? first(i) : first(0); - } - return *this; - } - - /** get the first span which can be interpreted as a real (floating-point) number */ - basic_substring first_real_span() const - { - basic_substring ne = first_non_empty_span(); - if(ne.empty()) - return ne; - size_t skip_start = (ne.str[0] == '+' || ne.str[0] == '-'); - C4_ASSERT(skip_start == 0 || skip_start == 1); - // if we have at least three digits after the leading sign, it - // can be decimal, or hex, or bin or oct. Ex: - // non-decimal: 0x0, 0b0, 0o0 - // decimal: 1.0, 10., 1e1, 100, inf, nan, infinity - if(ne.len >= skip_start+3) - { - // if it does not have leading 0, it must be decimal, or it is not a real - if(ne.str[skip_start] != '0') - { - if(ne.str[skip_start] == 'i') // is it infinity or inf? - { - basic_substring word = ne._word_follows(skip_start + 1, "nfinity"); - if(word.len) - return word; - return ne._word_follows(skip_start + 1, "nf"); - } - else if(ne.str[skip_start] == 'n') // is it nan? - { - return ne._word_follows(skip_start + 1, "an"); - } - else // must be a decimal, or it is not a real - { - return ne._first_real_span_dec(skip_start); - } - } - else // starts with 0. is it 0x, 0b or 0o? - { - const char next = ne.str[skip_start + 1]; - // hexadecimal - if(next == 'x' || next == 'X') - return ne._first_real_span_hex(skip_start + 2); - // binary - else if(next == 'b' || next == 'B') - return ne._first_real_span_bin(skip_start + 2); - // octal - else if(next == 'o' || next == 'O') - return ne._first_real_span_oct(skip_start + 2); - // none of the above. may still be a decimal. - else - return ne._first_real_span_dec(skip_start); // do not skip the 0. - } - } - // less than 3 chars after the leading sign. It is either a - // decimal or it is not a real. (cannot be any of 0x0, etc). - return ne._first_real_span_dec(skip_start); - } - - /** true if the character is a delimiter character *at the end* */ - static constexpr C4_ALWAYS_INLINE C4_CONST bool _is_delim_char(char c) noexcept - { - return c == ' ' || c == '\n' - || c == ']' || c == ')' || c == '}' - || c == ',' || c == ';' || c == '\r' || c == '\t' || c == '\0'; - } - - /** true if the character is in [0-9a-fA-F] */ - static constexpr C4_ALWAYS_INLINE C4_CONST bool _is_hex_char(char c) noexcept - { - return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); - } - - C4_NO_INLINE C4_PURE basic_substring _word_follows(size_t pos, csubstr word) const noexcept - { - size_t posend = pos + word.len; - if(len >= posend && sub(pos, word.len) == word) - if(len == posend || _is_delim_char(str[posend])) - return first(posend); - return first(0); - } - - // this function is declared inside the class to avoid a VS error with __declspec(dllimport) - C4_NO_INLINE C4_PURE basic_substring _first_real_span_dec(size_t pos) const noexcept - { - bool intchars = false; - bool fracchars = false; - bool powchars; - // integral part - for( ; pos < len; ++pos) - { - const char c = str[pos]; - if(c >= '0' && c <= '9') - { - intchars = true; - } - else if(c == '.') - { - ++pos; - goto fractional_part_dec; - } - else if(c == 'e' || c == 'E') - { - ++pos; - goto power_part_dec; - } - else if(_is_delim_char(c)) - { - return intchars ? first(pos) : first(0); - } - else - { - return first(0); - } - } - // no . or p were found; this is either an integral number - // or not a number at all - return intchars ? - *this : - first(0); - fractional_part_dec: - C4_ASSERT(pos > 0); - C4_ASSERT(str[pos - 1] == '.'); - for( ; pos < len; ++pos) - { - const char c = str[pos]; - if(c >= '0' && c <= '9') - { - fracchars = true; - } - else if(c == 'e' || c == 'E') - { - ++pos; - goto power_part_dec; - } - else if(_is_delim_char(c)) - { - return intchars || fracchars ? first(pos) : first(0); - } - else - { - return first(0); - } - } - return intchars || fracchars ? - *this : - first(0); - power_part_dec: - C4_ASSERT(pos > 0); - C4_ASSERT(str[pos - 1] == 'e' || str[pos - 1] == 'E'); - // either a + or a - is expected here, followed by more chars. - // also, using (pos+1) in this check will cause an early - // return when no more chars follow the sign. - if(len <= (pos+1) || ((!intchars) && (!fracchars))) - return first(0); - ++pos; // this was the sign. - // ... so the (pos+1) ensures that we enter the loop and - // hence that there exist chars in the power part - powchars = false; - for( ; pos < len; ++pos) - { - const char c = str[pos]; - if(c >= '0' && c <= '9') - powchars = true; - else if(powchars && _is_delim_char(c)) - return first(pos); - else - return first(0); - } - return *this; - } - - // this function is declared inside the class to avoid a VS error with __declspec(dllimport) - C4_NO_INLINE C4_PURE basic_substring _first_real_span_hex(size_t pos) const noexcept - { - bool intchars = false; - bool fracchars = false; - bool powchars; - // integral part - for( ; pos < len; ++pos) - { - const char c = str[pos]; - if(_is_hex_char(c)) - { - intchars = true; - } - else if(c == '.') - { - ++pos; - goto fractional_part_hex; - } - else if(c == 'p' || c == 'P') - { - ++pos; - goto power_part_hex; - } - else if(_is_delim_char(c)) - { - return intchars ? first(pos) : first(0); - } - else - { - return first(0); - } - } - // no . or p were found; this is either an integral number - // or not a number at all - return intchars ? - *this : - first(0); - fractional_part_hex: - C4_ASSERT(pos > 0); - C4_ASSERT(str[pos - 1] == '.'); - for( ; pos < len; ++pos) - { - const char c = str[pos]; - if(_is_hex_char(c)) - { - fracchars = true; - } - else if(c == 'p' || c == 'P') - { - ++pos; - goto power_part_hex; - } - else if(_is_delim_char(c)) - { - return intchars || fracchars ? first(pos) : first(0); - } - else - { - return first(0); - } - } - return intchars || fracchars ? - *this : - first(0); - power_part_hex: - C4_ASSERT(pos > 0); - C4_ASSERT(str[pos - 1] == 'p' || str[pos - 1] == 'P'); - // either a + or a - is expected here, followed by more chars. - // also, using (pos+1) in this check will cause an early - // return when no more chars follow the sign. - if(len <= (pos+1) || (str[pos] != '+' && str[pos] != '-') || ((!intchars) && (!fracchars))) - return first(0); - ++pos; // this was the sign. - // ... so the (pos+1) ensures that we enter the loop and - // hence that there exist chars in the power part - powchars = false; - for( ; pos < len; ++pos) - { - const char c = str[pos]; - if(c >= '0' && c <= '9') - powchars = true; - else if(powchars && _is_delim_char(c)) - return first(pos); - else - return first(0); - } - return *this; - } - - // this function is declared inside the class to avoid a VS error with __declspec(dllimport) - C4_NO_INLINE C4_PURE basic_substring _first_real_span_bin(size_t pos) const noexcept - { - bool intchars = false; - bool fracchars = false; - bool powchars; - // integral part - for( ; pos < len; ++pos) - { - const char c = str[pos]; - if(c == '0' || c == '1') - { - intchars = true; - } - else if(c == '.') - { - ++pos; - goto fractional_part_bin; - } - else if(c == 'p' || c == 'P') - { - ++pos; - goto power_part_bin; - } - else if(_is_delim_char(c)) - { - return intchars ? first(pos) : first(0); - } - else - { - return first(0); - } - } - // no . or p were found; this is either an integral number - // or not a number at all - return intchars ? - *this : - first(0); - fractional_part_bin: - C4_ASSERT(pos > 0); - C4_ASSERT(str[pos - 1] == '.'); - for( ; pos < len; ++pos) - { - const char c = str[pos]; - if(c == '0' || c == '1') - { - fracchars = true; - } - else if(c == 'p' || c == 'P') - { - ++pos; - goto power_part_bin; - } - else if(_is_delim_char(c)) - { - return intchars || fracchars ? first(pos) : first(0); - } - else - { - return first(0); - } - } - return intchars || fracchars ? - *this : - first(0); - power_part_bin: - C4_ASSERT(pos > 0); - C4_ASSERT(str[pos - 1] == 'p' || str[pos - 1] == 'P'); - // either a + or a - is expected here, followed by more chars. - // also, using (pos+1) in this check will cause an early - // return when no more chars follow the sign. - if(len <= (pos+1) || (str[pos] != '+' && str[pos] != '-') || ((!intchars) && (!fracchars))) - return first(0); - ++pos; // this was the sign. - // ... so the (pos+1) ensures that we enter the loop and - // hence that there exist chars in the power part - powchars = false; - for( ; pos < len; ++pos) - { - const char c = str[pos]; - if(c >= '0' && c <= '9') - powchars = true; - else if(powchars && _is_delim_char(c)) - return first(pos); - else - return first(0); - } - return *this; - } - - // this function is declared inside the class to avoid a VS error with __declspec(dllimport) - C4_NO_INLINE C4_PURE basic_substring _first_real_span_oct(size_t pos) const noexcept - { - bool intchars = false; - bool fracchars = false; - bool powchars; - // integral part - for( ; pos < len; ++pos) - { - const char c = str[pos]; - if(c >= '0' && c <= '7') - { - intchars = true; - } - else if(c == '.') - { - ++pos; - goto fractional_part_oct; - } - else if(c == 'p' || c == 'P') - { - ++pos; - goto power_part_oct; - } - else if(_is_delim_char(c)) - { - return intchars ? first(pos) : first(0); - } - else - { - return first(0); - } - } - // no . or p were found; this is either an integral number - // or not a number at all - return intchars ? - *this : - first(0); - fractional_part_oct: - C4_ASSERT(pos > 0); - C4_ASSERT(str[pos - 1] == '.'); - for( ; pos < len; ++pos) - { - const char c = str[pos]; - if(c >= '0' && c <= '7') - { - fracchars = true; - } - else if(c == 'p' || c == 'P') - { - ++pos; - goto power_part_oct; - } - else if(_is_delim_char(c)) - { - return intchars || fracchars ? first(pos) : first(0); - } - else - { - return first(0); - } - } - return intchars || fracchars ? - *this : - first(0); - power_part_oct: - C4_ASSERT(pos > 0); - C4_ASSERT(str[pos - 1] == 'p' || str[pos - 1] == 'P'); - // either a + or a - is expected here, followed by more chars. - // also, using (pos+1) in this check will cause an early - // return when no more chars follow the sign. - if(len <= (pos+1) || (str[pos] != '+' && str[pos] != '-') || ((!intchars) && (!fracchars))) - return first(0); - ++pos; // this was the sign. - // ... so the (pos+1) ensures that we enter the loop and - // hence that there exist chars in the power part - powchars = false; - for( ; pos < len; ++pos) - { - const char c = str[pos]; - if(c >= '0' && c <= '9') - powchars = true; - else if(powchars && _is_delim_char(c)) - return first(pos); - else - return first(0); - } - return *this; - } - - /** @} */ - -public: - - /** @name Splitting methods */ - /** @{ */ - - /** returns true if the string has not been exhausted yet, meaning - * it's ok to call next_split() again. When no instance of sep - * exists in the string, returns the full string. When the input - * is an empty string, the output string is the empty string. */ - bool next_split(C sep, size_t *C4_RESTRICT start_pos, basic_substring *C4_RESTRICT out) const - { - if(C4_LIKELY(*start_pos < len)) - { - for(size_t i = *start_pos, e = len; i < e; i++) - { - if(str[i] == sep) - { - out->assign(str + *start_pos, i - *start_pos); - *start_pos = i+1; - return true; - } - } - out->assign(str + *start_pos, len - *start_pos); - *start_pos = len + 1; - return true; - } - else - { - bool valid = len > 0 && (*start_pos == len); - if(valid && !empty() && str[len-1] == sep) - { - out->assign(str + len, (size_t)0); // the cast is needed to prevent overload ambiguity - } - else - { - out->assign(str + len + 1, (size_t)0); // the cast is needed to prevent overload ambiguity - } - *start_pos = len + 1; - return valid; - } - } - -private: - - struct split_proxy_impl - { - struct split_iterator_impl - { - split_proxy_impl const* m_proxy; - basic_substring m_str; - size_t m_pos; - NCC_ m_sep; - - split_iterator_impl(split_proxy_impl const* proxy, size_t pos, C sep) - : m_proxy(proxy), m_pos(pos), m_sep(sep) - { - _tick(); - } - - void _tick() - { - m_proxy->m_str.next_split(m_sep, &m_pos, &m_str); - } - - split_iterator_impl& operator++ () { _tick(); return *this; } - split_iterator_impl operator++ (int) { split_iterator_impl it = *this; _tick(); return it; } - - basic_substring& operator* () { return m_str; } - basic_substring* operator-> () { return &m_str; } - - bool operator!= (split_iterator_impl const& that) const - { - return !(this->operator==(that)); - } - bool operator== (split_iterator_impl const& that) const - { - C4_XASSERT((m_sep == that.m_sep) && "cannot compare split iterators with different separators"); - if(m_str.size() != that.m_str.size()) - return false; - if(m_str.data() != that.m_str.data()) - return false; - return m_pos == that.m_pos; - } - }; - - basic_substring m_str; - size_t m_start_pos; - C m_sep; - - split_proxy_impl(basic_substring str_, size_t start_pos, C sep) - : m_str(str_), m_start_pos(start_pos), m_sep(sep) - { - } - - split_iterator_impl begin() const - { - auto it = split_iterator_impl(this, m_start_pos, m_sep); - return it; - } - split_iterator_impl end() const - { - size_t pos = m_str.size() + 1; - auto it = split_iterator_impl(this, pos, m_sep); - return it; - } - }; - -public: - - using split_proxy = split_proxy_impl; - - /** a view into the splits */ - split_proxy split(C sep, size_t start_pos=0) const - { - C4_XASSERT((start_pos >= 0 && start_pos < len) || empty()); - auto ss = sub(0, len); - auto it = split_proxy(ss, start_pos, sep); - return it; - } - -public: - - /** pop right: return the first split from the right. Use - * gpop_left() to get the reciprocal part. - */ - basic_substring pop_right(C sep=C('/'), bool skip_empty=false) const - { - if(C4_LIKELY(len > 1)) - { - auto pos = last_of(sep); - if(pos != npos) - { - if(pos + 1 < len) // does not end with sep - { - return sub(pos + 1); // return from sep to end - } - else // the string ends with sep - { - if( ! skip_empty) - { - return sub(pos + 1, 0); - } - auto ppos = last_not_of(sep); // skip repeated seps - if(ppos == npos) // the string is all made of seps - { - return sub(0, 0); - } - // find the previous sep - auto pos0 = last_of(sep, ppos); - if(pos0 == npos) // only the last sep exists - { - return sub(0); // return the full string (because skip_empty is true) - } - ++pos0; - return sub(pos0); - } - } - else // no sep was found, return the full string - { - return *this; - } - } - else if(len == 1) - { - if(begins_with(sep)) - { - return sub(0, 0); - } - return *this; - } - else // an empty string - { - return basic_substring(); - } - } - - /** return the first split from the left. Use gpop_right() to get - * the reciprocal part. */ - basic_substring pop_left(C sep = C('/'), bool skip_empty=false) const - { - if(C4_LIKELY(len > 1)) - { - auto pos = first_of(sep); - if(pos != npos) - { - if(pos > 0) // does not start with sep - { - return sub(0, pos); // return everything up to it - } - else // the string starts with sep - { - if( ! skip_empty) - { - return sub(0, 0); - } - auto ppos = first_not_of(sep); // skip repeated seps - if(ppos == npos) // the string is all made of seps - { - return sub(0, 0); - } - // find the next sep - auto pos0 = first_of(sep, ppos); - if(pos0 == npos) // only the first sep exists - { - return sub(0); // return the full string (because skip_empty is true) - } - C4_XASSERT(pos0 > 0); - // return everything up to the second sep - return sub(0, pos0); - } - } - else // no sep was found, return the full string - { - return sub(0); - } - } - else if(len == 1) - { - if(begins_with(sep)) - { - return sub(0, 0); - } - return sub(0); - } - else // an empty string - { - return basic_substring(); - } - } - -public: - - /** greedy pop left. eg, csubstr("a/b/c").gpop_left('/')="c" */ - basic_substring gpop_left(C sep = C('/'), bool skip_empty=false) const - { - auto ss = pop_right(sep, skip_empty); - ss = left_of(ss); - if(ss.find(sep) != npos) - { - if(ss.ends_with(sep)) - { - if(skip_empty) - { - ss = ss.trimr(sep); - } - else - { - ss = ss.sub(0, ss.len-1); // safe to subtract because ends_with(sep) is true - } - } - } - return ss; - } - - /** greedy pop right. eg, csubstr("a/b/c").gpop_right('/')="a" */ - basic_substring gpop_right(C sep = C('/'), bool skip_empty=false) const - { - auto ss = pop_left(sep, skip_empty); - ss = right_of(ss); - if(ss.find(sep) != npos) - { - if(ss.begins_with(sep)) - { - if(skip_empty) - { - ss = ss.triml(sep); - } - else - { - ss = ss.sub(1); - } - } - } - return ss; - } - - /** @} */ - -public: - - /** @name Path-like manipulation methods */ - /** @{ */ - - basic_substring basename(C sep=C('/')) const - { - auto ss = pop_right(sep, /*skip_empty*/true); - ss = ss.trimr(sep); - return ss; - } - - basic_substring dirname(C sep=C('/')) const - { - auto ss = basename(sep); - ss = ss.empty() ? *this : left_of(ss); - return ss; - } - - C4_ALWAYS_INLINE basic_substring name_wo_extshort() const - { - return gpop_left('.'); - } - - C4_ALWAYS_INLINE basic_substring name_wo_extlong() const - { - return pop_left('.'); - } - - C4_ALWAYS_INLINE basic_substring extshort() const - { - return pop_right('.'); - } - - C4_ALWAYS_INLINE basic_substring extlong() const - { - return gpop_right('.'); - } - - /** @} */ - -public: - - /** @name Content-modification methods (only for non-const C) */ - /** @{ */ - - /** convert the string to upper-case - * @note this method requires that the string memory is writeable and is SFINAEd out for const C */ - C4_REQUIRE_RW(void) toupper() - { - for(size_t i = 0; i < len; ++i) - { - str[i] = static_cast(::toupper(str[i])); - } - } - - /** convert the string to lower-case - * @note this method requires that the string memory is writeable and is SFINAEd out for const C */ - C4_REQUIRE_RW(void) tolower() - { - for(size_t i = 0; i < len; ++i) - { - str[i] = static_cast(::tolower(str[i])); - } - } - -public: - - /** fill the entire contents with the given @p val - * @note this method requires that the string memory is writeable and is SFINAEd out for const C */ - C4_REQUIRE_RW(void) fill(C val) - { - for(size_t i = 0; i < len; ++i) - { - str[i] = val; - } - } - -public: - - /** set the current substring to a copy of the given csubstr - * @note this method requires that the string memory is writeable and is SFINAEd out for const C */ - C4_REQUIRE_RW(void) copy_from(ro_substr that, size_t ifirst=0, size_t num=npos) - { - C4_ASSERT(ifirst >= 0 && ifirst <= len); - num = num != npos ? num : len - ifirst; - num = num < that.len ? num : that.len; - C4_ASSERT(ifirst + num >= 0 && ifirst + num <= len); - // calling memcpy with null strings is undefined behavior - // and will wreak havoc in calling code's branches. - // see https://github.com/biojppm/rapidyaml/pull/264#issuecomment-1262133637 - if(num) - memcpy(str + sizeof(C) * ifirst, that.str, sizeof(C) * num); - } - -public: - - /** reverse in place - * @note this method requires that the string memory is writeable and is SFINAEd out for const C */ - C4_REQUIRE_RW(void) reverse() - { - if(len == 0) return; - detail::_do_reverse(str, str + len - 1); - } - - /** revert a subpart in place - * @note this method requires that the string memory is writeable and is SFINAEd out for const C */ - C4_REQUIRE_RW(void) reverse_sub(size_t ifirst, size_t num) - { - C4_ASSERT(ifirst >= 0 && ifirst <= len); - C4_ASSERT(ifirst + num >= 0 && ifirst + num <= len); - if(num == 0) return; - detail::_do_reverse(str + ifirst, str + ifirst + num - 1); - } - - /** revert a range in place - * @note this method requires that the string memory is writeable and is SFINAEd out for const C */ - C4_REQUIRE_RW(void) reverse_range(size_t ifirst, size_t ilast) - { - C4_ASSERT(ifirst >= 0 && ifirst <= len); - C4_ASSERT(ilast >= 0 && ilast <= len); - if(ifirst == ilast) return; - detail::_do_reverse(str + ifirst, str + ilast - 1); - } - -public: - - /** erase part of the string. eg, with char s[] = "0123456789", - * substr(s).erase(3, 2) = "01256789", and s is now "01245678989" - * @note this method requires that the string memory is writeable and is SFINAEd out for const C */ - C4_REQUIRE_RW(basic_substring) erase(size_t pos, size_t num) - { - C4_ASSERT(pos >= 0 && pos+num <= len); - size_t num_to_move = len - pos - num; - memmove(str + pos, str + pos + num, sizeof(C) * num_to_move); - return basic_substring{str, len - num}; - } - - /** @note this method requires that the string memory is writeable and is SFINAEd out for const C */ - C4_REQUIRE_RW(basic_substring) erase_range(size_t first, size_t last) - { - C4_ASSERT(first <= last); - return erase(first, static_cast(last-first)); - } - - /** erase a part of the string. - * @note @p sub must be a substring of this string - * @note this method requires that the string memory is writeable and is SFINAEd out for const C */ - C4_REQUIRE_RW(basic_substring) erase(ro_substr sub) - { - C4_ASSERT(is_super(sub)); - C4_ASSERT(sub.str >= str); - return erase(static_cast(sub.str - str), sub.len); - } - -public: - - /** replace every occurrence of character @p value with the character @p repl - * @return the number of characters that were replaced - * @note this method requires that the string memory is writeable and is SFINAEd out for const C */ - C4_REQUIRE_RW(size_t) replace(C value, C repl, size_t pos=0) - { - C4_ASSERT((pos >= 0 && pos <= len) || pos == npos); - size_t did_it = 0; - while((pos = find(value, pos)) != npos) - { - str[pos++] = repl; - ++did_it; - } - return did_it; - } - - /** replace every occurrence of each character in @p value with - * the character @p repl. - * @return the number of characters that were replaced - * @note this method requires that the string memory is writeable and is SFINAEd out for const C */ - C4_REQUIRE_RW(size_t) replace(ro_substr chars, C repl, size_t pos=0) - { - C4_ASSERT((pos >= 0 && pos <= len) || pos == npos); - size_t did_it = 0; - while((pos = first_of(chars, pos)) != npos) - { - str[pos++] = repl; - ++did_it; - } - return did_it; - } - - /** replace @p pattern with @p repl, and write the result into - * @dst. pattern and repl don't need equal sizes. - * - * @return the required size for dst. No overflow occurs if - * dst.len is smaller than the required size; this can be used to - * determine the required size for an existing container. */ - size_t replace_all(rw_substr dst, ro_substr pattern, ro_substr repl, size_t pos=0) const - { - C4_ASSERT( ! pattern.empty()); //!< @todo relax this precondition - C4_ASSERT( ! this ->overlaps(dst)); //!< @todo relax this precondition - C4_ASSERT( ! pattern.overlaps(dst)); - C4_ASSERT( ! repl .overlaps(dst)); - C4_ASSERT((pos >= 0 && pos <= len) || pos == npos); - C4_SUPPRESS_WARNING_GCC_PUSH - C4_SUPPRESS_WARNING_GCC("-Warray-bounds") // gcc11 has a false positive here - #if (!defined(__clang__)) && (defined(__GNUC__) && (__GNUC__ >= 7)) - C4_SUPPRESS_WARNING_GCC("-Wstringop-overflow") // gcc11 has a false positive here - #endif - #define _c4append(first, last) \ - { \ - C4_ASSERT((last) >= (first)); \ - size_t num = static_cast((last) - (first)); \ - if(num > 0 && sz + num <= dst.len) \ - { \ - memcpy(dst.str + sz, first, num * sizeof(C)); \ - } \ - sz += num; \ - } - size_t sz = 0; - size_t b = pos; - _c4append(str, str + pos); - do { - size_t e = find(pattern, b); - if(e == npos) - { - _c4append(str + b, str + len); - break; - } - _c4append(str + b, str + e); - _c4append(repl.begin(), repl.end()); - b = e + pattern.size(); - } while(b < len && b != npos); - return sz; - #undef _c4append - C4_SUPPRESS_WARNING_GCC_POP - } - - /** @} */ - -}; // template class basic_substring - - -#undef C4_REQUIRE_RW -#undef C4_REQUIRE_RO -#undef C4_NC2C - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -/** Because of a C++ limitation, substr cannot provide simultaneous - * overloads for constructing from a char[N] and a char*; the latter - * will always be chosen by the compiler. So this specialization is - * provided to simplify obtaining a substr from a char*. Being a - * function has the advantage of highlighting the strlen() cost. - * - * @see to_csubstr - * @see For a more detailed explanation on why the overloads cannot - * coexist, see http://cplusplus.bordoon.com/specializeForCharacterArrays.html */ -inline substr to_substr(char *s) -{ - return substr(s, s ? strlen(s) : 0); -} - -/** Because of a C++ limitation, substr cannot provide simultaneous - * overloads for constructing from a char[N] and a char*; the latter - * will always be chosen by the compiler. So this specialization is - * provided to simplify obtaining a substr from a char*. Being a - * function has the advantage of highlighting the strlen() cost. - * - * @see to_substr - * @see For a more detailed explanation on why the overloads cannot - * coexist, see http://cplusplus.bordoon.com/specializeForCharacterArrays.html */ -inline csubstr to_csubstr(char *s) -{ - return csubstr(s, s ? strlen(s) : 0); -} - -/** Because of a C++ limitation, substr cannot provide simultaneous - * overloads for constructing from a const char[N] and a const char*; - * the latter will always be chosen by the compiler. So this - * specialization is provided to simplify obtaining a substr from a - * char*. Being a function has the advantage of highlighting the - * strlen() cost. - * - * @overload to_csubstr - * @see to_substr - * @see For a more detailed explanation on why the overloads cannot - * coexist, see http://cplusplus.bordoon.com/specializeForCharacterArrays.html */ -inline csubstr to_csubstr(const char *s) -{ - return csubstr(s, s ? strlen(s) : 0); -} - - -/** neutral version for use in generic code */ -inline csubstr to_csubstr(csubstr s) -{ - return s; -} - -/** neutral version for use in generic code */ -inline csubstr to_csubstr(substr s) -{ - return s; -} - -/** neutral version for use in generic code */ -inline substr to_substr(substr s) -{ - return s; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -template inline bool operator== (const C (&s)[N], basic_substring const that) { return that.compare(s) == 0; } -template inline bool operator!= (const C (&s)[N], basic_substring const that) { return that.compare(s) != 0; } -template inline bool operator< (const C (&s)[N], basic_substring const that) { return that.compare(s) > 0; } -template inline bool operator> (const C (&s)[N], basic_substring const that) { return that.compare(s) < 0; } -template inline bool operator<= (const C (&s)[N], basic_substring const that) { return that.compare(s) >= 0; } -template inline bool operator>= (const C (&s)[N], basic_substring const that) { return that.compare(s) <= 0; } - -template inline bool operator== (C const c, basic_substring const that) { return that.compare(c) == 0; } -template inline bool operator!= (C const c, basic_substring const that) { return that.compare(c) != 0; } -template inline bool operator< (C const c, basic_substring const that) { return that.compare(c) > 0; } -template inline bool operator> (C const c, basic_substring const that) { return that.compare(c) < 0; } -template inline bool operator<= (C const c, basic_substring const that) { return that.compare(c) >= 0; } -template inline bool operator>= (C const c, basic_substring const that) { return that.compare(c) <= 0; } - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -/** @define C4_SUBSTR_NO_OSTREAM_LSHIFT doctest does not deal well with - * template operator<< - * @see https://github.com/onqtam/doctest/pull/431 */ -#ifndef C4_SUBSTR_NO_OSTREAM_LSHIFT -#ifdef __clang__ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wsign-conversion" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wsign-conversion" -#endif - -/** output the string to a stream */ -template -inline OStream& operator<< (OStream& os, basic_substring s) -{ - os.write(s.str, s.len); - return os; -} - -// this causes ambiguity -///** this is used by google test */ -//template -//inline void PrintTo(basic_substring s, OStream* os) -//{ -// os->write(s.str, s.len); -//} - -#ifdef __clang__ -# pragma clang diagnostic pop -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#endif -#endif // !C4_SUBSTR_NO_OSTREAM_LSHIFT - -} // namespace c4 - - -#ifdef __clang__ -# pragma clang diagnostic pop -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#endif - -#endif /* _C4_SUBSTR_HPP_ */ diff --git a/thirdparty/ryml/ext/c4core/src/c4/substr_fwd.hpp b/thirdparty/ryml/ext/c4core/src/c4/substr_fwd.hpp deleted file mode 100644 index 63d01b595..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/substr_fwd.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _C4_SUBSTR_FWD_HPP_ -#define _C4_SUBSTR_FWD_HPP_ - -#include "c4/export.hpp" - -namespace c4 { - -#ifndef DOXYGEN -template struct basic_substring; -using csubstr = C4CORE_EXPORT basic_substring; -using substr = C4CORE_EXPORT basic_substring; -#endif // !DOXYGEN - -} // namespace c4 - -#endif /* _C4_SUBSTR_FWD_HPP_ */ diff --git a/thirdparty/ryml/ext/c4core/src/c4/szconv.hpp b/thirdparty/ryml/ext/c4core/src/c4/szconv.hpp deleted file mode 100644 index 76cec1146..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/szconv.hpp +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef _C4_SZCONV_HPP_ -#define _C4_SZCONV_HPP_ - -/** @file szconv.hpp utilities to deal safely with narrowing conversions */ - -#include "c4/config.hpp" -#include "c4/error.hpp" - -#include - -namespace c4 { - -/** @todo this would be so much easier with calls to numeric_limits::max()... */ -template -struct is_narrower_size : std::conditional -< - (std::is_signed::value == std::is_signed::value) - ? - (sizeof(SizeOut) < sizeof(SizeIn)) - : - ( - (sizeof(SizeOut) < sizeof(SizeIn)) - || - ( - (sizeof(SizeOut) == sizeof(SizeIn)) - && - (std::is_signed::value && std::is_unsigned::value) - ) - ), - std::true_type, - std::false_type ->::type -{ - static_assert(std::is_integral::value, "must be integral type"); - static_assert(std::is_integral::value, "must be integral type"); -}; - - -/** when SizeOut is wider than SizeIn, assignment can occur without reservations */ -template -C4_ALWAYS_INLINE -typename std::enable_if< ! is_narrower_size::value, SizeOut>::type -szconv(SizeIn sz) noexcept -{ - return static_cast(sz); -} - -/** when SizeOut is narrower than SizeIn, narrowing will occur, so we check - * for overflow. Note that this check is done only if C4_XASSERT is enabled. - * @see C4_XASSERT */ -template -C4_ALWAYS_INLINE -typename std::enable_if::value, SizeOut>::type -szconv(SizeIn sz) C4_NOEXCEPT_X -{ - C4_XASSERT(sz >= 0); - C4_XASSERT_MSG((SizeIn)sz <= (SizeIn)std::numeric_limits::max(), "size conversion overflow: in=%zu", (size_t)sz); - SizeOut szo = static_cast(sz); - return szo; -} - -} // namespace c4 - -#endif /* _C4_SZCONV_HPP_ */ diff --git a/thirdparty/ryml/ext/c4core/src/c4/type_name.hpp b/thirdparty/ryml/ext/c4core/src/c4/type_name.hpp deleted file mode 100644 index 41f13562b..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/type_name.hpp +++ /dev/null @@ -1,125 +0,0 @@ -#ifndef _C4_TYPENAME_HPP_ -#define _C4_TYPENAME_HPP_ - -/** @file type_name.hpp compile-time type name */ - -#include "c4/span.hpp" - -/// @cond dev -struct _c4t -{ - const char *str; - size_t sz; - template - constexpr _c4t(const char (&s)[N]) : str(s), sz(N-1) {} // take off the \0 -}; -// this is a more abbreviated way of getting the type name -// (if we used span in the return type, the name would involve -// templates and would create longer type name strings, -// as well as larger differences between compilers) -template -C4_CONSTEXPR14 C4_ALWAYS_INLINE -_c4t _c4tn() -{ - auto p = _c4t(C4_PRETTY_FUNC); - return p; -} -/// @endcond - - -namespace c4 { - -/** compile-time type name - * @see http://stackoverflow.com/a/20170989/5875572 */ -template -C4_CONSTEXPR14 cspan type_name() -{ - const _c4t p = _c4tn(); - -#if (0) // _C4_THIS_IS_A_DEBUG_SCAFFOLD - for(size_t index = 0; index < p.sz; ++index) - { - printf(" %2c", p.str[index]); - } - printf("\n"); - for(size_t index = 0; index < p.sz; ++index) - { - printf(" %2d", (int)index); - } - printf("\n"); -#endif - -#if defined(_MSC_VER) -# if defined(__clang__) // Visual Studio has the clang toolset - // example: - // ..........................xxx. - // _c4t __cdecl _c4tn() [T = int] - enum : size_t { tstart = 26, tend = 1}; - -# elif defined(C4_MSVC_2015) || defined(C4_MSVC_2017) || defined(C4_MSVC_2019) || defined(C4_MSVC_2022) - // Note: subtract 7 at the end because the function terminates with ">(void)" in VS2015+ - cspan::size_type tstart = 26, tend = 7; - - const char *s = p.str + tstart; // look at the start - - // we're not using strcmp() or memcmp() to spare the #include - - // does it start with 'class '? - if(p.sz > 6 && s[0] == 'c' && s[1] == 'l' && s[2] == 'a' && s[3] == 's' && s[4] == 's' && s[5] == ' ') - { - tstart += 6; - } - // does it start with 'struct '? - else if(p.sz > 7 && s[0] == 's' && s[1] == 't' && s[2] == 'r' && s[3] == 'u' && s[4] == 'c' && s[5] == 't' && s[6] == ' ') - { - tstart += 7; - } - -# else - C4_NOT_IMPLEMENTED(); -# endif - -#elif defined(__ICC) - // example: - // ........................xxx. - // "_c4t _c4tn() [with T = int]" - enum : size_t { tstart = 23, tend = 1}; - -#elif defined(__clang__) - // example: - // ...................xxx. - // "_c4t _c4tn() [T = int]" - enum : size_t { tstart = 18, tend = 1}; - -#elif defined(__GNUC__) - #if __GNUC__ >= 7 && C4_CPP >= 14 - // example: - // ..................................xxx. - // "constexpr _c4t _c4tn() [with T = int]" - enum : size_t { tstart = 33, tend = 1 }; - #else - // example: - // ........................xxx. - // "_c4t _c4tn() [with T = int]" - enum : size_t { tstart = 23, tend = 1 }; - #endif -#else - C4_NOT_IMPLEMENTED(); -#endif - - cspan o(p.str + tstart, p.sz - tstart - tend); - - return o; -} - -/** compile-time type name - * @overload */ -template -C4_CONSTEXPR14 C4_ALWAYS_INLINE cspan type_name(T const&) -{ - return type_name(); -} - -} // namespace c4 - -#endif //_C4_TYPENAME_HPP_ diff --git a/thirdparty/ryml/ext/c4core/src/c4/types.hpp b/thirdparty/ryml/ext/c4core/src/c4/types.hpp deleted file mode 100644 index 394a808fd..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/types.hpp +++ /dev/null @@ -1,492 +0,0 @@ -#ifndef _C4_TYPES_HPP_ -#define _C4_TYPES_HPP_ - -#include -#include -#include - -#if __cplusplus >= 201103L -#include // for integer_sequence and friends -#endif - -#include "c4/preprocessor.hpp" -#include "c4/language.hpp" - -/** @file types.hpp basic types, and utility macros and traits for types. - * @ingroup basic_headers */ - -/** @defgroup types Type utilities */ - -namespace c4 { - -/** @defgroup intrinsic_types Intrinsic types - * @ingroup types - * @{ */ - -using cbyte = const char; /**< a constant byte */ -using byte = char; /**< a mutable byte */ - -using i8 = int8_t; -using i16 = int16_t; -using i32 = int32_t; -using i64 = int64_t; -using u8 = uint8_t; -using u16 = uint16_t; -using u32 = uint32_t; -using u64 = uint64_t; - -using f32 = float; -using f64 = double; - -using ssize_t = typename std::make_signed::type; - -/** @} */ - -//-------------------------------------------------- - -/** @defgroup utility_types Utility types - * @ingroup types - * @{ */ - -// some tag types - -/** a tag type for initializing the containers with variadic arguments a la - * initializer_list, minus the initializer_list overload problems. - */ -struct aggregate_t {}; -/** @see aggregate_t */ -constexpr const aggregate_t aggregate{}; - -/** a tag type for specifying the initial capacity of allocatable contiguous storage */ -struct with_capacity_t {}; -/** @see with_capacity_t */ -constexpr const with_capacity_t with_capacity{}; - -/** a tag type for disambiguating template parameter packs in variadic template overloads */ -struct varargs_t {}; -/** @see with_capacity_t */ -constexpr const varargs_t varargs{}; - - -//-------------------------------------------------- - -/** whether a value should be used in place of a const-reference in argument passing. */ -template -struct cref_uses_val -{ - enum { value = ( - std::is_scalar::value - || - ( -#if C4_CPP >= 20 - (std::is_trivially_copyable::value && std::is_standard_layout::value) -#else - std::is_pod::value -#endif - && - sizeof(T) <= sizeof(size_t))) }; -}; -/** utility macro to override the default behaviour for c4::fastcref - @see fastcref */ -#define C4_CREF_USES_VAL(T) \ -template<> \ -struct cref_uses_val \ -{ \ - enum { value = true }; \ -}; - -/** Whether to use pass-by-value or pass-by-const-reference in a function argument - * or return type. */ -template -using fastcref = typename std::conditional::value, T, T const&>::type; - -//-------------------------------------------------- - -/** Just what its name says. Useful sometimes as a default empty policy class. */ -struct EmptyStruct -{ - template EmptyStruct(T && ...){} -}; - -/** Just what its name says. Useful sometimes as a default policy class to - * be inherited from. */ -struct EmptyStructVirtual -{ - virtual ~EmptyStructVirtual() = default; - template EmptyStructVirtual(T && ...){} -}; - - -/** */ -template -struct inheritfrom : public T {}; - -//-------------------------------------------------- -// Utilities to make a class obey size restrictions (eg, min size or size multiple of). -// DirectX usually makes this restriction with uniform buffers. -// This is also useful for padding to prevent false-sharing. - -/** how many bytes must be added to size such that the result is at least minsize? */ -C4_ALWAYS_INLINE constexpr size_t min_remainder(size_t size, size_t minsize) noexcept -{ - return size < minsize ? minsize-size : 0; -} - -/** how many bytes must be added to size such that the result is a multiple of multipleof? */ -C4_ALWAYS_INLINE constexpr size_t mult_remainder(size_t size, size_t multipleof) noexcept -{ - return (((size % multipleof) != 0) ? (multipleof-(size % multipleof)) : 0); -} - -/* force the following class to be tightly packed. */ -#pragma pack(push, 1) -/** pad a class with more bytes at the end. - * @see http://stackoverflow.com/questions/21092415/force-c-structure-to-pack-tightly */ -template -struct Padded : public T -{ - using T::T; - using T::operator=; - Padded(T const& val) : T(val) {} - Padded(T && val) : T(val) {} - char ___c4padspace___[BytesToPadAtEnd]; -}; -#pragma pack(pop) -/** When the padding argument is 0, we cannot declare the char[] array. */ -template -struct Padded : public T -{ - using T::T; - using T::operator=; - Padded(T const& val) : T(val) {} - Padded(T && val) : T(val) {} -}; - -/** make T have a size which is at least Min bytes */ -template -using MinSized = Padded; - -/** make T have a size which is a multiple of Mult bytes */ -template -using MultSized = Padded; - -/** make T have a size which is simultaneously: - * -bigger or equal than Min - * -a multiple of Mult */ -template -using MinMultSized = MultSized, Mult>; - -/** make T be suitable for use as a uniform buffer. (at least with DirectX). */ -template -using UbufSized = MinMultSized; - - -//----------------------------------------------------------------------------- - -#define C4_NO_COPY_CTOR(ty) ty(ty const&) = delete -#define C4_NO_MOVE_CTOR(ty) ty(ty &&) = delete -#define C4_NO_COPY_ASSIGN(ty) ty& operator=(ty const&) = delete -#define C4_NO_MOVE_ASSIGN(ty) ty& operator=(ty &&) = delete -#define C4_DEFAULT_COPY_CTOR(ty) ty(ty const&) noexcept = default -#define C4_DEFAULT_MOVE_CTOR(ty) ty(ty &&) noexcept = default -#define C4_DEFAULT_COPY_ASSIGN(ty) ty& operator=(ty const&) noexcept = default -#define C4_DEFAULT_MOVE_ASSIGN(ty) ty& operator=(ty &&) noexcept = default - -#define C4_NO_COPY_OR_MOVE_CTOR(ty) \ - C4_NO_COPY_CTOR(ty); \ - C4_NO_MOVE_CTOR(ty) - -#define C4_NO_COPY_OR_MOVE_ASSIGN(ty) \ - C4_NO_COPY_ASSIGN(ty); \ - C4_NO_MOVE_ASSIGN(ty) - -#define C4_NO_COPY_OR_MOVE(ty) \ - C4_NO_COPY_OR_MOVE_CTOR(ty); \ - C4_NO_COPY_OR_MOVE_ASSIGN(ty) - -#define C4_DEFAULT_COPY_AND_MOVE_CTOR(ty) \ - C4_DEFAULT_COPY_CTOR(ty); \ - C4_DEFAULT_MOVE_CTOR(ty) - -#define C4_DEFAULT_COPY_AND_MOVE_ASSIGN(ty) \ - C4_DEFAULT_COPY_ASSIGN(ty); \ - C4_DEFAULT_MOVE_ASSIGN(ty) - -#define C4_DEFAULT_COPY_AND_MOVE(ty) \ - C4_DEFAULT_COPY_AND_MOVE_CTOR(ty); \ - C4_DEFAULT_COPY_AND_MOVE_ASSIGN(ty) - -/** @see https://en.cppreference.com/w/cpp/named_req/TriviallyCopyable */ -#define C4_MUST_BE_TRIVIAL_COPY(ty) \ - static_assert(std::is_trivially_copyable::value, #ty " must be trivially copyable") - -/** @} */ - - -//----------------------------------------------------------------------------- - -/** @defgroup traits_types Type traits utilities - * @ingroup types - * @{ */ - -// http://stackoverflow.com/questions/10821380/is-t-an-instance-of-a-template-in-c -template class X, typename T> struct is_instance_of_tpl : std::false_type {}; -template class X, typename... Y> struct is_instance_of_tpl> : std::true_type {}; - -//----------------------------------------------------------------------------- - -/** SFINAE. use this macro to enable a template function overload -based on a compile-time condition. -@code -// define an overload for a non-pod type -template::value)> -void foo() { std::cout << "pod type\n"; } - -// define an overload for a non-pod type -template::value)> -void foo() { std::cout << "nonpod type\n"; } - -struct non_pod -{ - non_pod() : name("asdfkjhasdkjh") {} - const char *name; -}; - -int main() -{ - foo(); // prints "pod type" - foo(); // prints "nonpod type" -} -@endcode */ -#define C4_REQUIRE_T(cond) typename std::enable_if::type* = nullptr - -/** enable_if for a return type - * @see C4_REQUIRE_T */ -#define C4_REQUIRE_R(cond, type_) typename std::enable_if::type - -//----------------------------------------------------------------------------- -/** define a traits class reporting whether a type provides a member typedef */ -#define C4_DEFINE_HAS_TYPEDEF(member_typedef) \ -template \ -struct has_##stype \ -{ \ -private: \ - \ - typedef char yes; \ - typedef struct { char array[2]; } no; \ - \ - template \ - static yes _test(typename C::member_typedef*); \ - \ - template \ - static no _test(...); \ - \ -public: \ - \ - enum { value = (sizeof(_test(0)) == sizeof(yes)) }; \ - \ -} - - -/** @} */ - - -//----------------------------------------------------------------------------- - - -/** @defgroup type_declarations Type declaration utilities - * @ingroup types - * @{ */ - -#define _c4_DEFINE_ARRAY_TYPES_WITHOUT_ITERATOR(T, I) \ - \ - using size_type = I; \ - using ssize_type = typename std::make_signed::type; \ - using difference_type = typename std::make_signed::type; \ - \ - using value_type = T; \ - using pointer = T*; \ - using const_pointer = T const*; \ - using reference = T&; \ - using const_reference = T const& - -#define _c4_DEFINE_TUPLE_ARRAY_TYPES_WITHOUT_ITERATOR(interior_types, I) \ - \ - using size_type = I; \ - using ssize_type = typename std::make_signed::type; \ - using difference_type = typename std::make_signed::type; \ - \ - template using value_type = typename std::tuple_element< n, std::tuple>::type; \ - template using pointer = value_type*; \ - template using const_pointer = value_type const*; \ - template using reference = value_type&; \ - template using const_reference = value_type const& - - -#define _c4_DEFINE_ARRAY_TYPES(T, I) \ - \ - _c4_DEFINE_ARRAY_TYPES_WITHOUT_ITERATOR(T, I); \ - \ - using iterator = T*; \ - using const_iterator = T const*; \ - using reverse_iterator = std::reverse_iterator; \ - using const_reverse_iterator = std::reverse_iterator - - -#define _c4_DEFINE_TUPLE_ARRAY_TYPES(interior_types, I) \ - \ - _c4_DEFINE_TUPLE_ARRAY_TYPES_WITHOUT_ITERATOR(interior_types, I); \ - \ - template using iterator = value_type*; \ - template using const_iterator = value_type const*; \ - template using reverse_iterator = std::reverse_iterator< value_type*>; \ - template using const_reverse_iterator = std::reverse_iterator< value_type const*> - - - -/** @} */ - - -//----------------------------------------------------------------------------- - - -/** @defgroup compatility_utilities Backport implementation of some Modern C++ utilities - * @ingroup types - * @{ */ - -//----------------------------------------------------------------------------- -// index_sequence and friends are available only for C++14 and later. -// A C++11 implementation is provided here. -// This implementation was copied over from clang. -// see http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/utility?revision=211563&view=markup#l687 - -#if __cplusplus > 201103L - -using std::integer_sequence; -using std::index_sequence; -using std::make_integer_sequence; -using std::make_index_sequence; -using std::index_sequence_for; - -#else - -/** C++11 implementation of integer sequence - * @see https://en.cppreference.com/w/cpp/utility/integer_sequence - * @see taken from clang: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/utility?revision=211563&view=markup#l687 */ -template -struct integer_sequence -{ - static_assert(std::is_integral<_Tp>::value, - "std::integer_sequence can only be instantiated with an integral type" ); - using value_type = _Tp; - static constexpr size_t size() noexcept { return sizeof...(_Ip); } -}; - -/** C++11 implementation of index sequence - * @see https://en.cppreference.com/w/cpp/utility/integer_sequence - * @see taken from clang: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/utility?revision=211563&view=markup#l687 */ -template -using index_sequence = integer_sequence; - -/** @cond DONT_DOCUMENT_THIS */ -namespace __detail { - -template -struct __repeat; - -template -struct __repeat, _Extra...> -{ - using type = integer_sequence<_Tp, - _Np..., - sizeof...(_Np) + _Np..., - 2 * sizeof...(_Np) + _Np..., - 3 * sizeof...(_Np) + _Np..., - 4 * sizeof...(_Np) + _Np..., - 5 * sizeof...(_Np) + _Np..., - 6 * sizeof...(_Np) + _Np..., - 7 * sizeof...(_Np) + _Np..., - _Extra...>; -}; - -template struct __parity; -template struct __make : __parity<_Np % 8>::template __pmake<_Np> {}; - -template<> struct __make<0> { using type = integer_sequence; }; -template<> struct __make<1> { using type = integer_sequence; }; -template<> struct __make<2> { using type = integer_sequence; }; -template<> struct __make<3> { using type = integer_sequence; }; -template<> struct __make<4> { using type = integer_sequence; }; -template<> struct __make<5> { using type = integer_sequence; }; -template<> struct __make<6> { using type = integer_sequence; }; -template<> struct __make<7> { using type = integer_sequence; }; - -template<> struct __parity<0> { template struct __pmake : __repeat::type> {}; }; -template<> struct __parity<1> { template struct __pmake : __repeat::type, _Np - 1> {}; }; -template<> struct __parity<2> { template struct __pmake : __repeat::type, _Np - 2, _Np - 1> {}; }; -template<> struct __parity<3> { template struct __pmake : __repeat::type, _Np - 3, _Np - 2, _Np - 1> {}; }; -template<> struct __parity<4> { template struct __pmake : __repeat::type, _Np - 4, _Np - 3, _Np - 2, _Np - 1> {}; }; -template<> struct __parity<5> { template struct __pmake : __repeat::type, _Np - 5, _Np - 4, _Np - 3, _Np - 2, _Np - 1> {}; }; -template<> struct __parity<6> { template struct __pmake : __repeat::type, _Np - 6, _Np - 5, _Np - 4, _Np - 3, _Np - 2, _Np - 1> {}; }; -template<> struct __parity<7> { template struct __pmake : __repeat::type, _Np - 7, _Np - 6, _Np - 5, _Np - 4, _Np - 3, _Np - 2, _Np - 1> {}; }; - -template -struct __convert -{ - template struct __result; - template<_Tp ..._Np> struct __result> - { - using type = integer_sequence<_Up, _Np...>; - }; -}; - -template -struct __convert<_Tp, _Tp> -{ - template struct __result - { - using type = _Up; - }; -}; - -template -using __make_integer_sequence_unchecked = typename __detail::__convert::template __result::type>::type; - -template -struct __make_integer_sequence -{ - static_assert(std::is_integral<_Tp>::value, - "std::make_integer_sequence can only be instantiated with an integral type" ); - static_assert(0 <= _Ep, "std::make_integer_sequence input shall not be negative"); - typedef __make_integer_sequence_unchecked<_Tp, _Ep> type; -}; - -} // namespace __detail -/** @endcond */ - - -/** C++11 implementation of index sequence - * @see https://en.cppreference.com/w/cpp/utility/integer_sequence - * @see taken from clang: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/utility?revision=211563&view=markup#l687 */ -template -using make_integer_sequence = typename __detail::__make_integer_sequence<_Tp, _Np>::type; - -/** C++11 implementation of index sequence - * @see https://en.cppreference.com/w/cpp/utility/integer_sequence - * @see taken from clang: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/utility?revision=211563&view=markup#l687 */ -template -using make_index_sequence = make_integer_sequence; - -/** C++11 implementation of index sequence - * @see https://en.cppreference.com/w/cpp/utility/integer_sequence - * @see taken from clang: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/utility?revision=211563&view=markup#l687 */ -template -using index_sequence_for = make_index_sequence; -#endif - -/** @} */ - - -} // namespace c4 - -#endif /* _C4_TYPES_HPP_ */ diff --git a/thirdparty/ryml/ext/c4core/src/c4/unrestrict.hpp b/thirdparty/ryml/ext/c4core/src/c4/unrestrict.hpp deleted file mode 100644 index 552f9ccff..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/unrestrict.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#ifdef _C4_RESTRICT_HPP_ // must match the include guard from restrict.hpp - -/** @file unrestrict.hpp cleans up restrict macros */ - -#undef $ -#undef $$ -#undef c$ -#undef c$$ - -#undef _C4_RESTRICT_HPP_ - -#ifdef __clang__ -# pragma clang diagnostic pop -#elif defined(__GNUC__) -#endif - -#endif /* _C4_RESTRICT_HPP_ */ diff --git a/thirdparty/ryml/ext/c4core/src/c4/utf.cpp b/thirdparty/ryml/ext/c4core/src/c4/utf.cpp deleted file mode 100644 index f1d509015..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/utf.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include "c4/utf.hpp" -#include "c4/charconv.hpp" - -namespace c4 { - -size_t decode_code_point(uint8_t *C4_RESTRICT buf, size_t buflen, const uint32_t code) -{ - C4_UNUSED(buflen); - C4_ASSERT(buflen >= 4); - if (code <= UINT32_C(0x7f)) - { - buf[0] = (uint8_t)code; - return 1u; - } - else if(code <= UINT32_C(0x7ff)) - { - buf[0] = (uint8_t)(UINT32_C(0xc0) | (code >> 6)); /* 110xxxxx */ - buf[1] = (uint8_t)(UINT32_C(0x80) | (code & UINT32_C(0x3f))); /* 10xxxxxx */ - return 2u; - } - else if(code <= UINT32_C(0xffff)) - { - buf[0] = (uint8_t)(UINT32_C(0xe0) | ((code >> 12))); /* 1110xxxx */ - buf[1] = (uint8_t)(UINT32_C(0x80) | ((code >> 6) & UINT32_C(0x3f))); /* 10xxxxxx */ - buf[2] = (uint8_t)(UINT32_C(0x80) | ((code ) & UINT32_C(0x3f))); /* 10xxxxxx */ - return 3u; - } - else if(code <= UINT32_C(0x10ffff)) - { - buf[0] = (uint8_t)(UINT32_C(0xf0) | ((code >> 18))); /* 11110xxx */ - buf[1] = (uint8_t)(UINT32_C(0x80) | ((code >> 12) & UINT32_C(0x3f))); /* 10xxxxxx */ - buf[2] = (uint8_t)(UINT32_C(0x80) | ((code >> 6) & UINT32_C(0x3f))); /* 10xxxxxx */ - buf[3] = (uint8_t)(UINT32_C(0x80) | ((code ) & UINT32_C(0x3f))); /* 10xxxxxx */ - return 4u; - } - return 0; -} - -substr decode_code_point(substr out, csubstr code_point) -{ - C4_ASSERT(out.len >= 4); - C4_ASSERT(!code_point.begins_with("U+")); - C4_ASSERT(!code_point.begins_with("\\x")); - C4_ASSERT(!code_point.begins_with("\\u")); - C4_ASSERT(!code_point.begins_with("\\U")); - C4_ASSERT(!code_point.begins_with('0')); - C4_ASSERT(code_point.len <= 8); - C4_ASSERT(code_point.len > 0); - uint32_t code_point_val; - C4_CHECK(read_hex(code_point, &code_point_val)); - size_t ret = decode_code_point((uint8_t*)out.str, out.len, code_point_val); - C4_ASSERT(ret <= 4); - return out.first(ret); -} - -} // namespace c4 diff --git a/thirdparty/ryml/ext/c4core/src/c4/utf.hpp b/thirdparty/ryml/ext/c4core/src/c4/utf.hpp deleted file mode 100644 index 116b20593..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/utf.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef C4_UTF_HPP_ -#define C4_UTF_HPP_ - -#include "c4/language.hpp" -#include "c4/substr_fwd.hpp" -#include -#include - -namespace c4 { - -substr decode_code_point(substr out, csubstr code_point); -size_t decode_code_point(uint8_t *C4_RESTRICT buf, size_t buflen, const uint32_t code); - -} // namespace c4 - -#endif // C4_UTF_HPP_ diff --git a/thirdparty/ryml/ext/c4core/src/c4/windows.hpp b/thirdparty/ryml/ext/c4core/src/c4/windows.hpp deleted file mode 100644 index d94c66c55..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/windows.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _C4_WINDOWS_HPP_ -#define _C4_WINDOWS_HPP_ - -#if defined(_WIN64) || defined(_WIN32) -#include "c4/windows_push.hpp" -#include -#include "c4/windows_pop.hpp" -#endif - -#endif /* _C4_WINDOWS_HPP_ */ diff --git a/thirdparty/ryml/ext/c4core/src/c4/windows_pop.hpp b/thirdparty/ryml/ext/c4core/src/c4/windows_pop.hpp deleted file mode 100644 index e055af6fa..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/windows_pop.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef _C4_WINDOWS_POP_HPP_ -#define _C4_WINDOWS_POP_HPP_ - -#if defined(_WIN64) || defined(_WIN32) - -#ifdef _c4_AMD64_ -# undef _c4_AMD64_ -# undef _AMD64_ -#endif -#ifdef _c4_X86_ -# undef _c4_X86_ -# undef _X86_ -#endif -#ifdef _c4_ARM_ -# undef _c4_ARM_ -# undef _ARM_ -#endif - -#ifdef _c4_NOMINMAX -# undef _c4_NOMINMAX -# undef NOMINMAX -#endif - -#ifdef NOGDI -# undef _c4_NOGDI -# undef NOGDI -#endif - -#ifdef VC_EXTRALEAN -# undef _c4_VC_EXTRALEAN -# undef VC_EXTRALEAN -#endif - -#ifdef WIN32_LEAN_AND_MEAN -# undef _c4_WIN32_LEAN_AND_MEAN -# undef WIN32_LEAN_AND_MEAN -#endif - -#endif /* defined(_WIN64) || defined(_WIN32) */ - -#endif /* _C4_WINDOWS_POP_HPP_ */ diff --git a/thirdparty/ryml/ext/c4core/src/c4/windows_push.hpp b/thirdparty/ryml/ext/c4core/src/c4/windows_push.hpp deleted file mode 100644 index 156fe2fb4..000000000 --- a/thirdparty/ryml/ext/c4core/src/c4/windows_push.hpp +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef _C4_WINDOWS_PUSH_HPP_ -#define _C4_WINDOWS_PUSH_HPP_ - -/** @file windows_push.hpp sets up macros to include windows header files - * without pulling in all of - * - * @see #include windows_pop.hpp to undefine these macros - * - * @see https://aras-p.info/blog/2018/01/12/Minimizing-windows.h/ */ - - -#if defined(_WIN64) || defined(_WIN32) - -#if defined(_M_AMD64) -# ifndef _AMD64_ -# define _c4_AMD64_ -# define _AMD64_ -# endif -#elif defined(_M_IX86) -# ifndef _X86_ -# define _c4_X86_ -# define _X86_ -# endif -#elif defined(_M_ARM64) -# ifndef _ARM64_ -# define _c4_ARM64_ -# define _ARM64_ -# endif -#elif defined(_M_ARM) -# ifndef _ARM_ -# define _c4_ARM_ -# define _ARM_ -# endif -#endif - -#ifndef NOMINMAX -# define _c4_NOMINMAX -# define NOMINMAX -#endif - -#ifndef NOGDI -# define _c4_NOGDI -# define NOGDI -#endif - -#ifndef VC_EXTRALEAN -# define _c4_VC_EXTRALEAN -# define VC_EXTRALEAN -#endif - -#ifndef WIN32_LEAN_AND_MEAN -# define _c4_WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -#endif - -/* If defined, the following flags inhibit definition - * of the indicated items. - * - * NOGDICAPMASKS - CC_*, LC_*, PC_*, CP_*, TC_*, RC_ - * NOVIRTUALKEYCODES - VK_* - * NOWINMESSAGES - WM_*, EM_*, LB_*, CB_* - * NOWINSTYLES - WS_*, CS_*, ES_*, LBS_*, SBS_*, CBS_* - * NOSYSMETRICS - SM_* - * NOMENUS - MF_* - * NOICONS - IDI_* - * NOKEYSTATES - MK_* - * NOSYSCOMMANDS - SC_* - * NORASTEROPS - Binary and Tertiary raster ops - * NOSHOWWINDOW - SW_* - * OEMRESOURCE - OEM Resource values - * NOATOM - Atom Manager routines - * NOCLIPBOARD - Clipboard routines - * NOCOLOR - Screen colors - * NOCTLMGR - Control and Dialog routines - * NODRAWTEXT - DrawText() and DT_* - * NOGDI - All GDI defines and routines - * NOKERNEL - All KERNEL defines and routines - * NOUSER - All USER defines and routines - * NONLS - All NLS defines and routines - * NOMB - MB_* and MessageBox() - * NOMEMMGR - GMEM_*, LMEM_*, GHND, LHND, associated routines - * NOMETAFILE - typedef METAFILEPICT - * NOMINMAX - Macros min(a,b) and max(a,b) - * NOMSG - typedef MSG and associated routines - * NOOPENFILE - OpenFile(), OemToAnsi, AnsiToOem, and OF_* - * NOSCROLL - SB_* and scrolling routines - * NOSERVICE - All Service Controller routines, SERVICE_ equates, etc. - * NOSOUND - Sound driver routines - * NOTEXTMETRIC - typedef TEXTMETRIC and associated routines - * NOWH - SetWindowsHook and WH_* - * NOWINOFFSETS - GWL_*, GCL_*, associated routines - * NOCOMM - COMM driver routines - * NOKANJI - Kanji support stuff. - * NOHELP - Help engine interface. - * NOPROFILER - Profiler interface. - * NODEFERWINDOWPOS - DeferWindowPos routines - * NOMCX - Modem Configuration Extensions - */ - -#endif /* defined(_WIN64) || defined(_WIN32) */ - -#endif /* _C4_WINDOWS_PUSH_HPP_ */ diff --git a/thirdparty/ryml/ext/c4core/tbump.toml b/thirdparty/ryml/ext/c4core/tbump.toml deleted file mode 100644 index 310c606d6..000000000 --- a/thirdparty/ryml/ext/c4core/tbump.toml +++ /dev/null @@ -1,48 +0,0 @@ -# Uncomment this if your project is hosted on GitHub: -# github_url = "https://github.com///" - -[version] -current = "0.1.11" - -# Example of a semver regexp. -# Make sure this matches current_version before -# using tbump -regex = ''' - (?P\d+) - \. - (?P\d+) - \. - (?P\d+) - .* - ''' - -[git] -message_template = "Bump to {new_version}" -tag_template = "v{new_version}" - -# For each file to patch, add a [[file]] config -# section containing the path of the file, relative to the -# tbump.toml location. -[[file]] -src = "CMakeLists.txt" -search = "c4_project\\(VERSION {current_version}" -[[file]] -src = "test/test_install/CMakeLists.txt" -search = "c4_project\\(VERSION {current_version}" -[[file]] -src = "test/test_singleheader/CMakeLists.txt" -search = "c4_project\\(VERSION {current_version}" - -# You can specify a list of commands to -# run after the files have been patched -# and before the git commit is made - -# [[before_commit]] -# name = "check changelog" -# cmd = "grep -q {new_version} Changelog.rst" - -# Or run some commands after the git tag and the branch -# have been pushed: -# [[after_push]] -# name = "publish" -# cmd = "./publish.sh" diff --git a/thirdparty/ryml/ext/c4core/test/c4/libtest/archetypes.cpp b/thirdparty/ryml/ext/c4core/test/c4/libtest/archetypes.cpp deleted file mode 100644 index 9c4fb4310..000000000 --- a/thirdparty/ryml/ext/c4core/test/c4/libtest/archetypes.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "c4/libtest/archetypes.hpp" - -namespace c4 { -namespace archetypes { - -int IdOwner::s_current = 0; - -} // namespace archetypes -} // namespace c4 diff --git a/thirdparty/ryml/ext/c4core/test/c4/libtest/archetypes.hpp b/thirdparty/ryml/ext/c4core/test/c4/libtest/archetypes.hpp deleted file mode 100644 index 87a4644e9..000000000 --- a/thirdparty/ryml/ext/c4core/test/c4/libtest/archetypes.hpp +++ /dev/null @@ -1,551 +0,0 @@ -#ifndef _C4_TEST_ARCHETYPES_HPP_ -#define _C4_TEST_ARCHETYPES_HPP_ - -#ifdef C4CORE_SINGLE_HEADER -#include "c4/c4core_all.hpp" -#else -#include "c4/memory_resource.hpp" -#include "c4/allocator.hpp" -#include "c4/char_traits.hpp" -#endif -#include "c4/test.hpp" - -#include -#include -#include - -namespace c4 { - -template< class String > class sstream; - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -namespace archetypes { - -template< class T > void check_archetype(T const& a) { a.check(); } -template< class T > void check_archetype(T const& a, T const& ref) { a.check(ref); } -inline void check_archetype(char ) {} -inline void check_archetype(wchar_t ) {} -inline void check_archetype(int8_t ) {} -inline void check_archetype(uint8_t ) {} -inline void check_archetype(int16_t ) {} -inline void check_archetype(uint16_t) {} -inline void check_archetype(int32_t ) {} -inline void check_archetype(uint32_t) {} -inline void check_archetype(int64_t ) {} -inline void check_archetype(uint64_t) {} -inline void check_archetype(float ) {} -inline void check_archetype(double ) {} -inline void check_archetype(char a, char ref) { CHECK_EQ(a, ref); } -inline void check_archetype(wchar_t a, wchar_t ref) { CHECK_EQ(a, ref); } -inline void check_archetype(int8_t a, int8_t ref) { CHECK_EQ(a, ref); } -inline void check_archetype(uint8_t a, uint8_t ref) { CHECK_EQ(a, ref); } -inline void check_archetype(int16_t a, int16_t ref) { CHECK_EQ(a, ref); } -inline void check_archetype(uint16_t a, uint16_t ref) { CHECK_EQ(a, ref); } -inline void check_archetype(int32_t a, int32_t ref) { CHECK_EQ(a, ref); } -inline void check_archetype(uint32_t a, uint32_t ref) { CHECK_EQ(a, ref); } -inline void check_archetype(int64_t a, int64_t ref) { CHECK_EQ(a, ref); } -inline void check_archetype(uint64_t a, uint64_t ref) { CHECK_EQ(a, ref); } -inline void check_archetype(float a, float ref) { CHECK_EQ((double)a, doctest::Approx((double)ref)); } -inline void check_archetype(double a, double ref) { CHECK_EQ(a, doctest::Approx(ref)); } - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -template< class T, class Proto > -struct archetype_proto_base -{ - static T const& get(size_t which) - { - auto const& a = Proto::arr(); - C4_ASSERT(which < (int)a.size()); - return a[which]; - } - static std::array< T, 8 > dup() - { - std::array< T, 8 > d = Proto::arr; - return d; - } - static std::array< Counting, 8 > cdup() - { - std::array< Counting, 8 > d = Proto::carr; - return d; - } - static std::vector< T > dup(size_t n) - { - auto const& a = Proto::arr(); - std::vector< T > d; - d.reserve(n); - for(size_t i = 0, pos = 0; i < n; ++i, pos = ((pos+1)%a.size())) - { - d.push_back(a[pos]); - } - return d; - } - static std::vector< Counting > cdup(size_t n) - { - auto const& a = Proto::arr(); - std::vector< Counting > d; - d.reserve(n); - for(size_t i = 0, pos = 0; i < n; ++i, pos = ((pos+1)%a.size())) - { - d.push_back(a[pos]); - } - return d; - } -}; - -#ifdef __clang__ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wmissing-braces" // warning : suggest braces around initialization of subobject [-Wmissing-braces] -#endif - -// for scalar types: ints and floats -template< class T > -struct archetype_proto : public archetype_proto_base< T, archetype_proto > -{ - static_assert(std::is_fundamental< T >::value, "T must be a fundamental type"); - static std::array const& arr() - { - static const std::array arr_{0, 1, 2, 3, 4, 5, 6, 7}; - return arr_; - } - static std::array, 8> const& carr() - { - static const std::array, 8> arr_ = {0, 1, 2, 3, 4, 5, 6, 7}; - return arr_; - } - static std::initializer_list< T > il() - { - static const std::initializer_list< T > l{0, 1, 2, 3, 4, 5, 6, 7}; - return l; - } - static std::initializer_list< Counting > cil() - { - static const std::initializer_list< Counting > l = {0, 1, 2, 3, 4, 5, 6, 7}; - C4_ASSERT(l.size() == 8); - return l; - } -}; - -#define _C4_DECLARE_ARCHETYPE_PROTO(ty, ...) \ -template<> \ -struct archetype_proto : public archetype_proto_base< ty, archetype_proto > \ -{ \ - static std::array const& arr() \ - { \ - static const std::array arr_{__VA_ARGS__}; \ - return arr_; \ - } \ - static std::array, 8> const& carr() \ - { \ - static const std::array, 8> arr_{__VA_ARGS__}; \ - return arr_; \ - } \ - static std::initializer_list< ty > il() \ - { \ - static const std::initializer_list< ty > l{__VA_ARGS__}; \ - return l; \ - } \ - static std::initializer_list< Counting > cil() \ - { \ - static const std::initializer_list< Counting > l{__VA_ARGS__}; \ - return l; \ - } \ -} - -#define _C4_DECLARE_ARCHETYPE_PROTO_TPL1(tplparam1, ty, ...) \ -template< tplparam1 > \ -struct archetype_proto< ty > : public archetype_proto_base< ty, archetype_proto > \ -{ \ - static std::array const& arr() \ - { \ - static const std::array arr_{__VA_ARGS__}; \ - return arr_; \ - } \ - static std::array, 8> const& carr() \ - { \ - static const std::array, 8> arr_{__VA_ARGS__}; \ - return arr_; \ - } \ - static std::initializer_list< ty > il() \ - { \ - static const std::initializer_list< ty > l{__VA_ARGS__}; \ - return l; \ - } \ - static std::initializer_list< Counting > cil() \ - { \ - static const std::initializer_list< Counting > l{__VA_ARGS__}; \ - return l; \ - } \ -} - -_C4_DECLARE_ARCHETYPE_PROTO(std::string, - "str0", "str1", "str2", "str3", - "str4", "str5", "str6", "str7"); - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -/** Resource-owning archetype */ - -template< class T > -struct exvec3 -{ - T x, y, z; - bool operator== (exvec3 const& that) const - { - return x == that.x && y == that.y && z == that.z; - } -}; -template< class String, class T > -sstream< String >& operator<< (sstream< String >& ss, exvec3 const& v) -{ - using char_type = typename sstream< String >::char_type; - ss.printp(C4_TXTTY("({},{},{})", char_type), v.x, v.y, v.z); - return ss; -} -template< class String, class T > -sstream< String >& operator>> (sstream< String >& ss, exvec3 & v) -{ - using char_type = typename sstream< String >::char_type; - ss.scanp(C4_TXTTY("({},{},{})", char_type), v.x, v.y, v.z); - return ss; -} - -#define _ C4_COMMA -#define c4v(v0, v1, v2) exvec3{v0 _ v1 _ v2} -_C4_DECLARE_ARCHETYPE_PROTO_TPL1(class T, exvec3, - c4v(0, 1, 2), c4v(3, 4, 5), c4v(6, 7, 8), c4v(9, 10, 11), - c4v(100, 101, 102), c4v(103, 104, 105), c4v(106, 107, 108), c4v(109, 110, 111) - ); -#undef c4v -#undef _ - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -/** Resource-owning archetype */ -struct IdOwner -{ - static int s_current; - int id; - int val; - - void check() const - { - CHECK_UNARY(id > 0); - } - void check(IdOwner const& that) const - { - check(); - CHECK_NE(id, that.id); - } - - IdOwner(int v = 0) { id = ++s_current; val = v; } - ~IdOwner() { if(id > 0) --s_current; } - IdOwner(IdOwner const& that) { id = ++s_current; val = that.val; } - IdOwner(IdOwner && that) { id = that.id; val = that.val; that.id = 0; } - IdOwner& operator= (IdOwner const& that) { C4_CHECK(id > 0); --s_current; id = ++s_current; val = that.val; return *this; } - IdOwner& operator= (IdOwner && that) { C4_CHECK(id > 0); --s_current; id = that.id; val = that.val; that.id = 0; return *this; } - bool operator== (IdOwner const& that) const - { - return val == that.val; - } -}; - -_C4_DECLARE_ARCHETYPE_PROTO(IdOwner, 0, 1, 2, 3, 4, 5, 6, 7); - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -/** Memory-owning archetype, raw mem resource calls */ -template< class T > -struct MemOwner -{ - T *mem; - // prevent initialization order problems by using a memory resource here - MemoryResourceMalloc mr; - - void check() const - { - EXPECT_NE(mem, nullptr); - check_archetype(*mem); - } - void check(MemOwner const& that) const - { - EXPECT_NE(mem, that.mem); - } - - ~MemOwner() - { - if(!mem) return; - mem->~T(); - mr.deallocate(mem, sizeof(T), alignof(T)); - mem = nullptr; - } - - MemOwner() - { - mem = (T*)mr.allocate(sizeof(T), alignof(T)); - new (mem) T(); - } - template< class ...Args > - MemOwner(varargs_t, Args && ...args) - { - mem = (T*)mr.allocate(sizeof(T), alignof(T)); - new (mem) T(std::forward< Args >(args)...); - } - MemOwner(MemOwner const& that) - { - mem = (T*)mr.allocate(sizeof(T), alignof(T)); - new (mem) T(*that.mem); - } - MemOwner(MemOwner && that) - { - mem = that.mem; - that.mem = nullptr; - } - MemOwner& operator= (MemOwner const& that) - { - if(!mem) - { - mem = (T*)mr.allocate(sizeof(T), alignof(T)); - } - else - { - mem->~T(); - } - new (mem) T(*that.mem); - return *this; - } - MemOwner& operator= (MemOwner && that) - { - if(mem) - { - mem->~T(); - mr.deallocate(mem, sizeof(T), alignof(T)); - } - mem = that.mem; - that.mem = nullptr; - return *this; - } - bool operator== (MemOwner const& that) const - { - return *mem == *that.mem; - } -}; - -#define _ C4_COMMA -#define c4v(which) MemOwner{varargs _ archetype_proto::get(which)} -_C4_DECLARE_ARCHETYPE_PROTO_TPL1(class T, MemOwner, - c4v(0), c4v(1), c4v(2), c4v(3), - c4v(4), c4v(5), c4v(6), c4v(7) - ); -#undef c4v -#undef _ - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -/** Memory-owning archetype, with allocator */ -template< class T > -struct MemOwnerAlloc -{ - T *mem; - // prevent initialization order problems by using a memory resource here - MemoryResourceMalloc mr; - c4::Allocator< T > m_alloc; - using alloc_traits = std::allocator_traits< c4::Allocator< T > >; - - void check() const - { - EXPECT_NE(mem, nullptr); - check_archetype(*mem); - } - void check(MemOwnerAlloc const& that) const - { - check(); - EXPECT_NE(mem, that.mem); - } - - void free() - { - alloc_traits::destroy(m_alloc, mem); - alloc_traits::deallocate(m_alloc, mem, 1); - mem = nullptr; - } - ~MemOwnerAlloc() - { - if(!mem) return; - free(); - } - - MemOwnerAlloc() : m_alloc(&mr) - { - C4_ASSERT(m_alloc.resource() == &mr); - mem = alloc_traits::allocate(m_alloc, 1); - alloc_traits::construct(m_alloc, mem); - } - template< class ...Args > - MemOwnerAlloc(varargs_t, Args && ...args) : m_alloc(&mr) - { - mem = alloc_traits::allocate(m_alloc, 1); - alloc_traits::construct(m_alloc, mem, std::forward< Args >(args)...); - } - - MemOwnerAlloc(MemOwnerAlloc const& that) : m_alloc(&mr) - { - mem = alloc_traits::allocate(m_alloc, 1); - alloc_traits::construct(m_alloc, mem, *that.mem); - } - MemOwnerAlloc(MemOwnerAlloc && that) : m_alloc(&mr) - { - mem = that.mem; - that.mem = nullptr; - } - - MemOwnerAlloc& operator= (MemOwnerAlloc const& that) - { - if(!mem) - { - mem = alloc_traits::allocate(m_alloc, 1); - } - else - { - mem->~T(); - } - alloc_traits::construct(m_alloc, mem, *that.mem); - return *this; - } - MemOwnerAlloc& operator= (MemOwnerAlloc && that) - { - if(mem) - { - free(); - } - mem = that.mem; - that.mem = nullptr; - return *this; - } - - bool operator== (MemOwnerAlloc const& that) const - { - return *mem == *that.mem; - } -}; - -#define _ C4_COMMA -#define c4v(which) MemOwnerAlloc{varargs _ archetype_proto::get(which)} -_C4_DECLARE_ARCHETYPE_PROTO_TPL1(class T, MemOwnerAlloc, - c4v(0), c4v(1), c4v(2), c4v(3), - c4v(4), c4v(5), c4v(6), c4v(7) - ); -#undef c4v -#undef _ - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -/** base class archetype */ -struct Base -{ - virtual ~Base() = default; -protected: - Base() = default; -}; -/** derived class archetype */ -struct Derived : public Base -{ - -}; - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -template< class T > -struct InsidePtr -{ - T a; - T b; - T c; - T *ptr; - - InsidePtr(int which = 0) : a(), b(), c(), ptr(&a + (which % 3)) {} - InsidePtr(InsidePtr const& that) : a(that.a), b(that.b), c(that.c), ptr(&a + (that.ptr - &that.a)) {} - InsidePtr(InsidePtr && that) : a(std::move(that.a)), b(std::move(that.b)), c(std::move(that.c)), ptr(&a + (that.ptr - &that.a)) { that.ptr = nullptr; } - InsidePtr& operator= (InsidePtr const& that) { a = (that.a); b = (that.b); c = (that.c); ptr = (&a + (that.ptr - &that.a)); return *this; } - InsidePtr& operator= (InsidePtr && that) { a = std::move(that.a); b = std::move(that.b); c = std::move(that.c); ptr = (&a + (that.ptr - &that.a)); that.ptr = nullptr; return *this; } - ~InsidePtr() { EXPECT_TRUE(ptr == &a || ptr == &b || ptr == &c || ptr == nullptr); } - - void check() const - { - EXPECT_TRUE(ptr == &a || ptr == &b || ptr == &c); - } - void check(InsidePtr const& that) const - { - check(); - EXPECT_EQ(ptr - &a, that.ptr - &that.a); - } - bool operator== (InsidePtr const& that) const - { - return that.a == a && that.b == b && that.c == c && (ptr - &a) == (that.ptr - &that.a); - } - -}; - -#define _ C4_COMMA -_C4_DECLARE_ARCHETYPE_PROTO_TPL1(class T, InsidePtr, - 0, 1, 2, 3, 4, 5, 6, 7 - ); -#undef _ - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -# define CALL_FOR_SCALAR_ARCHETYPES(mcr) \ - mcr(int , int) \ - mcr(uint64_t , uint64_t) - -# define CALL_FOR_CONTAINEE_ARCHETYPES(mcr) \ - CALL_FOR_SCALAR_ARCHETYPES(mcr) \ - mcr(MemOwnerAlloc_std_string , archetypes::MemOwnerAlloc) - - - -using scalars_quick = std::tuple; -using scalars = std::tuple< - char, wchar_t, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t, float, double ->; -using containees_quick = std::tuple< - int, - uint64_t, - archetypes::MemOwnerAlloc ->; -using containees = std::tuple< - char, wchar_t, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t, float, double, - archetypes::exvec3, - archetypes::exvec3, - archetypes::IdOwner, - archetypes::MemOwner, - archetypes::MemOwner, - archetypes::MemOwnerAlloc, - archetypes::MemOwnerAlloc, - archetypes::InsidePtr, - archetypes::InsidePtr ->; - - -#ifdef __clang__ -# pragma clang diagnostic pop -#endif - -} // namespace archetypes -} // namespace c4 - -#endif // _C4_TEST_ARCHETYPES_HPP_ diff --git a/thirdparty/ryml/ext/c4core/test/c4/libtest/supprwarn_pop.hpp b/thirdparty/ryml/ext/c4core/test/c4/libtest/supprwarn_pop.hpp deleted file mode 100644 index 695035ef6..000000000 --- a/thirdparty/ryml/ext/c4core/test/c4/libtest/supprwarn_pop.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _C4_SUPPRWARN_POP_HPP_ -#define _C4_SUPPRWARN_POP_HPP_ - -#ifdef __clang__ -# pragma clang diagnostic pop -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#elif defined(_MSC_VER) -# pragma warning(pop) -#endif - -#endif /* SUPPRWARN_POP_H */ diff --git a/thirdparty/ryml/ext/c4core/test/c4/libtest/supprwarn_push.hpp b/thirdparty/ryml/ext/c4core/test/c4/libtest/supprwarn_push.hpp deleted file mode 100644 index 4651e227c..000000000 --- a/thirdparty/ryml/ext/c4core/test/c4/libtest/supprwarn_push.hpp +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef _C4_LIBTEST_SUPPRWARN_PUSH_HPP_ -#define _C4_LIBTEST_SUPPRWARN_PUSH_HPP_ - -/** @file supprwarn_push.hpp this file contains directives to make the - * compiler ignore warnings in test code. It should NOT be used for c4stl - * itself, but only in test code. */ - -#ifdef __clang__ -# pragma clang diagnostic push - /* NOTE: using , ## __VA_ARGS__ to deal with zero-args calls to - * variadic macros is not portable, but works in clang, gcc, msvc, icc. - * clang requires switching off compiler warnings for pedantic mode. - * @see http://stackoverflow.com/questions/32047685/variadic-macro-without-arguments */ -# pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" // warning: token pasting of ',' and __VA_ARGS__ is a GNU extension -# pragma clang diagnostic ignored "-Wunused-local-typedef" -# pragma clang diagnostic ignored "-Wsign-compare" // warning: comparison of integers of different signs: 'const unsigned long' and 'const int' -# pragma clang diagnostic ignored "-Wfloat-equal" // warning: comparing floating point with == or != is unsafe -# pragma clang diagnostic ignored "-Wwritable-strings" // ISO C++11 does not allow conversion from string literal to char* -# pragma clang diagnostic ignored "-Wunused-variable" -# pragma clang diagnostic ignored "-Wunused-parameter" -#elif defined(__GNUC__) -# pragma GCC diagnostic push - /* GCC also issues a warning for zero-args calls to variadic macros. - * This warning is switched on with -pedantic and apparently there is no - * easy way to turn it off as with clang. But marking this as a system - * header works. - * @see https://gcc.gnu.org/onlinedocs/cpp/System-Headers.html - * @see http://stackoverflow.com/questions/35587137/ */ -# pragma GCC system_header -# pragma GCC diagnostic ignored "-Wvariadic-macros" -# pragma GCC diagnostic ignored "-Wwrite-strings" // ISO C++ forbids converting a string constant to ‘C* {aka char*}’ -# pragma GCC diagnostic ignored "-Wunused-local-typedefs" -# pragma GCC diagnostic ignored "-Wunused-variable" -# pragma GCC diagnostic ignored "-Wunused-parameter" -# pragma GCC diagnostic ignored "-Wsign-compare" // warning: comparison of integers of different signs: 'const unsigned long' and 'const int' -# pragma GCC diagnostic ignored "-Wfloat-equal" // warning: comparing floating point with == or != is unsafe -# pragma GCC diagnostic ignored "-Wpedantic" -# pragma GCC diagnostic ignored "-pedantic" -#elif defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable:4018) // '>=': signed/unsigned mismatch -# pragma warning(disable:4127) // conditional expression is constant -# pragma warning(disable:4189) // local variable is initialized but not referenced -# pragma warning(disable:4389) // '==': signed/unsigned mismatch -# pragma warning(disable:4702) // unreachable code -#endif - -#endif /* _C4_LIBTEST_SUPPRWARN_PUSH_HPP_ */ diff --git a/thirdparty/ryml/ext/c4core/test/c4/libtest/test.cpp b/thirdparty/ryml/ext/c4core/test/c4/libtest/test.cpp deleted file mode 100644 index f005d24ac..000000000 --- a/thirdparty/ryml/ext/c4core/test/c4/libtest/test.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "c4/test.hpp" - -namespace c4 { - -size_t TestErrorOccurs::num_errors = 0; - -} // namespace c4 diff --git a/thirdparty/ryml/ext/c4core/test/c4/main.cpp b/thirdparty/ryml/ext/c4core/test/c4/main.cpp deleted file mode 100644 index 36c8001e6..000000000 --- a/thirdparty/ryml/ext/c4core/test/c4/main.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#define DOCTEST_CONFIG_SUPER_FAST_ASSERTS -#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN -#include diff --git a/thirdparty/ryml/ext/c4core/test/c4/test.hpp b/thirdparty/ryml/ext/c4core/test/c4/test.hpp deleted file mode 100644 index 936283a2a..000000000 --- a/thirdparty/ryml/ext/c4core/test/c4/test.hpp +++ /dev/null @@ -1,324 +0,0 @@ -#ifndef _C4_TEST_HPP_ -#define _C4_TEST_HPP_ - -#ifdef C4CORE_SINGLE_HEADER -#include "c4/c4core_all.hpp" -#else -#include "c4/config.hpp" -#include "c4/memory_resource.hpp" -#include "c4/allocator.hpp" -#include "c4/substr.hpp" -#endif -#include -#include - -// FIXME - these are just dumb placeholders -#define C4_LOGF_ERR(...) fprintf(stderr, __VA_ARGS__) -#define C4_LOGF_WARN(...) fprintf(stderr, __VA_ARGS__) -#define C4_LOGP(msg, ...) printf(msg) - -#define DOCTEST_CONFIG_SUPER_FAST_ASSERTS -#include - -#define CHECK_STREQ(lhs, rhs) CHECK_EQ(c4::to_csubstr(lhs), c4::to_csubstr(rhs)) -#define CHECK_FLOAT_EQ(lhs, rhs) CHECK((double)(lhs) == doctest::Approx((double)(rhs))) - - -namespace c4 { - -template -inline std::ostream& operator<< (std::ostream& stream, c4::basic_substring s) -{ - stream.write(s.str, std::streamsize(s.len)); - return stream; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -/** RAII class that tests whether an error occurs inside a scope. */ -struct TestErrorOccurs -{ - TestErrorOccurs(size_t num_expected_errors = 1) - : - expected_errors(num_expected_errors), - tmp_settings(c4::ON_ERROR_CALLBACK, &TestErrorOccurs::error_callback) - { - num_errors = 0; - } - ~TestErrorOccurs() - { - CHECK_EQ(num_errors, expected_errors); - num_errors = 0; - } - - size_t expected_errors; - static size_t num_errors; - ScopedErrorSettings tmp_settings; - static void error_callback(const char* /*msg*/, size_t /*msg_size*/) - { - ++num_errors; - } -}; - -#define C4_EXPECT_ERROR_OCCURS(...) \ - auto _testerroroccurs##__LINE__ = TestErrorOccurs(__VA_ARGS__) - -#if C4_USE_ASSERT -# define C4_EXPECT_ASSERT_TRIGGERS(...) C4_EXPECT_ERROR_OCCURS(__VA_ARGS__) -#else -# define C4_EXPECT_ASSERT_TRIGGERS(...) -#endif - -#if C4_USE_XASSERT -# define C4_EXPECT_XASSERT_TRIGGERS(...) C4_EXPECT_ERROR_OCCURS(__VA_ARGS__) -#else -# define C4_EXPECT_XASSERT_TRIGGERS(...) -#endif - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -/** count constructors, destructors and assigns */ -template< class T > -struct Counting -{ - using value_type = T; - - T obj; - - bool operator== (T const& that) const { return obj == that; } - - static bool log_ctors; - static size_t num_ctors; - template< class ...Args > - Counting(Args && ...args); - - static bool log_dtors; - static size_t num_dtors; - ~Counting(); - - static bool log_copy_ctors; - static size_t num_copy_ctors; - Counting(Counting const& that); - - static bool log_move_ctors; - static size_t num_move_ctors; - Counting(Counting && that); - - static bool log_copy_assigns; - static size_t num_copy_assigns; - Counting& operator= (Counting const& that); - - static bool log_move_assigns; - static size_t num_move_assigns; - Counting& operator= (Counting && that); - - - struct check_num - { - char const* name; - size_t const& what; - size_t const initial; - size_t const must_be_num; - check_num(char const* nm, size_t const& w, size_t n) : name(nm), what(w), initial(what), must_be_num(n) {} - ~check_num() - { - size_t del = what - initial; - INFO("# of " << name << " calls: expected " << must_be_num << ", but got " << del); - CHECK_EQ(del, must_be_num); - } - }; - - static check_num check_ctors(size_t n) { return check_num("ctor", num_ctors, n); } - static check_num check_dtors(size_t n) { return check_num("dtor", num_dtors, n); } - static check_num check_copy_ctors(size_t n) { return check_num("copy_ctor", num_copy_ctors, n); } - static check_num check_move_ctors(size_t n) { return check_num("move_ctor", num_move_ctors, n); } - static check_num check_copy_assigns(size_t n) { return check_num("copy_assign", num_copy_assigns, n); } - static check_num check_move_assigns(size_t n) { return check_num("move_assign", num_move_assigns, n); } - - struct check_num_ctors_dtors - { - check_num ctors, dtors; - check_num_ctors_dtors(size_t _ctors, size_t _dtors) - : - ctors(check_ctors(_ctors)), - dtors(check_dtors(_dtors)) - { - } - }; - static check_num_ctors_dtors check_ctors_dtors(size_t _ctors, size_t _dtors) - { - return check_num_ctors_dtors(_ctors, _dtors); - } - - struct check_num_all - { - check_num ctors, dtors, cp_ctors, mv_ctors, cp_assigns, mv_assigns; - check_num_all(size_t _ctors, size_t _dtors, size_t _cp_ctors, size_t _mv_ctors, size_t _cp_assigns, size_t _mv_assigns) - { - ctors = check_ctors(_ctors); - dtors = check_dtors(_dtors); - cp_ctors = check_copy_ctors(_cp_ctors); - mv_ctors = check_move_ctors(_mv_ctors); - cp_assigns = check_copy_assigns(_cp_assigns); - mv_assigns = check_move_assigns(_mv_assigns); - } - }; - static check_num_all check_all(size_t _ctors, size_t _dtors, size_t _cp_ctors, size_t _move_ctors, size_t _cp_assigns, size_t _mv_assigns) - { - return check_num_all(_ctors, _dtors, _cp_ctors, _move_ctors, _cp_assigns, _mv_assigns); - } - - static void reset() - { - num_ctors = 0; - num_dtors = 0; - num_copy_ctors = 0; - num_move_ctors = 0; - num_copy_assigns = 0; - num_move_assigns = 0; - } -}; - -template< class T > size_t Counting< T >::num_ctors = 0; -template< class T > bool Counting< T >::log_ctors = false; -template< class T > size_t Counting< T >::num_dtors = 0; -template< class T > bool Counting< T >::log_dtors = false; -template< class T > size_t Counting< T >::num_copy_ctors = 0; -template< class T > bool Counting< T >::log_copy_ctors = false; -template< class T > size_t Counting< T >::num_move_ctors = 0; -template< class T > bool Counting< T >::log_move_ctors = false; -template< class T > size_t Counting< T >::num_copy_assigns = 0; -template< class T > bool Counting< T >::log_copy_assigns = false; -template< class T > size_t Counting< T >::num_move_assigns = 0; -template< class T > bool Counting< T >::log_move_assigns = false; - -template< class T > -template< class ...Args > -Counting< T >::Counting(Args && ...args) : obj(std::forward< Args >(args)...) -{ - if(log_ctors) C4_LOGP("Counting[{}]::ctor #{}\n", (void*)this, num_ctors); - ++num_ctors; -} - -template< class T > -Counting< T >::~Counting() -{ - if(log_dtors) C4_LOGP("Counting[{}]::dtor #{}\n", (void*)this, num_dtors); - ++num_dtors; -} - -template< class T > -Counting< T >::Counting(Counting const& that) : obj(that.obj) -{ - if(log_copy_ctors) C4_LOGP("Counting[{}]::copy_ctor #{}\n", (void*)this, num_copy_ctors); - ++num_copy_ctors; -} - -template< class T > -Counting< T >::Counting(Counting && that) : obj(std::move(that.obj)) -{ - if(log_move_ctors) C4_LOGP("Counting[{}]::move_ctor #{}\n", (void*)this, num_move_ctors); - ++num_move_ctors; -} - -template< class T > -Counting< T >& Counting< T >::operator= (Counting const& that) -{ - obj = that.obj; - if(log_copy_assigns) C4_LOGP("Counting[{}]::copy_assign #{}\n", (void*)this, num_copy_assigns); - ++num_copy_assigns; - return *this; -} - -template< class T > -Counting< T >& Counting< T >::operator= (Counting && that) -{ - obj = std::move(that.obj); - if(log_move_assigns) C4_LOGP("Counting[{}]::move_assign #{}\n", (void*)this, num_move_assigns); - ++num_move_assigns; - return *this; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -/** @todo refactor to use RAII @see Counting */ -struct AllocationCountsChecker : public ScopedMemoryResourceCounts -{ - AllocationCounts first; - -public: - - AllocationCountsChecker() - : - ScopedMemoryResourceCounts(), - first(mr.counts()) - { - } - - AllocationCountsChecker(MemoryResource *mr_) - : - ScopedMemoryResourceCounts(mr_), - first(mr.counts()) - { - } - - void reset() - { - first = mr.counts(); - } - - /** check value of curr allocations and size */ - void check_curr(ssize_t expected_allocs, ssize_t expected_size) const - { - CHECK_EQ(mr.counts().curr.allocs, expected_allocs); - CHECK_EQ(mr.counts().curr.size, expected_size); - } - /** check delta of curr allocations and size since construction or last reset() */ - void check_curr_delta(ssize_t expected_allocs, ssize_t expected_size) const - { - AllocationCounts delta = mr.counts() - first; - CHECK_EQ(delta.curr.allocs, expected_allocs); - CHECK_EQ(delta.curr.size, expected_size); - } - - /** check value of total allocations and size */ - void check_total(ssize_t expected_allocs, ssize_t expected_size) const - { - CHECK_EQ(mr.counts().total.allocs, expected_allocs); - CHECK_EQ(mr.counts().total.size, expected_size); - } - /** check delta of total allocations and size since construction or last reset() */ - void check_total_delta(ssize_t expected_allocs, ssize_t expected_size) const - { - AllocationCounts delta = mr.counts() - first; - CHECK_EQ(delta.total.allocs, expected_allocs); - CHECK_EQ(delta.total.size, expected_size); - } - - /** check value of max allocations and size */ - void check_max(ssize_t expected_max_allocs, ssize_t expected_max_size) const - { - CHECK_EQ(mr.counts().max.allocs, expected_max_allocs); - CHECK_EQ(mr.counts().max.size, expected_max_size); - } - - /** check that since construction or the last reset(): - * - num_allocs occcurred - * - totaling total_size - * - of which the largest is max_size */ - void check_all_delta(ssize_t num_allocs, ssize_t total_size, ssize_t max_size) const - { - check_curr_delta(num_allocs, total_size); - check_total_delta(num_allocs, total_size); - check_max(num_allocs > mr.counts().max.allocs ? num_allocs : mr.counts().max.allocs, - max_size > mr.counts().max.size ? max_size : mr.counts().max.size); - } -}; - -} // namespace c4 - -#endif // _C4_LIBTEST_TEST_HPP_ diff --git a/thirdparty/ryml/ext/c4core/test/printintegers.py b/thirdparty/ryml/ext/c4core/test/printintegers.py deleted file mode 100644 index de7532491..000000000 --- a/thirdparty/ryml/ext/c4core/test/printintegers.py +++ /dev/null @@ -1,107 +0,0 @@ - - -def nb(val): - return [val-1, val, val+1] - - -def ipowers2(min, max): - vals = [] - v = int(min / 2) - while v < -10: - vals += nb(v) - v = int(v / 2) - vals += upowers2(max) - return vals - - -def upowers2(max): - vals = [] - v = 16 - while v < max: - vals += nb(v) - v *= 2 - return vals - - -def ipowers10(min, max): - vals = [] - v = -100 - while v > min: - vals += nb(v) - v *= 10 - vals += upowers10(max) - return vals - - -def upowers10(max): - vals = [] - v = 10 - while v < max: - vals += nb(v) - v *= 10 - return vals - - -def idiv10(min, max): - vals = [] - v = int(min / 10) - while v < -10: - vals.append(v) - v = int(v / 10) - vals += udiv10(max) - return vals - - -def udiv10(max): - vals = [] - v = int(max / 10) - while v > 10: - vals += nb(v) - v = int(v / 10) - return vals - - -def ivals(bits): - min = -(1 << (bits-1)) - max = -min-1 - vals = [min, min+1, min+2, min+3, min+4, min+5] - vals += ipowers2(min, max) - vals += ipowers10(min, max) - vals += idiv10(min, max) - vals += [-11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] - vals += [max-5, max-4, max-3, max-2, max-1, max] - return sorted(list(set(vals))) - - -def uvals(bits): - max = (1 << bits) - 1 - vals = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] - vals += upowers2(max) - vals += upowers10(max) - vals += udiv10(max) - vals += [max-5, max-4, max-3, max-2, max-1, max] - return sorted(list(set(vals))) - - - -def p(v): - return f' nc({v}, "{v}", "{hex(v)}", "{oct(v)}", "{bin(v)}"),' - - -def pn(numbits, fn): - print() - for a in fn(numbits): - print(p(a)) - - -pn(8, ivals) -pn(8, uvals) - -pn(16, ivals) -pn(16, uvals) - -pn(32, ivals) -pn(32, uvals) - -pn(64, ivals) -pn(64, uvals) diff --git a/thirdparty/ryml/ext/c4core/test/test_allocator.cpp b/thirdparty/ryml/ext/c4core/test/test_allocator.cpp deleted file mode 100644 index 78d0daf88..000000000 --- a/thirdparty/ryml/ext/c4core/test/test_allocator.cpp +++ /dev/null @@ -1,246 +0,0 @@ -#ifndef C4CORE_SINGLE_HEADER -#include "c4/allocator.hpp" -#endif - -#include "c4/test.hpp" -#include "c4/libtest/supprwarn_push.hpp" - -#include -#include -#include - -namespace c4 { - -template< class T > using small_adapter = c4::small_allocator< T >; -template< class T > using small_adapter_mr = c4::small_allocator_mr< T >; - -#define _c4definealloctypes(Alloc) \ -using AllocInt = typename Alloc::template rebind::other;\ -using AllocChar = typename Alloc::template rebind::other;\ -using _string = std::basic_string< char, std::char_traits, AllocChar >;\ -using AllocString = typename Alloc::template rebind<_string>::other;\ -using AllocPair = typename Alloc::template rebind>::other;\ -using _vector_int = std::vector;\ -using _vector_string = std::vector<_string, AllocString >;\ -using _map_string_int = std::map<_string, int, std::less<_string>, AllocPair >; - -//----------------------------------------------------------------------------- -template< class Alloc > -void test_traits_compat_construct(typename Alloc::value_type const& val, Alloc &a) -{ - using atraits = std::allocator_traits< Alloc >; - using value_type = typename Alloc::value_type; - - value_type *mem = a.allocate(1); - REQUIRE_NE(mem, nullptr); - atraits::construct(a, mem, val); - CHECK_EQ(*mem, val); - - atraits::destroy(a, mem); - a.deallocate(mem, 1); -} - -TEST_CASE("allocator.traits_compat_construct") -{ - allocator a; - test_traits_compat_construct(1, a); -} - -TEST_CASE("small_allocator.traits_compat_construct") -{ - small_allocator a; - test_traits_compat_construct(1, a); -} - -TEST_CASE("allocator_mr_global.traits_compat_construct") -{ - allocator_mr a; - test_traits_compat_construct(1, a); -} - -TEST_CASE("allocator_mr_linear.traits_compat_construct") -{ - MemoryResourceLinear mr(1024); - allocator_mr a(&mr); - test_traits_compat_construct(1, a); -} - -TEST_CASE("allocator_mr_linear_arr.traits_compat_construct") -{ - MemoryResourceLinearArr<1024> mr; - allocator_mr a(&mr); - test_traits_compat_construct(1, a); -} - -TEST_CASE("small_allocator_mr_global.traits_compat_construct") -{ - small_allocator_mr a; - test_traits_compat_construct(1, a); -} - -TEST_CASE("small_allocator_mr_linear.traits_compat_construct") -{ - MemoryResourceLinear mr(1024); - small_allocator_mr a(&mr); - test_traits_compat_construct(1, a); -} - -TEST_CASE("small_allocator_mr_linear_arr.traits_compat_construct") -{ - MemoryResourceLinearArr<1024> mr; - small_allocator_mr a(&mr); - test_traits_compat_construct(1, a); -} - -//----------------------------------------------------------------------------- - -template< class Alloc > -void clear_mr(Alloc a) -{ - auto mrl = dynamic_cast(a.resource()); - if(mrl) - { - mrl->clear(); - } -} - -template< class Alloc > -void do_std_containers_test(Alloc alloc) -{ - _c4definealloctypes(Alloc); - - { - _string v(alloc); - v.reserve(256); - v = "adskjhsdfkjdflkjsdfkjhsdfkjh"; - CHECK_EQ(v, "adskjhsdfkjdflkjsdfkjhsdfkjh"); - } - - clear_mr(alloc); - - { - int arr[128]; - for(int &i : arr) - { - i = 42; - } - _vector_int vi(arr, arr+C4_COUNTOF(arr), alloc); - for(int i : vi) - { - CHECK_EQ(i, 42); - } - } - - clear_mr(alloc); - - { - AllocChar a = alloc; - _vector_string v({"foo", "bar", "baz", "bat", "bax"}, a); - CHECK_EQ(v.size(), 5); - CHECK_EQ(v[0], "foo"); - CHECK_EQ(v[1], "bar"); - CHECK_EQ(v[2], "baz"); - CHECK_EQ(v[3], "bat"); - CHECK_EQ(v[4], "bax"); - } - - clear_mr(alloc); - - { - AllocString a = alloc; - _vector_string v(a); - v.resize(4); - int count = 0; - for(auto &s : v) - { - _string ss(size_t(64), (char)('0' + count++)); - s = ss; - } - } - - clear_mr(alloc); - - { -#if !defined(__GNUC__) || (__GNUC__ >= 5) - /* constructor does not exist on gcc < 5) */ - AllocPair a = alloc; - _map_string_int v(a); -#else - _map_string_int v; -#endif - CHECK_EQ(v.size(), 0); - v["foo"] = 0; - v["bar"] = 1; - v["baz"] = 2; - v["bat"] = 3; - CHECK_EQ(v.size(), 4); - CHECK_EQ(v["foo"], 0); - CHECK_EQ(v["bar"], 1); - CHECK_EQ(v["baz"], 2); - CHECK_EQ(v["bat"], 3); - } -} - -TEST_CASE("allocator_global.std_containers") -{ - allocator a; - do_std_containers_test(a); -} - -TEST_CASE("small_allocator_global.std_containers") -{ - /* this is failing, investigate - small_allocator a; - do_std_containers_test(a); - */ -} - -TEST_CASE("allocator_mr_global.std_containers") -{ - allocator_mr a; - do_std_containers_test(a); -} - -TEST_CASE("allocator_mr_linear.std_containers") -{ - MemoryResourceLinear mr(1024); - allocator_mr a(&mr); - do_std_containers_test(a); -} - -TEST_CASE("allocator_mr_linear_arr.std_containers") -{ - MemoryResourceLinearArr<1024> mr; - allocator_mr a(&mr); - do_std_containers_test(a); -} - -TEST_CASE("small_allocator_mr_global.std_containers") -{ - /* this is failing, investigate - small_allocator_mr a; - do_std_containers_test(a); - */ -} - -TEST_CASE("small_allocator_mr_linear.std_containers") -{ - /* this is failing, investigate - MemoryResourceLinear mr(1024); - small_allocator_mr a(&mr); - do_std_containers_test(a); - */ -} - -TEST_CASE("small_allocator_mr_linear_arr.std_containers") -{ - /* this is failing, investigate - MemoryResourceLinearArr<1024> mr; - small_allocator_mr a(&mr); - do_std_containers_test(a); - */ -} - -} // namespace c4 - -#include "c4/libtest/supprwarn_pop.hpp" diff --git a/thirdparty/ryml/ext/c4core/test/test_base64.cpp b/thirdparty/ryml/ext/c4core/test/test_base64.cpp deleted file mode 100644 index e638a0d81..000000000 --- a/thirdparty/ryml/ext/c4core/test/test_base64.cpp +++ /dev/null @@ -1,265 +0,0 @@ -#include "c4/test.hpp" -#ifndef C4CORE_SINGLE_HEADER -#include "c4/std/string.hpp" -#include "c4/std/vector.hpp" -#include "c4/format.hpp" -#include "c4/base64.hpp" -#endif - -#include "c4/libtest/supprwarn_push.hpp" - -#include - -C4_SUPPRESS_WARNING_MSVC_WITH_PUSH(4310) // cast truncates constant value - -namespace c4 { - -namespace detail { -void base64_test_tables(); -TEST_CASE("base64.infrastructure") -{ - #ifndef NDEBUG - detail::base64_test_tables(); - #endif -} -// Since some the macros in c4/cpu.cpp cannot identify endanness at compile -// time, we use a simple runtime endianness-detection routine. -bool is_little_endian() -{ - unsigned long const v = 1UL; - unsigned char b[sizeof(v)]; - std::memcpy(&b[0], &v, sizeof(v)); - return !!b[0]; -} -} // namespace detail - -csubstr native(csubstr little_endian, csubstr big_endian) -{ - return detail::is_little_endian() ? little_endian : big_endian; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -template -void test_base64_str_roundtrip(T const& val, csubstr expected, U *ws) -{ - char buf_[512]; - substr buf(buf_); - - csubstr encoded = to_chars_sub(buf, fmt::base64(val)); - CHECK(base64_valid(encoded)); - CHECK_EQ(encoded, expected); - CHECK_EQ(encoded.len % 4, 0); - - auto req = fmt::base64(*ws); - size_t written = from_chars(encoded, &req); - CHECK_EQ(ws->first(written), val); -} - -template -void test_base64_roundtrip(T const& val, csubstr expected) -{ - char buf_[512]; - substr buf(buf_); - - csubstr encoded = to_chars_sub(buf, fmt::base64(val)); - CHECK(base64_valid(encoded)); - CHECK_EQ(encoded, expected); - CHECK_EQ(encoded.len % 4, 0); - - T ws = {}; - auto req = fmt::base64(ws); - size_t written = from_chars(encoded, &req); - CHECK_EQ(written, sizeof(T)); - CHECK_EQ(ws, val); -} - -template -struct base64_test_pair -{ - T val; - csubstr encoded; -}; - -base64_test_pair base64_str_pairs[] = { -#define __(val, expected) {csubstr(val), csubstr(expected)} - __("" , "" ), - __("0" , "MA==" ), - __("1" , "MQ==" ), - __("2" , "Mg==" ), - __("3" , "Mw==" ), - __("4" , "NA==" ), - __("5" , "NQ==" ), - __("6" , "Ng==" ), - __("7" , "Nw==" ), - __("8" , "OA==" ), - __("9" , "OQ==" ), - __("10" , "MTA=" ), - __("123" , "MTIz" ), - __("1234" , "MTIzNA==" ), - __("1235" , "MTIzNQ==" ), - __("Man" , "TWFu" ), - __("Ma" , "TWE=" ), - __("M" , "TQ==" ), - __("deadbeef" , "ZGVhZGJlZWY=" ), - __("any carnal pleasure.", "YW55IGNhcm5hbCBwbGVhc3VyZS4="), - __("any carnal pleasure" , "YW55IGNhcm5hbCBwbGVhc3VyZQ=="), - __("any carnal pleasur" , "YW55IGNhcm5hbCBwbGVhc3Vy" ), - __("any carnal pleasu" , "YW55IGNhcm5hbCBwbGVhc3U=" ), - __("any carnal pleas" , "YW55IGNhcm5hbCBwbGVhcw==" ), - __( "pleasure.", "cGxlYXN1cmUu" ), - __( "leasure.", "bGVhc3VyZS4=" ), - __( "easure.", "ZWFzdXJlLg==" ), - __( "asure.", "YXN1cmUu" ), - __( "sure.", "c3VyZS4=" ), -#undef __ -}; - - -TEST_CASE("base64.str") -{ - char buf_[512]; - substr buf(buf_); - for(auto p : base64_str_pairs) - { - INFO(p.val); - test_base64_str_roundtrip(p.val, p.encoded, &buf); - } -} - -TEST_CASE_TEMPLATE("base64.8bit", T, int8_t, uint8_t) -{ - base64_test_pair pairs[] = { - {(T) 0, csubstr("AA==")}, - {(T) 1, csubstr("AQ==")}, - {(T) 2, csubstr("Ag==")}, - {(T) 3, csubstr("Aw==")}, - {(T) 4, csubstr("BA==")}, - {(T) 5, csubstr("BQ==")}, - {(T) 6, csubstr("Bg==")}, - {(T) 7, csubstr("Bw==")}, - {(T) 8, csubstr("CA==")}, - {(T) 9, csubstr("CQ==")}, - {(T) 10, csubstr("Cg==")}, - {(T) 11, csubstr("Cw==")}, - {(T) 12, csubstr("DA==")}, - {(T) 13, csubstr("DQ==")}, - {(T) 14, csubstr("Dg==")}, - {(T) 15, csubstr("Dw==")}, - {(T) 16, csubstr("EA==")}, - {(T) 17, csubstr("EQ==")}, - {(T) 18, csubstr("Eg==")}, - {(T) 19, csubstr("Ew==")}, - {(T) 20, csubstr("FA==")}, - {(T)127, csubstr("fw==")}, - {(T)128, csubstr("gA==")}, - {(T)254, csubstr("/g==")}, - {(T)255, csubstr("/w==")}, - }; - for(auto p : pairs) - { - INFO("val=" << (int)p.val << " expected=" << p.encoded); - test_base64_roundtrip(p.val, p.encoded); - } -} - -TEST_CASE_TEMPLATE("base64.16bit", T, int16_t, uint16_t) -{ - base64_test_pair pairs[] = { - { 0, native("AAA=", "AAA=")}, - { 1, native("AQA=", "AAE=")}, - { 2, native("AgA=", "AAI=")}, - { 3, native("AwA=", "AAM=")}, - { 4, native("BAA=", "AAQ=")}, - { 5, native("BQA=", "AAU=")}, - { 6, native("BgA=", "AAY=")}, - { 7, native("BwA=", "AAc=")}, - { 8, native("CAA=", "AAg=")}, - { 9, native("CQA=", "AAk=")}, - { 10, native("CgA=", "AAo=")}, - {1234, native("0gQ=", "BNI=")}, - }; - for(auto p : pairs) - { - INFO("val=" << p.val << " expected=" << p.encoded); - test_base64_roundtrip(p.val, p.encoded); - } -} - -TEST_CASE_TEMPLATE("base64.32bit", T, int32_t, uint32_t) -{ - base64_test_pair pairs[] = { - { 0, native("AAAAAA==", "AAAAAA==")}, - { 1, native("AQAAAA==", "AAAAAQ==")}, - { 2, native("AgAAAA==", "AAAAAg==")}, - { 3, native("AwAAAA==", "AAAAAw==")}, - { 4, native("BAAAAA==", "AAAABA==")}, - { 5, native("BQAAAA==", "AAAABQ==")}, - { 6, native("BgAAAA==", "AAAABg==")}, - { 7, native("BwAAAA==", "AAAABw==")}, - { 8, native("CAAAAA==", "AAAACA==")}, - { 9, native("CQAAAA==", "AAAACQ==")}, - { 10, native("CgAAAA==", "AAAACg==")}, - {1234, native("0gQAAA==", "AAAE0g==")}, - }; - for(auto p : pairs) - { - INFO("val=" << p.val << " expected=" << p.encoded); - test_base64_roundtrip(p.val, p.encoded); - } -} - -TEST_CASE_TEMPLATE("base64.64bit", T, int64_t, uint64_t) -{ - base64_test_pair pairs[] = { - { 0, native("AAAAAAAAAAA=", "AAAAAAAAAAA=")}, - { 1, native("AQAAAAAAAAA=", "AAAAAAAAAAE=")}, - { 2, native("AgAAAAAAAAA=", "AAAAAAAAAAI=")}, - { 3, native("AwAAAAAAAAA=", "AAAAAAAAAAM=")}, - { 4, native("BAAAAAAAAAA=", "AAAAAAAAAAQ=")}, - { 5, native("BQAAAAAAAAA=", "AAAAAAAAAAU=")}, - { 6, native("BgAAAAAAAAA=", "AAAAAAAAAAY=")}, - { 7, native("BwAAAAAAAAA=", "AAAAAAAAAAc=")}, - { 8, native("CAAAAAAAAAA=", "AAAAAAAAAAg=")}, - { 9, native("CQAAAAAAAAA=", "AAAAAAAAAAk=")}, - { 10, native("CgAAAAAAAAA=", "AAAAAAAAAAo=")}, - {1234, native("0gQAAAAAAAA=", "AAAAAAAABNI=")}, - {0xdeadbeef, native("776t3gAAAAA=", "AAAAAN6tvu8=")}, - }; - for(auto p : pairs) - { - INFO("val=" << p.val << " expected=" << p.encoded); - test_base64_roundtrip(p.val, p.encoded); - } -} - -TEST_CASE("base64.high_bits_u32") -{ - test_base64_roundtrip(UINT32_C(0xdeadbeef), native("776t3g==", "3q2+7w==")); - test_base64_roundtrip(UINT32_MAX, native("/////w==", "/////w==")); -} - -TEST_CASE("base64.high_bits_i32") -{ - test_base64_roundtrip(INT32_C(0x7fffffff), native("////fw==", "f////w==")); - test_base64_roundtrip(INT32_MAX, native("////fw==", "f////w==")); -} - -TEST_CASE("base64.high_bits_u64") -{ - test_base64_roundtrip(UINT64_MAX, native("//////////8=", "//////////8=")); -} - -TEST_CASE("base64.high_bits_i64") -{ - test_base64_roundtrip(INT64_MAX, native("/////////38=", "f/////////8=")); -} - -} // namespace c4 - -C4_SUPPRESS_WARNING_MSVC_POP - -#include "c4/libtest/supprwarn_pop.hpp" diff --git a/thirdparty/ryml/ext/c4core/test/test_bitmask.cpp b/thirdparty/ryml/ext/c4core/test/test_bitmask.cpp deleted file mode 100644 index e7137d2a5..000000000 --- a/thirdparty/ryml/ext/c4core/test/test_bitmask.cpp +++ /dev/null @@ -1,385 +0,0 @@ -#include -#include - -#ifndef C4CORE_SINGLE_HEADER -#include -#include -#endif - -#include - -#include "./test_enum_common.hpp" - -template -void cmp_enum(Enum lhs, Enum rhs) -{ - using I = typename std::underlying_type::type; - CHECK_EQ(static_cast(lhs), static_cast(rhs)); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - - -TEST_CASE("str2bm.simple_bitmask") -{ - using namespace c4; - std::vector str; - - CHECK_EQ(BM_NONE, str2bm("BM_NONE")); - CHECK_EQ(BM_NONE, str2bm("NONE")); - CHECK_EQ(BM_NONE, str2bm("0")); - CHECK_EQ(BM_NONE, str2bm("0x0")); - - CHECK_EQ(BM_FOO, str2bm("BM_FOO")); - CHECK_EQ(BM_FOO, str2bm("FOO")); - CHECK_EQ(BM_FOO, str2bm("1")); - CHECK_EQ(BM_FOO, str2bm("0x1")); - CHECK_EQ(BM_FOO, str2bm("BM_NONE|0x1")); - - CHECK_EQ(BM_BAR, str2bm("BM_BAR")); - CHECK_EQ(BM_BAR, str2bm("BAR")); - CHECK_EQ(BM_BAR, str2bm("2")); - CHECK_EQ(BM_BAR, str2bm("0x2")); - CHECK_EQ(BM_BAR, str2bm("BM_NONE|0x2")); - - CHECK_EQ(BM_BAZ, str2bm("BM_BAZ")); - CHECK_EQ(BM_BAZ, str2bm("BAZ")); - CHECK_EQ(BM_BAZ, str2bm("4")); - CHECK_EQ(BM_BAZ, str2bm("0x4")); - - CHECK_EQ(BM_FOO_BAR, str2bm("BM_FOO|BM_BAR")); - CHECK_EQ(BM_FOO_BAR, str2bm("BM_FOO|BAR")); - CHECK_EQ(BM_FOO_BAR, str2bm("FOO|BM_BAR")); - CHECK_EQ(BM_FOO_BAR, str2bm("BM_FOO_BAR")); - CHECK_EQ(BM_FOO_BAR, str2bm("FOO_BAR")); - CHECK_EQ(BM_FOO_BAR, str2bm("FOO|BAR")); - CHECK_EQ(BM_FOO_BAR, str2bm("0x1|0x2")); - CHECK_EQ(BM_FOO_BAR, str2bm("1|2")); - CHECK_EQ(BM_FOO_BAR, str2bm("0x3")); - CHECK_EQ(BM_FOO_BAR, str2bm("3")); - - CHECK_EQ(BM_FOO_BAR_BAZ, str2bm("BM_FOO|BM_BAR|BM_BAZ")); - CHECK_EQ(BM_FOO_BAR_BAZ, str2bm("BM_FOO|BM_BAR|BAZ")); - CHECK_EQ(BM_FOO_BAR_BAZ, str2bm("BM_FOO|BAR|BM_BAZ")); - CHECK_EQ(BM_FOO_BAR_BAZ, str2bm("FOO|BM_BAR|BM_BAZ")); - CHECK_EQ(BM_FOO_BAR_BAZ, str2bm("FOO|BM_BAR|BAZ")); - CHECK_EQ(BM_FOO_BAR_BAZ, str2bm("FOO|BAR|BM_BAZ")); - CHECK_EQ(BM_FOO_BAR_BAZ, str2bm("FOO|BAR|BAZ")); - CHECK_EQ(BM_FOO_BAR_BAZ, str2bm("FOO_BAR|BAZ")); - CHECK_EQ(BM_FOO_BAR_BAZ, str2bm("BM_FOO_BAR|BAZ")); - CHECK_EQ(BM_FOO_BAR_BAZ, str2bm("0x1|BAR|BAZ")); - CHECK_EQ(BM_FOO_BAR_BAZ, str2bm("FOO|0x2|BAZ")); - CHECK_EQ(BM_FOO_BAR_BAZ, str2bm("FOO|BAR|0x4")); - CHECK_EQ(BM_FOO_BAR_BAZ, str2bm("0x1|0x2|0x4")); - CHECK_EQ(BM_FOO_BAR_BAZ, str2bm("0x7")); - CHECK_EQ(BM_FOO_BAR_BAZ, str2bm("7")); -} - -TEST_CASE("str2bm.scoped_bitmask") -{ - using namespace c4; - std::vector str; - using bmt = MyBitmaskClass; - - cmp_enum(bmt::BM_NONE, (bmt)str2bm("MyBitmaskClass::BM_NONE")); - cmp_enum(bmt::BM_FOO, (bmt)str2bm("MyBitmaskClass::BM_FOO")); - cmp_enum(bmt::BM_BAR, (bmt)str2bm("MyBitmaskClass::BM_BAR")); - cmp_enum(bmt::BM_BAZ, (bmt)str2bm("MyBitmaskClass::BM_BAZ")); - cmp_enum(bmt::BM_FOO_BAR, (bmt)str2bm("MyBitmaskClass::BM_FOO_BAR")); - cmp_enum(bmt::BM_FOO_BAR_BAZ, (bmt)str2bm("MyBitmaskClass::BM_FOO_BAR_BAZ")); - cmp_enum(bmt::BM_NONE, (bmt)str2bm("BM_NONE")); - cmp_enum(bmt::BM_FOO, (bmt)str2bm("BM_FOO")); - cmp_enum(bmt::BM_BAR, (bmt)str2bm("BM_BAR")); - cmp_enum(bmt::BM_BAZ, (bmt)str2bm("BM_BAZ")); - cmp_enum(bmt::BM_FOO_BAR, (bmt)str2bm("BM_FOO_BAR")); - cmp_enum(bmt::BM_FOO_BAR_BAZ, (bmt)str2bm("BM_FOO_BAR_BAZ")); - cmp_enum(bmt::BM_NONE, (bmt)str2bm("NONE")); - cmp_enum(bmt::BM_FOO, (bmt)str2bm("FOO")); - cmp_enum(bmt::BM_BAR, (bmt)str2bm("BAR")); - cmp_enum(bmt::BM_BAZ, (bmt)str2bm("BAZ")); - cmp_enum(bmt::BM_FOO_BAR, (bmt)str2bm("FOO_BAR")); - cmp_enum(bmt::BM_FOO_BAR_BAZ, (bmt)str2bm("FOO_BAR_BAZ")); - - cmp_enum(bmt::BM_NONE, (bmt)str2bm("NONE")); - cmp_enum(bmt::BM_NONE, (bmt)str2bm("BM_NONE")); - cmp_enum(bmt::BM_NONE, (bmt)str2bm("MyBitmaskClass::BM_NONE")); - cmp_enum(bmt::BM_NONE, (bmt)str2bm("0")); - cmp_enum(bmt::BM_NONE, (bmt)str2bm("0x0")); - cmp_enum(bmt::BM_FOO, (bmt)str2bm("FOO")); - cmp_enum(bmt::BM_FOO, (bmt)str2bm("BM_FOO")); - cmp_enum(bmt::BM_FOO, (bmt)str2bm("MyBitmaskClass::BM_FOO")); - cmp_enum(bmt::BM_FOO, (bmt)str2bm("1")); - cmp_enum(bmt::BM_FOO, (bmt)str2bm("0x1")); - cmp_enum(bmt::BM_FOO, (bmt)str2bm("NONE|0x1")); - cmp_enum(bmt::BM_FOO, (bmt)str2bm("BM_NONE|0x1")); - cmp_enum(bmt::BM_FOO, (bmt)str2bm("MyBitmaskClass::BM_NONE|0x1")); - cmp_enum(bmt::BM_BAR, (bmt)str2bm("BAR")); - cmp_enum(bmt::BM_BAR, (bmt)str2bm("BM_BAR")); - cmp_enum(bmt::BM_BAR, (bmt)str2bm("MyBitmaskClass::BM_BAR")); - cmp_enum(bmt::BM_BAR, (bmt)str2bm("2")); - cmp_enum(bmt::BM_BAR, (bmt)str2bm("0x2")); - cmp_enum(bmt::BM_BAZ, (bmt)str2bm("BAZ")); - cmp_enum(bmt::BM_BAZ, (bmt)str2bm("BM_BAZ")); - cmp_enum(bmt::BM_BAZ, (bmt)str2bm("MyBitmaskClass::BM_BAZ")); - cmp_enum(bmt::BM_BAR, (bmt)str2bm("BM_NONE|0x2")); - cmp_enum(bmt::BM_BAR, (bmt)str2bm("MyBitmaskClass::BM_NONE|0x2")); - cmp_enum(bmt::BM_BAZ, (bmt)str2bm("4")); - cmp_enum(bmt::BM_BAZ, (bmt)str2bm("0x4")); - cmp_enum(bmt::BM_FOO_BAR, (bmt)str2bm("BM_FOO|BM_BAR")); - cmp_enum(bmt::BM_FOO_BAR, (bmt)str2bm("MyBitmaskClass::BM_FOO|MyBitmaskClass::BM_BAR")); - cmp_enum(bmt::BM_FOO_BAR, (bmt)str2bm("BM_FOO|BAR")); - cmp_enum(bmt::BM_FOO_BAR, (bmt)str2bm("MyBitmaskClass::BM_FOO|BAR")); - cmp_enum(bmt::BM_FOO_BAR, (bmt)str2bm("FOO|BM_BAR")); - cmp_enum(bmt::BM_FOO_BAR, (bmt)str2bm("FOO|MyBitmaskClass::BM_BAR")); - cmp_enum(bmt::BM_FOO_BAR, (bmt)str2bm("BM_FOO_BAR")); - cmp_enum(bmt::BM_FOO_BAR, (bmt)str2bm("MyBitmaskClass::BM_FOO_BAR")); - cmp_enum(bmt::BM_FOO_BAR, (bmt)str2bm("FOO_BAR")); - cmp_enum(bmt::BM_FOO_BAR, (bmt)str2bm("FOO|BAR")); - cmp_enum(bmt::BM_FOO_BAR, (bmt)str2bm("0x1|0x2")); - cmp_enum(bmt::BM_FOO_BAR, (bmt)str2bm("1|2")); - cmp_enum(bmt::BM_FOO_BAR, (bmt)str2bm("0x3")); - cmp_enum(bmt::BM_FOO_BAR, (bmt)str2bm("3")); - cmp_enum(bmt::BM_FOO_BAR_BAZ, (bmt)str2bm("BM_FOO|BM_BAR|BM_BAZ")); - cmp_enum(bmt::BM_FOO_BAR_BAZ, (bmt)str2bm("MyBitmaskClass::BM_FOO|MyBitmaskClass::BM_BAR|MyBitmaskClass::BM_BAZ")); - cmp_enum(bmt::BM_FOO_BAR_BAZ, (bmt)str2bm("BM_FOO|BM_BAR|BAZ")); - cmp_enum(bmt::BM_FOO_BAR_BAZ, (bmt)str2bm("MyBitmaskClass::BM_FOO|MyBitmaskClass::BM_BAR|BAZ")); - cmp_enum(bmt::BM_FOO_BAR_BAZ, (bmt)str2bm("BM_FOO|BAR|BM_BAZ")); - cmp_enum(bmt::BM_FOO_BAR_BAZ, (bmt)str2bm("BM_FOO|BAR|MyBitmaskClass::BM_BAZ")); - cmp_enum(bmt::BM_FOO_BAR_BAZ, (bmt)str2bm("FOO|BM_BAR|BM_BAZ")); - cmp_enum(bmt::BM_FOO_BAR_BAZ, (bmt)str2bm("FOO|MyBitmaskClass::BM_BAR|MyBitmaskClass::BM_BAZ")); - cmp_enum(bmt::BM_FOO_BAR_BAZ, (bmt)str2bm("FOO|BM_BAR|BAZ")); - cmp_enum(bmt::BM_FOO_BAR_BAZ, (bmt)str2bm("FOO|MyBitmaskClass::BM_BAR|BAZ")); - cmp_enum(bmt::BM_FOO_BAR_BAZ, (bmt)str2bm("FOO|BAR|BM_BAZ")); - cmp_enum(bmt::BM_FOO_BAR_BAZ, (bmt)str2bm("FOO|BAR|MyBitmaskClass::BM_BAZ")); - cmp_enum(bmt::BM_FOO_BAR_BAZ, (bmt)str2bm("FOO|BAR|BAZ")); - cmp_enum(bmt::BM_FOO_BAR_BAZ, (bmt)str2bm("FOO_BAR|BAZ")); - cmp_enum(bmt::BM_FOO_BAR_BAZ, (bmt)str2bm("MyBitmaskClass::BM_FOO_BAR|BAZ")); - cmp_enum(bmt::BM_FOO_BAR_BAZ, (bmt)str2bm("0x1|BAR|BAZ")); - cmp_enum(bmt::BM_FOO_BAR_BAZ, (bmt)str2bm("FOO|0x2|BAZ")); - cmp_enum(bmt::BM_FOO_BAR_BAZ, (bmt)str2bm("FOO|BAR|0x4")); - cmp_enum(bmt::BM_FOO_BAR_BAZ, (bmt)str2bm("0x1|0x2|0x4")); - cmp_enum(bmt::BM_FOO_BAR_BAZ, (bmt)str2bm("0x7")); - cmp_enum(bmt::BM_FOO_BAR_BAZ, (bmt)str2bm("0x7")); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//---------------------------------------------------------------------------- - -template -const char* do_bm2str(Enum e, std::vector *s, c4::EnumOffsetType which) -{ - size_t len = c4::bm2str(e, nullptr, 0, which); - C4_CHECK(len > 0); - s->resize(len); - C4_CHECK(s->data() != nullptr); - c4::bm2str(e, s->data(), s->size(), which); - return s->data(); -} - -TEST_CASE("bm2str.simple_bitmask") -{ - using namespace c4; - std::vector str; - - CHECK_STREQ(do_bm2str(BM_NONE, &str, EOFFS_NONE), "BM_NONE"); - CHECK_STREQ(do_bm2str(BM_FOO, &str, EOFFS_NONE), "BM_FOO"); - CHECK_STREQ(do_bm2str(BM_BAR, &str, EOFFS_NONE), "BM_BAR"); - CHECK_STREQ(do_bm2str(BM_BAZ, &str, EOFFS_NONE), "BM_BAZ"); - CHECK_STREQ(do_bm2str(BM_FOO_BAR, &str, EOFFS_NONE), "BM_FOO_BAR"); - CHECK_STREQ(do_bm2str(BM_FOO_BAR_BAZ, &str, EOFFS_NONE), "BM_FOO_BAR_BAZ"); - CHECK_STREQ(do_bm2str(BM_NONE, &str, EOFFS_CLS ), "BM_NONE"); - CHECK_STREQ(do_bm2str(BM_FOO, &str, EOFFS_CLS ), "BM_FOO"); - CHECK_STREQ(do_bm2str(BM_BAR, &str, EOFFS_CLS ), "BM_BAR"); - CHECK_STREQ(do_bm2str(BM_BAZ, &str, EOFFS_CLS ), "BM_BAZ"); - CHECK_STREQ(do_bm2str(BM_FOO_BAR, &str, EOFFS_CLS ), "BM_FOO_BAR"); - CHECK_STREQ(do_bm2str(BM_FOO_BAR_BAZ, &str, EOFFS_CLS ), "BM_FOO_BAR_BAZ"); - CHECK_STREQ(do_bm2str(BM_NONE, &str, EOFFS_PFX ), "NONE"); - CHECK_STREQ(do_bm2str(BM_FOO, &str, EOFFS_PFX ), "FOO"); - CHECK_STREQ(do_bm2str(BM_BAR, &str, EOFFS_PFX ), "BAR"); - CHECK_STREQ(do_bm2str(BM_BAZ, &str, EOFFS_PFX ), "BAZ"); - CHECK_STREQ(do_bm2str(BM_FOO_BAR, &str, EOFFS_PFX ), "FOO_BAR"); - CHECK_STREQ(do_bm2str(BM_FOO_BAR_BAZ, &str, EOFFS_PFX ), "FOO_BAR_BAZ"); -} - -TEST_CASE("bm2str.scoped_bitmask") -{ - using namespace c4; - std::vector str; - - CHECK_STREQ(do_bm2str(MyBitmaskClass::BM_NONE, &str, EOFFS_NONE), "MyBitmaskClass::BM_NONE"); - CHECK_STREQ(do_bm2str(MyBitmaskClass::BM_FOO, &str, EOFFS_NONE), "MyBitmaskClass::BM_FOO"); - CHECK_STREQ(do_bm2str(MyBitmaskClass::BM_BAR, &str, EOFFS_NONE), "MyBitmaskClass::BM_BAR"); - CHECK_STREQ(do_bm2str(MyBitmaskClass::BM_BAZ, &str, EOFFS_NONE), "MyBitmaskClass::BM_BAZ"); - CHECK_STREQ(do_bm2str(MyBitmaskClass::BM_FOO_BAR, &str, EOFFS_NONE), "MyBitmaskClass::BM_FOO_BAR"); - CHECK_STREQ(do_bm2str(MyBitmaskClass::BM_FOO_BAR_BAZ, &str, EOFFS_NONE), "MyBitmaskClass::BM_FOO_BAR_BAZ"); - CHECK_STREQ(do_bm2str(MyBitmaskClass::BM_NONE, &str, EOFFS_CLS ), "BM_NONE"); - CHECK_STREQ(do_bm2str(MyBitmaskClass::BM_FOO, &str, EOFFS_CLS ), "BM_FOO"); - CHECK_STREQ(do_bm2str(MyBitmaskClass::BM_BAR, &str, EOFFS_CLS ), "BM_BAR"); - CHECK_STREQ(do_bm2str(MyBitmaskClass::BM_BAZ, &str, EOFFS_CLS ), "BM_BAZ"); - CHECK_STREQ(do_bm2str(MyBitmaskClass::BM_FOO_BAR, &str, EOFFS_CLS ), "BM_FOO_BAR"); - CHECK_STREQ(do_bm2str(MyBitmaskClass::BM_FOO_BAR_BAZ, &str, EOFFS_CLS ), "BM_FOO_BAR_BAZ"); - CHECK_STREQ(do_bm2str(MyBitmaskClass::BM_NONE, &str, EOFFS_PFX ), "NONE"); - CHECK_STREQ(do_bm2str(MyBitmaskClass::BM_FOO, &str, EOFFS_PFX ), "FOO"); - CHECK_STREQ(do_bm2str(MyBitmaskClass::BM_BAR, &str, EOFFS_PFX ), "BAR"); - CHECK_STREQ(do_bm2str(MyBitmaskClass::BM_BAZ, &str, EOFFS_PFX ), "BAZ"); - CHECK_STREQ(do_bm2str(MyBitmaskClass::BM_FOO_BAR, &str, EOFFS_PFX ), "FOO_BAR"); - CHECK_STREQ(do_bm2str(MyBitmaskClass::BM_FOO_BAR_BAZ, &str, EOFFS_PFX ), "FOO_BAR_BAZ"); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//---------------------------------------------------------------------------- - -template -std::string do_bm2stream(Enum e, c4::EnumOffsetType which) -{ - std::stringstream ss; - c4::bm2stream(ss, e, which); - return ss.str(); -} - -TEST_CASE("bm2stream.simple_bitmask") -{ - using namespace c4; - - CHECK_EQ(do_bm2stream(BM_NONE, EOFFS_NONE), "BM_NONE"); - CHECK_EQ(do_bm2stream(BM_FOO, EOFFS_NONE), "BM_FOO"); - CHECK_EQ(do_bm2stream(BM_BAR, EOFFS_NONE), "BM_BAR"); - CHECK_EQ(do_bm2stream(BM_BAZ, EOFFS_NONE), "BM_BAZ"); - CHECK_EQ(do_bm2stream(BM_FOO_BAR, EOFFS_NONE), "BM_FOO_BAR"); - CHECK_EQ(do_bm2stream(BM_FOO_BAR_BAZ, EOFFS_NONE), "BM_FOO_BAR_BAZ"); - CHECK_EQ(do_bm2stream(BM_NONE, EOFFS_CLS ), "BM_NONE"); - CHECK_EQ(do_bm2stream(BM_FOO, EOFFS_CLS ), "BM_FOO"); - CHECK_EQ(do_bm2stream(BM_BAR, EOFFS_CLS ), "BM_BAR"); - CHECK_EQ(do_bm2stream(BM_BAZ, EOFFS_CLS ), "BM_BAZ"); - CHECK_EQ(do_bm2stream(BM_FOO_BAR, EOFFS_CLS ), "BM_FOO_BAR"); - CHECK_EQ(do_bm2stream(BM_FOO_BAR_BAZ, EOFFS_CLS ), "BM_FOO_BAR_BAZ"); - CHECK_EQ(do_bm2stream(BM_NONE, EOFFS_PFX ), "NONE"); - CHECK_EQ(do_bm2stream(BM_FOO, EOFFS_PFX ), "FOO"); - CHECK_EQ(do_bm2stream(BM_BAR, EOFFS_PFX ), "BAR"); - CHECK_EQ(do_bm2stream(BM_BAZ, EOFFS_PFX ), "BAZ"); - CHECK_EQ(do_bm2stream(BM_FOO_BAR, EOFFS_PFX ), "FOO_BAR"); - CHECK_EQ(do_bm2stream(BM_FOO_BAR_BAZ, EOFFS_PFX ), "FOO_BAR_BAZ"); -} - -TEST_CASE("bm2stream.scoped_bitmask") -{ - using namespace c4; - - CHECK_EQ(do_bm2stream(MyBitmaskClass::BM_NONE, EOFFS_NONE), "MyBitmaskClass::BM_NONE"); - CHECK_EQ(do_bm2stream(MyBitmaskClass::BM_FOO, EOFFS_NONE), "MyBitmaskClass::BM_FOO"); - CHECK_EQ(do_bm2stream(MyBitmaskClass::BM_BAR, EOFFS_NONE), "MyBitmaskClass::BM_BAR"); - CHECK_EQ(do_bm2stream(MyBitmaskClass::BM_BAZ, EOFFS_NONE), "MyBitmaskClass::BM_BAZ"); - CHECK_EQ(do_bm2stream(MyBitmaskClass::BM_FOO_BAR, EOFFS_NONE), "MyBitmaskClass::BM_FOO_BAR"); - CHECK_EQ(do_bm2stream(MyBitmaskClass::BM_FOO_BAR_BAZ, EOFFS_NONE), "MyBitmaskClass::BM_FOO_BAR_BAZ"); - CHECK_EQ(do_bm2stream(MyBitmaskClass::BM_NONE, EOFFS_CLS ), "BM_NONE"); - CHECK_EQ(do_bm2stream(MyBitmaskClass::BM_FOO, EOFFS_CLS ), "BM_FOO"); - CHECK_EQ(do_bm2stream(MyBitmaskClass::BM_BAR, EOFFS_CLS ), "BM_BAR"); - CHECK_EQ(do_bm2stream(MyBitmaskClass::BM_BAZ, EOFFS_CLS ), "BM_BAZ"); - CHECK_EQ(do_bm2stream(MyBitmaskClass::BM_FOO_BAR, EOFFS_CLS ), "BM_FOO_BAR"); - CHECK_EQ(do_bm2stream(MyBitmaskClass::BM_FOO_BAR_BAZ, EOFFS_CLS ), "BM_FOO_BAR_BAZ"); - CHECK_EQ(do_bm2stream(MyBitmaskClass::BM_NONE, EOFFS_PFX ), "NONE"); - CHECK_EQ(do_bm2stream(MyBitmaskClass::BM_FOO, EOFFS_PFX ), "FOO"); - CHECK_EQ(do_bm2stream(MyBitmaskClass::BM_BAR, EOFFS_PFX ), "BAR"); - CHECK_EQ(do_bm2stream(MyBitmaskClass::BM_BAZ, EOFFS_PFX ), "BAZ"); - CHECK_EQ(do_bm2stream(MyBitmaskClass::BM_FOO_BAR, EOFFS_PFX ), "FOO_BAR"); - CHECK_EQ(do_bm2stream(MyBitmaskClass::BM_FOO_BAR_BAZ, EOFFS_PFX ), "FOO_BAR_BAZ"); -} - -TEST_CASE("bm2stream.simple_bitmask_without_null_symbol") -{ - using namespace c4; - - CHECK_EQ(do_bm2stream(BM_KABOOM, EOFFS_NONE), "KABOOM"); - CHECK_EQ(do_bm2stream((BmWithoutNull)0, EOFFS_NONE), "0"); -} - -TEST_CASE("bm2stream.bitmask_class_without_null_symbol") -{ - using namespace c4; - - CHECK_EQ(do_bm2stream(BmClassWithoutNull::BM_KABOOM, EOFFS_PFX), "KABOOM"); - CHECK_EQ(do_bm2stream((BmClassWithoutNull)0, EOFFS_NONE), "0"); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//---------------------------------------------------------------------------- - -// TODO -template -void test_bm2str() -{ - using namespace c4; - using I = typename std::underlying_type::type; - int combination_depth = 4; - auto syms = esyms(); - - std::vector indices; - std::string str; - std::vector ws; - I val = 0, res; - size_t len; - - for(int k = 1; k <= combination_depth; ++k) - { - indices.clear(); - indices.resize(static_cast(k)); - while(1) - { - str.clear(); - val = 0; - for(auto i : indices) - { - if(!str.empty()) str += '|'; - str += syms[i].name; - val |= static_cast(syms[i].value); - //printf("%d", i); - } - //len = bm2str(val); // needed length - //ws.resize(len); - //bm2str(val, &ws[0], len); - //printf(": %s (%zu) %s\n", str.c_str(), (uint64_t)val, ws.data()); - - res = str2bm(str.data()); - CHECK_EQ(res, val); - - len = bm2str(res); // needed length - ws.resize(len); - bm2str(val, &ws[0], len); - res = str2bm(ws.data()); - CHECK_EQ(res, val); - - // write a string with the bitmask as an int - c4::catrs(&ws, val); - res = str2bm(str.data()); - CHECK_EQ(res, val); - - bool carry = true; - for(size_t i = static_cast(k-1); i != size_t(-1); --i) - { - if(indices[i] + 1 < syms.size()) - { - ++indices[i]; - carry = false; - break; - } - else - { - indices[i] = 0; - } - } - if(carry) - { - break; - } - } // while(1) - } // for k -} diff --git a/thirdparty/ryml/ext/c4core/test/test_blob.cpp b/thirdparty/ryml/ext/c4core/test/test_blob.cpp deleted file mode 100644 index b803ba864..000000000 --- a/thirdparty/ryml/ext/c4core/test/test_blob.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef C4CORE_SINGLE_HEADER -#include "c4/blob.hpp" -#endif - -#include "c4/test.hpp" - -#ifdef __clang__ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wcast-align" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wcast-align" -#endif - - -namespace c4 { - -template -void test_blob() -{ - T v; - blob b(v); - CHECK_EQ((T*)b.buf, &v); - CHECK_EQ(b.len, sizeof(T)); - - blob b2 = b; - CHECK_EQ((T*)b2.buf, &v); - CHECK_EQ(b2.len, sizeof(T)); -} - -TEST_CASE("blob.basic") -{ - test_blob(); -} - - -#ifdef __clang__ -# pragma clang diagnostic pop -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#endif - -} // namespace c4 diff --git a/thirdparty/ryml/ext/c4core/test/test_char_traits.cpp b/thirdparty/ryml/ext/c4core/test/test_char_traits.cpp deleted file mode 100644 index 0f4e01518..000000000 --- a/thirdparty/ryml/ext/c4core/test/test_char_traits.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef C4CORE_SINGLE_HEADER -#include "c4/char_traits.hpp" -#endif - -#include "c4/test.hpp" - -namespace c4 { - -TEST_CASE("num_needed_chars.char") -{ - CHECK_EQ(num_needed_chars(0), 0); - CHECK_EQ(num_needed_chars(1), 1); - CHECK_EQ(num_needed_chars(2), 2); - CHECK_EQ(num_needed_chars(3), 3); - CHECK_EQ(num_needed_chars(4), 4); - for(int i = 0; i < 100; ++i) - { - CHECK_EQ(num_needed_chars(i), i); - } -} - -TEST_CASE("num_needed_chars.wchar_t") -{ -#if defined(_MSC_VER) -#pragma warning(push) -#pragma warning(disable : 4127) // C4127: conditional expression is constant -#endif - if(sizeof(wchar_t) == 2) - { - CHECK_EQ(num_needed_chars( 0), 0); - CHECK_EQ(num_needed_chars( 1), 1); - CHECK_EQ(num_needed_chars( 2), 1); - CHECK_EQ(num_needed_chars( 3), 2); - CHECK_EQ(num_needed_chars( 4), 2); - CHECK_EQ(num_needed_chars( 97), 49); - CHECK_EQ(num_needed_chars( 98), 49); - CHECK_EQ(num_needed_chars( 99), 50); - CHECK_EQ(num_needed_chars(100), 50); - CHECK_EQ(num_needed_chars(101), 51); - } - else if(sizeof(wchar_t) == 4) - { - CHECK_EQ(num_needed_chars( 0), 0); - CHECK_EQ(num_needed_chars( 1), 1); - CHECK_EQ(num_needed_chars( 2), 1); - CHECK_EQ(num_needed_chars( 3), 1); - CHECK_EQ(num_needed_chars( 4), 1); - CHECK_EQ(num_needed_chars( 5), 2); - CHECK_EQ(num_needed_chars( 6), 2); - CHECK_EQ(num_needed_chars( 7), 2); - CHECK_EQ(num_needed_chars( 8), 2); - CHECK_EQ(num_needed_chars( 93), 24); - CHECK_EQ(num_needed_chars( 94), 24); - CHECK_EQ(num_needed_chars( 95), 24); - CHECK_EQ(num_needed_chars( 96), 24); - CHECK_EQ(num_needed_chars( 97), 25); - CHECK_EQ(num_needed_chars( 98), 25); - CHECK_EQ(num_needed_chars( 99), 25); - CHECK_EQ(num_needed_chars(100), 25); - CHECK_EQ(num_needed_chars(101), 26); - } -#if defined(_MSC_VER) -#pragma warning(pop) -#endif -} - -} // namespace c4 diff --git a/thirdparty/ryml/ext/c4core/test/test_charconv.cpp b/thirdparty/ryml/ext/c4core/test/test_charconv.cpp deleted file mode 100644 index baa840d1e..000000000 --- a/thirdparty/ryml/ext/c4core/test/test_charconv.cpp +++ /dev/null @@ -1,2743 +0,0 @@ -#ifdef C4CORE_SINGLE_HEADER -#include "c4/c4core_all.hpp" -#else -#include "c4/std/std.hpp" -#include "c4/charconv.hpp" -#include "c4/format.hpp" -#include "c4/type_name.hpp" -#endif - -#include "c4/libtest/supprwarn_push.hpp" - -C4_SUPPRESS_WARNING_GCC_PUSH -C4_SUPPRESS_WARNING_GCC("-Wfloat-equal") -C4_SUPPRESS_WARNING_GCC("-Wuseless-cast") -C4_SUPPRESS_WARNING_GCC("-Wconversion") -C4_SUPPRESS_WARNING_GCC("-Wtype-limits") -C4_SUPPRESS_WARNING_GCC("-Wfloat-equal") -#if defined (__GNUC__) && __GNUC_MAJOR__ >= 7 -C4_SUPPRESS_WARNING_GCC("-Wno-noexcept-type") -#endif -C4_SUPPRESS_WARNING_CLANG_PUSH -C4_SUPPRESS_WARNING_CLANG("-Wfloat-equal") - -#include - -#include "./test_numbers.hpp" - -namespace c4 { - -namespace { - -// skip the radix prefix: 0x, -0x, 0X, -0X, 0b, -0B, etc -csubstr nopfx(csubstr num) -{ - if(num.begins_with('-')) - num = num.sub(1); - if(num.len >= 2 && num[0] == '0') - { - switch(num[1]) - { - case 'x': case 'X': - case 'o': case 'O': - case 'b': case 'B': - num = num.sub(2); - } - } - return num; -} - -// filter out the radix prefix from anywhere: 0x, -0x, 0X, -0X, 0b, -0B, etc -csubstr nopfx(substr buf, csubstr num) -{ - REQUIRE_GE(buf.len, num.len); - if(num.begins_with('-')) - num = num.sub(1); - size_t pos = 0; - for(size_t i = 0; i < num.len; ++i) - { - const char c = num.str[i]; - if(c == '0') - { - const char n = i+1 < num.len ? num.str[i+1] : '\0'; - switch(n) - { - case 'x': case 'X': - case 'o': case 'O': - case 'b': case 'B': - ++i; - break; - default: - buf[pos++] = c; - break; - } - } - else - { - buf[pos++] = c; - } - } - return buf.first(pos); -} - -// capitalize the alphabetical characters -// eg 0xdeadbeef --> 0XDEADBEEF -substr capitalize(substr buf, csubstr str) -{ - C4_ASSERT(!buf.overlaps(str)); - memcpy(buf.str, str.str, str.len); - substr ret = buf.first(str.len); - ret.toupper(); - return ret; -} - -// prepend zeroes to the left of the number: -// eg 1234 --> 00001234 -// eg -1234 --> -00001234 -// eg 0x1234 --> 0x00001234 -// eg -0x1234 --> -0x00001234 -substr zpad(substr buf, csubstr str, size_t num_zeroes) -{ - C4_ASSERT(!buf.overlaps(str)); - size_t pos = 0; - if(str.len > 0 && str[0] == '-') - buf.str[pos++] = '-'; - if(str.len >= pos+2 && str[pos] == '0') - { - switch(str[pos+1]) - { - case 'x': case 'X': - case 'o': case 'O': - case 'b': case 'B': - memcpy(buf.str + pos, str.str + pos, 2); - pos += 2; - } - } - memset(buf.str + pos, '0', num_zeroes); - csubstr rem = str.sub(pos); - memcpy(buf.str + pos + num_zeroes, rem.str, rem.len); - return buf.first(str.len + num_zeroes); -} - -// get the front element of the type's test numbers -template -number_case const& front(size_t skip=0) -{ - return *(numbers::vals + skip); -} - -// get the back element of the type's test numbers -template -number_case const& back(size_t skip=0) -{ - return *(numbers::vals + C4_COUNTOF(numbers::vals) - 1 - skip); -} - -// given an element, get the n-th element previous to that -template -number_case const& prev(number_case const& curr, size_t less=1) -{ - C4_ASSERT(less >= 0); - size_t num = C4_COUNTOF(numbers::vals); - C4_ASSERT(&curr >= numbers::vals); - C4_ASSERT(&curr < numbers::vals + num); - size_t icurr = (size_t)(&curr - numbers::vals); - size_t prev = (icurr + num - less) % num; - return *(numbers::vals + prev); -} - -// given an element, get the n-th element after that -template -number_case const& next(number_case const& curr, size_t more=1) -{ - C4_ASSERT(more >= 0); - size_t num = C4_COUNTOF(numbers::vals); - C4_ASSERT(&curr >= numbers::vals); - C4_ASSERT(&curr < numbers::vals + num); - size_t icurr = (size_t)(&curr - numbers::vals); - size_t next = (icurr + more) % num; - return *(numbers::vals + next); -} - -// construct a string of a value such that it overflows an original value by a given amount -template -csubstr overflow_by(substr buf, T val, T how_much, T radix) -{ - C4_STATIC_ASSERT(std::is_integral::value); - C4_STATIC_ASSERT(sizeof(T) < sizeof(int64_t)); - using upcast_t = typename std::conditional::value, int64_t, uint64_t>::type; - upcast_t uval = (upcast_t) val; - uval += (upcast_t) how_much; - size_t len = xtoa(buf, uval, (upcast_t)radix); - REQUIRE_GE(buf.len, len); - return buf.first(len); -} - -// construct a string of a value such that it underflows an original value by a given amount -template -csubstr underflow_by(substr buf, T val, T how_much, T radix) -{ - C4_STATIC_ASSERT(std::is_integral::value); - C4_STATIC_ASSERT(sizeof(T) < sizeof(int64_t)); - using upcast_t = typename std::conditional::value, int64_t, uint64_t>::type; - upcast_t uval = (upcast_t) val; - uval -= (upcast_t) how_much; - size_t len = xtoa(buf, uval, (upcast_t)radix); - REQUIRE_GE(buf.len, len); - return buf.first(len); -} - -} // namespace - -TEST_CASE("charconv.to_chars_format") -{ -#if C4CORE_HAVE_STD_TO_CHARS - CHECK(FTOA_FLOAT == static_cast::type>(std::chars_format::fixed)); - CHECK(FTOA_SCIENT == static_cast::type>(std::chars_format::scientific)); - CHECK(FTOA_FLEX == static_cast::type>(std::chars_format::general)); - CHECK(FTOA_HEXA == static_cast::type>(std::chars_format::hex)); -#elif !C4CORE_HAVE_FAST_FLOAT - CHECK(FTOA_FLOAT == 'f'); - CHECK(FTOA_SCIENT == 'e'); - CHECK(FTOA_FLEX == 'g'); - CHECK(FTOA_HEXA == 'a'); -#endif -} - - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -TEST_CASE_TEMPLATE("test_util.number_cases", T, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t) -{ - ITER_NUMBERS(T, number) - { - if(number.val < 0) - continue; - INFO(number); - CHECK_GT(number.dec.len, 0); - CHECK_GT(number.hex.len, 2); - CHECK_GT(number.oct.len, 2); - CHECK_GT(number.bin.len, 2); - CHECK_UNARY(number.hex.begins_with("0x")); - CHECK_UNARY(number.oct.begins_with("0o")); - CHECK_UNARY(number.bin.begins_with("0b")); - } - REQUIRE_GT(C4_COUNTOF(numbers::vals), 2); - // - CHECK_EQ(&front(), numbers::vals + 0); - CHECK_EQ(&front(0), numbers::vals + 0); - CHECK_EQ(&front(1), numbers::vals + 1); - // - CHECK_EQ(&back(), numbers::vals + C4_COUNTOF(numbers::vals) - 1); - CHECK_EQ(&back(0), numbers::vals + C4_COUNTOF(numbers::vals) - 1); - CHECK_EQ(&back(1), numbers::vals + C4_COUNTOF(numbers::vals) - 2); - // - CHECK_EQ(&next(front() ), numbers::vals + 1); - CHECK_EQ(&next(front(), T(1)), numbers::vals + 1); - CHECK_EQ(&next(front(), T(2)), numbers::vals + 2); - // - CHECK_EQ(&next(back() ), numbers::vals + 0); - CHECK_EQ(&next(back(), T(1)), numbers::vals + 0); - CHECK_EQ(&next(back(), T(2)), numbers::vals + 1); - CHECK_EQ(&next(back(), T(3)), numbers::vals + 2); - // - CHECK_EQ(&prev(front()), numbers::vals + C4_COUNTOF(numbers::vals) - 1); - CHECK_EQ(&prev(front(), T(1)), numbers::vals + C4_COUNTOF(numbers::vals) - 1); - CHECK_EQ(&prev(front(), T(2)), numbers::vals + C4_COUNTOF(numbers::vals) - 2); - // - CHECK_EQ(&prev(back()), numbers::vals + C4_COUNTOF(numbers::vals) - 2); - CHECK_EQ(&prev(back(), T(1)), numbers::vals + C4_COUNTOF(numbers::vals) - 2); - CHECK_EQ(&prev(back(), T(2)), numbers::vals + C4_COUNTOF(numbers::vals) - 3); -} - -TEST_CASE("test_util.overflow_by") -{ - char buf_[128]; - substr buf = buf_; - REQUIRE_EQ(overflow_by(buf, INT8_C(127), INT8_C(0), INT8_C(10)), "127"); - REQUIRE_EQ(overflow_by(buf, INT8_C(127), INT8_C(0), INT8_C(16)), "0x7f"); - REQUIRE_EQ(overflow_by(buf, INT8_C(127), INT8_C(1), INT8_C(10)), "128"); - REQUIRE_EQ(overflow_by(buf, INT8_C(127), INT8_C(1), INT8_C(16)), "0x80"); - REQUIRE_EQ(overflow_by(buf, INT8_C(127), INT8_C(2), INT8_C(10)), "129"); - REQUIRE_EQ(overflow_by(buf, INT8_C(127), INT8_C(2), INT8_C(16)), "0x81"); -} - -TEST_CASE("test_util.underflow_by") -{ - char buf_[128]; - substr buf = buf_; - REQUIRE_EQ(underflow_by(buf, INT8_C(-128), INT8_C(0), INT8_C(10)), "-128"); - REQUIRE_EQ(underflow_by(buf, INT8_C(-128), INT8_C(0), INT8_C(16)), "-0x80"); - REQUIRE_EQ(underflow_by(buf, INT8_C(-128), INT8_C(1), INT8_C(10)), "-129"); - REQUIRE_EQ(underflow_by(buf, INT8_C(-128), INT8_C(1), INT8_C(16)), "-0x81"); - REQUIRE_EQ(underflow_by(buf, INT8_C(-128), INT8_C(2), INT8_C(10)), "-130"); - REQUIRE_EQ(underflow_by(buf, INT8_C(-128), INT8_C(2), INT8_C(16)), "-0x82"); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -TEST_CASE_TEMPLATE("digits_dec", T, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t) -{ - ITER_NUMBERS(T, number) - { - if(number.val < 0) - continue; - INFO(number); - CHECK_EQ(digits_dec(number.val), nopfx(number.dec).len); - } -} - -TEST_CASE_TEMPLATE("digits_hex", T, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t) -{ - ITER_NUMBERS(T, number) - { - if(number.val < 0) - continue; - INFO(number); - CHECK_EQ(digits_hex(number.val), nopfx(number.hex).len); - } -} - -TEST_CASE_TEMPLATE("digits_oct", T, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t) -{ - ITER_NUMBERS(T, number) - { - if(number.val < 0) - continue; - INFO(number); - CHECK_EQ(digits_oct(number.val), nopfx(number.oct).len); - } -} - - -TEST_CASE_TEMPLATE("digits_bin", T, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t) -{ - ITER_NUMBERS(T, number) - { - if(number.val < 0) - continue; - INFO(number); - CHECK_EQ(digits_bin(number.val), nopfx(number.bin).len); - } -} - - -//----------------------------------------------------------------------------- -TEST_CASE_TEMPLATE("write_dec_unchecked", T, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t) -{ - char buf_[128] = {}; - substr buf = buf_; - ITER_NUMBERS(T, number) - { - if(number.val < 0) - continue; - INFO(number); - unsigned digits = digits_dec(number.val); - REQUIRE_GE(buf.len, digits); - write_dec_unchecked(buf, number.val, digits); - CHECK_EQ(buf.first(digits), nopfx(number.dec)); - } -} - -TEST_CASE_TEMPLATE("write_hex_unchecked", T, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t) -{ - char buf_[128] = {}; - substr buf = buf_; - ITER_NUMBERS(T, number) - { - if(number.val < 0) - continue; - INFO(number); - unsigned digits = digits_hex(number.val); - REQUIRE_GE(buf.len, digits); - write_hex_unchecked(buf, number.val, digits); - CHECK_EQ(buf.first(digits), nopfx(number.hex)); - } -} - -TEST_CASE_TEMPLATE("write_oct_unchecked", T, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t) -{ - char buf_[128] = {}; - substr buf = buf_; - ITER_NUMBERS(T, number) - { - if(number.val < 0) - continue; - INFO(number); - unsigned digits = digits_hex(number.val); - REQUIRE_GE(buf.len, digits); - write_hex_unchecked(buf, number.val, digits); - CHECK_EQ(buf.first(digits), nopfx(number.hex)); - } -} - -TEST_CASE_TEMPLATE("write_bin_unchecked", T, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t) -{ - char buf_[128] = {}; - substr buf = buf_; - ITER_NUMBERS(T, number) - { - if(number.val < 0) - continue; - INFO(number); - unsigned digits = digits_bin(number.val); - REQUIRE_GE(buf.len, digits); - write_bin_unchecked(buf, number.val, digits); - CHECK_EQ(buf.first(digits), nopfx(number.bin)); - } -} - - -//----------------------------------------------------------------------------- -TEST_CASE_TEMPLATE("write_dec", T, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t) -{ - char buf_[128] = {}; - substr buf = buf_; - ITER_NUMBERS(T, number) - { - if(number.val < 0) - continue; - INFO(number); - REQUIRE_GE(buf.len, number.dec.len); - size_t retn = write_dec(substr{}, number.val); - CHECK_EQ(retn, number.dec.len); - size_t retb = write_dec(buf, number.val); - CHECK_EQ(retb, retn); - REQUIRE_EQ(retb, number.dec.len); - CHECK_EQ(buf.first(retb), number.dec); - } -} - -TEST_CASE_TEMPLATE("write_hex", T, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t) -{ - char buf_[128] = {}; - substr buf = buf_; - ITER_NUMBERS(T, number) - { - if(number.val < 0) - continue; - INFO(number); - REQUIRE_GE(buf.len, number.hex.sub(2).len); - size_t retn = write_hex(substr{}, number.val); - CHECK_EQ(retn, number.hex.sub(2).len); - size_t retb = write_hex(buf, number.val); - CHECK_EQ(retb, retn); - REQUIRE_EQ(retb, number.hex.sub(2).len); - CHECK_EQ(buf.first(retb), number.hex.sub(2)); - } -} - -TEST_CASE_TEMPLATE("write_oct", T, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t) -{ - char buf_[128] = {}; - substr buf = buf_; - ITER_NUMBERS(T, number) - { - if(number.val < 0) - continue; - INFO(number); - REQUIRE_GE(buf.len, number.oct.sub(2).len); - size_t retn = write_oct(substr{}, number.val); - CHECK_EQ(retn, number.oct.sub(2).len); - size_t retb = write_oct(buf, number.val); - CHECK_EQ(retb, retn); - REQUIRE_EQ(retb, number.oct.sub(2).len); - CHECK_EQ(buf.first(retb), nopfx(number.oct)); - } -} - -TEST_CASE_TEMPLATE("write_bin", T, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t) -{ - char buf_[128] = {}; - substr buf = buf_; - ITER_NUMBERS(T, number) - { - if(number.val < 0) - continue; - INFO(number); - REQUIRE_GE(buf.len, number.bin.sub(2).len); - size_t retb = write_bin(substr{}, number.val); - CHECK_EQ(retb, number.bin.sub(2).len); - size_t retn = write_bin(buf, number.val); - CHECK_EQ(retb, retn); - REQUIRE_EQ(retb, number.bin.sub(2).len); - CHECK_EQ(buf.first(retb), nopfx(number.bin)); - } -} - - -//----------------------------------------------------------------------------- -TEST_CASE_TEMPLATE("write_dec_digits", T, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t) -{ - char buf_[128] = {}; - substr buf = buf_; - SUBCASE("num digits smaller than length") - { - ITER_NUMBERS(T, number) - { - if(number.val < 0) - continue; - INFO(number); - for(int less_ : {0, 1, 2, 4, 8, (int)number.dec.len}) - { - size_t less = (size_t) less_; - if(less > number.dec.len) - continue; - size_t num_digits = number.dec.len - less; - INFO("less=" << less << " num_digits=" << num_digits); - size_t retn = write_dec(substr{}, number.val, num_digits); - CHECK_EQ(retn, number.dec.len); // the number must always be written - size_t retb = write_dec(buf, number.val, num_digits); - CHECK_EQ(retb, retn); - REQUIRE_EQ(retb, number.dec.len); - CHECK_EQ(buf.first(retb), number.dec); - } - } - } - SUBCASE("num digits larger than length") - { - ITER_NUMBERS(T, number) - { - if(number.val < 0) - continue; - INFO(number); - for(int more_ : {1, 2, 4, 8}) - { - size_t more = (size_t) more_; - size_t num_digits = number.dec.len + more; - INFO("more=" << more << " num_digits=" << num_digits); - size_t retn = write_dec(substr{}, number.val, num_digits); - CHECK_EQ(retn, num_digits); - size_t retb = write_dec(buf, number.val, num_digits); - CHECK_EQ(retb, retn); - REQUIRE_EQ(retb, num_digits); - csubstr result = buf.first(retb); - CHECK_EQ(result.last(number.dec.len), number.dec); - if(number.val) - { - CHECK_EQ(result.triml('0'), number.dec); - CHECK_EQ(result.first_not_of('0'), more); - } - else - { - CHECK(result.begins_with('0')); - CHECK_EQ(result.first_not_of('0'), csubstr::npos); - } - } - } - } -} - -TEST_CASE_TEMPLATE("write_hex_digits", T, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t) -{ - char buf_[128] = {}; - substr buf = buf_; - SUBCASE("num digits smaller than length") - { - ITER_NUMBERS(T, number) - { - if(number.val < 0) - continue; - INFO(number); - for(int less_ : {0, 1, 2, 4, 8, (int)number.hex.len}) - { - const csubstr hex = nopfx(number.hex); - size_t less = (size_t) less_; - if(less > hex.len) - continue; - size_t num_digits = hex.len - less; - INFO("less=" << less << " num_digits=" << num_digits); - size_t retn = write_hex(substr{}, number.val, num_digits); - CHECK_EQ(retn, hex.len); // the number must always be written - size_t retb = write_hex(buf, number.val, num_digits); - CHECK_EQ(retb, retn); - REQUIRE_EQ(retb, hex.len); - CHECK_EQ(buf.first(retb), hex); - } - } - } - SUBCASE("num digits larger than length") - { - ITER_NUMBERS(T, number) - { - if(number.val < 0) - continue; - INFO(number); - for(int more_ : {1, 2, 4, 8}) - { - const csubstr hex = nopfx(number.hex); - size_t more = (size_t) more_; - size_t num_digits = hex.len + more; - INFO("more=" << more << " num_digits=" << num_digits); - size_t retn = write_hex(substr{}, number.val, num_digits); - CHECK_EQ(retn, num_digits); - size_t retb = write_hex(buf, number.val, num_digits); - CHECK_EQ(retb, retn); - REQUIRE_EQ(retn, num_digits); - csubstr result = buf.first(retn); - CHECK_EQ(result.last(hex.len), hex); - if(number.val) - { - CHECK_EQ(result.triml('0'), hex); - CHECK_EQ(result.first_not_of('0'), more); - } - else - { - CHECK(result.begins_with('0')); - CHECK_EQ(result.first_not_of('0'), csubstr::npos); - } - } - } - } -} - -TEST_CASE_TEMPLATE("write_oct_digits", T, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t) -{ - char buf_[128] = {}; - substr buf = buf_; - SUBCASE("num digits smaller than length") - { - ITER_NUMBERS(T, number) - { - if(number.val < 0) - continue; - INFO(number); - for(int less_ : {0, 1, 2, 4, 8, (int)number.oct.len}) - { - const csubstr oct = nopfx(number.oct); - size_t less = (size_t) less_; - if(less > oct.len) - continue; - size_t num_digits = oct.len - less; - INFO("less=" << less << " num_digits=" << num_digits); - size_t retn = write_oct(substr{}, number.val, num_digits); - CHECK_EQ(retn, oct.len); // the number must always be written - size_t retb = write_oct(buf, number.val, num_digits); - CHECK_EQ(retb, retn); - REQUIRE_EQ(retb, oct.len); - CHECK_EQ(buf.first(retb), oct); - } - } - } - SUBCASE("num digits larger than length") - { - ITER_NUMBERS(T, number) - { - if(number.val < 0) - continue; - INFO(number); - for(int more_ : {1, 2, 4, 8}) - { - const csubstr oct = nopfx(number.oct); - size_t more = (size_t) more_; - size_t num_digits = oct.len + more; - INFO("more=" << more << " num_digits=" << num_digits); - size_t retn = write_oct(substr{}, number.val, num_digits); - CHECK_EQ(retn, num_digits); - size_t retb = write_oct(buf, number.val, num_digits); - CHECK_EQ(retb, retn); - REQUIRE_EQ(retb, num_digits); - csubstr result = buf.first(retb); - CHECK_EQ(result.last(oct.len), oct); - if(number.val) - { - CHECK_EQ(result.triml('0'), oct); - CHECK_EQ(result.first_not_of('0'), more); - } - else - { - CHECK(result.begins_with('0')); - CHECK_EQ(result.first_not_of('0'), csubstr::npos); - } - } - } - } -} - -TEST_CASE_TEMPLATE("write_bin_digits", T, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t) -{ - char buf_[128] = {}; - substr buf = buf_; - SUBCASE("num digits smaller than length") - { - ITER_NUMBERS(T, number) - { - if(number.val < 0) - continue; - INFO(number); - for(int less_ : {0, 1, 2, 4, 8, (int)number.bin.len}) - { - const csubstr bin = nopfx(number.bin); - size_t less = (size_t) less_; - if(less > bin.len) - continue; - size_t num_digits = bin.len - less; - INFO("less=" << less << " num_digits=" << num_digits); - size_t retn = write_bin(substr{}, number.val, num_digits); - CHECK_EQ(retn, bin.len); // the number must always be written - size_t retb = write_bin(buf, number.val, num_digits); - CHECK_EQ(retb, retn); - REQUIRE_EQ(retb, bin.len); - CHECK_EQ(buf.first(retb), bin); - } - } - } - SUBCASE("num digits larger than length") - { - ITER_NUMBERS(T, number) - { - if(number.val < 0) - continue; - INFO(number); - for(int more_ : {1, 2, 4, 8}) - { - const csubstr bin = nopfx(number.bin); - size_t more = (size_t) more_; - size_t num_digits = bin.len + more; - INFO("more=" << more << " num_digits=" << num_digits); - size_t retn = write_bin(substr{}, number.val, num_digits); - CHECK_EQ(retn, num_digits); - size_t retb = write_bin(buf, number.val, num_digits); - CHECK_EQ(retb, retn); - REQUIRE_EQ(retn, num_digits); - csubstr result = buf.first(retn); - CHECK_EQ(result.last(bin.len), bin); - if(number.val) - { - CHECK_EQ(result.triml('0'), bin); - CHECK_EQ(result.first_not_of('0'), more); - } - else - { - CHECK(result.begins_with('0')); - CHECK_EQ(result.first_not_of('0'), csubstr::npos); - } - } - } - } -} - - -//----------------------------------------------------------------------------- - -TEST_CASE_TEMPLATE("xtoa", T, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t) -{ - char buf_[128] = {}; - substr buf = buf_; - ITER_NUMBERS(T, number) - { - INFO(number); - { - buf.fill('?'); - size_t retn = xtoa(substr{}, number.val); - CHECK_EQ(retn, number.dec.len); - CHECK_UNARY(buf.begins_with('?') && buf.first_not_of('?') == csubstr::npos); - size_t retb = xtoa(buf, number.val); - CHECK_EQ(retn, retb); - REQUIRE_LE(retb, buf.len); - CHECK_EQ(buf.first(retb), number.dec); - T after_roundtrip = number.val + T(1); - CHECK(atox(buf.first(retb), &after_roundtrip)); - CHECK_EQ(after_roundtrip, number.val); - } - } -} - - -//----------------------------------------------------------------------------- - -TEST_CASE_TEMPLATE("xtoa_radix.dec", T, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t) -{ - char buf_[128] = {}; - substr buf = buf_; - ITER_NUMBERS(T, number) - { - INFO(number); - { - buf.fill('?'); - size_t retn = xtoa(substr{}, number.val, T(10)); - CHECK_EQ(retn, number.dec.len); - CHECK_UNARY(buf.begins_with('?') && buf.first_not_of('?') == csubstr::npos); - size_t retb = xtoa(buf, number.val, T(10)); - CHECK_EQ(retn, retb); - REQUIRE_LE(retb, buf.len); - CHECK_EQ(buf.first(retb), number.dec); - T after_roundtrip = number.val + T(1); - CHECK(atox(buf.first(retb), &after_roundtrip)); - CHECK_EQ(after_roundtrip, number.val); - } - const size_t adj = size_t(number.val < 0); - REQUIRE_LT(adj, number.dec.len); - const size_t dec_digits = number.dec.len - adj; - for(size_t more_digits = 0; more_digits < 6; ++more_digits) - { - buf.fill('?'); - size_t reqdigits = dec_digits + more_digits; - INFO("dec_digits=" << dec_digits << " more_digits=" << more_digits << " req_digits=" << reqdigits); - size_t retn = xtoa(substr{}, number.val, T(10), reqdigits); - CHECK_EQ(retn, reqdigits + size_t(number.val < 0)); - CHECK_UNARY(buf.begins_with('?') && buf.first_not_of('?') == csubstr::npos); - size_t retb = xtoa(buf, number.val, T(10), reqdigits); - CHECK_EQ(retn, retb); - REQUIRE_LE(retb, buf.len); - CHECK(buf.first(retb).ends_with(number.dec.sub(number.val < 0))); - T after_roundtrip = number.val + T(1); - CHECK(atox(buf.first(retb), &after_roundtrip)); - CHECK_EQ(after_roundtrip, number.val); - } - for(size_t less_digits = 0; less_digits < dec_digits; ++less_digits) - { - buf.fill('?'); - size_t reqdigits = dec_digits - less_digits; - INFO("dec_digits=" << dec_digits << " less_digits=" << less_digits << " req_digits=" << reqdigits); - size_t retn = xtoa(substr{}, number.val, T(10), reqdigits); - CHECK_EQ(retn, number.dec.len); - CHECK_UNARY(buf.begins_with('?') && buf.first_not_of('?') == csubstr::npos); - size_t retb = xtoa(buf, number.val, T(10), reqdigits); - CHECK_EQ(retn, retb); - REQUIRE_LE(retb, buf.len); - CHECK(buf.first(retb).ends_with(number.dec.sub(number.val < 0))); - T after_roundtrip = number.val + T(1); - CHECK(atox(buf.first(retb), &after_roundtrip)); - CHECK_EQ(after_roundtrip, number.val); - } - } -} - -TEST_CASE_TEMPLATE("xtoa_radix.hex", T, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t) -{ - char buf_[128] = {}; - substr buf = buf_; - ITER_NUMBERS(T, number) - { - INFO(number); - { - buf.fill('?'); - size_t retn = xtoa(substr{}, number.val, T(16)); - CHECK_EQ(retn, number.hex.len); - CHECK_UNARY(buf.begins_with('?') && buf.first_not_of('?') == csubstr::npos); - size_t retb = xtoa(buf, number.val, T(16)); - CHECK_EQ(retn, retb); - REQUIRE_LE(retb, buf.len); - CHECK_EQ(buf.first(retb), number.hex); - T after_roundtrip = number.val + T(1); - CHECK(atox(buf.first(retb), &after_roundtrip)); - CHECK_EQ(after_roundtrip, number.val); - } - const size_t adj = size_t(number.val < 0) + size_t(2); // 2 for 0x - REQUIRE_LT(adj, number.hex.len); - const size_t hex_digits = number.hex.len - adj; - for(size_t more_digits = 0; more_digits < 6; ++more_digits) - { - buf.fill('?'); - size_t reqdigits = hex_digits + more_digits; - INFO("more_digits=" << more_digits << " reqdigits=" << reqdigits); - size_t retn = xtoa(substr{}, number.val, T(16), reqdigits); - CHECK_EQ(retn, reqdigits + adj); - CHECK_UNARY(buf.begins_with('?') && buf.first_not_of('?') == csubstr::npos); - size_t retb = xtoa(buf, number.val, T(16), reqdigits); - CHECK_EQ(retn, retb); - REQUIRE_LE(retb, buf.len); - csubstr result = buf.first(retb); - csubstr ref = number.hex.sub(adj); - INFO("result=" << result << " ref=" << ref); - if(number.val < 0) - CHECK(buf.first(retb).begins_with('-')); - CHECK(result.ends_with(ref)); - T after_roundtrip = number.val + T(1); - CHECK(atox(buf.first(retb), &after_roundtrip)); - CHECK_EQ(after_roundtrip, number.val); - } - for(size_t less_digits = 0; less_digits < hex_digits; ++less_digits) - { - buf.fill('?'); - size_t reqdigits = hex_digits - less_digits; - INFO("hex_digits=" << hex_digits << " less_digits=" << less_digits << " req_digits=" << reqdigits); - size_t retn = xtoa(substr{}, number.val, T(16), reqdigits); - CHECK_EQ(retn, number.hex.len); - CHECK_UNARY(buf.begins_with('?') && buf.first_not_of('?') == csubstr::npos); - size_t retb = xtoa(buf, number.val, T(16), reqdigits); - CHECK_EQ(retn, retb); - REQUIRE_LE(retb, buf.len); - CHECK(buf.first(retb).ends_with(number.hex.sub(number.val < 0))); - T after_roundtrip = number.val + T(1); - CHECK(atox(buf.first(retb), &after_roundtrip)); - CHECK_EQ(after_roundtrip, number.val); - } - } -} - -TEST_CASE_TEMPLATE("xtoa_radix.oct", T, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t) -{ - char buf_[128] = {}; - substr buf = buf_; - ITER_NUMBERS(T, number) - { - INFO(number); - { - buf.fill('?'); - size_t retn = xtoa(substr{}, number.val, T(8)); - CHECK_EQ(retn, number.oct.len); - CHECK_UNARY(buf.begins_with('?') && buf.first_not_of('?') == csubstr::npos); - size_t retb = xtoa(buf, number.val, T(8)); - CHECK_EQ(retn, retb); - REQUIRE_LE(retb, buf.len); - CHECK_EQ(buf.first(retb), number.oct); - T after_roundtrip = number.val + T(1); - CHECK(atox(buf.first(retb), &after_roundtrip)); - CHECK_EQ(after_roundtrip, number.val); - } - const size_t adj = size_t(number.val < 0) + size_t(2); // 2 for 0o - REQUIRE_LT(adj, number.oct.len); - const size_t oct_digits = number.oct.len - adj; - for(size_t more_digits = 0; more_digits < 6; ++more_digits) - { - buf.fill('?'); - size_t reqdigits = oct_digits + more_digits; - INFO("more_digits=" << more_digits << " reqdigits=" << reqdigits); - size_t retn = xtoa(substr{}, number.val, T(8), reqdigits); - CHECK_EQ(retn, reqdigits + adj); - CHECK_UNARY(buf.begins_with('?') && buf.first_not_of('?') == csubstr::npos); - size_t retb = xtoa(buf, number.val, T(8), reqdigits); - CHECK_EQ(retn, retb); - REQUIRE_LE(retb, buf.len); - csubstr result = buf.first(retb); - csubstr ref = number.oct.sub(adj); - INFO("result=" << result << " ref=" << ref); - if(number.val < 0) - CHECK(buf.first(retb).begins_with('-')); - CHECK(result.ends_with(ref)); - T after_roundtrip = number.val + T(1); - CHECK(atox(buf.first(retb), &after_roundtrip)); - CHECK_EQ(after_roundtrip, number.val); - } - for(size_t less_digits = 0; less_digits < oct_digits; ++less_digits) - { - buf.fill('?'); - size_t reqdigits = oct_digits - less_digits; - INFO("oct_digits=" << oct_digits << " less_digits=" << less_digits << " req_digits=" << reqdigits); - size_t retn = xtoa(substr{}, number.val, T(8), reqdigits); - CHECK_EQ(retn, number.oct.len); - CHECK_UNARY(buf.begins_with('?') && buf.first_not_of('?') == csubstr::npos); - size_t retb = xtoa(buf, number.val, T(8), reqdigits); - CHECK_EQ(retn, retb); - REQUIRE_LE(retb, buf.len); - CHECK(buf.first(retb).ends_with(number.oct.sub(number.val < 0))); - T after_roundtrip = number.val + T(1); - CHECK(atox(buf.first(retb), &after_roundtrip)); - CHECK_EQ(after_roundtrip, number.val); - } - } -} - -TEST_CASE_TEMPLATE("xtoa_radix.bin", T, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t) -{ - char buf_[128] = {}; - substr buf = buf_; - ITER_NUMBERS(T, number) - { - INFO(number); - { - buf.fill('?'); - size_t retn = xtoa(substr{}, number.val, T(2)); - CHECK_EQ(retn, number.bin.len); - CHECK_UNARY(buf.begins_with('?') && buf.first_not_of('?') == csubstr::npos); - size_t retb = xtoa(buf, number.val, T(2)); - CHECK_EQ(retn, retb); - REQUIRE_LE(retb, buf.len); - CHECK_EQ(buf.first(retb), number.bin); - T after_roundtrip = number.val + T(1); - CHECK(atox(buf.first(retb), &after_roundtrip)); - CHECK_EQ(after_roundtrip, number.val); - } - const size_t adj = size_t(number.val < 0) + size_t(2); // 2 for 0b - REQUIRE_LT(adj, number.bin.len); - const size_t bin_digits = number.bin.len - adj; - for(size_t more_digits = 0; more_digits < 6; ++more_digits) - { - buf.fill('?'); - size_t reqdigits = bin_digits + more_digits; - INFO("more_digits=" << more_digits << " reqdigits=" << reqdigits); - size_t retn = xtoa(substr{}, number.val, T(2), reqdigits); - CHECK_EQ(retn, reqdigits + adj); - CHECK_UNARY(buf.begins_with('?') && buf.first_not_of('?') == csubstr::npos); - size_t retb = xtoa(buf, number.val, T(2), reqdigits); - CHECK_EQ(retn, retb); - REQUIRE_LE(retb, buf.len); - csubstr result = buf.first(retb); - csubstr ref = number.bin.sub(adj); - INFO("result=" << result << " ref=" << ref); - if(number.val < 0) - CHECK(buf.first(retb).begins_with('-')); - T after_roundtrip = number.val + T(1); - CHECK(atox(buf.first(retb), &after_roundtrip)); - CHECK_EQ(after_roundtrip, number.val); - } - for(size_t less_digits = 0; less_digits < bin_digits; ++less_digits) - { - buf.fill('?'); - size_t reqdigits = bin_digits - less_digits; - INFO("bin_digits=" << bin_digits << " less_digits=" << less_digits << " req_digits=" << reqdigits); - size_t retn = xtoa(substr{}, number.val, T(2), reqdigits); - CHECK_EQ(retn, number.bin.len); - CHECK_UNARY(buf.begins_with('?') && buf.first_not_of('?') == csubstr::npos); - size_t retb = xtoa(buf, number.val, T(2), reqdigits); - CHECK_EQ(retn, retb); - REQUIRE_LE(retb, buf.len); - CHECK(buf.first(retb).ends_with(number.bin.sub(number.val < 0))); - T after_roundtrip = number.val + T(1); - CHECK(atox(buf.first(retb), &after_roundtrip)); - CHECK_EQ(after_roundtrip, number.val); - } - } -} - - -//----------------------------------------------------------------------------- - - -TEST_CASE_TEMPLATE("overflows.in_range_does_not_overflow", T, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t) -{ - char buf_[128] = {}; - substr buf = buf_; - SUBCASE("dec") - { - ITER_NUMBERS(T, number) - { - INFO(number); - CHECK_FALSE(overflows(number.dec)); - CHECK_FALSE(overflows(capitalize(buf, number.dec))); - for(size_t numz : {1u, 4u, 6u}) - { - substr buf2 = zpad(buf, number.dec, numz); - CHECK_FALSE(overflows(buf2)); - buf2.toupper(); - CHECK_FALSE(overflows(buf2)); - } - } - } - SUBCASE("hex") - { - ITER_NUMBERS(T, number) - { - INFO(number); - CHECK_FALSE(overflows(number.hex)); - CHECK_FALSE(overflows(capitalize(buf, number.hex))); - for(size_t numz : {1u, 4u, 6u}) - { - substr buf2 = zpad(buf, number.hex, numz); - CHECK_FALSE(overflows(buf2)); - buf2.toupper(); - CHECK_FALSE(overflows(buf2)); - } - } - } - SUBCASE("oct") - { - ITER_NUMBERS(T, number) - { - INFO(number); - CHECK_FALSE(overflows(number.oct)); - CHECK_FALSE(overflows(capitalize(buf, number.oct))); - for(size_t numz : {1u, 4u, 6u}) - { - substr buf2 = zpad(buf, number.oct, numz); - CHECK_FALSE(overflows(buf2)); - buf2.toupper(); - CHECK_FALSE(overflows(buf2)); - } - } - } - SUBCASE("bin") - { - ITER_NUMBERS(T, number) - { - INFO(number); - CHECK_FALSE(overflows(number.bin)); - CHECK_FALSE(overflows(capitalize(buf, number.bin))); - for(size_t numz : {1u, 4u, 6u}) - { - substr buf2 = zpad(buf, number.bin, numz); - CHECK_FALSE(overflows(buf2)); - buf2.toupper(); - CHECK_FALSE(overflows(buf2)); - } - } - } -} - - -//----------------------------------------------------------------------------- - -TEST_CASE_TEMPLATE("read_dec", T, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t) -{ - char buf_[128] = {}; - substr buf = buf_; - SUBCASE("numbers") - { - ITER_NUMBERS(T, number) - { - if(number.val < T(0)) - continue; - INFO(number); - { - T val = number.val + T(1); - CHECK(read_dec(number.dec, &val)); - CHECK_EQ(val, number.val); - } - // capitalize - { - T val = number.val + T(1); - csubstr cbuf = capitalize(buf, number.dec); - CHECK(read_dec(cbuf, &val)); - CHECK_EQ(val, number.val); - } - // zero-prefix - for(size_t numz : {1u, 4u, 6u}) - { - T val = number.val + T(1); - substr buf2 = zpad(buf, number.dec, numz); - INFO("zprefix=" << buf2); - CHECK(read_dec(buf2, &val)); - CHECK_EQ(val, number.val); - buf2.toupper(); - CHECK(read_dec(buf2, &val)); - CHECK_EQ(val, number.val); - } - } - } - SUBCASE("fail") - { - T val = {}; - for(auto ic : invalid_cases) - { - if(ic.dec.empty()) - continue; - INFO(ic.dec); - CHECK(!read_dec(ic.dec, &val)); - } - } -} - -TEST_CASE_TEMPLATE("read_hex", T, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t) -{ - char buf_[128] = {}; - substr buf = buf_; - SUBCASE("numbers") - { - ITER_NUMBERS(T, number) - { - if(number.val < T(0)) - continue; - INFO(number); - // must not accept 0x prefix - { - T val = number.val + T(1); - CHECK(!read_hex(number.hex, &val)); - } - // must accept without prefix - csubstr hex = nopfx(number.hex); - INFO("nopfx(hex)=" << hex); - { - T val = number.val + T(1); - CHECK(read_hex(hex, &val)); - CHECK_EQ(val, number.val); - } - // capitalize - { - csubstr cbuf = capitalize(buf, hex); - INFO("capitalized=" << buf); - REQUIRE_EQ(cbuf.len, hex.len); - T val = number.val + T(1); - CHECK(read_hex(cbuf, &val)); - CHECK_EQ(val, number.val); - } - // zero-prefix - for(size_t numz : {1u, 4u, 6u}) - { - T val = number.val + T(1); - substr zprefix = zpad(buf, hex, numz); - INFO("zprefix='" << zprefix << "'"); - CHECK(read_hex(zprefix, &val)); - CHECK_EQ(val, number.val); - zprefix.toupper(); - CHECK(read_hex(zprefix, &val)); - CHECK_EQ(val, number.val); - } - } - } - SUBCASE("fail") - { - char buf2_[128] = {}; - substr buf2 = buf2_; - size_t icase = 0; - for(auto const& ic : invalid_cases) - { - csubstr cbuf = nopfx(buf, ic.hex); - csubstr cbuf2 = capitalize(buf2, cbuf); - INFO("case#=" << icase << " hex='" << ic.hex << "' nopfx(hex)='" << cbuf << "' capitalize(nopfx(hex))='" << cbuf2 << "'"); - REQUIRE_EQ(cbuf2.len, cbuf.len); - // must not accept 0x prefix - if(ic.hex.len) - { - T val = {}; - CHECK(!read_hex(ic.hex, &val)); - } - // it is invalid; must not accept even without 0x prefix - if(cbuf.len) - { - T val = {}; - CHECK(!read_hex(cbuf, &val)); - } - // capitalize - if(cbuf2.len) - { - T val = {}; - CHECK(!read_hex(cbuf2, &val)); - } - ++icase; - } - } -} - -TEST_CASE_TEMPLATE("read_oct", T, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t) -{ - char buf_[128] = {}; - substr buf = buf_; - SUBCASE("numbers") - { - ITER_NUMBERS(T, number) - { - if(number.val < T(0)) - continue; - INFO(number); - // must not accept 0x prefix - { - T val = number.val + T(1); - CHECK(!read_oct(number.oct, &val)); - } - // must accept without prefix - csubstr oct = nopfx(number.oct); - INFO("nopfx(oct)=" << oct); - { - T val = number.val + T(1); - CHECK(read_oct(oct, &val)); - CHECK_EQ(val, number.val); - } - // capitalize - { - csubstr cbuf = capitalize(buf, oct); - INFO("capitalized=" << buf); - REQUIRE_EQ(cbuf.len, oct.len); - T val = number.val + T(1); - CHECK(read_oct(cbuf, &val)); - CHECK_EQ(val, number.val); - } - // zero-prefix - for(size_t numz : {1u, 4u, 6u}) - { - T val = number.val + T(1); - substr zprefix = zpad(buf, oct, numz); - INFO("zprefix=" << zprefix); - CHECK(read_oct(zprefix, &val)); - CHECK_EQ(val, number.val); - zprefix.toupper(); - CHECK(read_oct(zprefix, &val)); - CHECK_EQ(val, number.val); - } - } - } - SUBCASE("fail") - { - char buf2_[128] = {}; - substr buf2 = buf2_; - size_t icase = 0; - for(auto const& ic : invalid_cases) - { - csubstr cbuf = nopfx(buf, ic.oct); - csubstr cbuf2 = capitalize(buf2, cbuf); - INFO("case#=" << icase << " oct='" << ic.oct << "' nopfx(oct)='" << cbuf << "' capitalize(nopfx(oct))='" << cbuf2 << "'"); - REQUIRE_EQ(cbuf2.len, cbuf.len); - // must not accept 0x prefix - if(ic.oct.len) - { - T val = {}; - CHECK(!read_oct(ic.oct, &val)); - } - // it is invalid; must not accept even without 0x prefix - if(cbuf.len) - { - T val = {}; - CHECK(!read_oct(cbuf, &val)); - } - // capitalize - if(cbuf2.len) - { - T val = {}; - CHECK(!read_oct(cbuf2, &val)); - } - ++icase; - } - } -} - -TEST_CASE_TEMPLATE("read_bin", T, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t) -{ - char buf_[128] = {}; - substr buf = buf_; - SUBCASE("numbers") - { - ITER_NUMBERS(T, number) - { - if(number.val < T(0)) - continue; - INFO(number); - // must not accept 0x prefix - { - T val = number.val + T(1); - CHECK(!read_bin(number.bin, &val)); - } - // must accept without prefix - csubstr bin = nopfx(number.bin); - INFO("nopfx(bin)=" << bin); - { - T val = number.val + T(1); - CHECK(read_bin(bin, &val)); - CHECK_EQ(val, number.val); - } - // capitalize - { - csubstr cbuf = capitalize(buf, bin); - INFO("capitalized=" << buf); - REQUIRE_EQ(cbuf.len, bin.len); - T val = number.val + T(1); - CHECK(read_bin(cbuf, &val)); - CHECK_EQ(val, number.val); - } - // zero-prefix - for(size_t numz : {1u, 4u, 6u}) - { - T val = number.val + T(1); - substr zprefix = zpad(buf, bin, numz); - INFO("zprefix=" << zprefix); - CHECK(read_bin(zprefix, &val)); - CHECK_EQ(val, number.val); - zprefix.toupper(); - CHECK(read_bin(zprefix, &val)); - CHECK_EQ(val, number.val); - } - } - } - SUBCASE("fail") - { - char buf2_[128] = {}; - substr buf2 = buf2_; - size_t icase = 0; - for(auto const& ic : invalid_cases) - { - csubstr cbuf = nopfx(buf, ic.bin); - csubstr cbuf2 = capitalize(buf2, cbuf); - INFO("case#=" << icase << " bin='" << ic.bin << "' nopfx(bin)='" << cbuf << "' capitalize(nopfx(bin))='" << cbuf2 << "'"); - REQUIRE_EQ(cbuf2.len, cbuf.len); - // must not accept 0x prefix - if(ic.bin.len) - { - T val = {}; - CHECK(!read_bin(ic.bin, &val)); - } - // it is invalid; must not accept even without 0x prefix - if(cbuf.len) - { - T val = {}; - CHECK(!read_bin(cbuf, &val)); - } - // capitalize - if(cbuf2.len) - { - T val = {}; - CHECK(!read_bin(cbuf2, &val)); - } - ++icase; - } - } -} - - -//----------------------------------------------------------------------------- - -TEST_CASE_TEMPLATE("atox", T, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t) -{ - char buf_[128] = {}; - substr buf = buf_; - SUBCASE("dec") - { - ITER_NUMBERS(T, number) - { - INFO(number); - { - T val = number.val + T(1); - CHECK(atox(number.dec, &val)); - CHECK_EQ(val, number.val); - } - // zero-prefix - for(size_t numz : {1u, 4u, 6u}) - { - T val = number.val + T(1); - substr zprefix = zpad(buf, number.dec, numz); - INFO("zprefix=" << zprefix); - CHECK(atox(zprefix, &val)); - CHECK_EQ(val, number.val); - } - } - } - SUBCASE("hex") - { - ITER_NUMBERS(T, number) - { - INFO(number); - { - T val = number.val + T(1); - CHECK(atox(number.hex, &val)); - CHECK_EQ(val, number.val); - } - // capitalize - { - T val = number.val + T(1); - csubstr cbuf = capitalize(buf, number.hex); - CHECK(atox(cbuf, &val)); - CHECK_EQ(val, number.val); - } - // zero-prefix - for(size_t numz : {1u, 4u, 6u}) - { - T val = number.val + T(1); - substr zprefix = zpad(buf, number.hex, numz); - INFO("zprefix=" << zprefix); - CHECK(atox(zprefix, &val)); - CHECK_EQ(val, number.val); - zprefix.toupper(); - CHECK(atox(zprefix, &val)); - CHECK_EQ(val, number.val); - } - } - } - SUBCASE("oct") - { - ITER_NUMBERS(T, number) - { - INFO(number); - { - T val = number.val + T(1); - CHECK(atox(number.oct, &val)); - CHECK_EQ(val, number.val); - } - // capitalize - { - T val = number.val + T(1); - csubstr cbuf = capitalize(buf, number.oct); - CHECK(atox(cbuf, &val)); - CHECK_EQ(val, number.val); - } - // zero-prefix - for(size_t numz : {1u, 4u, 6u}) - { - T val = number.val + T(1); - substr zprefix = zpad(buf, number.oct, numz); - INFO("zprefix=" << zprefix); - CHECK(atox(zprefix, &val)); - CHECK_EQ(val, number.val); - zprefix.toupper(); - CHECK(atox(zprefix, &val)); - CHECK_EQ(val, number.val); - } - } - } - SUBCASE("bin") - { - ITER_NUMBERS(T, number) - { - INFO(number); - { - T val = number.val + T(1); - CHECK(atox(number.bin, &val)); - CHECK_EQ(val, number.val); - } - // capitalize - { - T val = number.val + T(1); - csubstr cbuf = capitalize(buf, number.bin); - CHECK(atox(cbuf, &val)); - CHECK_EQ(val, number.val); - } - // zero-prefix - for(size_t numz : {1u, 4u, 6u}) - { - T val = number.val + T(1); - substr zprefix = zpad(buf, number.oct, numz); - INFO("zprefix=" << zprefix); - CHECK(atox(zprefix, &val)); - CHECK_EQ(val, number.val); - zprefix.toupper(); - CHECK(atox(zprefix, &val)); - CHECK_EQ(val, number.val); - } - } - } -} - -TEST_CASE_TEMPLATE("atox.fail", T, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t) -{ - char buf_[128] = {}; - substr buf = buf_; - SUBCASE("dec") - { - size_t icase = 0; - for(auto const& ic : invalid_cases) - { - csubstr cdec = capitalize(buf, ic.dec); - INFO("case#=" << icase << " dec='" << ic.dec << "' capitalize='" << cdec << "'"); - REQUIRE_EQ(cdec.len, ic.dec.len); - { - T val = {}; - CHECK(!atox(ic.dec, &val)); - } - { - T val = {}; - CHECK(!atox(cdec, &val)); - } - ++icase; - } - } - SUBCASE("hex") - { - size_t icase = 0; - for(auto const& ic : invalid_cases) - { - csubstr chex = capitalize(buf, ic.hex); - INFO("case#=" << icase << " hex='" << ic.hex << "' capitalize='" << chex << "'"); - REQUIRE_EQ(chex.len, ic.hex.len); - { - T val = {}; - CHECK(!atox(ic.hex, &val)); - } - { - T val = {}; - CHECK(!atox(chex, &val)); - } - ++icase; - } - } - SUBCASE("oct") - { - size_t icase = 0; - for(auto const& ic : invalid_cases) - { - csubstr coct = capitalize(buf, ic.oct); - INFO("case#=" << icase << " oct='" << ic.oct << "' capitalize='" << coct << "'"); - REQUIRE_EQ(coct.len, ic.oct.len); - { - T val = {}; - CHECK(!atox(ic.oct, &val)); - } - { - T val = {}; - CHECK(!atox(coct, &val)); - } - ++icase; - } - } - SUBCASE("bin") - { - size_t icase = 0; - for(auto const& ic : invalid_cases) - { - csubstr cbin = capitalize(buf, ic.bin); - INFO("case#=" << icase << " bin='" << ic.bin << "' capitalize='" << cbin << "'"); - REQUIRE_EQ(cbin.len, ic.bin.len); - { - T val = {}; - CHECK(!atox(ic.bin, &val)); - } - { - T val = {}; - CHECK(!atox(cbin, &val)); - } - ++icase; - } - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -template -void test_overflows(std::initializer_list args) -{ - for(const char *s : args) - CHECK_MESSAGE(overflows(to_csubstr(s)), "num=" << s); -} - -template -void test_no_overflows(std::initializer_list args) -{ - for(const char *s : args) - CHECK_MESSAGE(!overflows(to_csubstr(s)), "num=" << s); -} - -template -auto test_no_overflow_zeroes() - -> typename std::enable_if::value, void>::type -{ - test_no_overflows({ "-", "-0", "-000", "-0b0", "-0B0", "-0x0", "-0X0", "-0o0", "-0O0" }); - test_no_overflows({ "", "0", "000", "0b0", "0B0", "0x0", "0X0", "0o0", "0O0" }); -} - -template -auto test_no_overflow_zeroes() - -> typename std::enable_if::value, void>::type -{ - test_no_overflows({ "", "0", "000", "0b0", "0B0", "0x0", "0X0", "0o0", "0O0" }); -} - - -// test overflow in sizes smaller than 64 bit by upcasting -TEST_CASE_TEMPLATE("atox.overflow", T, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t) -{ - char buf_[128]; - substr buf = buf_; - auto do_test = [](bool is_overflow, number_case const& num, csubstr exceeded, number_case const& wrapped){ - char buf2_[128] = {}; - substr buf2 = buf2_; - INFO("exceeded=" << exceeded << " is_overflow=" << is_overflow); - INFO("num=" << num); - INFO("wrapped=" << wrapped); - CHECK_EQ(is_overflow, overflows(exceeded)); - if(is_overflow) - CHECK_NE(&num, &wrapped); - else - CHECK_EQ(&num, &wrapped); - { - T val = num.val + T(1); - CHECK(atox(exceeded, &val)); - CHECK_EQ(val, wrapped.val); - } - // capitalize - buf2 = capitalize(buf2_, exceeded); - INFO(buf2); - CHECK_EQ(is_overflow, overflows(buf2)); - { - T val = num.val + T(1); - CHECK(atox(buf2, &val)); - CHECK_EQ(val, wrapped.val); - } - // zero-pad on the left - for(size_t numz : {1u, 4u, 6u}) - { - buf2 = zpad(buf2_, exceeded, numz); - CHECK_EQ(is_overflow, overflows(buf2)); - { - T val = num.val + T(1); - CHECK(atox(buf2, &val)); - CHECK_EQ(val, wrapped.val); - } - buf2.toupper(); - CHECK_EQ(is_overflow, overflows(buf2)); - { - T val = num.val + T(1); - CHECK(atox(buf2, &val)); - CHECK_EQ(val, wrapped.val); - } - } - }; - auto do_test_overflow = [&](T exceed_how_much, T radix){ - REQUIRE(exceed_how_much >= 0); - number_case const& backelm = back(); - number_case const& wrapelm = next(backelm, (size_t)exceed_how_much); - csubstr exceeded = overflow_by(buf, backelm.val, exceed_how_much, radix); - do_test(exceed_how_much > 0, backelm, exceeded, wrapelm); - }; - auto do_test_underflow = [&](T exceed_how_much, T radix){ - REQUIRE(exceed_how_much >= 0); - number_case const& frntelm = front(); - number_case const& wrapelm = prev(frntelm, (size_t)exceed_how_much); - csubstr exceeded = underflow_by(buf, frntelm.val, exceed_how_much, radix); - do_test(exceed_how_much > 0, frntelm, exceeded, wrapelm); - }; - SUBCASE("zeroes") - { - test_no_overflow_zeroes(); - } - SUBCASE("dec") - { - do_test_underflow(T(0), T(10)); - do_test_underflow(T(1), T(10)); - do_test_underflow(T(2), T(10)); - do_test_underflow(T(3), T(10)); - do_test_underflow(T(4), T(10)); - do_test_underflow(T(5), T(10)); - do_test_overflow(T(0), T(10)); - do_test_overflow(T(1), T(10)); - do_test_overflow(T(2), T(10)); - do_test_overflow(T(3), T(10)); - do_test_overflow(T(4), T(10)); - do_test_overflow(T(5), T(10)); - } - SUBCASE("hex") - { - do_test_underflow(T(0), T(16)); - do_test_underflow(T(1), T(16)); - do_test_underflow(T(2), T(16)); - do_test_underflow(T(3), T(16)); - do_test_underflow(T(4), T(16)); - do_test_underflow(T(5), T(16)); - do_test_overflow(T(0), T(16)); - do_test_overflow(T(1), T(16)); - do_test_overflow(T(2), T(16)); - do_test_overflow(T(3), T(16)); - do_test_overflow(T(4), T(16)); - do_test_overflow(T(5), T(16)); - } - SUBCASE("oct") - { - do_test_underflow(T(0), T(8)); - do_test_underflow(T(1), T(8)); - do_test_underflow(T(2), T(8)); - do_test_underflow(T(3), T(8)); - do_test_underflow(T(4), T(8)); - do_test_underflow(T(5), T(8)); - do_test_overflow(T(0), T(8)); - do_test_overflow(T(1), T(8)); - do_test_overflow(T(2), T(8)); - do_test_overflow(T(3), T(8)); - do_test_overflow(T(4), T(8)); - do_test_overflow(T(5), T(8)); - } - SUBCASE("bin") - { - do_test_underflow(T(0), T(2)); - do_test_underflow(T(1), T(2)); - do_test_underflow(T(2), T(2)); - do_test_underflow(T(3), T(2)); - do_test_underflow(T(4), T(2)); - do_test_underflow(T(5), T(2)); - do_test_overflow(T(0), T(2)); - do_test_overflow(T(1), T(2)); - do_test_overflow(T(2), T(2)); - do_test_overflow(T(3), T(2)); - do_test_overflow(T(4), T(2)); - do_test_overflow(T(5), T(2)); - } -} - -TEST_CASE_TEMPLATE("atox.overflow64", T, int64_t, uint64_t) -{ - char buf_[128] = {}; - substr buf = buf_; - auto test_atox = [](csubstr s, overflow64case const& c){ - INFO("s=" << s); - T val = c.wrapped + T(1); - if(std::is_signed::value || !s.begins_with('-')) - { - CHECK(atox(s, &val)); - CHECK_EQ(val, c.wrapped); - } - else - { - CHECK(!atox(s, &val)); - } - }; - SUBCASE("zeroes") - { - test_no_overflow_zeroes(); - } - SUBCASE("dec") - { - for(auto c : overflow64cases::values) - { - INFO(c.dec); - CHECK_EQ(c.is_overflow, overflows(c.dec)); - test_atox(c.dec, c); - csubstr capitalized = capitalize(buf, c.dec); - CHECK_EQ(c.is_overflow, overflows(capitalized)); - test_atox(capitalized, c); - for(size_t numz : {1u, 4u, 6u}) - { - substr buf2 = zpad(buf, c.dec, numz); - CHECK_EQ(c.is_overflow, overflows(buf2)); - test_atox(buf2, c); - buf2.toupper(); - CHECK_EQ(c.is_overflow, overflows(buf2)); - test_atox(buf2, c); - } - } - } - SUBCASE("hex") - { - for(auto c : overflow64cases::values) - { - INFO(c.hex); - CHECK_EQ(c.is_overflow, overflows(c.hex)); - test_atox(c.hex, c); - csubstr capitalized = capitalize(buf, c.hex); - CHECK_EQ(c.is_overflow, overflows(capitalized)); - test_atox(capitalized, c); - for(size_t numz : {1u, 4u, 6u}) - { - substr buf2 = zpad(buf, c.hex, numz); - CHECK_EQ(c.is_overflow, overflows(buf2)); - test_atox(buf2, c); - buf2.toupper(); - CHECK_EQ(c.is_overflow, overflows(buf2)); - test_atox(buf2, c); - } - } - } - SUBCASE("oct") - { - for(auto c : overflow64cases::values) - { - INFO(c.oct); - CHECK_EQ(c.is_overflow, overflows(c.oct)); - test_atox(c.oct, c); - csubstr capitalized = capitalize(buf, c.oct); - CHECK_EQ(c.is_overflow, overflows(capitalized)); - test_atox(capitalized, c); - for(size_t numz : {1u, 4u, 6u}) - { - substr buf2 = zpad(buf, c.oct, numz); - CHECK_EQ(c.is_overflow, overflows(buf2)); - test_atox(buf2, c); - buf2.toupper(); - CHECK_EQ(c.is_overflow, overflows(buf2)); - test_atox(buf2, c); - } - } - } - SUBCASE("bin") - { - for(auto c : overflow64cases::values) - { - INFO(c.bin); - CHECK_EQ(c.is_overflow, overflows(c.bin)); - test_atox(c.bin, c); - csubstr capitalized = capitalize(buf, c.bin); - CHECK_EQ(c.is_overflow, overflows(capitalized)); - test_atox(capitalized, c); - for(size_t numz : {1u, 4u, 6u}) - { - substr buf2 = zpad(buf, c.bin, numz); - CHECK_EQ(c.is_overflow, overflows(buf2)); - test_atox(buf2, c); - buf2.toupper(); - CHECK_EQ(c.is_overflow, overflows(buf2)); - test_atox(buf2, c); - } - } - } -} - - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -template -void test_overflows_hex() -{ - T x = {}; - std::string str; - if (std::is_unsigned::value) - { - /* with leading zeroes */ - str = "0x0" + std::string(sizeof (T) * 2, 'F'); - CHECK_MESSAGE(!overflows(to_csubstr(str)), "num=" << str); - CHECK(atox(to_csubstr(str), &x)); - CHECK_EQ(std::numeric_limits::max(), x); - - str = "0x01" + std::string(sizeof (T) * 2, '0'); - CHECK_MESSAGE(overflows(to_csubstr(str)), "num=" << str); - CHECK(atox(to_csubstr(str), &x)); - CHECK_EQ(std::numeric_limits::min(), x); - } - else - { - /* with leading zeroes */ - str = "0x07" + std::string(sizeof (T) * 2 - 1, 'F'); - CHECK_MESSAGE(!overflows(to_csubstr(str)), "num=" << str); - CHECK(atox(to_csubstr(str), &x)); - CHECK_EQ(std::numeric_limits::max(), x); - - str = "0x0" + std::string(sizeof (T) * 2, 'F'); - CHECK_MESSAGE(overflows(to_csubstr(str)), "num=" << str); - CHECK(atox(to_csubstr(str), &x)); - CHECK_EQ(-1, x); - - str = "-0x08" + std::string(sizeof (T) * 2 - 1, '0'); - CHECK_MESSAGE(!overflows(to_csubstr(str)), "num=" << str); - CHECK(atox(to_csubstr(str), &x)); - CHECK_EQ(std::numeric_limits::min(), x); - - str = "-0x08" + std::string(sizeof (T) * 2 - 2, '0') + "1"; - CHECK_MESSAGE(overflows(to_csubstr(str)), "num=" << str); - CHECK(atox(to_csubstr(str), &x)); - CHECK_EQ(std::numeric_limits::max(), x); - } -} - -template -void test_overflows_bin() -{ - T x = {}; - std::string str; - if (std::is_unsigned::value) - { - /* with leading zeroes */ - str = "0b0" + std::string(sizeof (T) * 8, '1'); - CHECK_MESSAGE(!overflows(to_csubstr(str)), "num=" << str); - CHECK(atox(to_csubstr(str), &x)); - CHECK_EQ(std::numeric_limits::max(), x); - - str = "0b01" + std::string(sizeof (T) * 8, '0'); - CHECK_MESSAGE(overflows(to_csubstr(str)), "num=" << str); - CHECK(atox(to_csubstr(str), &x)); - CHECK_EQ(std::numeric_limits::min(), x); - } - else - { - /* with leading zeroes */ - str = "0b0" + std::string(sizeof (T) * 8 - 1, '1'); - CHECK_MESSAGE(!overflows(to_csubstr(str)), "num=" << str); - CHECK(atox(to_csubstr(str), &x)); - CHECK_EQ(std::numeric_limits::max(), x); - - str = "0b0" + std::string(sizeof (T) * 8, '1'); - CHECK_MESSAGE(overflows(to_csubstr(str)), "num=" << str); - CHECK(atox(to_csubstr(str), &x)); - CHECK_EQ(-1, x); - - str = "-0b01" + std::string(sizeof (T) * 8 - 1, '0'); - CHECK_MESSAGE(!overflows(to_csubstr(str)), "num=" << str); - CHECK(atox(to_csubstr(str), &x)); - CHECK_EQ(std::numeric_limits::min(), x); - - str = "-0b01" + std::string(sizeof (T) * 8 - 2, '0') + "1"; - CHECK_MESSAGE(overflows(to_csubstr(str)), "num=" << str); - CHECK(atox(to_csubstr(str), &x)); - CHECK_EQ(std::numeric_limits::max(), x); - } -} - -// TODO: test_overflows_oct - -template -typename std::enable_if::value, void>::type -test_overflows() -{ - for(int radix : { 2, 8, 10, 16 }) - { - char bufc[100] = {0}; - substr s(bufc); - INFO("radix=" << radix << " num=" << s); - - uint64_t max = (uint64_t) std::numeric_limits::max(); - size_t sz = utoa(s, max, (uint64_t)radix); - REQUIRE_LE(sz, s.size()); - CHECK(!overflows(s.first(sz))); - memset(s.str, 0, s.len); - sz = utoa(s, max + 1, (uint64_t)radix); - REQUIRE_LE(sz, s.size()); - CHECK(overflows(s.first(sz))); - } - - test_overflows_hex(); - test_overflows_bin(); - // TODO: octal -} - -template -typename std::enable_if::value, void>::type -test_overflows() -{ - for(int radix : { 2, 8, 10, 16 }) - { - char bufc[100] = {0}; - substr s(bufc); - INFO("radix=" << radix << " num=" << s); - - int64_t max = (int64_t) std::numeric_limits::max(); - size_t sz = itoa(s, max, (int64_t)radix); - REQUIRE_LE(sz, s.size()); - CHECK(!overflows(s.first(sz))); - memset(s.str, 0, s.len); - sz = itoa(s, max + 1, (int64_t)radix); - REQUIRE_LE(sz, s.size()); - CHECK(overflows(s.first(sz))); - - int64_t min = (int64_t) std::numeric_limits::min(); - sz = itoa(s, min, (int64_t)radix); - REQUIRE_LE(sz, s.size()); - CHECK(!overflows(s.first(sz))); - memset(s.str, 0, s.len); - sz = itoa(s, min - 1, (int64_t)radix); - REQUIRE_LE(sz, s.size()); - CHECK(overflows(s.first(sz))); - } - - test_overflows_hex(); - test_overflows_bin(); - // TODO: octal -} - -TEST_CASE_TEMPLATE("overflows.8bit_32bit", T, uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t) -{ - test_overflows(); -} - -TEST_CASE("overflows.u64") -{ - CHECK(!overflows("18446744073709551614")); - CHECK(!overflows("18446744073709551615")); - CHECK(overflows("18446744073709551616")); - - // more chars but leading zeroes - CHECK(!overflows("0018446744073709551615")); - - { /* with leading zeroes */ - std::string str; - uint64_t x = {}; - str = "0o01" + std::string(21, '7'); - CHECK_MESSAGE(!overflows(to_csubstr(str)), "num=" << str); - str = "0o02" + std::string(21, '0'); - CHECK_MESSAGE(overflows(to_csubstr(str)), "num=" << str); - CHECK(atox(to_csubstr(str), &x)); - CHECK_EQ(0, x); - } - - test_overflows_hex(); - test_overflows_bin(); -} - -TEST_CASE("overflows.i64") -{ - CHECK(!overflows("9223372036854775806")); - CHECK(!overflows("9223372036854775807")); - CHECK(overflows("9223372036854775808")); - CHECK(!overflows("-9223372036854775808")); - CHECK(overflows("-9223372036854775809")); - - // more chars, but leading zeroes - CHECK(!overflows("0009223372036854775807")); - CHECK(!overflows("-0009223372036854775807")); - - { /* with leading zeroes */ - std::string str; - int64_t x = {}; - str = "0o0" + std::string(21, '7'); - CHECK_MESSAGE(!overflows(to_csubstr(str)), "num=" << str); - str = "0o01" + std::string(21, '0'); - CHECK_MESSAGE(overflows(to_csubstr(str)), "num=" << str); - CHECK(atox(to_csubstr(str), &x)); - CHECK_EQ(std::numeric_limits::min(), x); - } - - test_overflows_hex(); - test_overflows_bin(); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -/** remove trailing digits after precision */ -template -T remprec10(T val, int precision) -{ - T fprec = T(1); - for(int i = 0; i < precision; ++i) - fprec *= T(10); - T rval = val * fprec; - return ((T)((int64_t)rval)) / fprec; -} - -template -T test_ator(csubstr s, T ref) -{ - INFO("str=" << s << " ref=" << ref); - T rval; - CHECK(atox(s, &rval)); - INFO("rval=" << rval); - CHECK_EQ(memcmp(&rval, &ref, sizeof(T)), 0); - return rval; -} - -template -void test_rtoa(substr buf, Real f, int precision, const char *scient, const char *flt, const char* flex, const char *hexa, const char *hexa_alternative=nullptr) -{ - size_t ret; - Real pf = remprec10(f, precision); - - { - INFO("num=" << f << " precision=" << precision << " scient=" << scient); - memset(buf.str, 0, buf.len); - ret = xtoa(buf, f, precision, FTOA_SCIENT); - REQUIRE_LE(ret, buf.len); - CHECK_EQ(buf.first(ret), to_csubstr(scient)); - test_ator(buf.first(ret), pf); - } - - { - INFO("num=" << f << " precision=" << precision << " flt=" << flt); - memset(buf.str, 0, ret); - ret = xtoa(buf, f, precision, FTOA_FLOAT); - REQUIRE_LE(ret, buf.len); - CHECK_EQ(buf.first(ret), to_csubstr(flt)); - test_ator(buf.first(ret), pf); - } - - { - INFO("num=" << f << " precision=" << precision << " flex=" << flex); - memset(buf.str, 0, ret); - ret = xtoa(buf, f, precision+1, FTOA_FLEX); - REQUIRE_LE(ret, buf.len); - CHECK_EQ(buf.first(ret), to_csubstr(flex)); - test_ator(buf.first(ret), pf); - } - - { - if(!hexa_alternative) - hexa_alternative = hexa; - INFO("num=" << f << " precision=" << precision << " hexa=" << hexa << " hexa_alternative=" << hexa_alternative); - memset(buf.str, 0, ret); - ret = xtoa(buf, f, precision, FTOA_HEXA); - REQUIRE_LE(ret, buf.len); - INFO("buf='" << buf.first(ret) << "'"); - - CHECK((buf.first(ret) == to_csubstr(hexa) || buf.first(ret) == to_csubstr(hexa_alternative))); - Real readback = {}; - CHECK(atox(buf.first(ret), &readback)); - INFO("readback=" << readback); - REQUIRE_EQ(xtoa(buf, readback, precision, FTOA_HEXA), ret); - Real readback2 = {}; - CHECK(atox(buf.first(ret), &readback2)); - INFO("readback2=" << readback2); - CHECK_EQ(memcmp(&readback2, &readback, sizeof(Real)), 0); - } -} - - -TEST_CASE("ftoa.basic") -{ - char bufc[128]; - substr buf(bufc); - C4_ASSERT(buf.len == sizeof(bufc)-1); - - // earlier versions of emscripten's sprintf() do not respect some - // precision values when printing in hexadecimal format. - // - // @see https://github.com/biojppm/c4core/pull/52 - #if defined(__EMSCRIPTEN__) && __EMSCRIPTEN_major__ < 3 - #define _c4emscripten_alt(alt) , alt - #define _c4emscripten_alt2(alt1, alt2) , alt2 - #else - #define _c4emscripten_alt(alt) - #define _c4emscripten_alt2(alt1, alt2) , alt1 - #endif - - float f = 1.1234123f; - double d = 1.1234123; - - test_rtoa(buf, f, 0, /*scient*/"1e+00", /*flt*/"1", /*flex*/"1", /*hexa*/"0x1p+0"); - test_rtoa(buf, d, 0, /*scient*/"1e+00", /*flt*/"1", /*flex*/"1", /*hexa*/"0x1p+0"); - - test_rtoa(buf, f, 1, /*scient*/"1.1e+00", /*flt*/"1.1", /*flex*/"1.1", /*hexa*/"0x1.2p+0"); - test_rtoa(buf, d, 1, /*scient*/"1.1e+00", /*flt*/"1.1", /*flex*/"1.1", /*hexa*/"0x1.2p+0"); - - test_rtoa(buf, f, 2, /*scient*/"1.12e+00", /*flt*/"1.12", /*flex*/"1.12", /*hexa*/"0x1.20p+0" _c4emscripten_alt("0x1.1f8p+0")); - test_rtoa(buf, d, 2, /*scient*/"1.12e+00", /*flt*/"1.12", /*flex*/"1.12", /*hexa*/"0x1.20p+0" _c4emscripten_alt("0x1.1f8p+0")); - - test_rtoa(buf, f, 3, /*scient*/"1.123e+00", /*flt*/"1.123", /*flex*/"1.123", /*hexa*/"0x1.1f9p+0" _c4emscripten_alt("0x1.1f98p+0")); - test_rtoa(buf, d, 3, /*scient*/"1.123e+00", /*flt*/"1.123", /*flex*/"1.123", /*hexa*/"0x1.1f9p+0" _c4emscripten_alt("0x1.1f98p+0")); - - test_rtoa(buf, f, 4, /*scient*/"1.1234e+00", /*flt*/"1.1234", /*flex*/"1.1234", /*hexa*/"0x1.1f98p+0"); - test_rtoa(buf, d, 4, /*scient*/"1.1234e+00", /*flt*/"1.1234", /*flex*/"1.1234", /*hexa*/"0x1.1f98p+0"); - - f = 1.01234123f; - d = 1.01234123; - - test_rtoa(buf, f, 0, /*scient*/"1e+00", /*flt*/"1", /*flex*/"1", /*hexa*/"0x1p+0"); - test_rtoa(buf, d, 0, /*scient*/"1e+00", /*flt*/"1", /*flex*/"1", /*hexa*/"0x1p+0"); - - test_rtoa(buf, f, 1, /*scient*/"1.0e+00", /*flt*/"1.0", /*flex*/"1", /*hexa*/"0x1.0p+0"); - test_rtoa(buf, d, 1, /*scient*/"1.0e+00", /*flt*/"1.0", /*flex*/"1", /*hexa*/"0x1.0p+0"); - - test_rtoa(buf, f, 2, /*scient*/"1.01e+00", /*flt*/"1.01", /*flex*/"1.01", /*hexa*/"0x1.03p+0"); - test_rtoa(buf, d, 2, /*scient*/"1.01e+00", /*flt*/"1.01", /*flex*/"1.01", /*hexa*/"0x1.03p+0"); - - test_rtoa(buf, f, 3, /*scient*/"1.012e+00", /*flt*/"1.012", /*flex*/"1.012", /*hexa*/"0x1.033p+0" _c4emscripten_alt2("0x1.032p+0", "0x1.0328p+0")); - test_rtoa(buf, d, 3, /*scient*/"1.012e+00", /*flt*/"1.012", /*flex*/"1.012", /*hexa*/"0x1.033p+0" _c4emscripten_alt2("0x1.032p+0", "0x1.0328p+0")); - - test_rtoa(buf, f, 4, /*scient*/"1.0123e+00", /*flt*/"1.0123", /*flex*/"1.0123", /*hexa*/"0x1.0329p+0"); - test_rtoa(buf, d, 4, /*scient*/"1.0123e+00", /*flt*/"1.0123", /*flex*/"1.0123", /*hexa*/"0x1.0329p+0"); - - f = 0.f; - d = 0.; - - test_rtoa(buf, f, 0, /*scient*/"0e+00", /*flt*/"0", /*flex*/"0", /*hexa*/"0x0p+0"); - test_rtoa(buf, d, 0, /*scient*/"0e+00", /*flt*/"0", /*flex*/"0", /*hexa*/"0x0p+0"); - - test_rtoa(buf, f, 1, /*scient*/"0.0e+00", /*flt*/"0.0", /*flex*/"0", /*hexa*/"0x0.0p+0"); - test_rtoa(buf, d, 1, /*scient*/"0.0e+00", /*flt*/"0.0", /*flex*/"0", /*hexa*/"0x0.0p+0"); - - test_rtoa(buf, f, 2, /*scient*/"0.00e+00", /*flt*/"0.00", /*flex*/"0", /*hexa*/"0x0.00p+0"); - test_rtoa(buf, d, 2, /*scient*/"0.00e+00", /*flt*/"0.00", /*flex*/"0", /*hexa*/"0x0.00p+0"); - - test_rtoa(buf, f, 3, /*scient*/"0.000e+00", /*flt*/"0.000", /*flex*/"0", /*hexa*/"0x0.000p+0" _c4emscripten_alt2("0x0.000p+0", "0x0.000p+0")); - test_rtoa(buf, d, 3, /*scient*/"0.000e+00", /*flt*/"0.000", /*flex*/"0", /*hexa*/"0x0.000p+0" _c4emscripten_alt2("0x0.000p+0", "0x0.000p+0")); - - test_rtoa(buf, f, 4, /*scient*/"0.0000e+00", /*flt*/"0.0000", /*flex*/"0", /*hexa*/"0x0.0000p+0"); - test_rtoa(buf, d, 4, /*scient*/"0.0000e+00", /*flt*/"0.0000", /*flex*/"0", /*hexa*/"0x0.0000p+0"); - - f = 1.f; - d = 1.; - - test_rtoa(buf, f, 0, /*scient*/"1e+00", /*flt*/"1", /*flex*/"1", /*hexa*/"0x1p+0"); - test_rtoa(buf, d, 0, /*scient*/"1e+00", /*flt*/"1", /*flex*/"1", /*hexa*/"0x1p+0"); - - test_rtoa(buf, f, 1, /*scient*/"1.0e+00", /*flt*/"1.0", /*flex*/"1", /*hexa*/"0x1.0p+0"); - test_rtoa(buf, d, 1, /*scient*/"1.0e+00", /*flt*/"1.0", /*flex*/"1", /*hexa*/"0x1.0p+0"); - - test_rtoa(buf, f, 2, /*scient*/"1.00e+00", /*flt*/"1.00", /*flex*/"1", /*hexa*/"0x1.00p+0"); - test_rtoa(buf, d, 2, /*scient*/"1.00e+00", /*flt*/"1.00", /*flex*/"1", /*hexa*/"0x1.00p+0"); - - test_rtoa(buf, f, 3, /*scient*/"1.000e+00", /*flt*/"1.000", /*flex*/"1", /*hexa*/"0x1.000p+0" _c4emscripten_alt2("0x1.000p+0", "0x1.000p+0")); - test_rtoa(buf, d, 3, /*scient*/"1.000e+00", /*flt*/"1.000", /*flex*/"1", /*hexa*/"0x1.000p+0" _c4emscripten_alt2("0x1.000p+0", "0x1.000p+0")); - - test_rtoa(buf, f, 4, /*scient*/"1.0000e+00", /*flt*/"1.0000", /*flex*/"1", /*hexa*/"0x1.0000p+0"); - test_rtoa(buf, d, 4, /*scient*/"1.0000e+00", /*flt*/"1.0000", /*flex*/"1", /*hexa*/"0x1.0000p+0"); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -TEST_CASE_TEMPLATE("atof.integral", T, float, double) -{ - auto t_ = [](csubstr str, int val){ - T rval = (T)10 * (T)val; - INFO("str=" << str); - bool ret = atox(str, &rval); - CHECK_EQ(ret, true); - CHECK_EQ(static_cast(rval), val); - CHECK_EQ(rval, (T)val); - }; - - csubstr s = "12345678"; - t_(s, 12345678); - t_(s.first(8), 12345678); - t_(s.first(7), 1234567); - t_(s.first(6), 123456); - t_(s.first(5), 12345); - t_(s.first(4), 1234); - t_(s.first(3), 123); - t_(s.first(2), 12); - t_(s.first(1), 1); -} - -TEST_CASE_TEMPLATE("atof.hexa", T, float, double) -{ - auto t_ = [](csubstr str, bool isok){ - T rval = {}; - INFO("str=" << str); - CHECK_EQ(atox(str, &rval), isok); - }; - #if C4CORE_NO_FAST_FLOAT - #define _scanf_accepts(expected) !expected - #else - #define _scanf_accepts(expected) expected - #endif - t_("0x1.p+0", true); - t_("0x1.p", _scanf_accepts(false)); - t_("0x1.p+", _scanf_accepts(false)); - t_("0x12p+0", true); - t_("0x12p", _scanf_accepts(false)); - t_("0xabcdef.abcdefp+0", true); - t_("0xABCDEF.ABCDEFp+0", true); - t_("0x1g", _scanf_accepts(false)); - t_("0x1.2", true); - t_("0x1.", true); - t_("0x1.0329p+0", true); - t_("0x1.0329P+0", true); - t_("0x1.aAaAaAp+0", true); - t_("0x1.agA+0", _scanf_accepts(false)); -} - -TEST_CASE_TEMPLATE("atof.infnan", T, float, double) -{ - T pinf = std::numeric_limits::infinity(); - T ninf = -std::numeric_limits::infinity(); - T nan = std::numeric_limits::quiet_NaN(); - T rval = {}; - test_ator("infinity", pinf); - test_ator("inf", pinf); - test_ator("-infinity", ninf); - test_ator("-inf", ninf); - test_ator("nan", nan); -} - -TEST_CASE_TEMPLATE("atof.fail_parse", T, float, double) -{ - auto t_ = [](csubstr str){ - T rval; - INFO("str=" << str << " rval=" << rval); - CHECK_EQ(atox(str, &rval), false); - }; - t_(".inf"); - t_("-.inf"); - t_(".nan"); - t_("-.nan"); - t_("not a float!"); - #ifndef C4CORE_NO_FAST_FLOAT - t_("0xfonix!"); - #endif - //t_("123.45not a float!"); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -TEST_CASE_TEMPLATE("to_chars.empty_buffer", T, uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t, void*) -{ - char buf_[100]; - substr buf = buf_; - CHECK_EQ(to_chars({}, T(101)), to_chars(buf_, T(101))); - CHECK_EQ(to_chars({}, T(101)), to_chars(buf , T(101))); -} -// due to an implementation quirk with sprintf, for floats the empty is GE -TEST_CASE_TEMPLATE("to_chars.empty_buffer", T, float, double) -{ - char buf_[100]; - substr buf = buf_; - CHECK_GE(to_chars({}, T(101)), to_chars(buf_, T(101))); - CHECK_GE(to_chars({}, T(101)), to_chars(buf , T(101))); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -TEST_CASE("to_chars.std_string") -{ - std::string foo("foo"); - char buf_[32]; - substr buf(buf_); - size_t result = to_chars(buf, foo); - CHECK_EQ(result, 3); - CHECK_EQ(buf.first(3), "foo"); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -TEST_CASE("to_chars.bool") -{ - char buf_[32]; - substr buf(buf_); - csubstr result = to_chars_sub(buf, true); - CHECK_EQ(result, "1"); - result = to_chars_sub(buf, false); - CHECK_EQ(result, "0"); -} - -TEST_CASE("from_chars.bool") -{ - bool result = false; - for(const char *s : {"1", "true", "True", "TRUE"}) - { - INFO("s='" << s << "'"); - bool ok = from_chars(to_csubstr(s), &result); - CHECK_UNARY(ok); - CHECK_UNARY(result); - } - for(const char *s : {"0", "false", "False", "FALSE"}) - { - INFO("s='" << s << "'"); - bool ok = from_chars(to_csubstr(s), &result); - CHECK_UNARY(ok); - CHECK_UNARY_FALSE(result); - } -} - -TEST_CASE("from_chars_first.bool") -{ - bool result = false; - for(const char *s : {"1", "10000", "2", "3", "10", "010", "001", "0001", "true", "True", "TRUE"}) - { - INFO("s='" << s << "'"); - bool ok = from_chars(to_csubstr(s), &result); - CHECK_UNARY(ok); - CHECK_UNARY(result); - } - for(const char *s : {"0", "00", "000", "0000", "false", "False", "FALSE"}) - { - INFO("s='" << s << "'"); - bool ok = from_chars(to_csubstr(s), &result); - CHECK_UNARY(ok); - CHECK_UNARY_FALSE(result); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -// test that no characters are trimmed at the end of -// the number due to printf-based implementations -// needing space for the \0 -template -void test_trimmed_fit(T v, csubstr expected) -{ - char buf_[128] = {}; - char buf2_[128] = {}; - substr buf(buf_); - substr buf2(buf_); - REQUIRE_GE(buf.len, expected.len); - REQUIRE_GE(buf2.len, expected.len); - csubstr result = to_chars_sub(buf, v); - CHECK_EQ(result, expected); - csubstr result2 = to_chars_sub(buf2.sub(result.len), v); - CHECK_EQ(result2, result); - std::string str; - catrs(&str, v); - CHECK_EQ(expected, to_csubstr(str)); - CHECK_EQ(result, to_csubstr(str)); -} - -TEST_CASE("to_chars.trimmed_fit_int") -{ - test_trimmed_fit(12345678, "12345678"); -} - -TEST_CASE("to_chars.trimmed_fit_float") -{ - test_trimmed_fit(0.374f, "0.374"); - test_trimmed_fit(12.374f, "12.374"); -} - -TEST_CASE("to_chars.trimmed_fit_double") -{ - test_trimmed_fit(0.374, "0.374"); - test_trimmed_fit(12.374, "12.374"); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -template -void to_chars_roundtrip(substr buf, T const& val, csubstr expected) -{ - T cp = {}; - INFO("val=" << val); - csubstr res = to_chars_sub(buf, val); - CHECK_EQ(res, expected); - bool ok = from_chars(res, &cp); - CHECK_UNARY(ok); - CHECK_EQ(cp, val); -} - -template -void to_chars_roundtrip(char (&buf)[N], csubstr val) -{ - char cp_[N] = {}; - substr cp = cp_; - INFO("val=" << val); - REQUIRE_LE(val.len, N); - csubstr res = to_chars_sub(buf, val); - CHECK_EQ(res.len, val.len); - CHECK_EQ(res, val); - bool ok = from_chars(res, &cp); - CHECK_UNARY(ok); - CHECK_EQ(cp, val); -} - - -TEST_CASE("to_chars.roundtrip_bool") -{ - char buf[128]; - to_chars_roundtrip(buf, false, "0"); - to_chars_roundtrip(buf, true, "1"); -} - - -TEST_CASE("to_chars.roundtrip_char") -{ - char buf[128]; - to_chars_roundtrip(buf, 'a', "a"); - to_chars_roundtrip(buf, 'b', "b"); - to_chars_roundtrip(buf, 'c', "c"); - to_chars_roundtrip(buf, 'd', "d"); -} - -#define C4_TEST_ROUNDTRIP_INT(ty) \ -TEST_CASE("to_chars.roundtrip_" #ty)\ -{\ - char buf[128];\ - to_chars_roundtrip(buf, 0, "0");\ - to_chars_roundtrip(buf, 1, "1");\ - to_chars_roundtrip(buf, 2, "2");\ - to_chars_roundtrip(buf, 3, "3");\ - to_chars_roundtrip(buf, 4, "4");\ -} -C4_TEST_ROUNDTRIP_INT(int8_t) -C4_TEST_ROUNDTRIP_INT(int16_t) -C4_TEST_ROUNDTRIP_INT(int32_t) -C4_TEST_ROUNDTRIP_INT(int64_t) -C4_TEST_ROUNDTRIP_INT(uint8_t) -C4_TEST_ROUNDTRIP_INT(uint16_t) -C4_TEST_ROUNDTRIP_INT(uint32_t) -C4_TEST_ROUNDTRIP_INT(uint64_t) -// some of the following types are not the same as above: -using ulong = unsigned long; -using uint = unsigned int; -C4_TEST_ROUNDTRIP_INT(int) -C4_TEST_ROUNDTRIP_INT(uint) -C4_TEST_ROUNDTRIP_INT(long) -C4_TEST_ROUNDTRIP_INT(ulong) -C4_TEST_ROUNDTRIP_INT(size_t) -C4_TEST_ROUNDTRIP_INT(intptr_t) -C4_TEST_ROUNDTRIP_INT(uintptr_t) - -#define C4_TEST_ROUNDTRIP_REAL(ty) \ -TEST_CASE("to_chars.roundtrip_" #ty)\ -{\ - char buf[128];\ - to_chars_roundtrip(buf, ty(0.0), "0");\ - to_chars_roundtrip(buf, ty(1.0), "1");\ - to_chars_roundtrip(buf, ty(2.0), "2");\ - to_chars_roundtrip(buf, ty(3.0), "3");\ - to_chars_roundtrip(buf, ty(4.0), "4");\ -} -C4_TEST_ROUNDTRIP_REAL(float) -C4_TEST_ROUNDTRIP_REAL(double) - -TEST_CASE("to_chars.roundtrip_substr") -{ - char buf[128]; - to_chars_roundtrip(buf, ""); - to_chars_roundtrip(buf, "0"); - to_chars_roundtrip(buf, "1"); - to_chars_roundtrip(buf, "2"); - to_chars_roundtrip(buf, "3"); - to_chars_roundtrip(buf, "4"); - to_chars_roundtrip(buf, "zhis iz a test"); -} - -TEST_CASE("to_chars.substr_enough_size") -{ - char orig_[] = "0123456789"; - substr orig = orig_; - char result_[20]; - substr result = result_; - size_t len = to_chars(result, orig); - CHECK_EQ(len, orig.len); - CHECK_NE(result.str, orig.str); - CHECK_EQ(result.first(10), orig); -} - -TEST_CASE("to_chars.substr_insufficient_size") -{ - char orig_[] = "0123456789"; - substr orig = orig_; - char result_[11] = {}; - substr result = result_; - result.len = 5; - size_t len = to_chars(result, orig); - CHECK_EQ(len, orig.len); - CHECK_NE(result.str, orig.str); - CHECK_EQ(result.first(5), "01234"); - CHECK_EQ(substr(result_).last(5), "\0\0\0\0\0"); -} - -TEST_CASE("from_chars.csubstr") -{ - csubstr orig = "0123456789"; - csubstr result; - CHECK_NE(result.str, orig.str); - CHECK_NE(result.len, orig.len); - bool ok = from_chars(orig, &result); - CHECK(ok); - CHECK_EQ(result.str, orig.str); - CHECK_EQ(result.len, orig.len); -} - -TEST_CASE("from_chars.substr_enough_size") -{ - char buf_[128] = {}; - substr result = buf_; - for(char r : result) - { - CHECK_EQ(r, '\0'); - } - bool ok = from_chars("0123456789", &result); - CHECK(ok); - CHECK_EQ(result.len, 10); - CHECK_EQ(result.str, buf_); - CHECK_EQ(result, "0123456789"); -} - -TEST_CASE("from_chars.substr_insufficient_size") -{ - char buf_[128] = {}; - substr buf = buf_; - buf.len = 0; - bool ok = from_chars("0123456789", &buf); - CHECK_FALSE(ok); - for(size_t i = 0; i < 10; ++i) - { - CHECK_EQ(buf_[i], '\0'); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -struct ptr_expected { void *ptr; c4::csubstr str; }; -const ptr_expected ptr_cases[] = { - {(void*)0x0, c4::csubstr("0x0")}, - {(void*)0x1234, c4::csubstr("0x1234")}, - {(void*)-0x1234, c4::csubstr("-0x1234")}, -}; - -template -void test_xtoa_ptr(const char *type_name) -{ - INFO("type=" << type_name); - char buf_[128] = {}; - c4::substr buf(buf_); - for(auto &pe : ptr_cases) - { - INFO("val=" << pe.str); - size_t ret = xtoa(buf, (T const*)pe.ptr); - CHECK_EQ(ret, pe.str.len); - CHECK_EQ(buf.first(ret), pe.str); - } -} - -template -void test_to_chars_ptr(const char *type_name) -{ - INFO("type=" << type_name); - char buf_[128] = {}; - c4::substr buf(buf_); - for(auto &pe : ptr_cases) - { - INFO("val=" << pe.str); - size_t ret = to_chars(buf, (T const*)pe.ptr); - CHECK_EQ(ret, pe.str.len); - CHECK_EQ(buf.first(ret), pe.str); - } -} - -template -void test_atox_ptr(const char *type_name) -{ - INFO("type=" << type_name); - for(auto &pe : ptr_cases) - { - T *ptr = nullptr; - INFO("val=" << pe.str); - bool ret = atox(pe.str, &ptr); - CHECK(ret); - CHECK_EQ((void*)ptr, pe.ptr); - } -} - -template -void test_from_chars_ptr(const char *type_name) -{ - INFO("type=" << type_name); - for(auto &pe : ptr_cases) - { - T *ptr = nullptr; - INFO("val=" << pe.str); - bool ret = from_chars(pe.str, &ptr); - CHECK(ret); - CHECK_EQ((void*)ptr, pe.ptr); - } -} - -template -void test_from_chars_first_ptr(const char *type_name) -{ - INFO("type=" << type_name); - for(auto &pe : ptr_cases) - { - T *ptr = nullptr; - INFO("val=" << pe.str); - bool ret = from_chars(pe.str, &ptr); - CHECK(ret); - CHECK_EQ((void*)ptr, pe.ptr); - } -} - - -TEST_CASE("xtoa.ptr") -{ - test_xtoa_ptr("void"); - test_xtoa_ptr("int"); - test_xtoa_ptr>("std::vector"); -} - -TEST_CASE("atox.ptr") -{ - test_atox_ptr("void"); - test_atox_ptr("int"); - test_atox_ptr>("std::vector"); -} - -TEST_CASE("to_chars.ptr") -{ - test_to_chars_ptr("void"); - test_to_chars_ptr("int"); - test_to_chars_ptr>("std::vector"); -} - -TEST_CASE("from_chars.ptr") -{ - test_from_chars_ptr("void"); - test_from_chars_ptr("int"); - test_from_chars_ptr>("std::vector"); -} - -TEST_CASE("from_chars_first.ptr") -{ - test_from_chars_first_ptr("void"); - test_from_chars_first_ptr("int"); - test_from_chars_first_ptr>("std::vector"); -} - -} // namespace c4 - - -C4_SUPPRESS_WARNING_GCC_POP -C4_SUPPRESS_WARNING_CLANG_POP - -#include "c4/libtest/supprwarn_pop.hpp" diff --git a/thirdparty/ryml/ext/c4core/test/test_ctor_dtor.cpp b/thirdparty/ryml/ext/c4core/test/test_ctor_dtor.cpp deleted file mode 100644 index f655fb17c..000000000 --- a/thirdparty/ryml/ext/c4core/test/test_ctor_dtor.cpp +++ /dev/null @@ -1,306 +0,0 @@ -#ifndef C4CORE_SINGLE_HEADER -#include "c4/ctor_dtor.hpp" -#endif - -#include "c4/libtest/supprwarn_push.hpp" - -#include -#include -#include - -namespace c4 { - -namespace { -struct subject -{ - static size_t ct_cp, ct_mv, cp, mv; - static void clear() { ct_cp = ct_mv = cp = mv = 0; } - subject(Counting const&) - { - ++ct_cp; - } - subject(Counting &&) - { - ++ct_mv; - } - subject(subject const&) - { - ++cp; - } - subject(subject &&) - { - ++mv; - } -}; -size_t subject::ct_cp = 0; -size_t subject::ct_mv = 0; -size_t subject::cp = 0; -size_t subject::mv = 0; -} // empty namespace - - -TEST_CASE("ctor_dtor.construct_n") -{ - using T = Counting; - C4_STATIC_ASSERT(sizeof(T) % alignof(T) == 0); - alignas(T) char buf1[100 * sizeof(T)]; - T* mem1 = reinterpret_cast(buf1); - - using cs = Counting; - - decltype(subject::ct_cp) num = 10; - - { - auto chc = T::check_num_ctors_dtors(num, 0); - auto ch = cs::check_num_ctors_dtors(1, 1); - cs s("bla"); - construct_n(mem1, num, s); - CHECK_EQ(subject::ct_cp, num); - subject::clear(); - } - - { - auto chc = T::check_num_ctors_dtors(num, 0); - auto ch = cs::check_num_ctors_dtors(1, 1); - construct_n(mem1, num, cs("bla")); // BAD!!! will call 10 moves - CHECK_EQ(subject::ct_cp, num); - subject::clear(); - } -} - - -//----------------------------------------------------------------------------- -template -void create_make_room_buffer(std::vector &orig) -{ - C4_STATIC_ASSERT(std::is_integral::value); - for(int i = 0, e = (int)orig.size(); i < e; ++i) - { - orig[static_cast(i)] = (T)(33 + i % (122 - 33)); // assign characters - } -} -template<> -void create_make_room_buffer(std::vector &orig) -{ - for(int i = 0, e = (int)orig.size(); i < e; ++i) - { - char c = (char)(33 + i % (122 - 33)); - orig[static_cast(i)].assign(10, c); - } -} - -template -void do_make_room_inplace(std::vector const& orig, std::vector & buf, - size_t bufsz, size_t room, size_t pos) -{ - buf = orig; - make_room(buf.data() + pos, bufsz, room); -} - -template -void do_make_room_srcdst(std::vector const& orig, std::vector & buf, - size_t bufsz, size_t room, size_t pos) -{ - buf.resize(orig.size()); - for(auto &t : buf) - { - t = T(); - } - make_room(buf.data(), orig.data(), bufsz, room, pos); -} - -template -void do_make_room_check(std::vector const& orig, std::vector & buf, - size_t bufsz, size_t room, size_t pos) -{ - for(size_t i = 0, e = orig.size(); i < e; ++i) - { - INFO("i=" << (int)i); - if(i < pos) - { - // memory before the move, must be untouched - CHECK_EQ(buf[i], orig[i]); - } - else - { - if(i >= pos && i < pos + room) - { - // this is the memory that was moved (at its origin) - //CHECK_EQ(buf[i], orig[i]) << "i=" << (int)i; - } - else if(i >= pos + room && i < pos + room + bufsz) - { - // this is the memory that was moved (at its destination) - CHECK_EQ(buf[i], orig[i - room]); - } - else - { - // this is memory at the end, must be untouched - CHECK_EQ(buf[i], orig[i]); - } - } - } -}; - -template -void do_make_room_inplace_test(std::vector const& orig, std::vector & buf, - size_t bufsz, size_t room, size_t pos) -{ - do_make_room_inplace(orig, buf, bufsz, room, pos); - do_make_room_check(orig, buf, bufsz, room, pos); -} - -template -void do_make_room_srcdst_test(std::vector const& orig, std::vector & buf, - size_t /*bufsz*/, size_t room, size_t pos) -{ - do_make_room_srcdst(orig, buf, buf.size() - room, room, pos); - do_make_room_check(orig, buf, buf.size() - room, room, pos); -} - -template -void test_make_room(Func test_func) -{ - std::vector orig(100), buf(100); - - create_make_room_buffer(orig); - - { - INFO("in the beginning without overlap"); - test_func(orig, buf, /*bufsz*/10, /*room*/10, /*pos*/0); - } - - { - INFO("in the beginning with overlap"); - test_func(orig, buf, /*bufsz*/10, /*room*/15, /*pos*/0); - } - - { - INFO("in the middle without overlap"); - test_func(orig, buf, /*bufsz*/10, /*room*/10, /*pos*/10); - } - - { - INFO("in the middle with overlap"); - test_func(orig, buf, /*bufsz*/10, /*room*/15, /*pos*/10); - } -} - -TEST_CASE_TEMPLATE("ctor_dtor.make_room_inplace", T, uint8_t, uint64_t, std::string) -{ - test_make_room(do_make_room_inplace_test); -} - -TEST_CASE_TEMPLATE("ctor_dtor.make_room_srcdst", T, uint8_t, uint64_t, std::string) -{ - test_make_room(&do_make_room_srcdst_test); -} - - -//----------------------------------------------------------------------------- - -template -void do_destroy_room_inplace(std::vector const& orig, std::vector & buf, - size_t bufsz, size_t room, size_t pos) -{ - buf = orig; - destroy_room(buf.data() + pos, bufsz - pos, room); -} - -template -void do_destroy_room_srcdst(std::vector const& orig, std::vector & buf, - size_t bufsz, size_t room, size_t pos) -{ - buf = orig; - destroy_room(buf.data(), orig.data(), bufsz, room, pos); -} - -template -void do_destroy_room_check(std::vector const& orig, std::vector & buf, - size_t bufsz, size_t room, size_t pos) -{ - for(size_t i = 0, e = orig.size(); i < e; ++i) - { - INFO("i=" << (int)i << " room=" << room << " pos=" << pos); - if(i < pos) - { - // memory before the destroy, should be untouched - CHECK_EQ(buf[i], orig[i]); - } - else - { - if(i >= pos && i < pos + room) - { - // this is the memory that was destroyed (at its origin) - } - else if(i >= pos + room && i < pos + room + bufsz) - { - // this is the memory that was moved (at its destination) - CHECK_EQ(buf[i - room], orig[i]); - } - else - { - // this is memory at the end, should be untouched - CHECK_EQ(buf[i], orig[i]); - } - } - } -}; - -template -void do_destroy_room_inplace_test(std::vector const& orig, std::vector & buf, - size_t room, size_t pos) -{ - do_destroy_room_inplace(orig, buf, buf.size(), room, pos); - do_destroy_room_check(orig, buf, buf.size(), room, pos); -} - -template -void do_destroy_room_srcdst_test(std::vector const& orig, std::vector & buf, - size_t room, size_t pos) -{ - do_destroy_room_srcdst(orig, buf, buf.size(), room, pos); - do_destroy_room_check(orig, buf, buf.size(), room, pos); -} - -template -void test_destroy_room(Func test_func) -{ - std::vector orig(100), buf(100); - - create_make_room_buffer(orig); - - { - INFO("in the beginning, room=10"); - test_func(orig, buf, /*room*/10, /*pos*/0); - } - - { - INFO("in the beginning, room=20"); - test_func(orig, buf, /*room*/20, /*pos*/0); - } - - { - INFO("in the middle, room=10"); - test_func(orig, buf, /*room*/10, /*pos*/10); - } - - { - INFO("in the middle, room=20"); - test_func(orig, buf, /*room*/20, /*pos*/10); - } -} - -TEST_CASE_TEMPLATE("ctor_dtor.destroy_room_inplace", T, uint8_t, uint64_t, std::string) -{ - test_destroy_room(do_destroy_room_inplace_test); -} - -TEST_CASE_TEMPLATE("ctor_dtor.destroy_room_srcdst", T, uint8_t, uint64_t, std::string) -{ - test_destroy_room(&do_destroy_room_srcdst_test); -} - -} // namespace c4 - -#include "c4/libtest/supprwarn_pop.hpp" diff --git a/thirdparty/ryml/ext/c4core/test/test_dump.cpp b/thirdparty/ryml/ext/c4core/test/test_dump.cpp deleted file mode 100644 index cfa7d991c..000000000 --- a/thirdparty/ryml/ext/c4core/test/test_dump.cpp +++ /dev/null @@ -1,1220 +0,0 @@ -#ifndef C4CORE_SINGLE_HEADER -#include "c4/substr.hpp" -#include "c4/std/std.hpp" -#include "c4/dump.hpp" -#include "c4/format.hpp" -#endif - -#include -#include "c4/libtest/supprwarn_push.hpp" - -#ifdef __clang__ -# pragma clang diagnostic push -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wuseless-cast" -#endif - -namespace c4 { - - -namespace example { - -std::string test_dumper_target = {}; -void test_dumper(csubstr str) -{ - test_dumper_target.append(str.str, str.len); -} - -template -void printf(csubstr fmt, Args&& ...args) -{ - static thread_local std::string writebuf(16, '\0'); - DumpResults results = format_dump_resume<&test_dumper>(c4::to_substr(writebuf), fmt, std::forward(args)...); - if(C4_UNLIKELY(results.bufsize > writebuf.size())) // bufsize will be that of the largest element serialized. Eg int(1), will require 1 byte. - { - size_t dup = 2 * writebuf.size(); - writebuf.resize(dup > results.bufsize ? dup : results.bufsize); - format_dump_resume<&test_dumper>(results, c4::to_substr(writebuf), fmt, std::forward(args)...); - } -} -} // namespace example - -TEST_CASE("printf_example") -{ - example::test_dumper_target.clear(); - SUBCASE("1") - { - example::printf("{} coffees per day.\n", 3); - CHECK_EQ(example::test_dumper_target, "3 coffees per day.\n"); - } - SUBCASE("2") - { - example::printf("{} would be {}.", "brecky", "nice"); - CHECK_EQ(example::test_dumper_target, "brecky would be nice."); - } - SUBCASE("resize writebuf") - { - // printed strings will not use the writebuf, so we write a zero-padded integer - size_t dim = 128; // pad with 128 zeroes - std::string s1(dim, '0'); - std::string s2(dim, '0'); - s1.back() = '1'; - s2.back() = '2'; - example::printf("{} cannot be {}", fmt::zpad(1, dim), fmt::zpad(2, dim)); - CHECK_EQ(example::test_dumper_target, s1 + " cannot be " + s2); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -TEST_CASE("DumpResults") -{ - DumpResults dr = {}; - CHECK_EQ(dr.bufsize, 0u); - CHECK_EQ(dr.lastok, DumpResults::noarg); - CHECK_UNARY(dr.write_arg(0)); - CHECK_FALSE(dr.success_until(0)); - CHECK_EQ(dr.argfail(), 0); -} - -struct DumpChecker -{ - static size_t s_num_calls; - static char s_workspace[100]; - static size_t s_accum_pos; - static char s_accum[100]; - static void s_reset() - { - s_num_calls = 0; - s_accum_pos = 0; - for(size_t i = 0; i < sizeof(s_workspace); ++i) - s_workspace[i] = '+'; - for(size_t i = 0; i < sizeof(s_accum); ++i) - s_accum[i] = '.'; - } - static void s_dump(csubstr buf) - { - REQUIRE_LT(buf.len, sizeof(s_workspace)); - REQUIRE_LT(s_accum_pos + buf.len, sizeof(s_accum)); - ++s_num_calls; - memcpy(s_accum + s_accum_pos, buf.str, buf.len); - s_accum_pos += buf.len; - } -}; -size_t DumpChecker::s_num_calls = 0; -char DumpChecker::s_workspace[100] = {}; -size_t DumpChecker::s_accum_pos = {}; -char DumpChecker::s_accum[100] = {}; - -struct CatDumpTplArg -{ - template - static size_t call_cat_dump(Args&& ...args) - { - return cat_dump<&DumpChecker::s_dump>(std::forward(args)...); - } - template - static DumpResults call_cat_dump_resume(Args&& ...args) - { - return cat_dump_resume<&DumpChecker::s_dump>(std::forward(args)...); - } - template - static size_t call_catsep_dump(Args&& ...args) - { - return catsep_dump<&DumpChecker::s_dump>(std::forward(args)...); - } - template - static DumpResults call_catsep_dump_resume(Args&& ...args) - { - return catsep_dump_resume<&DumpChecker::s_dump>(std::forward(args)...); - } - template - static size_t call_format_dump(Args&& ...args) - { - return format_dump<&DumpChecker::s_dump>(std::forward(args)...); - } - template - static DumpResults call_format_dump_resume(Args&& ...args) - { - return format_dump_resume<&DumpChecker::s_dump>(std::forward(args)...); - } -}; - -struct CatDumpFnArg -{ - template - static size_t call_cat_dump(Args&& ...args) - { - return cat_dump(&DumpChecker::s_dump, std::forward(args)...); - } - template - static DumpResults call_cat_dump_resume(Args&& ...args) - { - return cat_dump_resume(&DumpChecker::s_dump, std::forward(args)...); - } - template - static size_t call_catsep_dump(Args&& ...args) - { - return catsep_dump(&DumpChecker::s_dump, std::forward(args)...); - } - template - static DumpResults call_catsep_dump_resume(Args&& ...args) - { - return catsep_dump_resume(&DumpChecker::s_dump, std::forward(args)...); - } - template - static size_t call_format_dump(Args&& ...args) - { - return format_dump(&DumpChecker::s_dump, std::forward(args)...); - } - template - static DumpResults call_format_dump_resume(Args&& ...args) - { - return format_dump_resume(&DumpChecker::s_dump, std::forward(args)...); - } -}; - -namespace buffers { -int b1 = 1; -int b2 = 22; -int b3 = 333; -int b4 = 4444; -int sep = 90009; -size_t seplen = 5; -} - -TEST_CASE_TEMPLATE("cat_dump", T, CatDumpTplArg, CatDumpFnArg) -{ - using namespace buffers; - substr buf = DumpChecker::s_workspace; - auto accum = [&]{ return csubstr(DumpChecker::s_accum).first(DumpChecker::s_accum_pos); }; - SUBCASE("dont use the buffer with strings") - { - DumpChecker::s_reset(); - size_t needed_size = T::call_cat_dump(buf.first(0), b1); - CHECK_EQ(needed_size, 1); - CHECK_EQ(accum(), csubstr("")); - needed_size = T::call_cat_dump(buf.first(0), b1, b2); - CHECK_EQ(needed_size, 2); - CHECK_EQ(accum(), csubstr("")); - needed_size = T::call_cat_dump(buf.first(0), b1, b2, b3); - CHECK_EQ(needed_size, 3); - CHECK_EQ(accum(), csubstr("")); - needed_size = T::call_cat_dump(buf.first(0), b1, b2, b3, b4); - CHECK_EQ(needed_size, 4); - CHECK_EQ(accum(), csubstr("")); - DumpChecker::s_reset(); - needed_size = T::call_cat_dump(buf.first(0), ("1")); - CHECK_EQ(needed_size, 0); - CHECK_EQ(accum(), csubstr("")); - needed_size = T::call_cat_dump(buf.first(0), ("1"), ("22")); - CHECK_EQ(needed_size, 0); - CHECK_EQ(accum(), csubstr("")); - needed_size = T::call_cat_dump(buf.first(0), ("1"), ("22"), ("333")); - CHECK_EQ(needed_size, 0); - CHECK_EQ(accum(), csubstr("")); - needed_size = T::call_cat_dump(buf.first(0), ("1"), ("22"), ("333"), ("4444")); - CHECK_EQ(needed_size, 0); - CHECK_EQ(accum(), csubstr("")); - DumpChecker::s_reset(); - needed_size = T::call_cat_dump(buf.first(0), csubstr("1")); - CHECK_EQ(needed_size, 0); - CHECK_EQ(accum(), csubstr("")); - needed_size = T::call_cat_dump(buf.first(0), csubstr("1"), csubstr("22")); - CHECK_EQ(needed_size, 0); - CHECK_EQ(accum(), csubstr("")); - needed_size = T::call_cat_dump(buf.first(0), csubstr("1"), csubstr("22"), csubstr("333")); - CHECK_EQ(needed_size, 0); - CHECK_EQ(accum(), csubstr("")); - needed_size = T::call_cat_dump(buf.first(0), csubstr("1"), csubstr("22"), csubstr("333"), csubstr("4444")); - CHECK_EQ(needed_size, 0); - CHECK_EQ(accum(), csubstr("")); - DumpChecker::s_reset(); - needed_size = T::call_cat_dump(buf.first(1), b1); - CHECK_EQ(needed_size, 1); - CHECK_EQ(accum(), csubstr("1")); - needed_size = T::call_cat_dump(buf.first(1), b1, b2); - CHECK_EQ(needed_size, 2); - CHECK_EQ(accum(), csubstr("11")); - needed_size = T::call_cat_dump(buf.first(1), b1, b2, b3); - CHECK_EQ(needed_size, 3); - CHECK_EQ(accum(), csubstr("111")); - needed_size = T::call_cat_dump(buf.first(1), b1, b2, b3, b4); - CHECK_EQ(needed_size, 4); - CHECK_EQ(accum(), csubstr("1111")); - DumpChecker::s_reset(); - needed_size = T::call_cat_dump(buf.first(1), ("1")); - CHECK_EQ(needed_size, 0); - CHECK_EQ(accum(), csubstr("1")); - needed_size = T::call_cat_dump(buf.first(1), ("1"), ("22")); - CHECK_EQ(needed_size, 0); - CHECK_EQ(accum(), csubstr("1122")); - needed_size = T::call_cat_dump(buf.first(1), ("1"), ("22"), ("333")); - CHECK_EQ(needed_size, 0); - CHECK_EQ(accum(), csubstr("1122122333")); - needed_size = T::call_cat_dump(buf.first(1), ("1"), ("22"), ("333"), ("4444")); - CHECK_EQ(needed_size, 0); - CHECK_EQ(accum(), csubstr("11221223331223334444")); - DumpChecker::s_reset(); - needed_size = T::call_cat_dump(buf.first(1), csubstr("1")); - CHECK_EQ(needed_size, 0); - CHECK_EQ(accum(), csubstr("1")); - needed_size = T::call_cat_dump(buf.first(1), csubstr("1"), csubstr("22")); - CHECK_EQ(needed_size, 0); - CHECK_EQ(accum(), csubstr("1122")); - needed_size = T::call_cat_dump(buf.first(1), csubstr("1"), csubstr("22"), csubstr("333")); - CHECK_EQ(needed_size, 0); - CHECK_EQ(accum(), csubstr("1122122333")); - needed_size = T::call_cat_dump(buf.first(1), csubstr("1"), csubstr("22"), csubstr("333"), csubstr("4444")); - CHECK_EQ(needed_size, 0); - CHECK_EQ(accum(), csubstr("11221223331223334444")); - } - SUBCASE("1") - { - DumpChecker::s_reset(); - size_t needed_size = T::call_cat_dump(buf.first(0), b1); - CHECK_EQ(needed_size, 1u); - CHECK_EQ(DumpChecker::s_num_calls, 0); // no calls to dump - CHECK_EQ(buf.first(1), csubstr("+")); // nothing was written - CHECK_EQ(accum(), csubstr("")); // nothing was written - DumpChecker::s_reset(); - needed_size = T::call_cat_dump(buf, b1); - CHECK_EQ(needed_size, 1u); - CHECK_EQ(DumpChecker::s_num_calls, 1); - CHECK_EQ(buf.first(1), csubstr("1")); - CHECK_EQ(accum(), csubstr("1")); - } - SUBCASE("1 2") - { - DumpChecker::s_reset(); - size_t needed_size = T::call_cat_dump(buf.first(0), b1, b2); - CHECK_EQ(needed_size, 2); - CHECK_EQ(DumpChecker::s_num_calls, 0); - CHECK_EQ(buf.first(2), csubstr("++")); // nothing was written - CHECK_EQ(accum(), csubstr("")); - DumpChecker::s_reset(); - needed_size = T::call_cat_dump(buf.first(1), b1, b2); - CHECK_EQ(needed_size, 2); - CHECK_EQ(DumpChecker::s_num_calls, 1); - CHECK_EQ(buf.first(2), csubstr("1+")); // only the first character of b2 was written - CHECK_EQ(accum(), csubstr("1")); - DumpChecker::s_reset(); - needed_size = T::call_cat_dump(buf, b1, b2); - CHECK_EQ(needed_size, 2); - CHECK_EQ(DumpChecker::s_num_calls, 2); - CHECK_EQ(buf.first(2), csubstr("22")); - CHECK_EQ(accum(), csubstr("122")); - } - SUBCASE("2 1") - { - DumpChecker::s_reset(); - size_t needed_size = T::call_cat_dump(buf, b2, b1); - CHECK_EQ(needed_size, 2); - CHECK_EQ(DumpChecker::s_num_calls, 2); - CHECK_EQ(buf.first(2), csubstr("12")); // wrote 2 then 1 - CHECK_EQ(accum(), csubstr("221")); - } - SUBCASE("1 2 3 4") - { - DumpChecker::s_reset(); - size_t needed_size = T::call_cat_dump(buf.first(0), b1, b2, b3, b4); - CHECK_EQ(needed_size, 4); - CHECK_EQ(DumpChecker::s_num_calls, 0); - CHECK_EQ(buf.first(4), csubstr("++++")); - CHECK_EQ(accum(), csubstr("")); - DumpChecker::s_reset(); - needed_size = T::call_cat_dump(buf.first(1), b1, b2, b3, b4); - CHECK_EQ(needed_size, 4); - CHECK_EQ(DumpChecker::s_num_calls, 1); - CHECK_EQ(buf.first(4), csubstr("1+++")); - CHECK_EQ(accum(), csubstr("1")); - DumpChecker::s_reset(); - needed_size = T::call_cat_dump(buf.first(2), b1, b2, b3, b4); - CHECK_EQ(needed_size, 4); - CHECK_EQ(DumpChecker::s_num_calls, 2); - CHECK_EQ(buf.first(4), csubstr("22++")); - CHECK_EQ(accum(), csubstr("122")); - DumpChecker::s_reset(); - needed_size = T::call_cat_dump(buf.first(3), b1, b2, b3, b4); - CHECK_EQ(needed_size, 4); - CHECK_EQ(DumpChecker::s_num_calls, 3); - CHECK_EQ(buf.first(4), csubstr("333+")); - CHECK_EQ(accum(), csubstr("122333")); - DumpChecker::s_reset(); - needed_size = T::call_cat_dump(buf, b1, b2, b3, b4); - CHECK_EQ(needed_size, 4); - CHECK_EQ(DumpChecker::s_num_calls, 4); - CHECK_EQ(buf.first(4), csubstr("4444")); - CHECK_EQ(accum(), csubstr("1223334444")); - } - SUBCASE("4 3 2 1") - { - DumpChecker::s_reset(); - size_t needed_size = T::call_cat_dump(buf.first(0), b4, b3, b2, b1); - CHECK_EQ(needed_size, 4); - CHECK_EQ(DumpChecker::s_num_calls, 0); - CHECK_EQ(buf.first(4), csubstr("++++")); - CHECK_EQ(accum(), csubstr("")); - DumpChecker::s_reset(); - needed_size = T::call_cat_dump(buf.first(1), b4, b3, b2, b1); - CHECK_EQ(needed_size, 4); - CHECK_EQ(DumpChecker::s_num_calls, 0); - CHECK_EQ(buf.first(4), csubstr("++++")); - CHECK_EQ(accum(), csubstr("")); - DumpChecker::s_reset(); - needed_size = T::call_cat_dump(buf.first(2), b4, b3, b2, b1); - CHECK_EQ(needed_size, 4); - CHECK_EQ(DumpChecker::s_num_calls, 0); - CHECK_EQ(buf.first(4), csubstr("++++")); - CHECK_EQ(accum(), csubstr("")); - DumpChecker::s_reset(); - needed_size = T::call_cat_dump(buf.first(3), b4, b3, b2, b1); - CHECK_EQ(needed_size, 4); - CHECK_EQ(DumpChecker::s_num_calls, 0); - CHECK_EQ(buf.first(4), csubstr("++++")); - CHECK_EQ(accum(), csubstr("")); - DumpChecker::s_reset(); - needed_size = T::call_cat_dump(buf, b4, b3, b2, b1); - CHECK_EQ(needed_size, 4); - CHECK_EQ(DumpChecker::s_num_calls, 4); - CHECK_EQ(buf.first(4), csubstr("1234")); - CHECK_EQ(accum(), csubstr("4444333221")); - } -} - -TEST_CASE_TEMPLATE("cat_dump_resume", T, CatDumpTplArg, CatDumpFnArg) -{ - using namespace buffers; - substr buf = DumpChecker::s_workspace; - auto accum = [&]{ return csubstr(DumpChecker::s_accum).first(DumpChecker::s_accum_pos); }; - SUBCASE("1") - { - DumpChecker::s_reset(); - DumpResults ret = T::call_cat_dump_resume(buf.first(0), b1); - CHECK_UNARY(!ret.success_until(0)); - CHECK_UNARY(!ret.success_until(1)); - CHECK_UNARY(!ret.success_until(2)); - CHECK_EQ(ret.bufsize, 1); - CHECK_EQ(ret.lastok, DumpResults::noarg); - CHECK_EQ(ret.argfail(), 0); - CHECK_EQ(DumpChecker::s_num_calls, 0); // no calls to dump - CHECK_EQ(buf.first(1), csubstr("+")); // nothing was written - CHECK_EQ(accum(), csubstr("")); - DumpResults retry = T::call_cat_dump_resume(ret, buf.first(1), b1); - CHECK_UNARY(retry.success_until(0)); - CHECK_UNARY(!retry.success_until(1)); - CHECK_UNARY(!retry.success_until(2)); - CHECK_EQ(retry.bufsize, 1); - CHECK_EQ(retry.lastok, 0); - CHECK_EQ(retry.argfail(), 1); - CHECK_EQ(DumpChecker::s_num_calls, 1); - CHECK_EQ(buf.first(1), csubstr("1")); - CHECK_EQ(accum(), csubstr("1")); - } - SUBCASE("1 2") - { - DumpChecker::s_reset(); - DumpResults ret = T::call_cat_dump_resume(buf.first(0), b1, b2); - CHECK_UNARY(!ret.success_until(0)); - CHECK_UNARY(!ret.success_until(1)); - CHECK_UNARY(!ret.success_until(2)); - CHECK_EQ(ret.bufsize, 2); // finds the buf size at once - CHECK_EQ(ret.lastok, DumpResults::noarg); - CHECK_EQ(ret.argfail(), 0); - CHECK_EQ(DumpChecker::s_num_calls, 0); // no calls to dump - CHECK_EQ(buf.first(2), csubstr("++")); // nothing was written - CHECK_EQ(accum(), csubstr("")); - ret = T::call_cat_dump_resume(ret, buf.first(1), b1, b2); - CHECK_UNARY(!ret.success_until(0)); // ret.bufsize signals buffer is at least 2 - CHECK_UNARY(!ret.success_until(1)); - CHECK_UNARY(!ret.success_until(2)); - CHECK_EQ(ret.bufsize, 2); - CHECK_EQ(ret.lastok, DumpResults::noarg); - CHECK_EQ(ret.argfail(), 0); - CHECK_EQ(DumpChecker::s_num_calls, 0); - CHECK_EQ(buf.first(2), csubstr("++")); - CHECK_EQ(accum(), csubstr("")); - ret = T::call_cat_dump_resume(ret, buf.first(2), b1, b2); - CHECK_UNARY(ret.success_until(0)); - CHECK_UNARY(ret.success_until(1)); - CHECK_UNARY(!ret.success_until(2)); - CHECK_EQ(ret.bufsize, 2); - CHECK_EQ(ret.lastok, 1); - CHECK_EQ(ret.argfail(), 2); - CHECK_EQ(DumpChecker::s_num_calls, 2); - CHECK_EQ(buf.first(2), csubstr("22")); - CHECK_EQ(accum(), csubstr("122")); - } - SUBCASE("1 2 3 4") - { - DumpChecker::s_reset(); - DumpResults ret = T::call_cat_dump_resume(buf.first(0), b1, b2, b3, b4); - CHECK_UNARY(!ret.success_until(0)); - CHECK_UNARY(!ret.success_until(1)); - CHECK_UNARY(!ret.success_until(2)); - CHECK_UNARY(!ret.success_until(3)); - CHECK_EQ(ret.bufsize, 4); - CHECK_EQ(ret.lastok, DumpResults::noarg); - CHECK_EQ(ret.argfail(), 0); - CHECK_EQ(DumpChecker::s_num_calls, 0); // no calls to dump - CHECK_EQ(buf.first(4), csubstr("++++")); // nothing was written - CHECK_EQ(accum(), csubstr("")); - ret = T::call_cat_dump_resume(ret, buf.first(1), b1, b2, b3, b4); - CHECK_UNARY(!ret.success_until(0)); - CHECK_UNARY(!ret.success_until(1)); - CHECK_UNARY(!ret.success_until(2)); - CHECK_UNARY(!ret.success_until(3)); - CHECK_EQ(ret.bufsize, 4); - CHECK_EQ(ret.lastok, DumpResults::noarg); - CHECK_EQ(ret.argfail(), 0); - CHECK_EQ(DumpChecker::s_num_calls, 0); - CHECK_EQ(buf.first(4), csubstr("++++")); - CHECK_EQ(accum(), csubstr("")); - ret = T::call_cat_dump_resume(ret, buf.first(2), b1, b2, b3, b4); - CHECK_UNARY(!ret.success_until(0)); - CHECK_UNARY(!ret.success_until(1)); - CHECK_UNARY(!ret.success_until(2)); - CHECK_UNARY(!ret.success_until(3)); - CHECK_EQ(ret.bufsize, 4); - CHECK_EQ(ret.lastok, DumpResults::noarg); - CHECK_EQ(ret.argfail(), 0); - CHECK_EQ(DumpChecker::s_num_calls, 0); - CHECK_EQ(buf.first(4), csubstr("++++")); - CHECK_EQ(accum(), csubstr("")); - ret = T::call_cat_dump_resume(ret, buf.first(3), b1, b2, b3, b4); - CHECK_UNARY(!ret.success_until(0)); - CHECK_UNARY(!ret.success_until(1)); - CHECK_UNARY(!ret.success_until(2)); - CHECK_UNARY(!ret.success_until(3)); - CHECK_EQ(ret.bufsize, 4); - CHECK_EQ(ret.lastok, DumpResults::noarg); - CHECK_EQ(ret.argfail(), 0); - CHECK_EQ(DumpChecker::s_num_calls, 0); - CHECK_EQ(buf.first(4), csubstr("++++")); - CHECK_EQ(accum(), csubstr("")); - ret = T::call_cat_dump_resume(ret, buf.first(4), b1, b2, b3, b4); - CHECK_UNARY(ret.success_until(0)); - CHECK_UNARY(ret.success_until(1)); - CHECK_UNARY(ret.success_until(2)); - CHECK_UNARY(ret.success_until(3)); - CHECK_EQ(ret.bufsize, 4); - CHECK_EQ(ret.lastok, 3); - CHECK_EQ(ret.argfail(), 4); - CHECK_EQ(DumpChecker::s_num_calls, 4); - CHECK_EQ(buf.first(4), csubstr("4444")); - CHECK_EQ(accum(), csubstr("1223334444")); - } - SUBCASE("4 3 2 1") - { - DumpChecker::s_reset(); - DumpResults ret = T::call_cat_dump_resume(buf.first(0), b4, b3, b2, b1); - CHECK_UNARY(!ret.success_until(0)); - CHECK_UNARY(!ret.success_until(1)); - CHECK_UNARY(!ret.success_until(2)); - CHECK_UNARY(!ret.success_until(3)); - CHECK_EQ(ret.bufsize, 4); - CHECK_EQ(ret.lastok, DumpResults::noarg); - CHECK_EQ(ret.argfail(), 0); - CHECK_EQ(DumpChecker::s_num_calls, 0); // no calls to dump - CHECK_EQ(buf.first(4), csubstr("++++")); // nothing was written - CHECK_EQ(accum(), csubstr("")); - ret = T::call_cat_dump_resume(ret, buf.first(1), b4, b3, b2, b1); - CHECK_UNARY(!ret.success_until(0)); - CHECK_UNARY(!ret.success_until(1)); - CHECK_UNARY(!ret.success_until(2)); - CHECK_UNARY(!ret.success_until(3)); - CHECK_EQ(ret.bufsize, 4); - CHECK_EQ(ret.lastok, DumpResults::noarg); - CHECK_EQ(ret.argfail(), 0); - CHECK_EQ(DumpChecker::s_num_calls, 0); - CHECK_EQ(buf.first(4), csubstr("++++")); - CHECK_EQ(accum(), csubstr("")); - ret = T::call_cat_dump_resume(ret, buf.first(2), b4, b3, b2, b1); - CHECK_UNARY(!ret.success_until(0)); - CHECK_UNARY(!ret.success_until(1)); - CHECK_UNARY(!ret.success_until(2)); - CHECK_UNARY(!ret.success_until(3)); - CHECK_EQ(ret.bufsize, 4); - CHECK_EQ(ret.lastok, DumpResults::noarg); - CHECK_EQ(ret.argfail(), 0); - CHECK_EQ(DumpChecker::s_num_calls, 0); - CHECK_EQ(buf.first(4), csubstr("++++")); - CHECK_EQ(accum(), csubstr("")); - ret = T::call_cat_dump_resume(ret, buf.first(3), b4, b3, b2, b1); - CHECK_UNARY(!ret.success_until(0)); - CHECK_UNARY(!ret.success_until(1)); - CHECK_UNARY(!ret.success_until(2)); - CHECK_UNARY(!ret.success_until(3)); - CHECK_EQ(ret.bufsize, 4); - CHECK_EQ(ret.lastok, DumpResults::noarg); - CHECK_EQ(ret.argfail(), 0); - CHECK_EQ(DumpChecker::s_num_calls, 0); - CHECK_EQ(buf.first(4), csubstr("++++")); - CHECK_EQ(accum(), csubstr("")); - ret = T::call_cat_dump_resume(ret, buf.first(4), b4, b3, b2, b1); - CHECK_UNARY(ret.success_until(0)); - CHECK_UNARY(ret.success_until(1)); - CHECK_UNARY(ret.success_until(2)); - CHECK_UNARY(ret.success_until(3)); - CHECK_EQ(ret.bufsize, 4); - CHECK_EQ(ret.lastok, 3); - CHECK_EQ(ret.argfail(), 4); - CHECK_EQ(DumpChecker::s_num_calls, 4); - CHECK_EQ(buf.first(4), csubstr("1234")); - CHECK_EQ(accum(), csubstr("4444333221")); - } -} - - - -TEST_CASE_TEMPLATE("catsep_dump", T, CatDumpTplArg, CatDumpFnArg) -{ - using namespace buffers; - size_t needed_size; - substr buf = DumpChecker::s_workspace; - auto accum = [&]{ return csubstr(DumpChecker::s_accum).first(DumpChecker::s_accum_pos); }; - SUBCASE("1") - { - DumpChecker::s_reset(); - needed_size = T::call_catsep_dump(buf.first(0), sep, b1); - CHECK_EQ(needed_size, 1); - CHECK_EQ(DumpChecker::s_num_calls, 0); // no calls to dump - CHECK_EQ(buf.first(1), csubstr("+")); // nothing was written - CHECK_EQ(accum(), csubstr("")); // nothing was written - DumpChecker::s_reset(); - needed_size = T::call_catsep_dump(buf.first(1), sep, b1); - CHECK_EQ(needed_size, 1); - CHECK_EQ(DumpChecker::s_num_calls, 1); - CHECK_EQ(buf.first(1), csubstr("1")); - CHECK_EQ(accum(), csubstr("1")); - DumpChecker::s_reset(); - needed_size = T::call_catsep_dump(buf.first(1 + seplen), sep, b1); - CHECK_EQ(needed_size, 1); - CHECK_EQ(DumpChecker::s_num_calls, 1); // sep was not written - CHECK_EQ(buf.first(1), csubstr("1")); - CHECK_EQ(accum(), csubstr("1")); - DumpChecker::s_reset(); - needed_size = T::call_catsep_dump(buf, sep, b1); - CHECK_EQ(needed_size, 1); - CHECK_EQ(DumpChecker::s_num_calls, 1); // sep was not written - CHECK_EQ(buf.first(1), csubstr("1")); - CHECK_EQ(accum(), csubstr("1")); - } - SUBCASE("1 2") - { - DumpChecker::s_reset(); - needed_size = T::call_catsep_dump(buf.first(0), sep, b1, b2); - CHECK_EQ(needed_size, seplen); - CHECK_EQ(DumpChecker::s_num_calls, 0); - CHECK_EQ(buf.first(2), csubstr("++")); // nothing was written - CHECK_EQ(accum(), csubstr("")); - DumpChecker::s_reset(); - needed_size = T::call_catsep_dump(buf.first(1), sep, b1, b2); - CHECK_EQ(needed_size, seplen); - CHECK_EQ(DumpChecker::s_num_calls, 1); - CHECK_EQ(buf.first(2), csubstr("1+")); - CHECK_EQ(accum(), csubstr("1")); - DumpChecker::s_reset(); - needed_size = T::call_catsep_dump(buf.first(seplen), sep, b1, b2); - CHECK_EQ(needed_size, seplen); - CHECK_EQ(DumpChecker::s_num_calls, 3); - CHECK_EQ(buf.first(2), csubstr("22")); - CHECK_EQ(accum(), csubstr("19000922")); - DumpChecker::s_reset(); - needed_size = T::call_catsep_dump(buf, sep, b1, b2); - CHECK_EQ(needed_size, seplen); - CHECK_EQ(DumpChecker::s_num_calls, 3); - CHECK_EQ(buf.first(2), csubstr("22")); - CHECK_EQ(accum(), csubstr("19000922")); - } - SUBCASE("2 1") - { - DumpChecker::s_reset(); - needed_size = T::call_catsep_dump(buf.first(0), sep, b2, b1); - CHECK_EQ(needed_size, seplen); - CHECK_EQ(DumpChecker::s_num_calls, 0); - CHECK_EQ(buf.first(2), csubstr("++")); // nothing was written - CHECK_EQ(accum(), csubstr("")); - DumpChecker::s_reset(); - needed_size = T::call_catsep_dump(buf.first(1), sep, b2, b1); - CHECK_EQ(needed_size, seplen); - CHECK_EQ(DumpChecker::s_num_calls, 0); - CHECK_EQ(buf.first(2), csubstr("++")); - CHECK_EQ(accum(), csubstr("")); - DumpChecker::s_reset(); - needed_size = T::call_catsep_dump(buf.first(seplen), sep, b2, b1); - CHECK_EQ(needed_size, seplen); - CHECK_EQ(DumpChecker::s_num_calls, 3); - CHECK_EQ(buf.first(2), csubstr("10")); - CHECK_EQ(accum(), csubstr("22900091")); - DumpChecker::s_reset(); - needed_size = T::call_catsep_dump(buf, sep, b2, b1); - CHECK_EQ(needed_size, seplen); - CHECK_EQ(DumpChecker::s_num_calls, 3); - CHECK_EQ(buf.first(2), csubstr("10")); - CHECK_EQ(accum(), csubstr("22900091")); - } - SUBCASE("1 2 3 4") - { - DumpChecker::s_reset(); - needed_size = T::call_catsep_dump(buf.first(0), sep, b1, b2, b3, b4); - CHECK_EQ(needed_size, seplen); - CHECK_EQ(DumpChecker::s_num_calls, 0); - CHECK_EQ(buf.first(4), csubstr("++++")); - CHECK_EQ(accum(), csubstr("")); - DumpChecker::s_reset(); - needed_size = T::call_catsep_dump(buf.first(1), sep, b1, b2, b3, b4); - CHECK_EQ(needed_size, seplen); - CHECK_EQ(DumpChecker::s_num_calls, 1); - CHECK_EQ(buf.first(4), csubstr("1+++")); - CHECK_EQ(accum(), csubstr("1")); - DumpChecker::s_reset(); - needed_size = T::call_catsep_dump(buf.first(2), sep, b1, b2, b3, b4); - CHECK_EQ(needed_size, seplen); - CHECK_EQ(DumpChecker::s_num_calls, 1); - CHECK_EQ(buf.first(4), csubstr("1+++")); - CHECK_EQ(accum(), csubstr("1")); - DumpChecker::s_reset(); - needed_size = T::call_catsep_dump(buf.first(3), sep, b1, b2, b3, b4); - CHECK_EQ(needed_size, seplen); - CHECK_EQ(DumpChecker::s_num_calls, 1); - CHECK_EQ(buf.first(4), csubstr("1+++")); - CHECK_EQ(accum(), csubstr("1")); - DumpChecker::s_reset(); - needed_size = T::call_catsep_dump(buf, sep, b1, b2, b3, b4); - CHECK_EQ(needed_size, seplen); - CHECK_EQ(DumpChecker::s_num_calls, 7); - CHECK_EQ(buf.first(4), csubstr("4444")); - CHECK_EQ(accum(), csubstr("1900092290009333900094444")); - } - SUBCASE("4 3 2 1") - { - DumpChecker::s_reset(); - needed_size = T::call_catsep_dump(buf.first(0), sep, b4, b3, b2, b1); - CHECK_EQ(needed_size, seplen); - CHECK_EQ(DumpChecker::s_num_calls, 0); - CHECK_EQ(buf.first(4), csubstr("++++")); - CHECK_EQ(accum(), csubstr("")); - DumpChecker::s_reset(); - needed_size = T::call_catsep_dump(buf.first(1), sep, b4, b3, b2, b1); - CHECK_EQ(needed_size, seplen); - CHECK_EQ(DumpChecker::s_num_calls, 0); - CHECK_EQ(buf.first(4), csubstr("++++")); - CHECK_EQ(accum(), csubstr("")); - DumpChecker::s_reset(); - needed_size = T::call_catsep_dump(buf.first(2), sep, b4, b3, b2, b1); - CHECK_EQ(needed_size, seplen); - CHECK_EQ(DumpChecker::s_num_calls, 0); - CHECK_EQ(buf.first(4), csubstr("++++")); - CHECK_EQ(accum(), csubstr("")); - DumpChecker::s_reset(); - needed_size = T::call_catsep_dump(buf.first(3), sep, b4, b3, b2, b1); - CHECK_EQ(needed_size, seplen); - CHECK_EQ(DumpChecker::s_num_calls, 0); - CHECK_EQ(buf.first(4), csubstr("++++")); - CHECK_EQ(accum(), csubstr("")); - DumpChecker::s_reset(); - needed_size = T::call_catsep_dump(buf, sep, b4, b3, b2, b1); - CHECK_EQ(needed_size, seplen); - CHECK_EQ(DumpChecker::s_num_calls, 7); - CHECK_EQ(buf.first(4), csubstr("1000")); - CHECK_EQ(accum(), csubstr("4444900093339000922900091")); - } -} - - -TEST_CASE_TEMPLATE("catsep_dump_resume", T, CatDumpTplArg, CatDumpFnArg) -{ - using namespace buffers; - substr buf = DumpChecker::s_workspace; - auto accum = [&]{ return csubstr(DumpChecker::s_accum).first(DumpChecker::s_accum_pos); }; - SUBCASE("1") - { - DumpChecker::s_reset(); - DumpResults ret = T::call_catsep_dump_resume(buf.first(0), sep, b1); - CHECK_UNARY(!ret.success_until(0)); - CHECK_UNARY(!ret.success_until(1)); - CHECK_UNARY(!ret.success_until(2)); - CHECK_EQ(ret.bufsize, 1); - CHECK_EQ(ret.lastok, DumpResults::noarg); - CHECK_EQ(ret.argfail(), 0); - CHECK_EQ(DumpChecker::s_num_calls, 0); // no calls to dump - CHECK_EQ(buf.first(1), csubstr("+")); // nothing was written - CHECK_EQ(accum(), csubstr("")); - ret = T::call_catsep_dump_resume(ret, buf.first(1), sep, b1); - CHECK_UNARY(ret.success_until(0)); - CHECK_UNARY(!ret.success_until(1)); - CHECK_UNARY(!ret.success_until(2)); - CHECK_EQ(ret.bufsize, 1); - CHECK_EQ(ret.lastok, 0); - CHECK_EQ(ret.argfail(), 1); - CHECK_EQ(DumpChecker::s_num_calls, 1); - CHECK_EQ(buf.first(1), csubstr("1")); - CHECK_EQ(accum(), csubstr("1")); - ret = T::call_catsep_dump_resume(ret, buf, sep, b1); - CHECK_UNARY(ret.success_until(0)); - CHECK_UNARY(!ret.success_until(1)); - CHECK_UNARY(!ret.success_until(2)); - CHECK_EQ(ret.bufsize, 1); - CHECK_EQ(ret.lastok, 0); - CHECK_EQ(ret.argfail(), 1); - CHECK_EQ(DumpChecker::s_num_calls, 1); - CHECK_EQ(buf.first(1), csubstr("1")); - CHECK_EQ(accum(), csubstr("1")); - } - SUBCASE("1 2") - { - DumpChecker::s_reset(); - DumpResults ret = T::call_catsep_dump_resume(buf.first(0), sep, b1, b2); - CHECK_UNARY(!ret.success_until(0)); - CHECK_UNARY(!ret.success_until(1)); - CHECK_UNARY(!ret.success_until(2)); - CHECK_EQ(ret.bufsize, seplen); // finds the buf size at once - CHECK_EQ(ret.lastok, DumpResults::noarg); - CHECK_EQ(ret.argfail(), 0); - CHECK_EQ(DumpChecker::s_num_calls, 0); // no calls to dump - CHECK_EQ(buf.first(2), csubstr("++")); // nothing was written - CHECK_EQ(accum(), csubstr("")); - ret = T::call_catsep_dump_resume(ret, buf.first(1), sep, b1, b2); - CHECK_UNARY(ret.success_until(0)); // b1 - CHECK_UNARY(!ret.success_until(1)); // sep - CHECK_UNARY(!ret.success_until(2)); // b2 - CHECK_EQ(ret.bufsize, seplen); - CHECK_EQ(ret.lastok, 0); - CHECK_EQ(ret.argfail(), 1); // sep - CHECK_EQ(DumpChecker::s_num_calls, 1); - CHECK_EQ(buf.first(2), csubstr("1+")); - CHECK_EQ(accum(), csubstr("1")); - ret = T::call_catsep_dump_resume(ret, buf.first(2), sep, b1, b2); - CHECK_UNARY(ret.success_until(0)); // b1 - CHECK_UNARY(!ret.success_until(1)); // sep - CHECK_UNARY(!ret.success_until(2)); // b2 - CHECK_EQ(ret.bufsize, seplen); - CHECK_EQ(ret.lastok, 0); - CHECK_EQ(ret.argfail(), 1); // sep - CHECK_EQ(DumpChecker::s_num_calls, 1); - CHECK_EQ(buf.first(2), csubstr("1+")); - CHECK_EQ(accum(), csubstr("1")); - ret = T::call_catsep_dump_resume(ret, buf.first(seplen), sep, b1, b2); - CHECK_UNARY(ret.success_until(0)); - CHECK_UNARY(ret.success_until(1)); - CHECK_UNARY(ret.success_until(2)); - CHECK_EQ(ret.bufsize, seplen); - CHECK_EQ(ret.lastok, 2); - CHECK_EQ(ret.argfail(), 3); - CHECK_EQ(DumpChecker::s_num_calls, 3); - CHECK_EQ(buf.first(2), csubstr("22")); - CHECK_EQ(accum(), csubstr("19000922")); - } - SUBCASE("1 2 3 4") - { - DumpChecker::s_reset(); - DumpResults ret = T::call_catsep_dump_resume(buf.first(0), sep, b1, b2, b3, b4); - CHECK_UNARY(!ret.success_until(0)); - CHECK_EQ(ret.bufsize, seplen); - CHECK_EQ(ret.lastok, DumpResults::noarg); - CHECK_EQ(ret.argfail(), 0); - CHECK_EQ(DumpChecker::s_num_calls, 0); // no calls to dump - CHECK_EQ(buf.first(4), csubstr("++++")); // nothing was written - CHECK_EQ(accum(), csubstr("")); - ret = T::call_catsep_dump_resume(ret, buf.first(1), sep, b1, b2, b3, b4); - CHECK_UNARY(ret.success_until(0)); - CHECK_UNARY(!ret.success_until(1)); - CHECK_EQ(ret.bufsize, seplen); - CHECK_EQ(ret.lastok, 0); - CHECK_EQ(ret.argfail(), 1); - CHECK_EQ(DumpChecker::s_num_calls, 1); - CHECK_EQ(buf.first(4), csubstr("1+++")); // failed while writing sep - CHECK_EQ(accum(), csubstr("1")); - ret = T::call_catsep_dump_resume(ret, buf.first(2), sep, b1, b2, b3, b4); - CHECK_UNARY(ret.success_until(0)); - CHECK_UNARY(!ret.success_until(1)); - CHECK_EQ(ret.bufsize, seplen); - CHECK_EQ(ret.lastok, 0); - CHECK_EQ(ret.argfail(), 1); - CHECK_EQ(DumpChecker::s_num_calls, 1); - CHECK_EQ(buf.first(4), csubstr("1+++")); // failed while writing sep - CHECK_EQ(accum(), csubstr("1")); - ret = T::call_catsep_dump_resume(ret, buf.first(3), sep, b1, b2, b3, b4); - CHECK_UNARY(ret.success_until(0)); - CHECK_UNARY(!ret.success_until(1)); - CHECK_EQ(ret.bufsize, seplen); - CHECK_EQ(ret.lastok, 0); - CHECK_EQ(ret.argfail(), 1); - CHECK_EQ(DumpChecker::s_num_calls, 1); - CHECK_EQ(buf.first(4), csubstr("1+++")); - CHECK_EQ(accum(), csubstr("1")); - ret = T::call_catsep_dump_resume(ret, buf.first(4), sep, b1, b2, b3, b4); - CHECK_UNARY(ret.success_until(0)); - CHECK_UNARY(!ret.success_until(1)); - CHECK_EQ(ret.bufsize, seplen); - CHECK_EQ(ret.lastok, 0); - CHECK_EQ(ret.argfail(), 1); - CHECK_EQ(DumpChecker::s_num_calls, 1); - CHECK_EQ(buf.first(4), csubstr("1+++")); - CHECK_EQ(accum(), csubstr("1")); - ret = T::call_catsep_dump_resume(ret, buf.first(seplen), sep, b1, b2, b3, b4); - CHECK_UNARY(ret.success_until(0)); - CHECK_UNARY(ret.success_until(1)); - CHECK_UNARY(ret.success_until(2)); - CHECK_UNARY(ret.success_until(3)); - CHECK_UNARY(ret.success_until(4)); - CHECK_UNARY(ret.success_until(5)); - CHECK_UNARY(ret.success_until(6)); - CHECK_UNARY(!ret.success_until(7)); - CHECK_EQ(ret.bufsize, seplen); - CHECK_EQ(ret.lastok, 6); - CHECK_EQ(ret.argfail(), 7); - CHECK_EQ(DumpChecker::s_num_calls, 7); - CHECK_EQ(buf.first(seplen), csubstr("44449")); - CHECK_EQ(accum(), csubstr("1900092290009333900094444")); - } - SUBCASE("4 3 2 1") - { - DumpChecker::s_reset(); - DumpResults ret = T::call_catsep_dump_resume(buf.first(0), sep, b4, b3, b2, b1); - CHECK_UNARY(!ret.success_until(0)); - CHECK_EQ(ret.bufsize, seplen); - CHECK_EQ(ret.lastok, DumpResults::noarg); - CHECK_EQ(ret.argfail(), 0); - CHECK_EQ(DumpChecker::s_num_calls, 0); // no calls to dump - CHECK_EQ(buf.first(4), csubstr("++++")); // nothing was written - CHECK_EQ(accum(), csubstr("")); - ret = T::call_catsep_dump_resume(ret, buf.first(1), sep, b4, b3, b2, b1); - CHECK_UNARY(!ret.success_until(0)); - CHECK_EQ(ret.bufsize, seplen); - CHECK_EQ(ret.lastok, DumpResults::noarg); - CHECK_EQ(ret.argfail(), 0); - CHECK_EQ(DumpChecker::s_num_calls, 0); - CHECK_EQ(buf.first(4), csubstr("++++")); - CHECK_EQ(accum(), csubstr("")); - ret = T::call_catsep_dump_resume(ret, buf.first(2), sep, b4, b3, b2, b1); - CHECK_UNARY(!ret.success_until(0)); - CHECK_EQ(ret.bufsize, seplen); - CHECK_EQ(ret.lastok, DumpResults::noarg); - CHECK_EQ(ret.argfail(), 0); - CHECK_EQ(DumpChecker::s_num_calls, 0); - CHECK_EQ(buf.first(4), csubstr("++++")); - CHECK_EQ(accum(), csubstr("")); - ret = T::call_catsep_dump_resume(ret, buf.first(seplen), sep, b4, b3, b2, b1); - CHECK_UNARY(ret.success_until(0)); - CHECK_UNARY(ret.success_until(1)); - CHECK_UNARY(ret.success_until(2)); - CHECK_UNARY(ret.success_until(3)); - CHECK_UNARY(ret.success_until(4)); - CHECK_UNARY(ret.success_until(5)); - CHECK_UNARY(ret.success_until(6)); - CHECK_UNARY(!ret.success_until(7)); - CHECK_EQ(ret.bufsize, seplen); - CHECK_EQ(ret.lastok, 6); - CHECK_EQ(ret.argfail(), 7); - CHECK_EQ(DumpChecker::s_num_calls, 7); - CHECK_EQ(buf.first(seplen), csubstr("10009")); - CHECK_EQ(accum(), csubstr("4444900093339000922900091")); - } - SUBCASE("1 2 3 4 with seplen==3") - { - int s = 999; - DumpChecker::s_reset(); - DumpResults ret = T::call_catsep_dump_resume(buf.first(0), s, b1, b2, b3, b4); - CHECK_UNARY(!ret.success_until(0)); - CHECK_EQ(ret.bufsize, 4); - CHECK_EQ(ret.lastok, DumpResults::noarg); - CHECK_EQ(ret.argfail(), 0); - CHECK_EQ(DumpChecker::s_num_calls, 0); // no calls to dump - CHECK_EQ(buf.first(4), csubstr("++++")); // nothing was written - CHECK_EQ(accum(), csubstr("")); - ret = T::call_catsep_dump_resume(ret, buf.first(1), s, b1, b2, b3, b4); - CHECK_UNARY(ret.success_until(0)); - CHECK_UNARY(!ret.success_until(1)); - CHECK_EQ(ret.bufsize, 4); - CHECK_EQ(ret.lastok, 0); - CHECK_EQ(ret.argfail(), 1); - CHECK_EQ(DumpChecker::s_num_calls, 1); - CHECK_EQ(buf.first(4), csubstr("1+++")); // failed while writing sep - CHECK_EQ(accum(), csubstr("1")); - ret = T::call_catsep_dump_resume(ret, buf.first(2), s, b1, b2, b3, b4); - CHECK_UNARY(ret.success_until(0)); // b1 - CHECK_UNARY(!ret.success_until(1)); // s - CHECK_UNARY(!ret.success_until(2)); // b2 - CHECK_EQ(ret.bufsize, 4); - CHECK_EQ(ret.lastok, 0); - CHECK_EQ(ret.argfail(), 1); - CHECK_EQ(DumpChecker::s_num_calls, 1); - CHECK_EQ(buf.first(4), csubstr("1+++")); // failed while writing sep - CHECK_EQ(accum(), csubstr("1")); - ret = T::call_catsep_dump_resume(ret, buf.first(3), s, b1, b2, b3, b4); - CHECK_UNARY(ret.success_until(0)); - CHECK_UNARY(ret.success_until(1)); - CHECK_UNARY(ret.success_until(2)); - CHECK_UNARY(ret.success_until(3)); - CHECK_UNARY(ret.success_until(4)); - CHECK_UNARY(ret.success_until(5)); - CHECK_EQ(ret.bufsize, 4); - CHECK_EQ(ret.lastok, 5); - CHECK_EQ(ret.argfail(), 6); - CHECK_EQ(DumpChecker::s_num_calls, 6); - CHECK_EQ(buf.first(4), csubstr("999+")); // failed while writing b4 - CHECK_EQ(accum(), csubstr("199922999333999")); - ret = T::call_catsep_dump_resume(ret, buf.first(4), s, b1, b2, b3, b4); - CHECK_UNARY(ret.success_until(0)); - CHECK_UNARY(ret.success_until(1)); - CHECK_UNARY(ret.success_until(2)); - CHECK_UNARY(ret.success_until(3)); - CHECK_UNARY(ret.success_until(4)); - CHECK_UNARY(ret.success_until(5)); - CHECK_UNARY(ret.success_until(6)); - CHECK_UNARY(!ret.success_until(7)); - CHECK_EQ(ret.bufsize, 4); - CHECK_EQ(ret.lastok, 6); - CHECK_EQ(ret.argfail(), 7); - CHECK_EQ(DumpChecker::s_num_calls, 7); - CHECK_EQ(buf.first(5), csubstr("4444+")); - CHECK_EQ(accum(), csubstr("1999229993339994444")); - } -} - - -TEST_CASE_TEMPLATE("format_dump", T, CatDumpTplArg, CatDumpFnArg) -{ - using namespace buffers; - size_t needed_size; - substr buf = DumpChecker::s_workspace; - auto accum = [&]{ return csubstr(DumpChecker::s_accum).first(DumpChecker::s_accum_pos); }; - SUBCASE("no buffer is needed for strings") - { - csubstr fmt = "{}-{}-{}-{}"; - DumpChecker::s_reset(); - needed_size = T::call_format_dump(buf.first(0), fmt, "1", "22", "333", "4444"); // no buffer! - CHECK_EQ(needed_size, 0); - CHECK_EQ(DumpChecker::s_num_calls, 0); - CHECK_EQ(buf.first(1), csubstr("+")); - CHECK_EQ(accum(), csubstr("")); - DumpChecker::s_reset(); - CHECK_EQ(DumpChecker::s_num_calls, 0); - needed_size = T::call_format_dump(buf.first(1), fmt, "1", "22", "333", "4444"); // 1-len buffer, unused - CHECK_EQ(needed_size, 0); // no intermediate serialization is needed, since these are strings - CHECK_EQ(DumpChecker::s_num_calls, 7); // calls everything even when the buffer is empty - CHECK_EQ(accum(), csubstr("1-22-333-4444")); // dumped the full format string - } - SUBCASE("0") - { - csubstr fmt = "01234567890123456789"; - DumpChecker::s_reset(); - needed_size = T::call_format_dump(buf.first(0), fmt, b1, b2, b3, b4); - CHECK_EQ(needed_size, 0); // the longest sized argument format argument - CHECK_EQ(DumpChecker::s_num_calls, 0); // no calls when the buffer is empty - CHECK_EQ(buf.first(needed_size), csubstr("")); // nothing was written - CHECK_EQ(accum(), csubstr("")); // dumped the full format string - DumpChecker::s_reset(); - needed_size = T::call_format_dump(buf, fmt, b1, b2, b3, b4); - CHECK_EQ(needed_size, 0); // the longest sized argument format argument - CHECK_EQ(DumpChecker::s_num_calls, 1); - CHECK_EQ(buf.first(needed_size), csubstr("")); // nothing was written - CHECK_EQ(accum(), fmt); // dumped the full format string - } - SUBCASE("1") - { - // ____1____ 2 __3__ - csubstr fmt = "012345678_{}_34567"; - DumpChecker::s_reset(); - needed_size = T::call_format_dump(buf.first(0), fmt, b1); - CHECK_EQ(needed_size, 1); // the longest sized argument format argument - CHECK_EQ(DumpChecker::s_num_calls, 0); - CHECK_EQ(buf.first(2), csubstr("++")); // nothing was written - CHECK_EQ(accum(), csubstr("")); // dumped first part of the format string - DumpChecker::s_reset(); - needed_size = T::call_format_dump(buf.first(1), fmt, b1); - CHECK_EQ(needed_size, 1); - CHECK_EQ(DumpChecker::s_num_calls, 3); - CHECK_EQ(buf.first(2), csubstr("1+")); - CHECK_EQ(accum(), csubstr("012345678_1_34567")); - DumpChecker::s_reset(); - needed_size = T::call_format_dump(buf.first(1), fmt, b1, b2, b3, b4); // check that extra arguments are ignored - CHECK_EQ(needed_size, 1); - CHECK_EQ(DumpChecker::s_num_calls, 3); - CHECK_EQ(buf.first(2), csubstr("1+")); - CHECK_EQ(accum(), csubstr("012345678_1_34567")); - DumpChecker::s_reset(); - needed_size = T::call_format_dump(buf.first(1), fmt); // check that missing arguments are skipped - CHECK_EQ(needed_size, 0u); - CHECK_EQ(DumpChecker::s_num_calls, 1); - CHECK_EQ(buf.first(2), csubstr("++")); - CHECK_EQ(accum(), csubstr("012345678_{}_34567")); - } - SUBCASE("1 2") - { - // ____1____ 2 __3__ 4 _5_ - csubstr fmt = "012345678_{}_34567_{}_aaa"; - DumpChecker::s_reset(); - needed_size = T::call_format_dump(buf.first(0), fmt, b1, b2); - CHECK_EQ(needed_size, 2); // the longest sized argument format argument - CHECK_EQ(DumpChecker::s_num_calls, 0); - CHECK_EQ(buf.first(2), csubstr("++")); // nothing was written - CHECK_EQ(accum(), csubstr("")); // dumped first part of the format string - DumpChecker::s_reset(); - needed_size = T::call_format_dump(buf.first(1), fmt, b1, b2); - CHECK_EQ(needed_size, 2); - CHECK_EQ(DumpChecker::s_num_calls, 3); - CHECK_EQ(buf.first(2), csubstr("1+")); - CHECK_EQ(accum(), csubstr("012345678_1_34567_")); - DumpChecker::s_reset(); - needed_size = T::call_format_dump(buf.first(2), fmt, b1, b2); - CHECK_EQ(needed_size, 2); - CHECK_EQ(DumpChecker::s_num_calls, 5); - CHECK_EQ(buf.first(2), csubstr("22")); - CHECK_EQ(accum(), csubstr("012345678_1_34567_22_aaa")); - DumpChecker::s_reset(); - needed_size = T::call_format_dump(buf.first(1), fmt); // check that missing arguments are skipped - CHECK_EQ(needed_size, 0u); - CHECK_EQ(DumpChecker::s_num_calls, 1); - CHECK_EQ(buf.first(2), csubstr("++")); - CHECK_EQ(accum(), csubstr("012345678_{}_34567_{}_aaa")); - } - SUBCASE("1 2 3") - { - // 1 2 3 4 5 6 - csubstr fmt = "012345678_{}_34567_{}_aaa___{}"; - DumpChecker::s_reset(); - needed_size = T::call_format_dump(buf.first(0), fmt, b1, b2, b3); - CHECK_EQ(needed_size, 3); // the longest sized argument format argument - CHECK_EQ(DumpChecker::s_num_calls, 0); - CHECK_EQ(buf.first(2), csubstr("++")); // nothing was written - CHECK_EQ(accum(), csubstr("")); // dumped first part of the format string - DumpChecker::s_reset(); - needed_size = T::call_format_dump(buf.first(1), fmt, b1, b2, b3); - CHECK_EQ(needed_size, 3); - CHECK_EQ(DumpChecker::s_num_calls, 3); - CHECK_EQ(buf.first(2), csubstr("1+")); - CHECK_EQ(accum(), csubstr("012345678_1_34567_")); - DumpChecker::s_reset(); - needed_size = T::call_format_dump(buf.first(2), fmt, b1, b2, b3); - CHECK_EQ(needed_size, 3); - CHECK_EQ(DumpChecker::s_num_calls, 5); - CHECK_EQ(buf.first(2), csubstr("22")); - CHECK_EQ(accum(), csubstr("012345678_1_34567_22_aaa___")); - DumpChecker::s_reset(); - needed_size = T::call_format_dump(buf.first(3), fmt, b1, b2, b3); - CHECK_EQ(needed_size, 3); - CHECK_EQ(DumpChecker::s_num_calls, 6); - CHECK_EQ(buf.first(2), csubstr("33")); - CHECK_EQ(accum(), csubstr("012345678_1_34567_22_aaa___333")); - DumpChecker::s_reset(); - needed_size = T::call_format_dump(buf, fmt); // check that missing arguments are skipped - CHECK_EQ(needed_size, 0u); - CHECK_EQ(DumpChecker::s_num_calls, 1); - CHECK_EQ(buf.first(2), csubstr("++")); - CHECK_EQ(accum(), csubstr("012345678_{}_34567_{}_aaa___{}")); - DumpChecker::s_reset(); - needed_size = T::call_format_dump(buf, fmt, b1); // check that missing arguments are skipped - CHECK_EQ(needed_size, 1); - CHECK_EQ(DumpChecker::s_num_calls, 3); - CHECK_EQ(buf.first(2), csubstr("1+")); - CHECK_EQ(accum(), csubstr("012345678_1_34567_{}_aaa___{}")); - } -} - - -TEST_CASE_TEMPLATE("format_dump_resume", T, CatDumpTplArg, CatDumpFnArg) -{ - using namespace buffers; - substr buf = DumpChecker::s_workspace; - auto accum = [&]{ return csubstr(DumpChecker::s_accum).first(DumpChecker::s_accum_pos); }; - SUBCASE("1") - { - csubstr fmt = "aaa_then_{}_then_bbb"; - DumpChecker::s_reset(); - DumpResults ret = T::call_format_dump_resume(buf.first(0), fmt, b1); - CHECK_UNARY(!ret.success_until(0)); - CHECK_UNARY(!ret.success_until(1)); - CHECK_UNARY(!ret.success_until(2)); - CHECK_EQ(ret.bufsize, 1); - CHECK_EQ(ret.lastok, DumpResults::noarg); - CHECK_EQ(ret.argfail(), 0); - CHECK_EQ(DumpChecker::s_num_calls, 0); // no calls to dump - CHECK_EQ(buf.first(1), csubstr("+")); // nothing was written - CHECK_EQ(accum(), csubstr("")); - ret = T::call_format_dump_resume(ret, buf.first(1), fmt, b1); - CHECK_UNARY(ret.success_until(0)); - CHECK_UNARY(ret.success_until(1)); - CHECK_UNARY(ret.success_until(2)); - CHECK_EQ(ret.bufsize, 1); - CHECK_EQ(ret.lastok, 2); - CHECK_EQ(ret.argfail(), 3); - CHECK_EQ(DumpChecker::s_num_calls, 3); - CHECK_EQ(buf.first(2), csubstr("1+")); - CHECK_EQ(accum(), csubstr("aaa_then_1_then_bbb")); - } - SUBCASE("2") - { - csubstr fmt = "aaa_then_{}_then_bbb_then_{}__then_epilogue"; - DumpChecker::s_reset(); - DumpResults ret = T::call_format_dump_resume(buf.first(0), fmt, b1, b2); - CHECK_UNARY(!ret.success_until(0)); - CHECK_EQ(ret.bufsize, 2); - CHECK_EQ(ret.lastok, DumpResults::noarg); - CHECK_EQ(ret.argfail(), 0); - CHECK_EQ(DumpChecker::s_num_calls, 0); // no calls to dump - CHECK_EQ(buf.first(1), csubstr("+")); // nothing was written - CHECK_EQ(accum(), csubstr("")); - ret = T::call_format_dump_resume(ret, buf.first(1), fmt, b1, b2); - CHECK_UNARY(ret.success_until(0)); - CHECK_UNARY(ret.success_until(1)); - CHECK_UNARY(ret.success_until(2)); - CHECK_UNARY(!ret.success_until(3)); - CHECK_EQ(ret.bufsize, 2); - CHECK_EQ(ret.lastok, 2); - CHECK_EQ(ret.argfail(), 3); - CHECK_EQ(DumpChecker::s_num_calls, 3); - CHECK_EQ(buf.first(2), csubstr("1+")); - CHECK_EQ(accum(), csubstr("aaa_then_1_then_bbb_then_")); - ret = T::call_format_dump_resume(ret, buf.first(2), fmt, b1, b2); - CHECK_UNARY(ret.success_until(0)); - CHECK_UNARY(ret.success_until(1)); - CHECK_UNARY(ret.success_until(2)); - CHECK_UNARY(ret.success_until(3)); - CHECK_UNARY(ret.success_until(4)); - CHECK_EQ(ret.bufsize, 2); - CHECK_EQ(ret.lastok, 4); - CHECK_EQ(ret.argfail(), 5); - CHECK_EQ(DumpChecker::s_num_calls, 5); - CHECK_EQ(buf.first(2), csubstr("22")); - CHECK_EQ(accum(), csubstr("aaa_then_1_then_bbb_then_22__then_epilogue")); - } - SUBCASE("no args") - { - csubstr fmt = "no args { -- }"; - DumpChecker::s_reset(); - DumpResults ret = T::call_format_dump_resume(buf.first(0), fmt, b1, b2); - CHECK_UNARY(!ret.success_until(0)); - CHECK_EQ(ret.bufsize, 0); - CHECK_EQ(ret.lastok, DumpResults::noarg); - CHECK_EQ(ret.argfail(), 0); - CHECK_EQ(DumpChecker::s_num_calls, 0); // no calls to dump - CHECK_EQ(buf.first(1), csubstr("+")); // nothing was written - CHECK_EQ(accum(), csubstr("")); - ret = T::call_format_dump_resume(ret, buf.first(1), fmt, b1, b2); - CHECK_UNARY(ret.success_until(0)); - CHECK_UNARY(!ret.success_until(1)); - CHECK_EQ(ret.bufsize, 0); - CHECK_EQ(ret.lastok, 0); - CHECK_EQ(ret.argfail(), 1); - CHECK_EQ(DumpChecker::s_num_calls, 1); - CHECK_EQ(buf.first(2), "++"); - CHECK_EQ(accum(), fmt); - } -} - -} // namespace c4 - -#ifdef __clang__ -# pragma clang diagnostic pop -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#endif - -#include "c4/libtest/supprwarn_pop.hpp" diff --git a/thirdparty/ryml/ext/c4core/test/test_enum.cpp b/thirdparty/ryml/ext/c4core/test/test_enum.cpp deleted file mode 100644 index b2dad0bbd..000000000 --- a/thirdparty/ryml/ext/c4core/test/test_enum.cpp +++ /dev/null @@ -1,158 +0,0 @@ -#ifndef C4CORE_SINGLE_HEADER -#include -#include -#include -#endif - -#include - -#include "./test_enum_common.hpp" -#include "c4/libtest/supprwarn_push.hpp" -#include - - -TEST_CASE("eoffs.simple_enum") -{ - using namespace c4; - CHECK_EQ(eoffs_cls(), 0); - CHECK_EQ(eoffs_pfx(), 0); -} - -TEST_CASE("eoffs.scoped_enum") -{ - using namespace c4; - CHECK_EQ(eoffs_cls(), strlen("MyEnumClass::")); - CHECK_EQ(eoffs_pfx(), 0); -} - -TEST_CASE("eoffs.simple_bitmask") -{ - using namespace c4; - CHECK_EQ(eoffs_cls(), 0); - CHECK_EQ(eoffs_pfx(), strlen("BM_")); -} - -TEST_CASE("eoffs.scoped_bitmask") -{ - using namespace c4; - CHECK_EQ(eoffs_cls(), strlen("MyBitmaskClass::")); - CHECK_EQ(eoffs_pfx(), strlen("MyBitmaskClass::BM_")); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -#ifdef __clang__ -# pragma clang diagnostic push -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# if __GNUC__ >= 6 -# pragma GCC diagnostic ignored "-Wnull-dereference" -# endif -#endif - -template -void cmp_enum(Enum lhs, Enum rhs) -{ - using I = typename std::underlying_type::type; - CHECK_EQ(static_cast(lhs), static_cast(rhs)); -} - -template -void test_esyms() -{ - auto ss = c4::esyms(); - CHECK_NE(ss.size(), 0); - CHECK_FALSE(ss.empty()); - for(auto s : ss) - { - REQUIRE_NE(ss.find(s.name), nullptr); - REQUIRE_NE(ss.find(s.value), nullptr); - CHECK_STREQ(ss.find(s.name)->name, s.name); - CHECK_STREQ(ss.find(s.value)->name, s.name); - cmp_enum(ss.find(s.name)->value, s.value); - cmp_enum(ss.find(s.value)->value, s.value); - } -} - -#ifdef __clang__ -# pragma clang diagnostic pop -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#endif - - -TEST_CASE("esyms.simple_enum") -{ - test_esyms(); -} - -TEST_CASE("esyms.scoped_enum") -{ - test_esyms(); -} - -TEST_CASE("esyms.simple_bitmask") -{ - test_esyms(); -} - -TEST_CASE("esyms.scoped_bitmask") -{ - test_esyms(); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - - -template -void test_e2str() -{ - using namespace c4; - using I = typename std::underlying_type::type; - auto ss = esyms(); - CHECK_NE(ss.size(), 0); - CHECK_FALSE(ss.empty()); - for(auto const& p : ss) - { - // test round trips - cmp_enum(str2e(e2str(p.value)), p.value); - CHECK_STREQ(e2str(str2e(p.name)), p.name); - } -} - - -TEST_CASE("e2str.simple_enum") -{ - test_e2str(); -} - -TEST_CASE("e2str.scoped_enum") -{ - test_e2str(); - cmp_enum(c4::str2e("MyEnumClass::FOO"), MyEnumClass::FOO); - cmp_enum(c4::str2e("FOO"), MyEnumClass::FOO); -} - -TEST_CASE("e2str.simple_bitmask") -{ - test_e2str(); - cmp_enum(c4::str2e("BM_FOO"), BM_FOO); - cmp_enum(c4::str2e("FOO"), BM_FOO); -} - -TEST_CASE("e2str.scoped_bitmask") -{ - using I = typename std::underlying_type::type; - test_e2str(); - cmp_enum(c4::str2e("MyBitmaskClass::BM_FOO"), MyBitmaskClass::BM_FOO); - cmp_enum(c4::str2e("BM_FOO"), MyBitmaskClass::BM_FOO); - cmp_enum(c4::str2e("FOO"), MyBitmaskClass::BM_FOO); -} - -#include "c4/libtest/supprwarn_pop.hpp" diff --git a/thirdparty/ryml/ext/c4core/test/test_enum_common.hpp b/thirdparty/ryml/ext/c4core/test/test_enum_common.hpp deleted file mode 100644 index 9acd621cf..000000000 --- a/thirdparty/ryml/ext/c4core/test/test_enum_common.hpp +++ /dev/null @@ -1,213 +0,0 @@ -#ifndef _C4_ENUM_COMMON_HPP_ -#define _C4_ENUM_COMMON_HPP_ - -#ifndef C4CORE_SINGLE_HEADER -#include -#endif - -typedef enum { - FOO = 0, - BAR, - BAZ, -} MyEnum; - -namespace c4 { -template<> -inline const EnumSymbols esyms() -{ - static const EnumSymbols::Sym rs[] = - { - {FOO, "FOO"}, - {BAR, "BAR"}, - {BAZ, "BAZ"}, - }; - EnumSymbols r(rs); - return r; -} -} // namespace c4 - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -enum class MyEnumClass { - FOO = 0, - BAR, - BAZ, -}; - - -namespace c4 { -template<> -inline const EnumSymbols esyms() -{ - static const EnumSymbols::Sym rs[] = - { - {MyEnumClass::FOO, "MyEnumClass::FOO"}, - {MyEnumClass::BAR, "MyEnumClass::BAR"}, - {MyEnumClass::BAZ, "MyEnumClass::BAZ"}, - }; - EnumSymbols r(rs); - return r; -} - - -template<> -inline size_t eoffs_cls() -{ - return 13; // same as strlen("MyEnumClass::") -} -} // namespace c4 - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -typedef enum { - BM_NONE = 0, - BM_FOO = 1 << 0, - BM_BAR = 1 << 1, - BM_BAZ = 1 << 2, - BM_FOO_BAR = BM_FOO|BM_BAR, - BM_FOO_BAR_BAZ = BM_FOO|BM_BAR|BM_BAZ, -} MyBitmask; - -namespace c4 { -template<> -inline const EnumSymbols esyms() -{ - static const EnumSymbols::Sym rs[] = - { - {BM_NONE, "BM_NONE"}, - {BM_FOO, "BM_FOO"}, - {BM_BAR, "BM_BAR"}, - {BM_BAZ, "BM_BAZ"}, - {BM_FOO_BAR, "BM_FOO_BAR"}, - {BM_FOO_BAR_BAZ, "BM_FOO_BAR_BAZ"}, - }; - EnumSymbols r(rs); - return r; -} - -template<> -inline size_t eoffs_pfx() -{ - return 3; // same as strlen("BM_") -} -} // namespace c4 - - - -typedef enum { - // no null value - BM_KABOOM = 1, - BM_PAFF = 2, - BM_PEW = 4, - BM_POW = 7, -} BmWithoutNull; - - -namespace c4 { -template<> -inline const c4::EnumSymbols esyms() -{ - static const EnumSymbols::Sym rs[] = - { - {BM_KABOOM, "KABOOM"}, - {BM_PAFF , "PAFF"}, - {BM_PEW , "PEW"}, - {BM_POW , "POW"}, - }; - EnumSymbols r(rs); - return r; -} - -template<> -inline size_t eoffs_pfx() -{ - return 3; // same as strlen("BM_") -} -} // namespace c4 - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -enum class MyBitmaskClass { - BM_NONE = 0, - BM_FOO = 1 << 0, - BM_BAR = 1 << 1, - BM_BAZ = 1 << 2, - BM_FOO_BAR = BM_FOO|BM_BAR, - BM_FOO_BAR_BAZ = BM_FOO|BM_BAR|BM_BAZ, -}; - -namespace c4 { - -template<> -inline const EnumSymbols esyms() -{ - static const EnumSymbols::Sym rs[] = - { - {MyBitmaskClass::BM_NONE, "MyBitmaskClass::BM_NONE"}, - {MyBitmaskClass::BM_FOO, "MyBitmaskClass::BM_FOO"}, - {MyBitmaskClass::BM_BAR, "MyBitmaskClass::BM_BAR"}, - {MyBitmaskClass::BM_BAZ, "MyBitmaskClass::BM_BAZ"}, - {MyBitmaskClass::BM_FOO_BAR, "MyBitmaskClass::BM_FOO_BAR"}, - {MyBitmaskClass::BM_FOO_BAR_BAZ, "MyBitmaskClass::BM_FOO_BAR_BAZ"}, - }; - EnumSymbols r(rs); - return r; -} - -template<> inline size_t eoffs_cls< MyBitmaskClass >() -{ - return 16; // same as strlen("MyBitmaskClass::") -} -template<> inline size_t eoffs_pfx< MyBitmaskClass >() -{ - return 19; // same as strlen("MyBitmaskClass::BM_") -} - -} // namespace c4 - - -enum class BmClassWithoutNull { - // no null value - BM_KABOOM = 1, - BM_PAFF = 2, - BM_PEW = 4, - BM_POW = 7, -}; - - -namespace c4 { -template<> -inline const c4::EnumSymbols esyms() -{ - static const EnumSymbols::Sym rs[] = - { - {BmClassWithoutNull::BM_KABOOM, "BmClassWithoutNull::BM_KABOOM"}, - {BmClassWithoutNull::BM_PAFF , "BmClassWithoutNull::BM_PAFF"}, - {BmClassWithoutNull::BM_PEW , "BmClassWithoutNull::BM_PEW"}, - {BmClassWithoutNull::BM_POW , "BmClassWithoutNull::BM_POW"}, - }; - EnumSymbols r(rs); - return r; -} - -template<> inline size_t eoffs_cls() -{ - return strlen("BmClassWithoutNull::"); -} -template<> inline size_t eoffs_pfx() -{ - return strlen("BmClassWithoutNull::BM_"); -} -} // namespace c4 - - -#endif /* _C4_ENUM_COMMON_HPP_ */ diff --git a/thirdparty/ryml/ext/c4core/test/test_error.cpp b/thirdparty/ryml/ext/c4core/test/test_error.cpp deleted file mode 100644 index 96584ab92..000000000 --- a/thirdparty/ryml/ext/c4core/test/test_error.cpp +++ /dev/null @@ -1,635 +0,0 @@ -#ifndef C4CORE_SINGLE_HEADER -#include "c4/error.hpp" -#endif - -#include "c4/test.hpp" -#include "c4/libtest/supprwarn_push.hpp" - -C4_BEGIN_HIDDEN_NAMESPACE -bool got_an_error = false; -void error_callback(const char *msg, size_t msg_sz) -{ - CHECK_EQ(strncmp(msg, "bla bla", msg_sz), 0); - CHECK_EQ(msg_sz, 7); - got_an_error = true; -} -inline c4::ScopedErrorSettings tmp_err() -{ - got_an_error = false; - return c4::ScopedErrorSettings(c4::ON_ERROR_CALLBACK, error_callback); -} -C4_END_HIDDEN_NAMESPACE - -namespace c4 { - -TEST_CASE("Error.scoped_callback") -{ - auto orig = get_error_callback(); - { - auto tmp = tmp_err(); - CHECK_EQ(get_error_callback() == error_callback, true); - C4_ERROR("bla bla"); - CHECK_EQ(got_an_error, true); - } - CHECK_EQ(get_error_callback() == orig, true); -} - -} // namespace c4 - -TEST_CASE("Error.outside_of_c4_namespace") -{ - auto orig = c4::get_error_callback(); - { - auto tmp = tmp_err(); - CHECK_EQ(c4::get_error_callback() == error_callback, true); - C4_ERROR("bla bla"); - CHECK_EQ(got_an_error, true); - } - CHECK_EQ(c4::get_error_callback() == orig, true); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// WIP: new error handling code - - -#include // temporary; just for the exception example -#include // temporary; just for the exception example - -namespace c4 { - -#define C4_ERR_FMT_BUFFER_SIZE 256 - -using locref = c4::srcloc const& C4_RESTRICT; - -using pfn_err = void (*)(locref loc, void *data); -using pfn_warn = void (*)(locref loc, void *data); -using pfn_msg_begin = void (*)(locref loc, void *data); -using pfn_msg_part = void (*)(const char* msg, size_t size, void *data); -using pfn_msg_end = void (*)(void *data); - -struct ErrorCallbacks -{ - void *user_data; - - pfn_err err; - pfn_warn warn; - pfn_msg_begin msg_begin; - pfn_msg_part msg_part; - pfn_msg_end msg_end; - - bool msg_enabled() const { return msg_begin != nullptr; } - - template - void msg(const char (&s)[N]) - { - msg_part(s, N-1, user_data); - } - void msg(const char *msg, size_t sz) - { - msg_part(msg, sz, user_data); - } - void msg(char c) - { - msg_part(&c, 1, user_data); - } -}; - -#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 8 && __GNUC__ < 5 -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wmissing-field-initializers" -#endif -TEST_CASE("ErrorCallbacks.default_obj") -{ - ErrorCallbacks cb {}; - CHECK_EQ(cb.user_data, nullptr); - CHECK_EQ(cb.err, nullptr); - CHECK_EQ(cb.warn, nullptr); - CHECK_EQ(cb.msg_begin, nullptr); - CHECK_EQ(cb.msg_part, nullptr); - CHECK_EQ(cb.msg_end, nullptr); -} -#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 8 && __GNUC__ < 5 -#pragma GCC diagnostic pop -#endif - -template -struct ErrorCallbacksBridgeFull -{ - ErrorCallbacks callbacks() const - { - return { - (ErrBhv*)this, - ErrorCallbacksBridgeFull::on_err, - ErrorCallbacksBridgeFull::on_warn, - ErrorCallbacksBridgeFull::on_msg_begin, - ErrorCallbacksBridgeFull::on_msg_part, - ErrorCallbacksBridgeFull::on_msg_end, - }; - } - static void on_err(locref loc, void *data) - { - ((ErrBhv*)data)->err(loc); - } - static void on_warn(locref loc, void *data) - { - ((ErrBhv*)data)->warn(loc); - } - static void on_msg_begin(locref loc, void *data) - { - ((ErrBhv*)data)->msg_begin(loc); - } - static void on_msg_part(const char *part, size_t size, void *data) - { - ((ErrBhv*)data)->msg_part(part, size); - } - static void on_msg_end(void *data) - { - ((ErrBhv*)data)->msg_end(); - } -}; - -template -struct ErrorCallbacksBridge -{ - ErrorCallbacks callbacks() const - { - return { - (ErrBhv*)this, - ErrorCallbacksBridge::on_err, - ErrorCallbacksBridge::on_warn, - (pfn_msg_begin)nullptr, - (pfn_msg_part)nullptr, - (pfn_msg_end)nullptr - }; - } - static void on_err(locref loc, void *data) - { - ((ErrBhv*)data)->err(loc); - } - static void on_warn(locref loc, void *data) - { - ((ErrBhv*)data)->warn(loc); - } -}; - - -void fputi(int val, FILE *f); - -void _errmsg(locref loc) -{ - fputs(loc.file, stderr); - fputc(':', stderr); - fputi(loc.line, stderr); - fputs(": ", stderr); - fflush(stderr); -} - -void _errmsg(const char *part, size_t part_size) -{ - fwrite(part, 1u, part_size, stderr); - fflush(stderr); -} - -/** example implementation using old-style abort */ -struct ErrorBehaviorAbort : public ErrorCallbacksBridgeFull -{ - static void msg_begin(locref loc) - { - fputc('\n', stderr); - _errmsg(loc); - } - static void msg_part(const char *part, size_t part_size) - { - _errmsg(part, part_size); - } - static void msg_end() - { - fputc('\n', stderr); - fflush(stderr); - } - static void err(locref) - { - abort(); - } - static void warn(locref) - { - // nothing to do - } -}; - - -TEST_CASE("ErrorBehaviorAbort.default_obj") -{ - ErrorBehaviorAbort bhv; - auto cb = bhv.callbacks(); - CHECK_NE(cb.user_data, nullptr); - CHECK_NE(cb.err, nullptr); - CHECK_NE(cb.warn, nullptr); - CHECK_NE(cb.msg_begin, nullptr); - CHECK_NE(cb.msg_part, nullptr); - CHECK_NE(cb.msg_end, nullptr); -} - - -void fputi(int val, FILE *f); -void _append(std::string *s, int line); - -/** example implementation using vanilla c++ std::runtime_error */ -struct ErrorBehaviorRuntimeError : public ErrorCallbacksBridgeFull -{ - std::string exc_msg{}; - - void msg_begin(locref loc) - { - exc_msg.reserve(strlen(loc.file) + 16); - exc_msg = '\n'; - exc_msg += loc.file; - exc_msg += ':'; - _append(&exc_msg, loc.line); - exc_msg += ": "; - } - void msg_part(const char *part, size_t part_size) - { - exc_msg.append(part, part_size); - } - void msg_end() - { - std::cerr << exc_msg << "\n"; - } - void err(locref) - { - throw std::runtime_error(exc_msg); - } - void warn(locref) - { - } -}; - - - -TEST_CASE("ErrorBehaviorRuntimeError.default_obj") -{ - ErrorBehaviorRuntimeError bhv; - auto cb = bhv.callbacks(); - CHECK_NE(cb.user_data, nullptr); - CHECK_NE(cb.err, nullptr); - CHECK_NE(cb.warn, nullptr); - CHECK_NE(cb.msg_begin, nullptr); - CHECK_NE(cb.msg_part, nullptr); - CHECK_NE(cb.msg_end, nullptr); -} - - - - -ErrorBehaviorAbort s_err_abort = ErrorBehaviorAbort(); -ErrorCallbacks s_err_callbacks = s_err_abort.callbacks(); - - -void new_handle_error(locref loc, size_t msg_size, const char *msg) -{ - if(s_err_callbacks.msg_enabled()) - { - s_err_callbacks.msg_begin(loc, s_err_callbacks.user_data); - s_err_callbacks.msg("ERROR: "); - s_err_callbacks.msg(msg, msg_size); - s_err_callbacks.msg_end(s_err_callbacks.user_data); - } - s_err_callbacks.err(loc, s_err_callbacks.user_data); -} - -void new_handle_warning(locref loc, size_t msg_size, const char *msg) -{ - if(s_err_callbacks.msg_enabled()) - { - s_err_callbacks.msg_begin(loc, s_err_callbacks.user_data); - s_err_callbacks.msg("WARNING: "); - s_err_callbacks.msg(msg, msg_size); - s_err_callbacks.msg_end(s_err_callbacks.user_data); - } - s_err_callbacks.warn(loc, s_err_callbacks.user_data); -} - -template -C4_ALWAYS_INLINE void new_handle_error(locref loc, const char (&msg)[N]) -{ - new_handle_error(loc, N-1, msg); -} - -template -C4_ALWAYS_INLINE void new_handle_warning(locref loc, const char (&msg)[N]) -{ - new_handle_warning(loc, N-1, msg); -} - - -#define C4_ERROR_NEW(msg) c4::new_handle_error(C4_SRCLOC(), msg) -#define C4_WARNING_NEW(msg) c4::new_handle_warning(C4_SRCLOC(), msg) - -#define C4_ERROR_NEW_SZ(msg, msglen) c4::new_handle_error(C4_SRCLOC(), msglen, msg) -#define C4_WARNING_NEW_SZ(msg, msglen) c4::new_handle_warning(C4_SRCLOC(), msglen, msg) - -} // namespace c4 - -#ifndef C4CORE_SINGLE_HEADER -#include -#include -#endif - -namespace c4 { - -void fputi(int val, FILE *f) -{ - char buf[16]; - size_t ret = c4::itoa(buf, val); - ret = ret < sizeof(buf) ? ret : sizeof(buf); - fwrite(buf, 1u, ret, f); -} - -// to avoid using std::to_string() -void _append(std::string *s, int line) -{ - auto sz = s->size(); - s->resize(sz + 16); - auto ret = itoa(substr(&((*s)[0]) + sz, 16u), line); - s->resize(sz + ret); - if(ret >= sz) - { - itoa(substr(&((*s)[0]) + sz, 16u), line); - } -} - -} // namespace c4 -template -struct ScopedErrorBehavior -{ - c4::ErrorCallbacks m_prev; - ErrorBehavior m_tmp; - const char *m_name; - ScopedErrorBehavior(const char* name) : m_prev(c4::s_err_callbacks), m_tmp(), m_name(name) - { - c4::s_err_callbacks = m_tmp.callbacks(); - } - ~ScopedErrorBehavior() - { - c4::s_err_callbacks = m_prev; - } -}; -#define C4_TMP_ERR_BHV(bhv_ty) ScopedErrorBehavior(#bhv_ty) - -template -void test_error_exception(const char (&msg)[N]) -{ - INFO(msg); - { - auto tmp1 = C4_TMP_ERR_BHV(ErrorBehaviorAbort); - - { - auto tmp2 = C4_TMP_ERR_BHV(ErrorBehaviorRuntimeError); - - bool got_exc = false; - try { - C4_ERROR_NEW(msg); - } - catch(std::exception const& e) { - // check that the error terminates with the given message - auto what = c4::to_csubstr(e.what()).last(N-1); - CHECK_EQ(what, msg); - got_exc = (what == msg); - } - CHECK(got_exc); - - got_exc = false; - try { - C4_ERROR_NEW_SZ(msg, N-1); - } - catch(std::exception const& e) { - // check that the error terminates with the given message - auto what = c4::to_csubstr(e.what()).last(N-1); - CHECK_EQ(what, msg); - got_exc = (what == msg); - } - CHECK(got_exc); - } - } -} - -template -void test_warning_exception(const char (&msg)[N]) -{ - auto tmp = C4_TMP_ERR_BHV(ErrorBehaviorRuntimeError); - C4_WARNING_NEW(msg); - auto const& wmsg = tmp.m_tmp.exc_msg; - REQUIRE_FALSE(wmsg.empty()); - REQUIRE_GT(wmsg.size(), N); - auto what = c4::to_csubstr(wmsg.c_str()).last(N-1); - CHECK_EQ(what, msg); - - C4_WARNING_NEW_SZ(msg, N-1); - REQUIRE_FALSE(wmsg.empty()); - REQUIRE_GT(wmsg.size(), N); - what = c4::to_csubstr(wmsg.c_str()).last(N-1); - CHECK_EQ(what, msg); -} - -TEST_CASE("error.exception") -{ - test_error_exception("some error with some message"); - test_error_exception("some error with another message"); -} - -TEST_CASE("warning.exception") -{ - test_warning_exception("some warning"); - test_warning_exception("some other warning"); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -#ifndef C4CORE_SINGLE_HEADER -#include -#include -#endif - -namespace c4 { - -template -void _err_send(T const& arg) -{ - char buf[C4_ERR_FMT_BUFFER_SIZE]; - size_t num = to_chars(buf, arg); - num = num < C4_ERR_FMT_BUFFER_SIZE ? num : C4_ERR_FMT_BUFFER_SIZE; - s_err_callbacks.msg_part(buf, num, s_err_callbacks.user_data); -} - - -size_t _find_fmt(const char *C4_RESTRICT fmt, size_t len) -{ - for(size_t i = 0; i < len; ++i) - { - if(fmt[i] != '{') - { - continue; - } - if(i + 1 == len) - { - break; - } - if(fmt[i+1] == '}') - { - return i; - } - } - return (size_t)-1; -} - -void _err_fmt(size_t fmt_size, const char *C4_RESTRICT fmt) -{ - s_err_callbacks.msg_part(fmt, fmt_size, s_err_callbacks.user_data); -} - -template -void _err_fmt(size_t fmt_size, const char *C4_RESTRICT fmt, Arg const& C4_RESTRICT arg, Args const& C4_RESTRICT ...args) -{ - size_t pos = _find_fmt(fmt, fmt_size); - if(pos == (size_t)-1) - { - s_err_callbacks.msg_part(fmt, fmt_size, s_err_callbacks.user_data); - return; - } - s_err_callbacks.msg_part(fmt, pos, s_err_callbacks.user_data); - _err_send(arg); - pos += 2; - _err_fmt(fmt_size - pos, fmt + pos, args...); -} - -template -void err_fmt(locref loc, size_t fmt_size, const char *fmt, Args const& C4_RESTRICT ...args) -{ - s_err_callbacks.msg_begin(loc, s_err_callbacks.user_data); - s_err_callbacks.msg("ERROR: "); - _err_fmt(fmt_size, fmt, args...); - s_err_callbacks.msg_end(s_err_callbacks.user_data); - s_err_callbacks.err(loc, s_err_callbacks.user_data); -} - -template -void warn_fmt(locref loc, size_t fmt_size, const char *fmt, Args const& C4_RESTRICT ...args) -{ - s_err_callbacks.msg_begin(loc, s_err_callbacks.user_data); - s_err_callbacks.msg("WARNING: "); - _err_fmt(fmt_size, fmt, args...); - s_err_callbacks.msg_end(s_err_callbacks.user_data); - s_err_callbacks.warn(loc, s_err_callbacks.user_data); -} - -template -void err_fmt(locref loc, const char (&fmt)[N], Args const& C4_RESTRICT ...args) -{ - err_fmt(loc, N-1, fmt, args...); -} - -template -void warn_fmt(locref loc, const char (&fmt)[N], Args const& C4_RESTRICT ...args) -{ - warn_fmt(loc, N-1, fmt, args...); -} - -#define C4_ERROR_FMT_NEW(fmt, ...) c4::err_fmt(C4_SRCLOC(), fmt, __VA_ARGS__) -#define C4_WARNING_FMT_NEW(msg, ...) c4::warn_fmt(C4_SRCLOC(), fmt, __VA_ARGS__) - -#define C4_ERROR_FMT_NEW_SZ(fmt, fmtlen, ...) c4::err_fmt(C4_SRCLOC(), fmtlen, fmt, __VA_ARGS__) -#define C4_WARNING_FMT_NEW_SZ(fmt, fmtlen, ...) c4::warn_fmt(C4_SRCLOC(), fmtlen, fmt, __VA_ARGS__) - -} // namespace c4 - -template -void test_error_fmt_exception(const char (&expected)[M], const char (&fmt)[N], Args const& ...args) -{ - INFO(expected); - { - auto tmp1 = C4_TMP_ERR_BHV(ErrorBehaviorAbort); - - { - auto tmp2 = C4_TMP_ERR_BHV(ErrorBehaviorRuntimeError); - - bool got_exc = false; - try { - C4_ERROR_FMT_NEW(fmt, args...); - } - catch(std::exception const& e) { - // check that the error terminates with the given message - auto what = c4::to_csubstr(e.what()).last(M-1); - CHECK_EQ(what, expected); - got_exc = (what == expected); - } - CHECK(got_exc); - - got_exc = false; - try { - C4_ERROR_FMT_NEW_SZ(fmt, N-1, args...); - } - catch(std::exception const& e) { - // check that the error terminates with the given message - auto what = c4::to_csubstr(e.what()).last(M-1); - CHECK_EQ(what, expected); - got_exc = (what == expected); - } - CHECK(got_exc); - } - } -} - -template -void test_warning_fmt_exception(const char (&expected)[M], const char (&fmt)[N], Args const& ...args) -{ - INFO(expected); - - auto tmp = C4_TMP_ERR_BHV(ErrorBehaviorRuntimeError); - auto const& wmsg = tmp.m_tmp.exc_msg; - C4_WARNING_FMT_NEW(fmt, args...); - REQUIRE_FALSE(wmsg.empty()); - REQUIRE_GT(wmsg.size(), M); - auto what = c4::to_csubstr(wmsg.c_str()).last(M-1); - CHECK_EQ(what, expected); - - C4_WARNING_FMT_NEW_SZ(fmt, N-1, args...); - REQUIRE_FALSE(wmsg.empty()); - REQUIRE_GT(wmsg.size(), M); - what = c4::to_csubstr(wmsg.c_str()).last(M-1); - CHECK_EQ(what, expected); -} - - -TEST_CASE("error.fmt") -{ - test_error_fmt_exception("aaa is 2 is it not?", - "{} is {} is it not?", "aaa", 2); - test_error_fmt_exception("aaa is bbb is it not?", - "{} is {} is it not?", "aaa", "bbb"); - test_error_fmt_exception("aaa is {} is it not?", - "{} is {} is it not?", "aaa"); - test_error_fmt_exception("aaa is {} is it not?", - "{} is {} is it not?", "aaa"); -} - -TEST_CASE("warning.fmt") -{ - test_warning_fmt_exception("aaa is 2 is it not?", - "{} is {} is it not?", "aaa", 2); - test_warning_fmt_exception("aaa is bbb is it not?", - "{} is {} is it not?", "aaa", "bbb"); - test_warning_fmt_exception("aaa is {} is it not?", - "{} is {} is it not?", "aaa"); - test_warning_fmt_exception("aaa is {} is it not?", - "{} is {} is it not?", "aaa"); -} - - -#include "c4/libtest/supprwarn_pop.hpp" diff --git a/thirdparty/ryml/ext/c4core/test/test_error_exception.cpp b/thirdparty/ryml/ext/c4core/test/test_error_exception.cpp deleted file mode 100644 index fae0020b8..000000000 --- a/thirdparty/ryml/ext/c4core/test/test_error_exception.cpp +++ /dev/null @@ -1,108 +0,0 @@ -#ifndef C4CORE_SINGLE_HEADER -#include "c4/error.hpp" -#endif - -#include "c4/test.hpp" -#include -#include - - -C4_BEGIN_HIDDEN_NAMESPACE -bool got_an_error = false; -bool got_an_exception = false; -C4_END_HIDDEN_NAMESPACE - -void error_callback_throwing_exception(const char *msg_, size_t msg_sz) -{ - got_an_error = true; - c4::csubstr s(msg_, msg_sz); - if (s == "err1") throw 1; - else if(s == "err2") throw 2; - else if(s == "err3") throw 3; - else if(s == "err4") throw 4; - else throw std::runtime_error({msg_, msg_+msg_sz}); -} - -inline c4::ScopedErrorSettings tmp_err() -{ - got_an_error = false; - return c4::ScopedErrorSettings(c4::ON_ERROR_CALLBACK, error_callback_throwing_exception); -} - - -void test_exception(int which) -{ - if(which == 0) return; - CHECK_FALSE(got_an_exception); - CHECK_EQ(c4::get_error_callback() == error_callback_throwing_exception, false); - { - auto tmp = tmp_err(); - CHECK_EQ(got_an_error, false); - CHECK_EQ(c4::get_error_callback() == error_callback_throwing_exception, true); - try - { - if (which == 1) { C4_ERROR("err1"); } - else if(which == 2) { C4_ERROR("err2"); } - else if(which == 3) { C4_ERROR("err3"); } - else if(which == 4) { C4_ERROR("err4"); } - else { C4_ERROR("unknown error"); } - } - catch(int i) - { - got_an_exception = true; - CHECK_EQ(got_an_error, true); - CHECK_EQ(i, which); - throw; - } - catch(std::runtime_error const& e) - { - got_an_exception = true; - CHECK_EQ(got_an_error, true); - CHECK_STREQ(e.what(), "unknown error"); - throw; - } - // if we get here it means no exception was thrown - // so the test failed - FAIL("an exception was thrown"); - } - CHECK_EQ(c4::get_error_callback() == error_callback_throwing_exception, false); -} - - -// Although c4core does not use exceptions by default (*), you can have your -// error callback throw an exception which you can then catch on your code. -// This test covers that possibility. -// -// (*) Note that you can also configure c4core to throw an exception on error. - -TEST_CASE("error.exception_from_callback") -{ - // works! - got_an_exception = false; - CHECK_THROWS_AS(test_exception(-1), std::runtime_error); - CHECK(got_an_exception); - - got_an_exception = false; - CHECK_NOTHROW(test_exception(0)); - CHECK_FALSE(got_an_exception); - - got_an_exception = false; - CHECK_THROWS_AS(test_exception(1), int); - CHECK(got_an_exception); - - got_an_exception = false; - CHECK_THROWS_AS(test_exception(2), int); - CHECK(got_an_exception); - - got_an_exception = false; - CHECK_THROWS_AS(test_exception(3), int); - CHECK(got_an_exception); - - got_an_exception = false; - CHECK_THROWS_AS(test_exception(4), int); - CHECK(got_an_exception); - - got_an_exception = false; - CHECK_THROWS_AS(test_exception(6), std::runtime_error); - CHECK(got_an_exception); -} diff --git a/thirdparty/ryml/ext/c4core/test/test_format.cpp b/thirdparty/ryml/ext/c4core/test/test_format.cpp deleted file mode 100644 index 42a50dc75..000000000 --- a/thirdparty/ryml/ext/c4core/test/test_format.cpp +++ /dev/null @@ -1,1054 +0,0 @@ -#ifndef C4CORE_SINGLE_HEADER -#include "c4/substr.hpp" -#include "c4/std/std.hpp" -#include "c4/format.hpp" -#endif - -#include -#include "c4/libtest/supprwarn_push.hpp" - -#ifdef __clang__ -# pragma clang diagnostic push -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wuseless-cast" -#endif - -namespace c4 { - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - - -TEST_CASE_TEMPLATE("to_chars.fmt.bin", T, uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t) -{ - char bufc[128]; - substr buf(bufc); - - CHECK_EQ(to_chars_sub(buf, fmt::integral(T(21), T(2))), "0b10101"); - CHECK_EQ(to_chars_sub(buf, fmt::integral((T*)21, T(2))), "0b10101"); - CHECK_EQ(to_chars_sub(buf, fmt::integral((T const*)21, T(2))), "0b10101"); - CHECK_EQ(to_chars_sub(buf, fmt::integral(nullptr, T(2))), "0b0"); - CHECK_EQ(to_chars_sub(buf, fmt::bin(T(21))), "0b10101"); - CHECK_EQ(to_chars_sub(buf, fmt::bin((T*)21)), "0b10101"); - CHECK_EQ(to_chars_sub(buf, fmt::bin((T const*)21)), "0b10101"); - CHECK_EQ(to_chars_sub(buf, fmt::bin(nullptr)), "0b0"); -} - -TEST_CASE_TEMPLATE("to_chars.fmt.zpad.bin", T, uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t) -{ - char bufc[128]; - substr buf(bufc); - using namespace fmt; - CHECK_EQ(to_chars_sub(buf, zpad(integral(T(21), T(2)), 8u)), "0b00010101"); - CHECK_EQ(to_chars_sub(buf, zpad(integral((T*)21, T(2)), 8u)), "0b00010101"); - CHECK_EQ(to_chars_sub(buf, zpad(integral((T const*)21, T(2)), 8u)), "0b00010101"); - CHECK_EQ(to_chars_sub(buf, zpad(bin(T(21)), 8u)), "0b00010101"); - CHECK_EQ(to_chars_sub(buf, zpad(bin((T*)21), 8u)), "0b00010101"); - CHECK_EQ(to_chars_sub(buf, zpad(bin((T const*)21), 8u)), "0b00010101"); -} - -TEST_CASE_TEMPLATE("to_chars.fmt.oct", T, uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t) -{ - char bufc[128]; - substr buf(bufc); - - CHECK_EQ(to_chars_sub(buf, fmt::integral(T(65), T(8))), "0o101"); - CHECK_EQ(to_chars_sub(buf, fmt::integral((T*)65, T(8))), "0o101"); - CHECK_EQ(to_chars_sub(buf, fmt::integral((T const*)65, T(8))), "0o101"); - CHECK_EQ(to_chars_sub(buf, fmt::integral(nullptr, T(8))), "0o0"); - CHECK_EQ(to_chars_sub(buf, fmt::oct(T(65))), "0o101"); - CHECK_EQ(to_chars_sub(buf, fmt::oct((T*)65)), "0o101"); - CHECK_EQ(to_chars_sub(buf, fmt::oct((T const*)65)), "0o101"); - CHECK_EQ(to_chars_sub(buf, fmt::oct(nullptr)), "0o0"); -} - -TEST_CASE_TEMPLATE("to_chars.fmt.zpad.oct", T, uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t) -{ - char bufc[128]; - substr buf(bufc); - using namespace fmt; - CHECK_EQ(to_chars_sub(buf, zpad(integral(T(65), T(8)), 5u)), "0o00101"); - CHECK_EQ(to_chars_sub(buf, zpad(integral((T*)65, T(8)), 5u)), "0o00101"); - CHECK_EQ(to_chars_sub(buf, zpad(integral((T const*)65, T(8)), 5u)), "0o00101"); - CHECK_EQ(to_chars_sub(buf, zpad(oct(T(65)), 5u)), "0o00101"); - CHECK_EQ(to_chars_sub(buf, zpad(oct((T*)65), 5u)), "0o00101"); - CHECK_EQ(to_chars_sub(buf, zpad(oct((T const*)65), 5u)), "0o00101"); -} - -TEST_CASE_TEMPLATE("to_chars.fmt.hex", T, uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t) -{ - char bufc[128]; - substr buf(bufc); - CHECK_EQ(to_chars_sub(buf, fmt::integral(T(0x7f), T(16))), "0x7f"); - CHECK_EQ(to_chars_sub(buf, fmt::integral((T*)0x7f, T(16))), "0x7f"); - CHECK_EQ(to_chars_sub(buf, fmt::integral((T const*)0x7f, T(16))), "0x7f"); - CHECK_EQ(to_chars_sub(buf, fmt::integral(nullptr, T(16))), "0x0"); - CHECK_EQ(to_chars_sub(buf, fmt::hex(T(0x7f))), "0x7f"); - CHECK_EQ(to_chars_sub(buf, fmt::hex((T*)0x7f)), "0x7f"); - CHECK_EQ(to_chars_sub(buf, fmt::hex((T const*)0x7f)), "0x7f"); - CHECK_EQ(to_chars_sub(buf, fmt::hex(nullptr)), "0x0"); -} - -TEST_CASE_TEMPLATE("to_chars.fmt.zpad.hex", T, uint8_t, int8_t) -{ - char bufc[128]; - substr buf(bufc); - using namespace fmt; - buf.fill('?'); - CHECK_EQ(to_chars_sub(buf, zpad(integral(T(0x7f), T(16)), 5u)), "0x0007f"); - CHECK_EQ(to_chars_sub(buf, zpad(integral((T*)0x7f, T(16)), 5u)), "0x0007f"); - CHECK_EQ(to_chars_sub(buf, zpad(integral((T const*)0x7f, T(16)), 5u)), "0x0007f"); - CHECK_EQ(to_chars_sub(buf, zpad(hex(T(0x7f)), 5u)), "0x0007f"); - CHECK_EQ(to_chars_sub(buf, zpad(hex((T*)0x7f), 5u)), "0x0007f"); - CHECK_EQ(to_chars_sub(buf, zpad(hex((T const*)0x7f), 5u)), "0x0007f"); -} - - -TEST_CASE_TEMPLATE("to_chars.fmt.zpad", T, uint8_t, int8_t) -{ - char bufc[128]; - substr buf(bufc); - using namespace fmt; - CHECK_EQ(to_chars_sub(buf, zpad(T(10), 0)), "10"); - CHECK_EQ(to_chars_sub(buf, zpad(T(10), 1)), "10"); - CHECK_EQ(to_chars_sub(buf, zpad(T(10), 2)), "10"); - CHECK_EQ(to_chars_sub(buf, zpad(T(10), 3)), "010"); - CHECK_EQ(to_chars_sub(buf, zpad(T(10), 4)), "0010"); - CHECK_EQ(to_chars_sub(buf, zpad((T const*)17, 0)), "0x11"); - CHECK_EQ(to_chars_sub(buf, zpad((T const*)17, 1)), "0x11"); - CHECK_EQ(to_chars_sub(buf, zpad((T const*)17, 2)), "0x11"); - CHECK_EQ(to_chars_sub(buf, zpad((T const*)17, 3)), "0x011"); - CHECK_EQ(to_chars_sub(buf, zpad((T const*)17, 4)), "0x0011"); - CHECK_EQ(to_chars_sub(buf, zpad((T *)17, 0)), "0x11"); - CHECK_EQ(to_chars_sub(buf, zpad((T *)17, 1)), "0x11"); - CHECK_EQ(to_chars_sub(buf, zpad((T *)17, 2)), "0x11"); - CHECK_EQ(to_chars_sub(buf, zpad((T *)17, 3)), "0x011"); - CHECK_EQ(to_chars_sub(buf, zpad((T *)17, 4)), "0x0011"); - CHECK_EQ(to_chars_sub(buf, zpad(nullptr, 0)), "0x0"); - CHECK_EQ(to_chars_sub(buf, zpad(nullptr, 1)), "0x0"); - CHECK_EQ(to_chars_sub(buf, zpad(nullptr, 2)), "0x00"); - CHECK_EQ(to_chars_sub(buf, zpad(nullptr, 3)), "0x000"); - CHECK_EQ(to_chars_sub(buf, zpad(nullptr, 4)), "0x0000"); - CHECK_EQ(to_chars_sub(buf, zpad(integral(nullptr, T(10)), 0u)), "0"); - CHECK_EQ(to_chars_sub(buf, zpad(integral(nullptr, T(16)), 0u)), "0x0"); - CHECK_EQ(to_chars_sub(buf, zpad(integral(nullptr, T(2)), 0u)), "0b0"); - CHECK_EQ(to_chars_sub(buf, zpad(integral(nullptr, T(8)), 0u)), "0o0"); - CHECK_EQ(to_chars_sub(buf, zpad(hex(nullptr), 0u)), "0x0"); - CHECK_EQ(to_chars_sub(buf, zpad(bin(nullptr), 0u)), "0b0"); - CHECK_EQ(to_chars_sub(buf, zpad(oct(nullptr), 0u)), "0o0"); - CHECK_EQ(to_chars_sub(buf, zpad(integral(nullptr, T(10)), 5u)), "00000"); - CHECK_EQ(to_chars_sub(buf, zpad(integral(nullptr, T(16)), 5u)), "0x00000"); - CHECK_EQ(to_chars_sub(buf, zpad(integral(nullptr, T(2)), 5u)), "0b00000"); - CHECK_EQ(to_chars_sub(buf, zpad(integral(nullptr, T(8)), 5u)), "0o00000"); - CHECK_EQ(to_chars_sub(buf, zpad(hex(nullptr), 5u)), "0x00000"); - CHECK_EQ(to_chars_sub(buf, zpad(bin(nullptr), 5u)), "0b00000"); - CHECK_EQ(to_chars_sub(buf, zpad(oct(nullptr), 5u)), "0o00000"); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -template -void test_to_chars_real(T f, int precision, const char* flt, T fltv, const char *scient, T scientv) -{ - char bufc[64]; - substr buf(bufc); - substr r; - T copy; - - INFO("num=" << f); - - r = to_chars_sub(buf, fmt::real(f, precision)); - CHECK_EQ(r, to_csubstr(flt)); - from_chars(r, ©); - if(sizeof(T) == sizeof(float)) - { - CHECK_FLOAT_EQ((float)fltv, (float)copy); - } - else - { - CHECK_FLOAT_EQ(fltv, copy); - } - - r = to_chars_sub(buf, fmt::real(f, precision, FTOA_SCIENT)); - CHECK_EQ(r, to_csubstr(scient)); - from_chars(r, ©); - if(sizeof(T) == sizeof(float)) - { - CHECK_FLOAT_EQ((float)scientv, (float)copy); - } - else - { - CHECK_FLOAT_EQ(scientv, copy); - } -} - -TEST_CASE_TEMPLATE("to_chars.fmt.real", T, float, double) -{ - char bufc[128]; - substr buf(bufc); - - T f = static_cast(256.064); - test_to_chars_real(f, 0, "256", T(256.), "3e+02", T(300.)); - test_to_chars_real(f, 1, "256.1", T(256.1), "2.6e+02", T(260.)); - test_to_chars_real(f, 2, "256.06", T(256.06), "2.56e+02", T(256.)); - test_to_chars_real(f, 3, "256.064", T(256.064), "2.561e+02", T(256.1)); - test_to_chars_real(f, 4, "256.0640", T(256.0640), "2.5606e+02", T(256.06)); - test_to_chars_real(f, 5, "256.06400", T(256.06400), "2.56064e+02", T(256.064)); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -TEST_CASE("to_chars.fmt.boolalpha") -{ - char bufc[128]; - substr buf(bufc); - - CHECK_EQ(to_chars_sub(buf, true), "1"); - CHECK_EQ(to_chars_sub(buf, false), "0"); - CHECK_EQ(to_chars_sub(buf, fmt::boolalpha(true)), "true"); - CHECK_EQ(to_chars_sub(buf, 1), "1"); - CHECK_EQ(to_chars_sub(buf, fmt::boolalpha(1)), "true"); - CHECK_EQ(to_chars_sub(buf, fmt::boolalpha(10)), "true"); - CHECK_EQ(to_chars_sub(buf, fmt::boolalpha(false)), "false"); - CHECK_EQ(to_chars_sub(buf, fmt::boolalpha(0)), "false"); - CHECK_EQ(to_chars_sub(buf, fmt::boolalpha(0u)), "false"); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -TEST_CASE("align.left.overflow") -{ - CHECK_EQ(to_chars(substr(), fmt::left(' ', 91u)), 91u); - CHECK_EQ(to_chars(substr(), fmt::left("0123456789.123456789.123456789.123456789", 91u)), 91u); - CHECK_EQ(to_chars(substr(), fmt::left("0123456789.123456789.123456789.123456789", 30u)), 40u); -} - -TEST_CASE("align.right.overflow") -{ - CHECK_EQ(to_chars(substr(), fmt::right(' ', 91u)), 91u); - CHECK_EQ(to_chars(substr(), fmt::right("0123456789.123456789.123456789.123456789", 91u)), 91u); - CHECK_EQ(to_chars(substr(), fmt::right("0123456789.123456789.123456789.123456789", 30u)), 40u); -} - -TEST_CASE("align.left") -{ - char buf[128] = {}; - CHECK_EQ(to_chars_sub(buf, fmt::left("1", 1)), "1"); - CHECK_EQ(to_chars_sub(buf, fmt::left("1", 2)), "1 "); - CHECK_EQ(to_chars_sub(buf, fmt::left("1", 3)), "1 "); - CHECK_EQ(to_chars_sub(buf, fmt::left("1", 4)), "1 "); - CHECK_EQ(to_chars_sub(buf, fmt::left("1", 5)), "1 "); - CHECK_EQ(to_chars_sub(buf, fmt::left("1", 6)), "1 "); - CHECK_EQ(to_chars_sub(buf, fmt::left("1", 7)), "1 "); - CHECK_EQ(to_chars_sub(buf, fmt::left("1", 8)), "1 "); - CHECK_EQ(to_chars_sub(buf, fmt::left("1", 9)), "1 "); - - CHECK_EQ(to_chars_sub(buf, fmt::left("1", 1, '+')), "1"); - CHECK_EQ(to_chars_sub(buf, fmt::left("1", 2, '+')), "1+"); - CHECK_EQ(to_chars_sub(buf, fmt::left("1", 3, '+')), "1++"); - CHECK_EQ(to_chars_sub(buf, fmt::left("1", 4, '+')), "1+++"); - CHECK_EQ(to_chars_sub(buf, fmt::left("1", 5, '+')), "1++++"); - CHECK_EQ(to_chars_sub(buf, fmt::left("1", 6, '+')), "1+++++"); - CHECK_EQ(to_chars_sub(buf, fmt::left("1", 7, '+')), "1++++++"); - CHECK_EQ(to_chars_sub(buf, fmt::left("1", 8, '+')), "1+++++++"); - CHECK_EQ(to_chars_sub(buf, fmt::left("1", 9, '+')), "1++++++++"); - - CHECK_EQ(to_chars_sub(buf, fmt::left("01234", 0)), "01234"); - CHECK_EQ(to_chars_sub(buf, fmt::left("01234", 1)), "01234"); - CHECK_EQ(to_chars_sub(buf, fmt::left("01234", 2)), "01234"); - CHECK_EQ(to_chars_sub(buf, fmt::left("01234", 3)), "01234"); - CHECK_EQ(to_chars_sub(buf, fmt::left("01234", 4)), "01234"); - CHECK_EQ(to_chars_sub(buf, fmt::left("01234", 5)), "01234"); - CHECK_EQ(to_chars_sub(buf, fmt::left("01234", 6)), "01234 "); - CHECK_EQ(to_chars_sub(buf, fmt::left("01234", 7)), "01234 "); - CHECK_EQ(to_chars_sub(buf, fmt::left("01234", 8)), "01234 "); - CHECK_EQ(to_chars_sub(buf, fmt::left("01234", 9)), "01234 "); - - CHECK_EQ(to_chars_sub(buf, fmt::left(1234, 0)), "1234"); - CHECK_EQ(to_chars_sub(buf, fmt::left(1234, 1)), "1234"); - CHECK_EQ(to_chars_sub(buf, fmt::left(1234, 2)), "1234"); - CHECK_EQ(to_chars_sub(buf, fmt::left(1234, 3)), "1234"); - CHECK_EQ(to_chars_sub(buf, fmt::left(1234, 4)), "1234"); - CHECK_EQ(to_chars_sub(buf, fmt::left(1234, 5)), "1234 "); - CHECK_EQ(to_chars_sub(buf, fmt::left(1234, 6)), "1234 "); - CHECK_EQ(to_chars_sub(buf, fmt::left(1234, 7)), "1234 "); - CHECK_EQ(to_chars_sub(buf, fmt::left(1234, 8)), "1234 "); - CHECK_EQ(to_chars_sub(buf, fmt::left(1234, 9)), "1234 "); -} - - -TEST_CASE("align.right") -{ - char buf[128] = {}; - CHECK_EQ(to_chars_sub(buf, fmt::right("1", 1)), "1"); - CHECK_EQ(to_chars_sub(buf, fmt::right("1", 2)), " 1"); - CHECK_EQ(to_chars_sub(buf, fmt::right("1", 3)), " 1"); - CHECK_EQ(to_chars_sub(buf, fmt::right("1", 4)), " 1"); - CHECK_EQ(to_chars_sub(buf, fmt::right("1", 5)), " 1"); - CHECK_EQ(to_chars_sub(buf, fmt::right("1", 6)), " 1"); - CHECK_EQ(to_chars_sub(buf, fmt::right("1", 7)), " 1"); - CHECK_EQ(to_chars_sub(buf, fmt::right("1", 8)), " 1"); - CHECK_EQ(to_chars_sub(buf, fmt::right("1", 9)), " 1"); - - CHECK_EQ(to_chars_sub(buf, fmt::right("1", 1, '+')), "1"); - CHECK_EQ(to_chars_sub(buf, fmt::right("1", 2, '+')), "+1"); - CHECK_EQ(to_chars_sub(buf, fmt::right("1", 3, '+')), "++1"); - CHECK_EQ(to_chars_sub(buf, fmt::right("1", 4, '+')), "+++1"); - CHECK_EQ(to_chars_sub(buf, fmt::right("1", 5, '+')), "++++1"); - CHECK_EQ(to_chars_sub(buf, fmt::right("1", 6, '+')), "+++++1"); - CHECK_EQ(to_chars_sub(buf, fmt::right("1", 7, '+')), "++++++1"); - CHECK_EQ(to_chars_sub(buf, fmt::right("1", 8, '+')), "+++++++1"); - CHECK_EQ(to_chars_sub(buf, fmt::right("1", 9, '+')), "++++++++1"); - - CHECK_EQ(to_chars_sub(buf, fmt::right("01234", 0)), "01234"); - CHECK_EQ(to_chars_sub(buf, fmt::right("01234", 1)), "01234"); - CHECK_EQ(to_chars_sub(buf, fmt::right("01234", 2)), "01234"); - CHECK_EQ(to_chars_sub(buf, fmt::right("01234", 3)), "01234"); - CHECK_EQ(to_chars_sub(buf, fmt::right("01234", 4)), "01234"); - CHECK_EQ(to_chars_sub(buf, fmt::right("01234", 5)), "01234"); - CHECK_EQ(to_chars_sub(buf, fmt::right("01234", 6)), " 01234"); - CHECK_EQ(to_chars_sub(buf, fmt::right("01234", 7)), " 01234"); - CHECK_EQ(to_chars_sub(buf, fmt::right("01234", 8)), " 01234"); - CHECK_EQ(to_chars_sub(buf, fmt::right("01234", 9)), " 01234"); - - CHECK_EQ(to_chars_sub(buf, fmt::right(1234, 0)), "1234"); - CHECK_EQ(to_chars_sub(buf, fmt::right(1234, 1)), "1234"); - CHECK_EQ(to_chars_sub(buf, fmt::right(1234, 2)), "1234"); - CHECK_EQ(to_chars_sub(buf, fmt::right(1234, 3)), "1234"); - CHECK_EQ(to_chars_sub(buf, fmt::right(1234, 4)), "1234"); - CHECK_EQ(to_chars_sub(buf, fmt::right(1234, 5)), " 1234"); - CHECK_EQ(to_chars_sub(buf, fmt::right(1234, 6)), " 1234"); - CHECK_EQ(to_chars_sub(buf, fmt::right(1234, 7)), " 1234"); - CHECK_EQ(to_chars_sub(buf, fmt::right(1234, 8)), " 1234"); - CHECK_EQ(to_chars_sub(buf, fmt::right(1234, 9)), " 1234"); - - CHECK_EQ(to_chars_sub(buf, fmt::real(0.124, 1)), "0.1"); // we assume this in what follows - CHECK_EQ(to_chars_sub(buf, fmt::real(0.124, 2)), "0.12"); - CHECK_EQ(to_chars_sub(buf, fmt::real(0.124, 3)), "0.124"); - CHECK_EQ(to_chars_sub(buf, fmt::right(fmt::real(0.124, 1), 0)), "0.1"); - CHECK_EQ(to_chars_sub(buf, fmt::right(fmt::real(0.124, 1), 1)), "0.1"); - CHECK_EQ(to_chars_sub(buf, fmt::right(fmt::real(0.124, 1), 2)), "0.1"); - CHECK_EQ(to_chars_sub(buf, fmt::right(fmt::real(0.124, 1), 3)), "0.1"); - CHECK_EQ(to_chars_sub(buf, fmt::right(fmt::real(0.124, 1), 4)), " 0.1"); - CHECK_EQ(to_chars_sub(buf, fmt::right(fmt::real(0.124, 1), 5)), " 0.1"); - CHECK_EQ(to_chars_sub(buf, fmt::right(fmt::real(0.124, 1), 6)), " 0.1"); - CHECK_EQ(to_chars_sub(buf, fmt::right(fmt::real(0.124, 1), 7)), " 0.1"); - CHECK_EQ(to_chars_sub(buf, fmt::right(fmt::real(0.124, 2), 0)), "0.12"); - CHECK_EQ(to_chars_sub(buf, fmt::right(fmt::real(0.124, 2), 1)), "0.12"); - CHECK_EQ(to_chars_sub(buf, fmt::right(fmt::real(0.124, 2), 2)), "0.12"); - CHECK_EQ(to_chars_sub(buf, fmt::right(fmt::real(0.124, 2), 3)), "0.12"); - CHECK_EQ(to_chars_sub(buf, fmt::right(fmt::real(0.124, 2), 4)), "0.12"); - CHECK_EQ(to_chars_sub(buf, fmt::right(fmt::real(0.124, 2), 5)), " 0.12"); - CHECK_EQ(to_chars_sub(buf, fmt::right(fmt::real(0.124, 2), 6)), " 0.12"); - CHECK_EQ(to_chars_sub(buf, fmt::right(fmt::real(0.124, 2), 7)), " 0.12"); - CHECK_EQ(to_chars_sub(buf, fmt::right(fmt::real(0.124, 3), 0)), "0.124"); - CHECK_EQ(to_chars_sub(buf, fmt::right(fmt::real(0.124, 3), 1)), "0.124"); - CHECK_EQ(to_chars_sub(buf, fmt::right(fmt::real(0.124, 3), 2)), "0.124"); - CHECK_EQ(to_chars_sub(buf, fmt::right(fmt::real(0.124, 3), 3)), "0.124"); - CHECK_EQ(to_chars_sub(buf, fmt::right(fmt::real(0.124, 3), 4)), "0.124"); - CHECK_EQ(to_chars_sub(buf, fmt::right(fmt::real(0.124, 3), 5)), "0.124"); - CHECK_EQ(to_chars_sub(buf, fmt::right(fmt::real(0.124, 3), 6)), " 0.124"); - CHECK_EQ(to_chars_sub(buf, fmt::right(fmt::real(0.124, 3), 7)), " 0.124"); - - CHECK_EQ(to_chars_sub(buf, fmt::right(fmt::real(1234.5222, 1), 7)), " 1234.5"); - auto r = [](double val, size_t width) { return fmt::right(fmt::real(val, 1), width); }; - CHECK_EQ(to_chars_sub(buf, r(1234.5, 7)), " 1234.5"); - c4::format(buf, "freq={}Hz\0", r(1234.5, 7)); - CHECK_EQ(to_csubstr(buf).len, to_csubstr("freq= 1234.5Hz").len); - CHECK_EQ(to_csubstr(buf), "freq= 1234.5Hz"); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -TEST_CASE("cat.vars") -{ - char buf[256]; - substr sp(buf); - csubstr result; - size_t sz; - - sz = cat(buf, 1, ' ', 2, ' ', 3, ' ', 4); - result = sp.left_of(sz); - CHECK_EQ(result, "1 2 3 4"); -} - -#ifdef C4_TUPLE_TO_STR -TEST_CASE("cat.tuple") -{ - char buf[256]; - substr sp(buf); - csubstr result; - size_t sz; - - sz = cat(buf, std::forward_as_tuple(1, ' ', 2, ' ', 3, ' ', 4)); - result = sp.left_of(sz); - CHECK_EQ(result, "1 2 3 4"); -} -#endif // C4_TUPLE_TO_STR - -TEST_CASE("uncat.vars") -{ - size_t sz; - size_t npos = csubstr::npos; - int v1 = 0, v2 = 0, v3 = 0, v4 = 0; - - sz = uncat("1 2 3 4", v1, v2, v3, v4); - CHECK_NE(sz, npos); - CHECK_EQ(sz, 7); - CHECK_EQ(v1, 1); - CHECK_EQ(v2, 2); - CHECK_EQ(v3, 3); - CHECK_EQ(v4, 4); -} - -#ifdef C4_TUPLE_TO_STR -TEST_CASE("uncat.tuple") -{ - size_t sz; - int v1 = 0, v2 = 0, v3 = 0, v4 = 0; - - auto tp = std::forward_as_tuple(v1, v2, v3, v4); - sz = uncat("1 2 3 4", tp); - CHECK_NE(sz, csubstr::npos); - CHECK_EQ(sz, 7); - CHECK_EQ(v1, 1); - CHECK_EQ(v2, 2); - CHECK_EQ(v3, 3); - CHECK_EQ(v4, 4); -} -#endif // C4_TUPLE_TO_STR - - -TEST_CASE("catsep.vars") -{ - char buf[256]; - substr sp(buf); - csubstr result; - size_t sz; - - sz = catsep(buf, ' ', 1, 2); - CHECK_EQ(sz, 3); - result = sp.left_of(sz); - CHECK_EQ(result, "1 2"); - - sz = catsep(buf, '/', 1, 2); - CHECK_EQ(sz, 3); - result = sp.left_of(sz); - CHECK_EQ(result, "1/2"); - - sz = catsep(buf, ' ', 1, 2, 3, 4); - CHECK_EQ(sz, 7); - result = sp.left_of(sz); - CHECK_EQ(result, "1 2 3 4"); - - sz = catsep(buf, '/', 1, 2, 3, 4); - CHECK_EQ(sz, 7); - result = sp.left_of(sz); - CHECK_EQ(result, "1/2/3/4"); -} - -#ifdef C4_TUPLE_TO_STR -TEST_CASE("catsep.tuple") -{ - char buf[256]; - substr sp(buf); - csubstr result; - size_t sz; - - sz = catsep(buf, ' ', std::forward_as_tuple(1, 2)); - CHECK_EQ(sz, 3); - result = sp.left_of(sz); - CHECK_EQ(result, "1 2"); - - sz = catsep(buf, '/', std::forward_as_tuple(1, 2)); - CHECK_EQ(sz, 3); - result = sp.left_of(sz); - CHECK_EQ(result, "1/2"); - - sz = catsep(buf, ' ', std::forward_as_tuple(1, 2, 3, 4)); - CHECK_EQ(sz, 7); - result = sp.left_of(sz); - CHECK_EQ(result, "1 2 3 4"); - - sz = catsep(buf, '/', std::forward_as_tuple(1, 2, 3, 4)); - CHECK_EQ(sz, 7); - result = sp.left_of(sz); - CHECK_EQ(result, "1/2/3/4"); -} -#endif // C4_TUPLE_TO_STR - -TEST_CASE("uncatsep.vars") -{ - size_t sz; - int v1 = 0, v2 = 0, v3 = 0, v4 = 0; - char sep; - - sz = uncatsep("1 2 3 4", sep, v1, v2, v3, v4); - CHECK_EQ(sz, 7); - CHECK_EQ(v1, 1); - CHECK_EQ(v2, 2); - CHECK_EQ(v3, 3); - CHECK_EQ(v4, 4); -} - -#ifdef C4_TUPLE_TO_STR -TEST_CASE("uncatsep.tuple") -{ - size_t sz; - int v1 = 0, v2 = 0, v3 = 0, v4 = 0; - char sep; - - auto tp = std::forward_as_tuple(v1, v2, v3, v4); - sz = uncatsep("1 2 3 4", sep, tp); - CHECK_EQ(sz, 7); - CHECK_EQ(v1, 1); - CHECK_EQ(v2, 2); - CHECK_EQ(v3, 3); - CHECK_EQ(v4, 4); -} -#endif // C4_TUPLE_TO_STR - -TEST_CASE("format.vars") -{ - char buf[256]; - substr sp(buf); - csubstr result; - size_t sz; - - sz = format(buf, "{} and {} and {} and {}", 1, 2, 3, 4); - CHECK_EQ(sz, strlen("1 and 2 and 3 and 4")); - result = sp.left_of(sz); - CHECK_EQ(result, "1 and 2 and 3 and 4"); - - sz = format(buf, "{} and {} and {} and {}", 1, 2, 3, 4, 5, 6, 7); - CHECK_EQ(sz, 19); - result = sp.left_of(sz); - CHECK_EQ(result, "1 and 2 and 3 and 4"); - - sz = format(buf, "{} and {} and {} and {}", 1, 2, 3); - CHECK_EQ(sz, 20); - result = sp.left_of(sz); - CHECK_EQ(result, "1 and 2 and 3 and {}"); - - sz = format(buf, "{} and {} and {} and {}", 1, 2); - CHECK_EQ(sz, 21); - result = sp.left_of(sz); - CHECK_EQ(result, "1 and 2 and {} and {}"); - - sz = format(buf, "{} and {} and {} and {}", 1); - CHECK_EQ(sz, 22); - result = sp.left_of(sz); - CHECK_EQ(result, "1 and {} and {} and {}"); - - sz = format(buf, "{} and {} and {} and {}"); - CHECK_EQ(sz, 23); - result = sp.left_of(sz); - CHECK_EQ(result, "{} and {} and {} and {}"); - - sz = format(buf, "{} args only at the begin", 1); - CHECK_EQ(sz, csubstr("1 args only at the begin").len); - result = sp.left_of(sz); - CHECK_EQ(result, csubstr("1 args only at the begin")); -} - -TEST_CASE("format.empty_buffer") -{ - size_t sz = format({}, "{} and {} and {} and {}", 1, 2, 3, 4); - CHECK_EQ(sz, strlen("1 and 2 and 3 and 4")); - char buf_[128]; - substr buf = buf_; - sz = format(buf, "{} and {} and {} and {}", 1, 2, 3, 4); - CHECK_EQ(sz, strlen("1 and 2 and 3 and 4")); - CHECK_EQ(format(buf, "{} and {} and {} and {}", 1, 2, 3, 4), - format({} , "{} and {} and {} and {}", 1, 2, 3, 4)); - CHECK_EQ(to_chars({}, 101), to_chars(buf, 101)); // eq for all integers - CHECK_GE(to_chars({}, 0.1f), to_chars(buf, 0.1f)); // ge for all floats, due to a sprintf quirk - CHECK_EQ(format(buf, "a={} foo {} {} bar {}", 101, 10, 11, 12), - format({} , "a={} foo {} {} bar {}", 101, 10, 11, 12)); -} - -#ifdef C4_TUPLE_TO_STR -TEST_CASE("format.tuple") -{ - char buf[256]; - substr sp(buf); - csubstr result; - size_t sz; - - sz = format(buf, "{} and {} and {} and {}", std::forward_as_tuple(1, 2, 3, 4)); - CHECK_EQ(sz, 19); - result = sp.left_of(sz); - CHECK_EQ(result, "1 and 2 and 3 and 4"); - - sz = format(buf, "{} and {} and {} and {}", std::forward_as_tuple(1, 2, 3, 4, 5, 6, 7)); - CHECK_EQ(sz, 19); - result = sp.left_of(sz); - CHECK_EQ(result, "1 and 2 and 3 and 4"); - - sz = format(buf, "{} and {} and {} and {}", std::forward_as_tuple(1, 2, 3)); - CHECK_EQ(sz, 20); - result = sp.left_of(sz); - CHECK_EQ(result, "1 and 2 and 3 and {}"); - - sz = format(buf, "{} and {} and {} and {}", std::forward_as_tuple(1, 2)); - CHECK_EQ(sz, 21); - result = sp.left_of(sz); - CHECK_EQ(result, "1 and 2 and {} and {}"); - - sz = format(buf, "{} and {} and {} and {}", std::forward_as_tuple(1)); - CHECK_EQ(sz, 22); - result = sp.left_of(sz); - CHECK_EQ(result, "1 and {} and {} and {}"); - - sz = format(buf, "{} and {} and {} and {}"); - CHECK_EQ(sz, 23); - result = sp.left_of(sz); - CHECK_EQ(result, "{} and {} and {} and {}"); -} -#endif // C4_TUPLE_TO_STR - -TEST_CASE("unformat.vars") -{ - size_t sz; - int v1 = 0, v2 = 0, v3 = 0, v4 = 0; - - sz = unformat("1 and 2 and 3 and 4", "{} and {} and {} and {}", v1, v2, v3, v4); - CHECK_EQ(sz, 19); - CHECK_EQ(v1, 1); - CHECK_EQ(v2, 2); - CHECK_EQ(v3, 3); - CHECK_EQ(v4, 4); - - v1 = 0; - sz = unformat("1 and 2 and 3 and 4" , "3", v1); - CHECK_EQ(sz, 1); - CHECK_EQ(v1, 0); - - v1 = 0; - sz = unformat("1,2,3,,,", "{},{},{}", v1, v2, v3); - CHECK_EQ(sz, 5); - CHECK_EQ(v1, 1); - CHECK_EQ(v2, 2); - CHECK_EQ(v3, 3); - - v1 = v2 = v3 = 0; - sz = unformat("1,2,3,,,", "{},{},{},,,", v1, v2, v3); - CHECK_EQ(sz, 8); // make sure we count the trailing characters in the format - CHECK_EQ(v1, 1); - CHECK_EQ(v2, 2); - CHECK_EQ(v3, 3); -} - -#ifdef C4_TUPLE_TO_STR -TEST_CASE("unformat.tuple") -{ - size_t sz; - int v1 = 0, v2 = 0, v3 = 0, v4 = 0; - - auto tp = std::forward_as_tuple(v1, v2, v3, v4); - sz = unformat("1 and 2 and 3 and 4", "{} and {} and {} and {}", tp); - CHECK_EQ(sz, 19); - CHECK_EQ(v1, 1); - CHECK_EQ(v2, 2); - CHECK_EQ(v3, 3); - CHECK_EQ(v4, 4); -} -#endif // C4_TUPLE_TO_STR - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -TEST_CASE("catrs.basic") -{ - std::vector buf; - - catrs(&buf); - CHECK_EQ(to_csubstr(buf), ""); - - catrs(&buf, 1, 2, 3, 4); - CHECK_EQ(to_csubstr(buf), "1234"); - catrs(&buf, 5, 6, 7, 8); - CHECK_EQ(to_csubstr(buf), "5678"); -} - -TEST_CASE("catrs.basic_return") -{ - auto bufv = catrs>(9, 8, 7, 6, 5, 4, 3, 2, 1, 0); - CHECK_EQ(to_csubstr(bufv), "9876543210"); - bufv = catrs>(); - CHECK_EQ(to_csubstr(bufv), ""); - CHECK(bufv.empty()); - - auto bufs = catrs(9, 8, 7, 6, 5, 4, 3, 2, 1, 0); - CHECK_EQ(to_csubstr(bufs), "9876543210"); -} - -TEST_CASE("catrs.basic_append") -{ - std::vector buf; - - catrs(append, &buf); - CHECK_EQ(to_csubstr(buf), ""); - - catrs(append, &buf, 1, 2, 3, 4); - CHECK_EQ(to_csubstr(buf), "1234"); - catrs(append, &buf, 5, 6, 7, 8); - CHECK_EQ(to_csubstr(buf), "12345678"); - catrs(append, &buf, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8); - CHECK_EQ(to_csubstr(buf), "123456789012345678"); -} - -template -void catrs_perfect_fwd(Args && ...args) -{ - catrs(std::forward(args)...); -} - -TEST_CASE("catrs.perfect_fwd") -{ - std::vector buf; - catrs_perfect_fwd(&buf, 1, 2, 3, 4); - CHECK_EQ(to_csubstr(buf), "1234"); - catrs_perfect_fwd(&buf, 5, 6, 7, 8); - CHECK_EQ(to_csubstr(buf), "5678"); -} - -template -void catrs_const_fwd(Args const& ...args) -{ - catrs(args...); -} - -TEST_CASE("catrs.const_fwd") -{ - std::vector buf; - catrs_const_fwd(&buf, 1, 2, 3, 4); - CHECK_EQ(to_csubstr(buf), "1234"); - catrs_const_fwd(&buf, 5, 6, 7, 8); - CHECK_EQ(to_csubstr(buf), "5678"); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -TEST_CASE("catseprs.basic") -{ - std::vector buf; - - catseprs(&buf, ' '); - CHECK_EQ(to_csubstr(buf), ""); - - catseprs(&buf, ' ', 1, 2, 3, 4); - CHECK_EQ(to_csubstr(buf), "1 2 3 4"); - catseprs(&buf, ' ', 5, 6, 7, 8); - CHECK_EQ(to_csubstr(buf), "5 6 7 8"); - - catseprs(&buf, ',', 1, 2, 3, 4); - CHECK_EQ(to_csubstr(buf), "1,2,3,4"); - catseprs(&buf, ',', 5, 6, 7, 8); - CHECK_EQ(to_csubstr(buf), "5,6,7,8"); - - catseprs(&buf, '/', 1, 2, 3, 4); - CHECK_EQ(to_csubstr(buf), "1/2/3/4"); - catseprs(&buf, '/', 5, 6, 7, 8); - CHECK_EQ(to_csubstr(buf), "5/6/7/8"); - - catseprs(&buf, "///", 1, 2, 3, 4); - CHECK_EQ(to_csubstr(buf), "1///2///3///4"); - catseprs(&buf, "///", 5, 6, 7, 8); - CHECK_EQ(to_csubstr(buf), "5///6///7///8"); - - catseprs(&buf, 5678, 1, 2, 3, 4); - CHECK_EQ(to_csubstr(buf), "1567825678356784"); - catseprs(&buf, 1234, 5, 6, 7, 8); - CHECK_EQ(to_csubstr(buf), "5123461234712348"); -} - -TEST_CASE("catseprs.basic_return") -{ - auto bufv = catseprs>('a', 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); - CHECK_EQ(to_csubstr(bufv), "9a8a7a6a5a4a3a2a1a0"); - - auto bufs = catseprs('a', 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); - CHECK_EQ(to_csubstr(bufs), "9a8a7a6a5a4a3a2a1a0"); -} - -TEST_CASE("catseprs.basic_append") -{ - std::vector buf; - - auto ret = catseprs(append, &buf, ' '); - CHECK_EQ(to_csubstr(buf), ""); - CHECK_EQ(ret, ""); - - ret = catseprs(append, &buf, ' ', 1, 2, 3, 4); - CHECK_EQ(to_csubstr(buf), "1 2 3 4"); - CHECK_EQ(ret, "1 2 3 4"); - ret = catseprs(append, &buf, ' ', 5, 6, 7, 8); - CHECK_EQ(to_csubstr(buf), "1 2 3 45 6 7 8"); - CHECK_EQ(ret, "5 6 7 8"); - ret = catseprs(append, &buf, ' ', 9, 0, 1, 2, 3, 4, 5, 6, 7, 8); - CHECK_EQ(to_csubstr(buf), "1 2 3 45 6 7 89 0 1 2 3 4 5 6 7 8"); - CHECK_EQ(ret, "9 0 1 2 3 4 5 6 7 8"); - - ret = catseprs(append, &buf, ' '); - CHECK_EQ(to_csubstr(buf), "1 2 3 45 6 7 89 0 1 2 3 4 5 6 7 8"); - CHECK_EQ(ret, ""); -} - -template -void catseprs_perfect_fwd(Args && ...args) -{ - catseprs(std::forward(args)...); -} - -template -void catseprs_const_fwd(Args const& ...args) -{ - catseprs(args...); -} - -TEST_CASE("catseprs.perfect_fwd") -{ - std::vector buf; - catseprs_perfect_fwd(&buf, '.', 1, 2, 3, 4); - CHECK_EQ(to_csubstr(buf), "1.2.3.4"); - catseprs_perfect_fwd(&buf, 0, 5, 6, 7, 8); - CHECK_EQ(to_csubstr(buf), "5060708"); -} - -TEST_CASE("catseprs.const_fwd") -{ - std::vector buf; - catseprs_const_fwd(&buf, '.', 1, 2, 3, 4); - CHECK_EQ(to_csubstr(buf), "1.2.3.4"); - catseprs_const_fwd(&buf, 0, 5, 6, 7, 8); - CHECK_EQ(to_csubstr(buf), "5060708"); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -TEST_CASE("formatrs.basic") -{ - std::vector buf; - - formatrs(&buf, ""); - CHECK(buf.empty()); - - formatrs(&buf, "{} goes with food, {} goes with heat, {} anytime", "wine", "beer", "coffee"); - CHECK_EQ(to_csubstr(buf), "wine goes with food, beer goes with heat, coffee anytime"); - - formatrs(&buf, ""); - CHECK(buf.empty()); -} - -TEST_CASE("formatrs.basic_return") -{ - auto bufv = formatrs>("{} goes with food, {} goes with heat, {} anytime", "wine", "beer", "coffee"); - CHECK_EQ(to_csubstr(bufv), "wine goes with food, beer goes with heat, coffee anytime"); - - auto bufs = formatrs("{} goes with food, {} goes with heat, {} anytime", "wine", "beer", "coffee"); - CHECK_EQ(to_csubstr(bufs), "wine goes with food, beer goes with heat, coffee anytime"); -} - -TEST_CASE("formatrs.basic_append") -{ - std::vector buf; - - formatrs(append, &buf, "{} goes with food", "wine"); - CHECK_EQ(to_csubstr(buf), "wine goes with food"); - formatrs(append, &buf, ", {} goes with heat", "beer"); - CHECK_EQ(to_csubstr(buf), "wine goes with food, beer goes with heat"); - formatrs(append, &buf, ", {} anytime", "coffee"); - CHECK_EQ(to_csubstr(buf), "wine goes with food, beer goes with heat, coffee anytime"); - - formatrs(append, &buf, ". And water. {} glass of {}cl in the morning clears you up for the day", 1, 40); - CHECK_EQ(to_csubstr(buf), "wine goes with food, beer goes with heat, coffee anytime. And water. 1 glass of 40cl in the morning clears you up for the day"); -} - -template -void formatrs_perfect_fwd(Args && ...args) -{ - formatrs(std::forward(args)...); -} - -template -void formatrs_const_fwd(Args const& ...args) -{ - formatrs(args...); -} - -TEST_CASE("formatrs.perfect_fwd") -{ - std::vector buf; - formatrs_perfect_fwd(&buf, "Too much of anything is bad, but too much {} is {}.", "Champagne", "just right"); - CHECK_EQ(to_csubstr(buf), "Too much of anything is bad, but too much Champagne is just right."); - formatrs_perfect_fwd(&buf, "{}, I am tasting the {}", "Come quickly", "stars!"); - CHECK_EQ(to_csubstr(buf), "Come quickly, I am tasting the stars!"); - formatrs_perfect_fwd(&buf, "{} the only wine that leaves a {} {} after {}.", "Champagne is", "woman", "beautiful", "drinking it"); - CHECK_EQ(to_csubstr(buf), "Champagne is the only wine that leaves a woman beautiful after drinking it."); - formatrs_perfect_fwd(&buf, "Remember {}, it's not just {} we are fighting for, it's {}", "gentlemen", "France", "Champagne!"); - CHECK_EQ(to_csubstr(buf), "Remember gentlemen, it's not just France we are fighting for, it's Champagne!"); - // https://www.townandcountrymag.com/leisure/drinks/how-to/g828/the-10-best-quotes-about-champagne/ -} - -TEST_CASE("formatrs.const_fwd") -{ - std::vector buf; - formatrs_const_fwd(&buf, "Too much of anything is bad, but too much {} is {}.", "Champagne", "just right"); - CHECK_EQ(to_csubstr(buf), "Too much of anything is bad, but too much Champagne is just right."); - formatrs_const_fwd(&buf, "{}, I am tasting the {}", "Come quickly", "stars!"); - CHECK_EQ(to_csubstr(buf), "Come quickly, I am tasting the stars!"); - formatrs_const_fwd(&buf, "{} the only wine that leaves a {} {} after {}.", "Champagne is", "woman", "beautiful", "drinking it"); - CHECK_EQ(to_csubstr(buf), "Champagne is the only wine that leaves a woman beautiful after drinking it."); - formatrs_const_fwd(&buf, "Remember {}, it's not just {} we are fighting for, it's {}", "gentlemen", "France", "Champagne!"); - CHECK_EQ(to_csubstr(buf), "Remember gentlemen, it's not just France we are fighting for, it's Champagne!"); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -template -void test_hex(T in, csubstr expected) -{ - INFO("expected=" << expected); - SUBCASE("charbuf") - { - char buf_[128] = {}; - substr buf = buf_; - buf.fill('?'); // this will be executed before each case - SUBCASE("sz=0") - { - CHECK_EQ(cat(buf.first(0), fmt::hex(in)), expected.len); - CHECK_EQ(buf[0], '?'); - CHECK_EQ(buf.trimr('?'), ""); - } - SUBCASE("sz=1") - { - CHECK_EQ(cat(buf.first(1), fmt::hex(in)), expected.len); - CHECK_EQ(buf[0], '?'); - CHECK_EQ(buf.trimr('?'), ""); - } - SUBCASE("sz=2") - { - CHECK_EQ(cat(buf.first(2), fmt::hex(in)), expected.len); - CHECK_EQ(buf[0], '?'); - CHECK_EQ(buf.trimr('?'), ""); - } - SUBCASE("full") - { - REQUIRE_EQ(cat(buf, fmt::hex(in)), expected.len); - CHECK_EQ(buf.first(expected.len), expected); - CHECK_EQ(buf.trimr('?'), expected); - } - } - SUBCASE("vector") - { - std::vector buf; - catrs(&buf, fmt::hex(in)); - CHECK_EQ(buf.size(), expected.len); - CHECK_EQ(to_csubstr(buf), expected); - } -} - -TEST_CASE("fmt.hex") -{ - test_hex(0, "0x0"); - test_hex(nullptr, "0x0"); - test_hex(254, "0xfe"); - test_hex(255, "0xff"); - test_hex(256, "0x100"); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -template void test_raw_roundtrip(const char *valstr, T const& orig) -{ - INFO("valstr=" << valstr); - alignas(alignof(T)) char buf_[2 * (sizeof(T) + alignof(T))] = {}; - substr buf = buf_; - - fmt::const_raw_wrapper rawwrap = fmt::raw(orig); - REQUIRE_EQ((void*)rawwrap.buf, (void*)&orig); - REQUIRE_EQ(rawwrap.len, sizeof(orig)); - - for(size_t i = 0; i < alignof(T); ++i) - { - INFO(" i=" << i); - // make sure to cover unaligned buffers - substr sbuf = buf.sub(i); - size_t szwrite = c4::to_chars(sbuf, fmt::raw(orig)); - REQUIRE_LE(szwrite, sbuf.len); - if(i == 0) - { - REQUIRE_EQ(szwrite, sizeof(T)); - } - else - { - REQUIRE_GT(szwrite, sizeof(T)); - } - T copy = {}; - REQUIRE_NE(copy, orig); - bool ok = c4::from_chars_first(sbuf, fmt::raw(copy)); - REQUIRE_EQ(ok, true); - CHECK_EQ(copy, orig); - - // cover also insufficient buffers - sbuf = sbuf.first(sizeof(T)-1); - memset(buf.str, 0, buf.len); - szwrite = c4::to_chars(sbuf, fmt::raw(orig)); - REQUIRE_GT(szwrite, sbuf.len); - for(char c : buf) - { - CHECK_EQ(c, 0); - } - } -} - -TEST_CASE("fmt.raw_int") -{ - #define _(v) test_raw_roundtrip(#v, v) - - _(int(1)); - _(int(2)); - _(int(-1)); - _(int(-2)); - - #undef _ -} - -} // namespace c4 - -#ifdef __clang__ -# pragma clang diagnostic pop -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#endif - -#include "c4/libtest/supprwarn_pop.hpp" diff --git a/thirdparty/ryml/ext/c4core/test/test_log.cpp b/thirdparty/ryml/ext/c4core/test/test_log.cpp deleted file mode 100644 index 2f5b56734..000000000 --- a/thirdparty/ryml/ext/c4core/test/test_log.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#include "c4/log.hpp" - -#include "c4/libtest/supprwarn_push.hpp" -#include "c4/test.hpp" - -namespace c4 { - -TEST(LogBuffer, basic) -{ -#define _CHECK(s, str) \ - EXPECT_EQ(strncmp(s.rd(), str, s.pos), 0) << " string was '" << s.rd() << "'"; \ - s.clear(); \ - EXPECT_EQ(s.pos, 0);\ - EXPECT_EQ(s.buf[0], '\0') - - LogBuffer b; - const char *foo = "Foo"; - const char *bars_str = "123"; - int bars = 123; - - // raw writing - b.write("hello world I am "); - b.write(foo); - b.write(" and I frobnicate "); - b.write(bars_str); // only accepts const char* - b.write(" Bars"); - _CHECK(b, "hello world I am Foo and I frobnicate 123 Bars"); - - // chevron-style AKA iostream-style - b << "hello world I am " << foo << " and I frobnicate " << bars << " Bars"; - _CHECK(b, "hello world I am Foo and I frobnicate 123 Bars"); - - // c-style, not type safe - b.printf("hello world I am %s and I frobnicate %d Bars", foo, bars); - _CHECK(b, "hello world I am Foo and I frobnicate 123 Bars"); - - // python-style, type safe - b.print("hello world I am {} and I frobnicate {} Bars", foo, bars); - _CHECK(b, "hello world I am Foo and I frobnicate 123 Bars"); - - // r-style, type safe - b.cat("hello world I am ", foo, " and I frobnicate ", bars, " Bars"); - _CHECK(b, "hello world I am Foo and I frobnicate 123 Bars"); - - // using separators: this is unpractical... - const char *s[] = {"now", "we", "have", "11", "strings", "to", "cat", "one", "after", "the", "other"}; - b.cat(s[0], ' ', s[1], ' ', s[2], ' ', s[3], ' ', s[4], ' ', - s[5], ' ', s[6], ' ', s[7], ' ', s[8], ' ', s[9], ' ', s[10]); - _CHECK(b, "now we have 11 strings to cat one after the other"); - - // ... and this resolves it - b.catsep(' ', s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[8], s[9], s[10]); - _CHECK(b, "now we have 11 strings to cat one after the other"); - - b.catsep('_', s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[8], s[9], s[10]); - _CHECK(b, "now_we_have_11_strings_to_cat_one_after_the_other"); - - // can be a full string - b.catsep("____", s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[8], s[9], s[10]); - _CHECK(b, "now____we____have____11____strings____to____cat____one____after____the____other"); - - // or just a general object - b.catsep(22, s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[8], s[9], s[10]); - _CHECK(b, "now22we22have221122strings22to22cat22one22after22the22other"); - -} - -} // namespace c4 - -#include "c4/libtest/supprwarn_pop.hpp" diff --git a/thirdparty/ryml/ext/c4core/test/test_memory_resource.cpp b/thirdparty/ryml/ext/c4core/test/test_memory_resource.cpp deleted file mode 100644 index 7ae7a71ac..000000000 --- a/thirdparty/ryml/ext/c4core/test/test_memory_resource.cpp +++ /dev/null @@ -1,255 +0,0 @@ -#ifndef C4CORE_SINGLE_HEADER -#include "c4/memory_resource.hpp" -#endif - -#include "c4/libtest/supprwarn_push.hpp" - -#include - -#include "c4/test.hpp" - -namespace c4 { - -TEST_CASE("set_aalloc.basic") -{ - auto a = get_aalloc(); - set_aalloc(nullptr); - CHECK_EQ(get_aalloc(), nullptr); - set_aalloc(a); - CHECK_EQ(get_aalloc(), a); -} - -TEST_CASE("set_afree.basic") -{ - auto a = get_afree(); - set_afree(nullptr); - CHECK_EQ(get_afree(), nullptr); - set_afree(a); - CHECK_EQ(get_afree(), a); -} - -TEST_CASE("set_arealloc.basic") -{ - auto a = get_arealloc(); - set_arealloc(nullptr); - CHECK_EQ(get_arealloc(), nullptr); - set_arealloc(a); - CHECK_EQ(get_arealloc(), a); -} - -//----------------------------------------------------------------------------- -namespace detail { -void* aalloc_impl(size_t size, size_t alignment=alignof(max_align_t)); -void* arealloc_impl(void *ptr, size_t oldsz, size_t newsz, size_t alignment=alignof(max_align_t)); -void afree_impl(void *ptr); -} // namespace detail - -TEST_CASE("aalloc_impl.error_bad_align") -{ -#if defined(C4_POSIX) - C4_EXPECT_ERROR_OCCURS(1); - auto *mem = detail::aalloc_impl(64, 9); // allocating with a non-power of two value is invalid - CHECK_EQ(mem, nullptr); -#endif -} - -TEST_CASE("aalloc_impl.error_out_of_mem") -{ -#if defined(C4_POSIX) - if(sizeof(size_t) != 8) return; // valgrind complains that size is -1 - C4_EXPECT_ERROR_OCCURS(1); - size_t sz = std::numeric_limits::max(); - sz /= 2; - auto *mem = detail::aalloc_impl(sz); - CHECK_EQ(mem, nullptr); -#endif -} - -//----------------------------------------------------------------------------- - -void do_test_realloc(arealloc_pfn fn) -{ -#define _set(dim) for(uint8_t i = 0; i < dim; ++i) { mem[i] = static_cast(i); } -#define _check(dim) for(uint8_t i = 0; i < dim; ++i) { CHECK_EQ(mem[i], i); } - - char *mem = (char*) aalloc(16, alignof(max_align_t)); - _set(16u); - _check(16u); - mem = (char*) fn(mem, 16, 20, alignof(max_align_t)); - _check(16u); - mem = (char*) fn(mem, 8, 20, alignof(max_align_t)); - _check(8u); - afree(mem); - -#undef _set -#undef _check -} - -TEST_CASE("realloc_impl.basic") -{ - do_test_realloc(&detail::arealloc_impl); -} - -TEST_CASE("realloc.basic") -{ - do_test_realloc(&arealloc); -} - - -//----------------------------------------------------------------------------- - -void do_memreslinear_realloc_test(MemoryResourceLinear &mr) -{ - C4_ASSERT(mr.capacity() >= 128); // this is needed for the tests below - - char * mem = (char*) mr.allocate(32); - CHECK_EQ(mem-(char*)mr.mem(), 0); - CHECK_EQ(mr.size(), 32); - CHECK_EQ(mr.slack(), mr.capacity() - 32); - - mem = (char*) mr.reallocate(mem, 32, 16); - CHECK_EQ(mem-(char*)mr.mem(), 0); - CHECK_EQ(mr.size(), 16); - CHECK_EQ(mr.slack(), mr.capacity() - 16); - - mem = (char*) mr.reallocate(mem, 16, 64); - CHECK_EQ(mem-(char*)mr.mem(), 0); - CHECK_EQ(mr.size(), 64); - CHECK_EQ(mr.slack(), mr.capacity() - 64); - - mem = (char*) mr.reallocate(mem, 64, 32); - CHECK_EQ(mem-(char*)mr.mem(), 0); - CHECK_EQ(mr.size(), 32); - CHECK_EQ(mr.slack(), mr.capacity() - 32); - - - char *mem2 = (char*) mr.allocate(32); - CHECK_EQ(mem-(char*)mr.mem(), 0); - CHECK_EQ(mem2-(char*)mr.mem(), 32); - CHECK_EQ(mr.size(), 64); - CHECK_EQ(mr.slack(), mr.capacity() - 64); - - mem = (char*) mr.reallocate(mem, 32, 16); - CHECK_EQ(mem-(char*)mr.mem(), 0); - CHECK_EQ(mr.size(), 64); - CHECK_EQ(mr.slack(), mr.capacity() - 64); -} - -TEST_CASE("MemoryResourceLinear.reallocate") -{ - MemoryResourceLinear mr(128); - do_memreslinear_realloc_test(mr); -} - -TEST_CASE("MemoryResourceLinearArr.reallocate") -{ - MemoryResourceLinearArr<128> mr; - do_memreslinear_realloc_test(mr); -} - - -//----------------------------------------------------------------------------- - -TEST_CASE("MemoryResourceLinear.error_out_of_mem") -{ - { - C4_EXPECT_ERROR_OCCURS(0); - MemoryResourceLinear mr(8); - mr.allocate(2); - } - - { - C4_EXPECT_ERROR_OCCURS(2); - MemoryResourceLinear mr(8); - mr.allocate(9); - } -} - -TEST_CASE("MemoryResourceLinearArr.error_out_of_mem") -{ - { - C4_EXPECT_ERROR_OCCURS(0); - MemoryResourceLinearArr<8> mr; - mr.allocate(2); - } - - { - C4_EXPECT_ERROR_OCCURS(2); - MemoryResourceLinearArr<8> mr; - mr.allocate(9); - } -} - - -//----------------------------------------------------------------------------- - -TEST_CASE("ScopedMemoryResource.basic") -{ - auto *before = get_memory_resource(); - { - MemoryResourceCounts mrc; - ScopedMemoryResource smr(&mrc); - CHECK_EQ(get_memory_resource(), &mrc); - } - CHECK_EQ(get_memory_resource(), before); -} - -TEST_CASE("ScopedMemoryResourceCounts.basic") -{ - auto *before = get_memory_resource(); - { - auto sac = ScopedMemoryResourceCounts{}; - CHECK_EQ(get_memory_resource(), &sac.mr); - } - CHECK_EQ(get_memory_resource(), before); -} - -TEST_CASE("ScopedMemoryResourceCounts.counts") -{ - auto *before = get_memory_resource(); - C4_UNUSED(before); - - { - auto checker = AllocationCountsChecker(); - auto *mr = &checker.mr; - - for(size_t sz : {16u, 32u, 64u, 128u}) - { - void *mem = mr->allocate(sz); - checker.check_all_delta(1, static_cast(sz), static_cast(sz)); - mr->deallocate(mem, sz); - checker.reset(); - } - checker.check_curr(0, 0); - checker.check_total(4, 240); - checker.check_max(1, 128); - } - - { - auto checker = AllocationCountsChecker(); - auto *mr = &checker.mr; - - std::pair mem[4] = {{0,16}, {0,32}, {0,64}, {0,128}}; - for(auto& m : mem) - { - m.first = mr->allocate(m.second); - checker.check_curr_delta(1, static_cast(m.second)); - checker.reset(); - } - checker.check_curr(4, 240); - checker.check_total(4, 240); - checker.check_max(4, 240); - for(auto& m : mem) - { - mr->deallocate(m.first, m.second); - } - checker.check_curr(0, 0); - checker.check_total(4, 240); - checker.check_max(4, 240); - } - -} - -} // namespace c4 - -#include "c4/libtest/supprwarn_pop.hpp" diff --git a/thirdparty/ryml/ext/c4core/test/test_memory_util.cpp b/thirdparty/ryml/ext/c4core/test/test_memory_util.cpp deleted file mode 100644 index 36509070c..000000000 --- a/thirdparty/ryml/ext/c4core/test/test_memory_util.cpp +++ /dev/null @@ -1,415 +0,0 @@ -#ifndef C4CORE_SINGLE_HEADER -#include "c4/memory_util.hpp" -#endif - -#include "c4/libtest/supprwarn_push.hpp" - -#include -#include - -namespace c4 { - -TEST_CASE("mem_overlaps") -{ - csubstr buf = "0123456789012345678901234567890123456789"; - CHECK_EQ(buf.len, 40); - auto overlaps = [](csubstr lhs, csubstr rhs){ - bool res = mem_overlaps(lhs.str, rhs.str, lhs.len, rhs.len); - CHECK(res == lhs.overlaps(rhs)); - return res; - }; - CHECK(!overlaps(buf.first(0), buf.last(0))); - CHECK(!overlaps(buf.first(5), buf.last(5))); - CHECK(!overlaps(buf.first(10), buf.last(10))); - CHECK(!overlaps(buf.first(20), buf.last(20))); - CHECK(overlaps(buf.first(21), buf.last(20))); - CHECK(overlaps(buf.first(20), buf.last(21))); - CHECK(!overlaps(buf.first(0), buf)); - CHECK(overlaps(buf.first(1), buf)); - CHECK(!overlaps(buf, buf.last(0))); - CHECK(overlaps(buf, buf.last(1))); - CHECK(!overlaps(buf.first(20), buf.last(20))); - CHECK(overlaps(buf.first(21), buf.last(20))); - CHECK(overlaps(buf.first(20), buf.first(21))); -} - -TEST_CASE("mem_repeatT.one_repetition") -{ - char buf[120] = {0}; - - mem_repeat(buf, "123", 2, 1); - CHECK_EQ(strcmp(buf, "12"), 0); - - mem_repeat(buf, "123", 3, 1); - CHECK_EQ(strcmp(buf, "123"), 0); -} - -TEST_CASE("mem_repeatT.basic") -{ - char buf[120] = {0}; - - mem_zero(buf); - - mem_repeat(buf, "123", 2, 2); - CHECK_EQ(strcmp(buf, "1212"), 0); - CHECK_EQ(buf[4], '\0'); - - mem_zero(buf); - - mem_repeat(buf, "123", 3, 2); - CHECK_EQ(strcmp(buf, "123123"), 0); - CHECK_EQ(buf[6], '\0'); - - mem_zero(buf); - - mem_repeat(buf, "123", 2, 3); - CHECK_EQ(strcmp(buf, "121212"), 0); - CHECK_EQ(buf[6], '\0'); - - mem_zero(buf, sizeof(buf)); - - mem_repeat(buf, "123", 3, 3); - CHECK_EQ(strcmp(buf, "123123123"), 0); - CHECK_EQ(buf[9], '\0'); - - mem_zero(buf, sizeof(buf)); - - mem_repeat(buf, "123", 2, 4); - CHECK_EQ(strcmp(buf, "12121212"), 0); - CHECK_EQ(buf[8], '\0'); - - mem_zero(buf, sizeof(buf)); - - mem_repeat(buf, "123", 3, 4); - CHECK_EQ(strcmp(buf, "123123123123"), 0); - CHECK_EQ(buf[12], '\0'); - - mem_zero(buf, sizeof(buf)); - - mem_repeat(buf, "123", 2, 5); - CHECK_EQ(strcmp(buf, "1212121212"), 0); - CHECK_EQ(buf[10], '\0'); - - mem_zero(buf, sizeof(buf)); - - mem_repeat(buf, "123", 3, 5); - CHECK_EQ(strcmp(buf, "123123123123123"), 0); - CHECK_EQ(buf[15], '\0'); - - mem_zero(buf, sizeof(buf)); - - mem_repeat(buf, "123", 2, 6); - CHECK_EQ(strcmp(buf, "121212121212"), 0); - CHECK_EQ(buf[12], '\0'); - - mem_zero(buf, sizeof(buf)); - - mem_repeat(buf, "123", 3, 6); - CHECK_EQ(strcmp(buf, "123123123123123123"), 0); - CHECK_EQ(buf[18], '\0'); -} - - -//----------------------------------------------------------------------------- - -TEST_CASE("is_aligned.basic") -{ - CHECK(is_aligned((int*)0x0)); - CHECK_FALSE(is_aligned((int*)0x1)); - CHECK_FALSE(is_aligned((int*)0x2)); - CHECK_FALSE(is_aligned((int*)0x3)); - CHECK_FALSE(is_aligned((int*)0x3)); - CHECK(is_aligned((int*)0x4)); -} - - -//----------------------------------------------------------------------------- - -TEST_CASE_TEMPLATE("lsb.basic", T, uint8_t, uint16_t, uint32_t, uint64_t) -{ - //CHECK_EQ(lsb( 0), T(0)); - CHECK_EQ(lsb( 1), T(0)); - CHECK_EQ(lsb( 2), T(1)); - CHECK_EQ(lsb( 3), T(0)); - CHECK_EQ(lsb( 4), T(2)); - CHECK_EQ(lsb( 5), T(0)); - CHECK_EQ(lsb( 6), T(1)); - CHECK_EQ(lsb( 7), T(0)); - CHECK_EQ(lsb( 8), T(3)); - CHECK_EQ(lsb( 9), T(0)); - CHECK_EQ(lsb(10), T(1)); - CHECK_EQ(lsb(11), T(0)); - CHECK_EQ(lsb(12), T(2)); - CHECK_EQ(lsb(13), T(0)); - CHECK_EQ(lsb(14), T(1)); - CHECK_EQ(lsb(15), T(0)); - CHECK_EQ(lsb(16), T(4)); -} - -TEST_CASE_TEMPLATE("lsb11.basic", T, uint8_t, uint16_t, uint32_t, uint64_t) -{ - //CHECK_EQ((lsb11::value), T(0)); - CHECK_EQ((lsb11::value), T(0)); - CHECK_EQ((lsb11::value), T(1)); - CHECK_EQ((lsb11::value), T(0)); - CHECK_EQ((lsb11::value), T(2)); - CHECK_EQ((lsb11::value), T(0)); - CHECK_EQ((lsb11::value), T(1)); - CHECK_EQ((lsb11::value), T(0)); - CHECK_EQ((lsb11::value), T(3)); - CHECK_EQ((lsb11::value), T(0)); - CHECK_EQ((lsb11::value), T(1)); - CHECK_EQ((lsb11::value), T(0)); - CHECK_EQ((lsb11::value), T(2)); - CHECK_EQ((lsb11::value), T(0)); - CHECK_EQ((lsb11::value), T(1)); - CHECK_EQ((lsb11::value), T(0)); - CHECK_EQ((lsb11::value), T(4)); -} - - -//----------------------------------------------------------------------------- - -TEST_CASE_TEMPLATE("ipow.float", T, float, double) -{ - SUBCASE("base 1, signed exponent") - { - CHECK_FLOAT_EQ(ipow(T(1), int(0)), T(1)); - CHECK_FLOAT_EQ(ipow(T(1), int(1)), T(1)); - CHECK_FLOAT_EQ(ipow(T(1), int(2)), T(1)); - CHECK_FLOAT_EQ(ipow(T(1), -int(1)), T(1)); - CHECK_FLOAT_EQ(ipow(T(1), -int(2)), T(1)); - CHECK_FLOAT_EQ((ipow(int(0))), T(1)); - CHECK_FLOAT_EQ((ipow(int(1))), T(1)); - CHECK_FLOAT_EQ((ipow(int(2))), T(1)); - CHECK_FLOAT_EQ((ipow(-int(1))), T(1)); - CHECK_FLOAT_EQ((ipow(-int(2))), T(1)); - } - SUBCASE("base 1, unsigned exponent") - { - CHECK_FLOAT_EQ(ipow(T(1), unsigned(0)), T(1)); - CHECK_FLOAT_EQ(ipow(T(1), unsigned(1)), T(1)); - CHECK_FLOAT_EQ(ipow(T(1), unsigned(2)), T(1)); - CHECK_FLOAT_EQ((ipow(unsigned(0))), T(1)); - CHECK_FLOAT_EQ((ipow(unsigned(1))), T(1)); - CHECK_FLOAT_EQ((ipow(unsigned(2))), T(1)); - } - SUBCASE("base 2, signed exponent") - { - CHECK_FLOAT_EQ(ipow(T(2), int(0)), T(1)); - CHECK_FLOAT_EQ(ipow(T(2), int(1)), T(2)); - CHECK_FLOAT_EQ(ipow(T(2), int(2)), T(4)); - CHECK_FLOAT_EQ(ipow(T(2), int(7)), T(128)); - CHECK_FLOAT_EQ(ipow(T(2), -int(1)), T(0.5)); - CHECK_FLOAT_EQ(ipow(T(2), -int(2)), T(0.25)); - CHECK_FLOAT_EQ(ipow(T(2), -int(3)), T(0.125)); - CHECK_FLOAT_EQ(ipow(T(2), -int(4)), T(0.0625)); - CHECK_FLOAT_EQ((ipow(int(0))), T(1)); - CHECK_FLOAT_EQ((ipow(int(1))), T(2)); - CHECK_FLOAT_EQ((ipow(int(2))), T(4)); - CHECK_FLOAT_EQ((ipow(int(7))), T(128)); - CHECK_FLOAT_EQ((ipow(-int(1))), T(0.5)); - CHECK_FLOAT_EQ((ipow(-int(2))), T(0.25)); - CHECK_FLOAT_EQ((ipow(-int(3))), T(0.125)); - CHECK_FLOAT_EQ((ipow(-int(4))), T(0.0625)); - } - SUBCASE("base 2, unsigned exponent") - { - CHECK_FLOAT_EQ(ipow(T(2), unsigned(0)), T(1)); - CHECK_FLOAT_EQ(ipow(T(2), unsigned(1)), T(2)); - CHECK_FLOAT_EQ(ipow(T(2), unsigned(2)), T(4)); - CHECK_FLOAT_EQ(ipow(T(2), unsigned(6)), T(64)); - CHECK_FLOAT_EQ((ipow(unsigned(0))), T(1)); - CHECK_FLOAT_EQ((ipow(unsigned(1))), T(2)); - CHECK_FLOAT_EQ((ipow(unsigned(2))), T(4)); - CHECK_FLOAT_EQ((ipow(unsigned(6))), T(64)); - } -} - -TEST_CASE_TEMPLATE("ipow", T, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t) -{ - SUBCASE("base 1, signed exponent") - { - CHECK_EQ(ipow(T(1), int(0)), T(1)); - CHECK_EQ(ipow(T(1), int(1)), T(1)); - CHECK_EQ(ipow(T(1), int(2)), T(1)); - CHECK_EQ(ipow(T(1), -int(1)), T(1)); - CHECK_EQ(ipow(T(1), -int(2)), T(1)); - CHECK_EQ(ipow(int(0)), T(1)); - CHECK_EQ(ipow(int(1)), T(1)); - CHECK_EQ(ipow(int(2)), T(1)); - CHECK_EQ(ipow(-int(1)), T(1)); - CHECK_EQ(ipow(-int(2)), T(1)); - } - SUBCASE("base 1, unsigned exponent") - { - CHECK_EQ(ipow(T(1), unsigned(0)), T(1)); - CHECK_EQ(ipow(T(1), unsigned(1)), T(1)); - CHECK_EQ(ipow(T(1), unsigned(2)), T(1)); - CHECK_EQ(ipow(unsigned(0)), T(1)); - CHECK_EQ(ipow(unsigned(1)), T(1)); - CHECK_EQ(ipow(unsigned(2)), T(1)); - } - SUBCASE("base 2, signed exponent") - { - CHECK_EQ(ipow(T(2), int(0)), T(1)); - CHECK_EQ(ipow(T(2), int(1)), T(2)); - CHECK_EQ(ipow(T(2), int(2)), T(4)); - CHECK_EQ(ipow(T(2), int(6)), T(64)); - CHECK_EQ(ipow(T(2), -int(1)), T(0)); - CHECK_EQ(ipow(T(2), -int(2)), T(0)); - CHECK_EQ(ipow(T(2), -int(6)), T(0)); - CHECK_EQ(ipow(int(0)), T(1)); - CHECK_EQ(ipow(int(1)), T(2)); - CHECK_EQ(ipow(int(2)), T(4)); - CHECK_EQ(ipow(int(6)), T(64)); - CHECK_EQ(ipow(-int(1)), T(0)); - CHECK_EQ(ipow(-int(2)), T(0)); - CHECK_EQ(ipow(-int(7)), T(0)); - } - SUBCASE("base 2, unsigned exponent") - { - CHECK_EQ(ipow(T(2), unsigned(0)), T(1)); - CHECK_EQ(ipow(T(2), unsigned(1)), T(2)); - CHECK_EQ(ipow(T(2), unsigned(2)), T(4)); - CHECK_EQ(ipow(T(2), unsigned(6)), T(64)); - CHECK_EQ(ipow(unsigned(0)), T(1)); - CHECK_EQ(ipow(unsigned(1)), T(2)); - CHECK_EQ(ipow(unsigned(2)), T(4)); - CHECK_EQ(ipow(unsigned(6)), T(64)); - } -} - - -//----------------------------------------------------------------------------- - -TEST_CASE_TEMPLATE("msb.basic", T, uint8_t, uint16_t, uint32_t, uint64_t) -{ - CHECK_EQ(msb(T( 1)), 0u); - CHECK_EQ(msb(T( 2)), 1u); - CHECK_EQ(msb(T( 3)), 1u); - CHECK_EQ(msb(T( 4)), 2u); - CHECK_EQ(msb(T( 5)), 2u); - CHECK_EQ(msb(T( 6)), 2u); - CHECK_EQ(msb(T( 7)), 2u); - CHECK_EQ(msb(T( 8)), 3u); - CHECK_EQ(msb(T( 9)), 3u); - CHECK_EQ(msb(T(10)), 3u); - CHECK_EQ(msb(T(11)), 3u); - CHECK_EQ(msb(T(12)), 3u); - CHECK_EQ(msb(T(13)), 3u); - CHECK_EQ(msb(T(14)), 3u); - CHECK_EQ(msb(T(15)), 3u); - CHECK_EQ(msb(T(16)), 4u); - CHECK_EQ(msb(std::numeric_limits::max()), 8u * sizeof(T) - 1u); -} - -TEST_CASE_TEMPLATE("msb11.basic", T, uint8_t, uint16_t, uint32_t, uint64_t) -{ - CHECK_EQ((msb11::value), T(0)); - CHECK_EQ((msb11::value), T(1)); - CHECK_EQ((msb11::value), T(1)); - CHECK_EQ((msb11::value), T(2)); - CHECK_EQ((msb11::value), T(2)); - CHECK_EQ((msb11::value), T(2)); - CHECK_EQ((msb11::value), T(2)); - CHECK_EQ((msb11::value), T(3)); - CHECK_EQ((msb11::value), T(3)); - CHECK_EQ((msb11::value), T(3)); - CHECK_EQ((msb11::value), T(3)); - CHECK_EQ((msb11::value), T(3)); - CHECK_EQ((msb11::value), T(3)); - CHECK_EQ((msb11::value), T(3)); - CHECK_EQ((msb11::value), T(3)); - CHECK_EQ((msb11::value), T(4)); - CHECK_EQ((msb11::max()>::value), 8u * sizeof(T) - 1u); -} - - -//----------------------------------------------------------------------------- -// contiguous mask - -template T _mask() { return T(0); } -template T _mask(int bit, Bits ...bits) { return (T)(T(1) << bit | _mask(bits...)); } - -TEST_CASE_TEMPLATE("contiguous_mask.basic", T, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t) -{ - CHECK_EQ(contiguous_mask(0, 0), _mask()); - CHECK_EQ(contiguous_mask(0, 1), _mask(0)); - CHECK_EQ(contiguous_mask(0, 2), _mask(0, 1)); - CHECK_EQ(contiguous_mask(0, 3), _mask(0, 1, 2)); - CHECK_EQ(contiguous_mask(0, 4), _mask(0, 1, 2, 3)); - CHECK_EQ(contiguous_mask(1, 4), _mask( 1, 2, 3)); - CHECK_EQ(contiguous_mask(2, 4), _mask( 2, 3)); - CHECK_EQ(contiguous_mask(3, 4), _mask( 3)); - CHECK_EQ(contiguous_mask(4, 4), _mask()); -} - -TEST_CASE_TEMPLATE("contiguous_mask11.basic", T, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t) -{ - CHECK_EQ((contiguous_mask11::value), _mask()); - CHECK_EQ((contiguous_mask11::value), _mask(0)); - CHECK_EQ((contiguous_mask11::value), _mask(0, 1)); - CHECK_EQ((contiguous_mask11::value), _mask(0, 1, 2)); - CHECK_EQ((contiguous_mask11::value), _mask(0, 1, 2, 3)); - CHECK_EQ((contiguous_mask11::value), _mask( 1, 2, 3)); - CHECK_EQ((contiguous_mask11::value), _mask( 2, 3)); - CHECK_EQ((contiguous_mask11::value), _mask( 3)); - CHECK_EQ((contiguous_mask11::value), _mask()); -} - - -//----------------------------------------------------------------------------- - - -template struct sz { char buf[N]; }; -template< > struct sz<0> { }; -template void check_tp() -{ - #if defined(__clang__) - # pragma clang diagnostic push - #elif defined(__GNUC__) - # pragma GCC diagnostic push - # if __GNUC__ >= 7 - # pragma GCC diagnostic ignored "-Wduplicated-branches" - # endif - #endif - size_t expected; - if(F != 0 && S != 0) expected = F+S; - else if(F == 0 && S != 0) expected = S; - else if(F != 0 && S == 0) expected = F; // -Wduplicated-branches: false positive here - else /* F == 0 && S == 0)*/expected = 1; - #if defined(__clang__) - # pragma clang diagnostic pop - #elif defined(__GNUC__) - # pragma GCC diagnostic pop - #endif - INFO("F=" << F << " S=" << S); - CHECK_EQ(sizeof(tight_pair, sz>), expected); -} - - -TEST_CASE("tight_pair.basic") -{ - check_tp<0,0>(); - check_tp<0,1>(); - check_tp<0,2>(); - check_tp<0,3>(); - check_tp<0,4>(); - - check_tp<0,0>(); - check_tp<1,0>(); - check_tp<2,0>(); - check_tp<3,0>(); - check_tp<4,0>(); - - check_tp<0,0>(); - check_tp<1,1>(); - check_tp<2,2>(); - check_tp<3,3>(); - check_tp<4,4>(); -} - -} // namespace c4 - -#include "c4/libtest/supprwarn_pop.hpp" diff --git a/thirdparty/ryml/ext/c4core/test/test_numbers.hpp b/thirdparty/ryml/ext/c4core/test/test_numbers.hpp deleted file mode 100644 index d310b36ba..000000000 --- a/thirdparty/ryml/ext/c4core/test/test_numbers.hpp +++ /dev/null @@ -1,1863 +0,0 @@ -#ifndef C4CORE_SINGLE_HEADER -#include -#include -#endif -#include - -namespace c4 { - -template -struct overflow64case -{ - bool is_overflow; - T wrapped; - csubstr dec; - csubstr hex; - csubstr oct; - csubstr bin; -}; - -template -struct overflow64cases; - -#define oc(T, is_overflow, wrapped, dec, hex, oct, bin) \ - overflow64case{is_overflow, wrapped, csubstr{dec}, csubstr{hex}, csubstr{oct}, csubstr{bin}} - -template<> -struct overflow64cases -{ - #define INT64_1(v) INT64_C(v) - INT64_C(1) // the min value is not representable! - static constexpr const overflow64case values[] = { - oc(int64_t, true , INT64_C( 9223372036854775803), "-9223372036854775813", "-0x8000000000000005", "-0o1000000000000000000005", "-0b1000000000000000000000000000000000000000000000000000000000000101"), - oc(int64_t, true , INT64_C( 9223372036854775804), "-9223372036854775812", "-0x8000000000000004", "-0o1000000000000000000004", "-0b1000000000000000000000000000000000000000000000000000000000000100"), - oc(int64_t, true , INT64_C( 9223372036854775805), "-9223372036854775811", "-0x8000000000000003", "-0o1000000000000000000003", "-0b1000000000000000000000000000000000000000000000000000000000000011"), - oc(int64_t, true , INT64_C( 9223372036854775806), "-9223372036854775810", "-0x8000000000000002", "-0o1000000000000000000002", "-0b1000000000000000000000000000000000000000000000000000000000000010"), - oc(int64_t, true , INT64_C( 9223372036854775807), "-9223372036854775809", "-0x8000000000000001", "-0o1000000000000000000001", "-0b1000000000000000000000000000000000000000000000000000000000000001"), - oc(int64_t, false, INT64_1(-9223372036854775807), "-9223372036854775808", "-0x8000000000000000", "-0o1000000000000000000000", "-0b1000000000000000000000000000000000000000000000000000000000000000"), - oc(int64_t, false, INT64_C(-9223372036854775807), "-9223372036854775807", "-0x7fffffffffffffff", "-0o777777777777777777777" , "-0b111111111111111111111111111111111111111111111111111111111111111"), - oc(int64_t, false, INT64_C(-9223372036854775806), "-9223372036854775806", "-0x7ffffffffffffffe", "-0o777777777777777777776" , "-0b111111111111111111111111111111111111111111111111111111111111110"), - oc(int64_t, false, INT64_C(-9223372036854775805), "-9223372036854775805", "-0x7ffffffffffffffd", "-0o777777777777777777775" , "-0b111111111111111111111111111111111111111111111111111111111111101"), - oc(int64_t, false, INT64_C( 9223372036854775804), "9223372036854775804", "0x7ffffffffffffffc", "0o777777777777777777774" , "0b111111111111111111111111111111111111111111111111111111111111100"), - oc(int64_t, false, INT64_C( 9223372036854775805), "9223372036854775805", "0x7ffffffffffffffd", "0o777777777777777777775" , "0b111111111111111111111111111111111111111111111111111111111111101"), - oc(int64_t, false, INT64_C( 9223372036854775806), "9223372036854775806", "0x7ffffffffffffffe", "0o777777777777777777776" , "0b111111111111111111111111111111111111111111111111111111111111110"), - oc(int64_t, false, INT64_C( 9223372036854775807), "9223372036854775807", "0x7fffffffffffffff", "0o777777777777777777777" , "0b111111111111111111111111111111111111111111111111111111111111111"), - oc(int64_t, true , INT64_1(-9223372036854775807), "9223372036854775808", "0x8000000000000000", "0o1000000000000000000000", "0b1000000000000000000000000000000000000000000000000000000000000000"), - oc(int64_t, true , INT64_C(-9223372036854775807), "9223372036854775809", "0x8000000000000001", "0o1000000000000000000001", "0b1000000000000000000000000000000000000000000000000000000000000001"), - oc(int64_t, true , INT64_C(-9223372036854775806), "9223372036854775810", "0x8000000000000002", "0o1000000000000000000002", "0b1000000000000000000000000000000000000000000000000000000000000010"), - oc(int64_t, true , INT64_C(-9223372036854775805), "9223372036854775811", "0x8000000000000003", "0o1000000000000000000003", "0b1000000000000000000000000000000000000000000000000000000000000011"), - oc(int64_t, true , INT64_C(-9223372036854775804), "9223372036854775812", "0x8000000000000004", "0o1000000000000000000004", "0b1000000000000000000000000000000000000000000000000000000000000100"), - }; -}; - -template<> -struct overflow64cases -{ - static constexpr const overflow64case values[] = { - oc(uint64_t, true , UINT64_C(18446744073709551611), "-5" , "-0x5" , "-0o5" , "-0b101"), - oc(uint64_t, true , UINT64_C(18446744073709551612), "-4" , "-0x4" , "-0o4" , "-0b100"), - oc(uint64_t, true , UINT64_C(18446744073709551613), "-3" , "-0x3" , "-0o3" , "-0b11"), - oc(uint64_t, true , UINT64_C(18446744073709551614), "-2" , "-0x2" , "-0o2" , "-0b10"), - oc(uint64_t, true , UINT64_C(18446744073709551615), "-1" , "-0x1" , "-0o1" , "-0b1"), - oc(uint64_t, false, UINT64_C( 0), "0" , "0x0" , "0o0" , "0b0"), - oc(uint64_t, false, UINT64_C( 1), "1" , "0x1" , "0o1" , "0b1"), - oc(uint64_t, false, UINT64_C( 2), "2" , "0x2" , "0o2" , "0b10"), - oc(uint64_t, false, UINT64_C( 3), "3" , "0x3" , "0o3" , "0b11"), - oc(uint64_t, false, UINT64_C(18446744073709551612), "18446744073709551612", "0xfffffffffffffffc" , "0o1777777777777777777774" , "0b1111111111111111111111111111111111111111111111111111111111111100"), - oc(uint64_t, false, UINT64_C(18446744073709551613), "18446744073709551613", "0xfffffffffffffffd" , "0o1777777777777777777775" , "0b1111111111111111111111111111111111111111111111111111111111111101"), - oc(uint64_t, false, UINT64_C(18446744073709551614), "18446744073709551614", "0xfffffffffffffffe" , "0o1777777777777777777776" , "0b1111111111111111111111111111111111111111111111111111111111111110"), - oc(uint64_t, false, UINT64_C(18446744073709551615), "18446744073709551615", "0xffffffffffffffff" , "0o1777777777777777777777" , "0b1111111111111111111111111111111111111111111111111111111111111111"), - oc(uint64_t, true , UINT64_C( 0), "18446744073709551616", "0x10000000000000000", "0o20000000000000000000000", "0b10000000000000000000000000000000000000000000000000000000000000000"), - oc(uint64_t, true , UINT64_C( 1), "18446744073709551617", "0x10000000000000001", "0o20000000000000000000001", "0b10000000000000000000000000000000000000000000000000000000000000001"), - oc(uint64_t, true , UINT64_C( 2), "18446744073709551618", "0x10000000000000002", "0o20000000000000000000002", "0b10000000000000000000000000000000000000000000000000000000000000010"), - oc(uint64_t, true , UINT64_C( 3), "18446744073709551619", "0x10000000000000003", "0o20000000000000000000003", "0b10000000000000000000000000000000000000000000000000000000000000011"), - oc(uint64_t, true , UINT64_C( 4), "18446744073709551620", "0x10000000000000004", "0o20000000000000000000004", "0b10000000000000000000000000000000000000000000000000000000000000100"), - oc(uint64_t, true , UINT64_C( 5), "18446744073709551621", "0x10000000000000005", "0o20000000000000000000005", "0b10000000000000000000000000000000000000000000000000000000000000101"), - }; -}; - -constexpr const overflow64case overflow64cases::values[]; -constexpr const overflow64case overflow64cases::values[]; - -#undef oc - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -struct invalid_case -{ - csubstr dec, hex, oct, bin; -}; - -C4_INLINE_CONSTEXPR const invalid_case invalid_cases[] = { -#define ic(dec, hex, oct, bin) \ - invalid_case{csubstr{dec}, csubstr{hex}, csubstr{oct}, csubstr{bin}} - ic("" , "" , "" , ""), - ic(" " , " " , " " , " "), - ic("." , "." , "." , "."), - ic("-" , "-" , "-" , "-"), - ic("\t" , "\t" , "\t" , "\t"), - ic("\n" , "\n" , "\n" , "\n"), - ic("...", "..." , "..." , "..."), - ic("===", "===" , "===" , "==="), - ic("=??", "???" , "???" , "???"), - ic("12a", "0x12g", "0o128", "0b102"), - ic("0.1", "0x1.2", "0o1.2", "0b1.1"), - ic("0,1", "0x1,2", "0o1,2", "0b1,1"), - ic("zz" , "0xzz" , "0ozz" , "0bzz"), - ic("" , "0x" , "0o" , "0b"), - ic("- " , "-0x" , "-0o" , "-0b"), - ic("2 0", "0x2 0", "0o2 0", "0b1 0"), - ic(" 2" , " 0x2" , " 0o2" , " 0b1"), - ic("\t2", "\t0x2", "\t0o2", "\t0b1"), - ic("\n2", "nt0x2", "\n0o2", "\n0b1"), - ic("2 " , "0x2 " , "0o2 " , "0b1 "), - ic("2\t", "0x2\t", "0o2\t", "0b1\t"), - ic("2\n", "0x2\n", "0o2\n", "0b1\n"), - ic("nan", "nan", "nan", "nan"), - ic("NaN", "NaN", "NaN", "NaN"), - ic("Inf", "Inf", "Inf", "Inf"), - ic("inf", "inf", "inf", "inf"), - ic("infinity", "infinity", "infinity", "infinity"), - ic("Infinity", "Infinity", "Infinity", "Infinity"), - ic("somevalue", "somevalue", "somevalue", "somevalue"), - ic("2345kjhiuy3245", "2345kjhiuy3245", "2345kjhiuy3245", "2345kjhiuy3245"), -#undef ic -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -template -struct number_case -{ - T val; - csubstr dec; - csubstr hex; - csubstr oct; - csubstr bin; -}; - -template -std::ostream& operator<< (std::ostream& s, number_case const& nc) -{ - using upcast_t = typename std::conditional::value, - int64_t, - uint64_t>::type>::type; - s << "val=" << (upcast_t)nc.val << " " - << "dec=" << nc.dec << " " - << "hex=" << nc.hex << " " - << "oct=" << nc.oct << " " - << "bin=" << nc.bin; - return s; -} - -template struct numbers; - -#define ITER_NUMBERS(ty, number_name) for(number_case const& C4_RESTRICT number_name : numbers::vals) - -C4_SUPPRESS_WARNING_MSVC_PUSH -C4_SUPPRESS_WARNING_MSVC(4146) -C4_SUPPRESS_WARNING_MSVC(4305) -C4_SUPPRESS_WARNING_MSVC(4310) - -// these numbers were generated with printintegers.py, in this dir. - -template<> -struct numbers -{ - using value_type = int8_t; - static C4_INLINE_CONSTEXPR const number_case vals[] = { -#define nc(val, dec, hex, bin, oct) \ - number_case{(value_type)INT8_C(val), csubstr{dec}, csubstr{hex}, csubstr{bin}, csubstr{oct}} - nc(-128, "-128", "-0x80", "-0o200", "-0b10000000"), - nc(-127, "-127", "-0x7f", "-0o177", "-0b1111111"), - nc(-126, "-126", "-0x7e", "-0o176", "-0b1111110"), - nc(-125, "-125", "-0x7d", "-0o175", "-0b1111101"), - nc(-124, "-124", "-0x7c", "-0o174", "-0b1111100"), - nc(-123, "-123", "-0x7b", "-0o173", "-0b1111011"), - nc(-101, "-101", "-0x65", "-0o145", "-0b1100101"), - nc(-100, "-100", "-0x64", "-0o144", "-0b1100100"), - nc(-99, "-99", "-0x63", "-0o143", "-0b1100011"), - nc(-65, "-65", "-0x41", "-0o101", "-0b1000001"), - nc(-64, "-64", "-0x40", "-0o100", "-0b1000000"), - nc(-63, "-63", "-0x3f", "-0o77", "-0b111111"), - nc(-33, "-33", "-0x21", "-0o41", "-0b100001"), - nc(-32, "-32", "-0x20", "-0o40", "-0b100000"), - nc(-31, "-31", "-0x1f", "-0o37", "-0b11111"), - nc(-17, "-17", "-0x11", "-0o21", "-0b10001"), - nc(-16, "-16", "-0x10", "-0o20", "-0b10000"), - nc(-15, "-15", "-0xf", "-0o17", "-0b1111"), - nc(-12, "-12", "-0xc", "-0o14", "-0b1100"), - nc(-11, "-11", "-0xb", "-0o13", "-0b1011"), - nc(-10, "-10", "-0xa", "-0o12", "-0b1010"), - nc(-9, "-9", "-0x9", "-0o11", "-0b1001"), - nc(-8, "-8", "-0x8", "-0o10", "-0b1000"), - nc(-7, "-7", "-0x7", "-0o7", "-0b111"), - nc(-6, "-6", "-0x6", "-0o6", "-0b110"), - nc(-5, "-5", "-0x5", "-0o5", "-0b101"), - nc(-4, "-4", "-0x4", "-0o4", "-0b100"), - nc(-3, "-3", "-0x3", "-0o3", "-0b11"), - nc(-2, "-2", "-0x2", "-0o2", "-0b10"), - nc(-1, "-1", "-0x1", "-0o1", "-0b1"), - nc(0, "0", "0x0", "0o0", "0b0"), - nc(1, "1", "0x1", "0o1", "0b1"), - nc(2, "2", "0x2", "0o2", "0b10"), - nc(3, "3", "0x3", "0o3", "0b11"), - nc(4, "4", "0x4", "0o4", "0b100"), - nc(5, "5", "0x5", "0o5", "0b101"), - nc(6, "6", "0x6", "0o6", "0b110"), - nc(7, "7", "0x7", "0o7", "0b111"), - nc(8, "8", "0x8", "0o10", "0b1000"), - nc(9, "9", "0x9", "0o11", "0b1001"), - nc(10, "10", "0xa", "0o12", "0b1010"), - nc(11, "11", "0xb", "0o13", "0b1011"), - nc(12, "12", "0xc", "0o14", "0b1100"), - nc(13, "13", "0xd", "0o15", "0b1101"), - nc(15, "15", "0xf", "0o17", "0b1111"), - nc(16, "16", "0x10", "0o20", "0b10000"), - nc(17, "17", "0x11", "0o21", "0b10001"), - nc(31, "31", "0x1f", "0o37", "0b11111"), - nc(32, "32", "0x20", "0o40", "0b100000"), - nc(33, "33", "0x21", "0o41", "0b100001"), - nc(63, "63", "0x3f", "0o77", "0b111111"), - nc(64, "64", "0x40", "0o100", "0b1000000"), - nc(65, "65", "0x41", "0o101", "0b1000001"), - nc(99, "99", "0x63", "0o143", "0b1100011"), - nc(100, "100", "0x64", "0o144", "0b1100100"), - nc(101, "101", "0x65", "0o145", "0b1100101"), - nc(122, "122", "0x7a", "0o172", "0b1111010"), - nc(123, "123", "0x7b", "0o173", "0b1111011"), - nc(124, "124", "0x7c", "0o174", "0b1111100"), - nc(125, "125", "0x7d", "0o175", "0b1111101"), - nc(126, "126", "0x7e", "0o176", "0b1111110"), - nc(127, "127", "0x7f", "0o177", "0b1111111"), -#undef nc - }; -}; - - -template<> -struct numbers -{ - using value_type = uint8_t; - static C4_INLINE_CONSTEXPR const number_case vals[] = { -#define nc(val, dec, hex, bin, oct) \ - number_case{(value_type)UINT8_C(val), csubstr{dec}, csubstr{hex}, csubstr{bin}, csubstr{oct}} - nc(0, "0", "0x0", "0o0", "0b0"), - nc(1, "1", "0x1", "0o1", "0b1"), - nc(2, "2", "0x2", "0o2", "0b10"), - nc(3, "3", "0x3", "0o3", "0b11"), - nc(4, "4", "0x4", "0o4", "0b100"), - nc(5, "5", "0x5", "0o5", "0b101"), - nc(6, "6", "0x6", "0o6", "0b110"), - nc(7, "7", "0x7", "0o7", "0b111"), - nc(8, "8", "0x8", "0o10", "0b1000"), - nc(9, "9", "0x9", "0o11", "0b1001"), - nc(10, "10", "0xa", "0o12", "0b1010"), - nc(11, "11", "0xb", "0o13", "0b1011"), - nc(15, "15", "0xf", "0o17", "0b1111"), - nc(16, "16", "0x10", "0o20", "0b10000"), - nc(17, "17", "0x11", "0o21", "0b10001"), - nc(24, "24", "0x18", "0o30", "0b11000"), - nc(25, "25", "0x19", "0o31", "0b11001"), - nc(26, "26", "0x1a", "0o32", "0b11010"), - nc(31, "31", "0x1f", "0o37", "0b11111"), - nc(32, "32", "0x20", "0o40", "0b100000"), - nc(33, "33", "0x21", "0o41", "0b100001"), - nc(63, "63", "0x3f", "0o77", "0b111111"), - nc(64, "64", "0x40", "0o100", "0b1000000"), - nc(65, "65", "0x41", "0o101", "0b1000001"), - nc(99, "99", "0x63", "0o143", "0b1100011"), - nc(100, "100", "0x64", "0o144", "0b1100100"), - nc(101, "101", "0x65", "0o145", "0b1100101"), - nc(127, "127", "0x7f", "0o177", "0b1111111"), - nc(128, "128", "0x80", "0o200", "0b10000000"), - nc(129, "129", "0x81", "0o201", "0b10000001"), - nc(251, "251", "0xfb", "0o373", "0b11111011"), - nc(252, "252", "0xfc", "0o374", "0b11111100"), - nc(253, "253", "0xfd", "0o375", "0b11111101"), - nc(254, "254", "0xfe", "0o376", "0b11111110"), - nc(255, "255", "0xff", "0o377", "0b11111111"), -#undef nc - }; -}; - - -template<> -struct numbers -{ - using value_type = int16_t; - static C4_INLINE_CONSTEXPR const number_case vals[] = { -#define nc(val, dec, hex, bin, oct) \ - number_case{(value_type)INT16_C(val), csubstr{dec}, csubstr{hex}, csubstr{bin}, csubstr{oct}} - nc(-32768, "-32768", "-0x8000", "-0o100000", "-0b1000000000000000"), - nc(-32767, "-32767", "-0x7fff", "-0o77777", "-0b111111111111111"), - nc(-32766, "-32766", "-0x7ffe", "-0o77776", "-0b111111111111110"), - nc(-32765, "-32765", "-0x7ffd", "-0o77775", "-0b111111111111101"), - nc(-32764, "-32764", "-0x7ffc", "-0o77774", "-0b111111111111100"), - nc(-32763, "-32763", "-0x7ffb", "-0o77773", "-0b111111111111011"), - nc(-16385, "-16385", "-0x4001", "-0o40001", "-0b100000000000001"), - nc(-16384, "-16384", "-0x4000", "-0o40000", "-0b100000000000000"), - nc(-16383, "-16383", "-0x3fff", "-0o37777", "-0b11111111111111"), - nc(-10001, "-10001", "-0x2711", "-0o23421", "-0b10011100010001"), - nc(-10000, "-10000", "-0x2710", "-0o23420", "-0b10011100010000"), - nc(-9999, "-9999", "-0x270f", "-0o23417", "-0b10011100001111"), - nc(-8193, "-8193", "-0x2001", "-0o20001", "-0b10000000000001"), - nc(-8192, "-8192", "-0x2000", "-0o20000", "-0b10000000000000"), - nc(-8191, "-8191", "-0x1fff", "-0o17777", "-0b1111111111111"), - nc(-4097, "-4097", "-0x1001", "-0o10001", "-0b1000000000001"), - nc(-4096, "-4096", "-0x1000", "-0o10000", "-0b1000000000000"), - nc(-4095, "-4095", "-0xfff", "-0o7777", "-0b111111111111"), - nc(-3276, "-3276", "-0xccc", "-0o6314", "-0b110011001100"), - nc(-2049, "-2049", "-0x801", "-0o4001", "-0b100000000001"), - nc(-2048, "-2048", "-0x800", "-0o4000", "-0b100000000000"), - nc(-2047, "-2047", "-0x7ff", "-0o3777", "-0b11111111111"), - nc(-1025, "-1025", "-0x401", "-0o2001", "-0b10000000001"), - nc(-1024, "-1024", "-0x400", "-0o2000", "-0b10000000000"), - nc(-1023, "-1023", "-0x3ff", "-0o1777", "-0b1111111111"), - nc(-1001, "-1001", "-0x3e9", "-0o1751", "-0b1111101001"), - nc(-1000, "-1000", "-0x3e8", "-0o1750", "-0b1111101000"), - nc(-999, "-999", "-0x3e7", "-0o1747", "-0b1111100111"), - nc(-513, "-513", "-0x201", "-0o1001", "-0b1000000001"), - nc(-512, "-512", "-0x200", "-0o1000", "-0b1000000000"), - nc(-511, "-511", "-0x1ff", "-0o777", "-0b111111111"), - nc(-327, "-327", "-0x147", "-0o507", "-0b101000111"), - nc(-257, "-257", "-0x101", "-0o401", "-0b100000001"), - nc(-256, "-256", "-0x100", "-0o400", "-0b100000000"), - nc(-255, "-255", "-0xff", "-0o377", "-0b11111111"), - nc(-129, "-129", "-0x81", "-0o201", "-0b10000001"), - nc(-128, "-128", "-0x80", "-0o200", "-0b10000000"), - nc(-127, "-127", "-0x7f", "-0o177", "-0b1111111"), - nc(-101, "-101", "-0x65", "-0o145", "-0b1100101"), - nc(-100, "-100", "-0x64", "-0o144", "-0b1100100"), - nc(-99, "-99", "-0x63", "-0o143", "-0b1100011"), - nc(-65, "-65", "-0x41", "-0o101", "-0b1000001"), - nc(-64, "-64", "-0x40", "-0o100", "-0b1000000"), - nc(-63, "-63", "-0x3f", "-0o77", "-0b111111"), - nc(-33, "-33", "-0x21", "-0o41", "-0b100001"), - nc(-32, "-32", "-0x20", "-0o40", "-0b100000"), - nc(-31, "-31", "-0x1f", "-0o37", "-0b11111"), - nc(-17, "-17", "-0x11", "-0o21", "-0b10001"), - nc(-16, "-16", "-0x10", "-0o20", "-0b10000"), - nc(-15, "-15", "-0xf", "-0o17", "-0b1111"), - nc(-11, "-11", "-0xb", "-0o13", "-0b1011"), - nc(-10, "-10", "-0xa", "-0o12", "-0b1010"), - nc(-9, "-9", "-0x9", "-0o11", "-0b1001"), - nc(-8, "-8", "-0x8", "-0o10", "-0b1000"), - nc(-7, "-7", "-0x7", "-0o7", "-0b111"), - nc(-6, "-6", "-0x6", "-0o6", "-0b110"), - nc(-5, "-5", "-0x5", "-0o5", "-0b101"), - nc(-4, "-4", "-0x4", "-0o4", "-0b100"), - nc(-3, "-3", "-0x3", "-0o3", "-0b11"), - nc(-2, "-2", "-0x2", "-0o2", "-0b10"), - nc(-1, "-1", "-0x1", "-0o1", "-0b1"), - nc(0, "0", "0x0", "0o0", "0b0"), - nc(1, "1", "0x1", "0o1", "0b1"), - nc(2, "2", "0x2", "0o2", "0b10"), - nc(3, "3", "0x3", "0o3", "0b11"), - nc(4, "4", "0x4", "0o4", "0b100"), - nc(5, "5", "0x5", "0o5", "0b101"), - nc(6, "6", "0x6", "0o6", "0b110"), - nc(7, "7", "0x7", "0o7", "0b111"), - nc(8, "8", "0x8", "0o10", "0b1000"), - nc(9, "9", "0x9", "0o11", "0b1001"), - nc(10, "10", "0xa", "0o12", "0b1010"), - nc(11, "11", "0xb", "0o13", "0b1011"), - nc(15, "15", "0xf", "0o17", "0b1111"), - nc(16, "16", "0x10", "0o20", "0b10000"), - nc(17, "17", "0x11", "0o21", "0b10001"), - nc(31, "31", "0x1f", "0o37", "0b11111"), - nc(32, "32", "0x20", "0o40", "0b100000"), - nc(33, "33", "0x21", "0o41", "0b100001"), - nc(63, "63", "0x3f", "0o77", "0b111111"), - nc(64, "64", "0x40", "0o100", "0b1000000"), - nc(65, "65", "0x41", "0o101", "0b1000001"), - nc(99, "99", "0x63", "0o143", "0b1100011"), - nc(100, "100", "0x64", "0o144", "0b1100100"), - nc(101, "101", "0x65", "0o145", "0b1100101"), - nc(127, "127", "0x7f", "0o177", "0b1111111"), - nc(128, "128", "0x80", "0o200", "0b10000000"), - nc(129, "129", "0x81", "0o201", "0b10000001"), - nc(255, "255", "0xff", "0o377", "0b11111111"), - nc(256, "256", "0x100", "0o400", "0b100000000"), - nc(257, "257", "0x101", "0o401", "0b100000001"), - nc(326, "326", "0x146", "0o506", "0b101000110"), - nc(327, "327", "0x147", "0o507", "0b101000111"), - nc(328, "328", "0x148", "0o510", "0b101001000"), - nc(511, "511", "0x1ff", "0o777", "0b111111111"), - nc(512, "512", "0x200", "0o1000", "0b1000000000"), - nc(513, "513", "0x201", "0o1001", "0b1000000001"), - nc(999, "999", "0x3e7", "0o1747", "0b1111100111"), - nc(1000, "1000", "0x3e8", "0o1750", "0b1111101000"), - nc(1001, "1001", "0x3e9", "0o1751", "0b1111101001"), - nc(1023, "1023", "0x3ff", "0o1777", "0b1111111111"), - nc(1024, "1024", "0x400", "0o2000", "0b10000000000"), - nc(1025, "1025", "0x401", "0o2001", "0b10000000001"), - nc(2047, "2047", "0x7ff", "0o3777", "0b11111111111"), - nc(2048, "2048", "0x800", "0o4000", "0b100000000000"), - nc(2049, "2049", "0x801", "0o4001", "0b100000000001"), - nc(3275, "3275", "0xccb", "0o6313", "0b110011001011"), - nc(3276, "3276", "0xccc", "0o6314", "0b110011001100"), - nc(3277, "3277", "0xccd", "0o6315", "0b110011001101"), - nc(4095, "4095", "0xfff", "0o7777", "0b111111111111"), - nc(4096, "4096", "0x1000", "0o10000", "0b1000000000000"), - nc(4097, "4097", "0x1001", "0o10001", "0b1000000000001"), - nc(8191, "8191", "0x1fff", "0o17777", "0b1111111111111"), - nc(8192, "8192", "0x2000", "0o20000", "0b10000000000000"), - nc(8193, "8193", "0x2001", "0o20001", "0b10000000000001"), - nc(9999, "9999", "0x270f", "0o23417", "0b10011100001111"), - nc(10000, "10000", "0x2710", "0o23420", "0b10011100010000"), - nc(10001, "10001", "0x2711", "0o23421", "0b10011100010001"), - nc(16383, "16383", "0x3fff", "0o37777", "0b11111111111111"), - nc(16384, "16384", "0x4000", "0o40000", "0b100000000000000"), - nc(16385, "16385", "0x4001", "0o40001", "0b100000000000001"), - nc(32762, "32762", "0x7ffa", "0o77772", "0b111111111111010"), - nc(32763, "32763", "0x7ffb", "0o77773", "0b111111111111011"), - nc(32764, "32764", "0x7ffc", "0o77774", "0b111111111111100"), - nc(32765, "32765", "0x7ffd", "0o77775", "0b111111111111101"), - nc(32766, "32766", "0x7ffe", "0o77776", "0b111111111111110"), - nc(32767, "32767", "0x7fff", "0o77777", "0b111111111111111"), -#undef nc - }; -}; - - -template<> -struct numbers -{ - using value_type = uint16_t; - static C4_INLINE_CONSTEXPR const number_case vals[] = { -#define nc(val, dec, hex, bin, oct) \ - number_case{(value_type)UINT16_C(val), csubstr{dec}, csubstr{hex}, csubstr{bin}, csubstr{oct}} - nc(0, "0", "0x0", "0o0", "0b0"), - nc(1, "1", "0x1", "0o1", "0b1"), - nc(2, "2", "0x2", "0o2", "0b10"), - nc(3, "3", "0x3", "0o3", "0b11"), - nc(4, "4", "0x4", "0o4", "0b100"), - nc(5, "5", "0x5", "0o5", "0b101"), - nc(6, "6", "0x6", "0o6", "0b110"), - nc(7, "7", "0x7", "0o7", "0b111"), - nc(8, "8", "0x8", "0o10", "0b1000"), - nc(9, "9", "0x9", "0o11", "0b1001"), - nc(10, "10", "0xa", "0o12", "0b1010"), - nc(11, "11", "0xb", "0o13", "0b1011"), - nc(15, "15", "0xf", "0o17", "0b1111"), - nc(16, "16", "0x10", "0o20", "0b10000"), - nc(17, "17", "0x11", "0o21", "0b10001"), - nc(31, "31", "0x1f", "0o37", "0b11111"), - nc(32, "32", "0x20", "0o40", "0b100000"), - nc(33, "33", "0x21", "0o41", "0b100001"), - nc(63, "63", "0x3f", "0o77", "0b111111"), - nc(64, "64", "0x40", "0o100", "0b1000000"), - nc(65, "65", "0x41", "0o101", "0b1000001"), - nc(66, "66", "0x42", "0o102", "0b1000010"), - nc(99, "99", "0x63", "0o143", "0b1100011"), - nc(100, "100", "0x64", "0o144", "0b1100100"), - nc(101, "101", "0x65", "0o145", "0b1100101"), - nc(127, "127", "0x7f", "0o177", "0b1111111"), - nc(128, "128", "0x80", "0o200", "0b10000000"), - nc(129, "129", "0x81", "0o201", "0b10000001"), - nc(255, "255", "0xff", "0o377", "0b11111111"), - nc(256, "256", "0x100", "0o400", "0b100000000"), - nc(257, "257", "0x101", "0o401", "0b100000001"), - nc(511, "511", "0x1ff", "0o777", "0b111111111"), - nc(512, "512", "0x200", "0o1000", "0b1000000000"), - nc(513, "513", "0x201", "0o1001", "0b1000000001"), - nc(654, "654", "0x28e", "0o1216", "0b1010001110"), - nc(655, "655", "0x28f", "0o1217", "0b1010001111"), - nc(656, "656", "0x290", "0o1220", "0b1010010000"), - nc(999, "999", "0x3e7", "0o1747", "0b1111100111"), - nc(1000, "1000", "0x3e8", "0o1750", "0b1111101000"), - nc(1001, "1001", "0x3e9", "0o1751", "0b1111101001"), - nc(1023, "1023", "0x3ff", "0o1777", "0b1111111111"), - nc(1024, "1024", "0x400", "0o2000", "0b10000000000"), - nc(1025, "1025", "0x401", "0o2001", "0b10000000001"), - nc(2047, "2047", "0x7ff", "0o3777", "0b11111111111"), - nc(2048, "2048", "0x800", "0o4000", "0b100000000000"), - nc(2049, "2049", "0x801", "0o4001", "0b100000000001"), - nc(4095, "4095", "0xfff", "0o7777", "0b111111111111"), - nc(4096, "4096", "0x1000", "0o10000", "0b1000000000000"), - nc(4097, "4097", "0x1001", "0o10001", "0b1000000000001"), - nc(6552, "6552", "0x1998", "0o14630", "0b1100110011000"), - nc(6553, "6553", "0x1999", "0o14631", "0b1100110011001"), - nc(6554, "6554", "0x199a", "0o14632", "0b1100110011010"), - nc(8191, "8191", "0x1fff", "0o17777", "0b1111111111111"), - nc(8192, "8192", "0x2000", "0o20000", "0b10000000000000"), - nc(8193, "8193", "0x2001", "0o20001", "0b10000000000001"), - nc(9999, "9999", "0x270f", "0o23417", "0b10011100001111"), - nc(10000, "10000", "0x2710", "0o23420", "0b10011100010000"), - nc(10001, "10001", "0x2711", "0o23421", "0b10011100010001"), - nc(16383, "16383", "0x3fff", "0o37777", "0b11111111111111"), - nc(16384, "16384", "0x4000", "0o40000", "0b100000000000000"), - nc(16385, "16385", "0x4001", "0o40001", "0b100000000000001"), - nc(32767, "32767", "0x7fff", "0o77777", "0b111111111111111"), - nc(32768, "32768", "0x8000", "0o100000", "0b1000000000000000"), - nc(32769, "32769", "0x8001", "0o100001", "0b1000000000000001"), - nc(65531, "65531", "0xfffb", "0o177773", "0b1111111111111011"), - nc(65532, "65532", "0xfffc", "0o177774", "0b1111111111111100"), - nc(65533, "65533", "0xfffd", "0o177775", "0b1111111111111101"), - nc(65534, "65534", "0xfffe", "0o177776", "0b1111111111111110"), - nc(65535, "65535", "0xffff", "0o177777", "0b1111111111111111"), -#undef nc - }; -}; - - -template<> -struct numbers -{ - using value_type = int32_t; - static C4_INLINE_CONSTEXPR const number_case vals[] = { -#define nc(val, dec, hex, bin, oct) \ - number_case{(value_type)INT32_C(val), csubstr{dec}, csubstr{hex}, csubstr{bin}, csubstr{oct}} - nc(-2147483648, "-2147483648", "-0x80000000", "-0o20000000000", "-0b10000000000000000000000000000000"), - nc(-2147483647, "-2147483647", "-0x7fffffff", "-0o17777777777", "-0b1111111111111111111111111111111"), - nc(-2147483646, "-2147483646", "-0x7ffffffe", "-0o17777777776", "-0b1111111111111111111111111111110"), - nc(-2147483645, "-2147483645", "-0x7ffffffd", "-0o17777777775", "-0b1111111111111111111111111111101"), - nc(-2147483644, "-2147483644", "-0x7ffffffc", "-0o17777777774", "-0b1111111111111111111111111111100"), - nc(-2147483643, "-2147483643", "-0x7ffffffb", "-0o17777777773", "-0b1111111111111111111111111111011"), - nc(-1073741825, "-1073741825", "-0x40000001", "-0o10000000001", "-0b1000000000000000000000000000001"), - nc(-1073741824, "-1073741824", "-0x40000000", "-0o10000000000", "-0b1000000000000000000000000000000"), - nc(-1073741823, "-1073741823", "-0x3fffffff", "-0o7777777777", "-0b111111111111111111111111111111"), - nc(-1000000001, "-1000000001", "-0x3b9aca01", "-0o7346545001", "-0b111011100110101100101000000001"), - nc(-1000000000, "-1000000000", "-0x3b9aca00", "-0o7346545000", "-0b111011100110101100101000000000"), - nc(-999999999, "-999999999", "-0x3b9ac9ff", "-0o7346544777", "-0b111011100110101100100111111111"), - nc(-536870913, "-536870913", "-0x20000001", "-0o4000000001", "-0b100000000000000000000000000001"), - nc(-536870912, "-536870912", "-0x20000000", "-0o4000000000", "-0b100000000000000000000000000000"), - nc(-536870911, "-536870911", "-0x1fffffff", "-0o3777777777", "-0b11111111111111111111111111111"), - nc(-268435457, "-268435457", "-0x10000001", "-0o2000000001", "-0b10000000000000000000000000001"), - nc(-268435456, "-268435456", "-0x10000000", "-0o2000000000", "-0b10000000000000000000000000000"), - nc(-268435455, "-268435455", "-0xfffffff", "-0o1777777777", "-0b1111111111111111111111111111"), - nc(-214748364, "-214748364", "-0xccccccc", "-0o1463146314", "-0b1100110011001100110011001100"), - nc(-134217729, "-134217729", "-0x8000001", "-0o1000000001", "-0b1000000000000000000000000001"), - nc(-134217728, "-134217728", "-0x8000000", "-0o1000000000", "-0b1000000000000000000000000000"), - nc(-134217727, "-134217727", "-0x7ffffff", "-0o777777777", "-0b111111111111111111111111111"), - nc(-100000001, "-100000001", "-0x5f5e101", "-0o575360401", "-0b101111101011110000100000001"), - nc(-100000000, "-100000000", "-0x5f5e100", "-0o575360400", "-0b101111101011110000100000000"), - nc(-99999999, "-99999999", "-0x5f5e0ff", "-0o575360377", "-0b101111101011110000011111111"), - nc(-67108865, "-67108865", "-0x4000001", "-0o400000001", "-0b100000000000000000000000001"), - nc(-67108864, "-67108864", "-0x4000000", "-0o400000000", "-0b100000000000000000000000000"), - nc(-67108863, "-67108863", "-0x3ffffff", "-0o377777777", "-0b11111111111111111111111111"), - nc(-33554433, "-33554433", "-0x2000001", "-0o200000001", "-0b10000000000000000000000001"), - nc(-33554432, "-33554432", "-0x2000000", "-0o200000000", "-0b10000000000000000000000000"), - nc(-33554431, "-33554431", "-0x1ffffff", "-0o177777777", "-0b1111111111111111111111111"), - nc(-21474836, "-21474836", "-0x147ae14", "-0o121727024", "-0b1010001111010111000010100"), - nc(-16777217, "-16777217", "-0x1000001", "-0o100000001", "-0b1000000000000000000000001"), - nc(-16777216, "-16777216", "-0x1000000", "-0o100000000", "-0b1000000000000000000000000"), - nc(-16777215, "-16777215", "-0xffffff", "-0o77777777", "-0b111111111111111111111111"), - nc(-10000001, "-10000001", "-0x989681", "-0o46113201", "-0b100110001001011010000001"), - nc(-10000000, "-10000000", "-0x989680", "-0o46113200", "-0b100110001001011010000000"), - nc(-9999999, "-9999999", "-0x98967f", "-0o46113177", "-0b100110001001011001111111"), - nc(-8388609, "-8388609", "-0x800001", "-0o40000001", "-0b100000000000000000000001"), - nc(-8388608, "-8388608", "-0x800000", "-0o40000000", "-0b100000000000000000000000"), - nc(-8388607, "-8388607", "-0x7fffff", "-0o37777777", "-0b11111111111111111111111"), - nc(-4194305, "-4194305", "-0x400001", "-0o20000001", "-0b10000000000000000000001"), - nc(-4194304, "-4194304", "-0x400000", "-0o20000000", "-0b10000000000000000000000"), - nc(-4194303, "-4194303", "-0x3fffff", "-0o17777777", "-0b1111111111111111111111"), - nc(-2147483, "-2147483", "-0x20c49b", "-0o10142233", "-0b1000001100010010011011"), - nc(-2097153, "-2097153", "-0x200001", "-0o10000001", "-0b1000000000000000000001"), - nc(-2097152, "-2097152", "-0x200000", "-0o10000000", "-0b1000000000000000000000"), - nc(-2097151, "-2097151", "-0x1fffff", "-0o7777777", "-0b111111111111111111111"), - nc(-1048577, "-1048577", "-0x100001", "-0o4000001", "-0b100000000000000000001"), - nc(-1048576, "-1048576", "-0x100000", "-0o4000000", "-0b100000000000000000000"), - nc(-1048575, "-1048575", "-0xfffff", "-0o3777777", "-0b11111111111111111111"), - nc(-1000001, "-1000001", "-0xf4241", "-0o3641101", "-0b11110100001001000001"), - nc(-1000000, "-1000000", "-0xf4240", "-0o3641100", "-0b11110100001001000000"), - nc(-999999, "-999999", "-0xf423f", "-0o3641077", "-0b11110100001000111111"), - nc(-524289, "-524289", "-0x80001", "-0o2000001", "-0b10000000000000000001"), - nc(-524288, "-524288", "-0x80000", "-0o2000000", "-0b10000000000000000000"), - nc(-524287, "-524287", "-0x7ffff", "-0o1777777", "-0b1111111111111111111"), - nc(-262145, "-262145", "-0x40001", "-0o1000001", "-0b1000000000000000001"), - nc(-262144, "-262144", "-0x40000", "-0o1000000", "-0b1000000000000000000"), - nc(-262143, "-262143", "-0x3ffff", "-0o777777", "-0b111111111111111111"), - nc(-214748, "-214748", "-0x346dc", "-0o643334", "-0b110100011011011100"), - nc(-131073, "-131073", "-0x20001", "-0o400001", "-0b100000000000000001"), - nc(-131072, "-131072", "-0x20000", "-0o400000", "-0b100000000000000000"), - nc(-131071, "-131071", "-0x1ffff", "-0o377777", "-0b11111111111111111"), - nc(-100001, "-100001", "-0x186a1", "-0o303241", "-0b11000011010100001"), - nc(-100000, "-100000", "-0x186a0", "-0o303240", "-0b11000011010100000"), - nc(-99999, "-99999", "-0x1869f", "-0o303237", "-0b11000011010011111"), - nc(-65537, "-65537", "-0x10001", "-0o200001", "-0b10000000000000001"), - nc(-65536, "-65536", "-0x10000", "-0o200000", "-0b10000000000000000"), - nc(-65535, "-65535", "-0xffff", "-0o177777", "-0b1111111111111111"), - nc(-32769, "-32769", "-0x8001", "-0o100001", "-0b1000000000000001"), - nc(-32768, "-32768", "-0x8000", "-0o100000", "-0b1000000000000000"), - nc(-32767, "-32767", "-0x7fff", "-0o77777", "-0b111111111111111"), - nc(-21474, "-21474", "-0x53e2", "-0o51742", "-0b101001111100010"), - nc(-16385, "-16385", "-0x4001", "-0o40001", "-0b100000000000001"), - nc(-16384, "-16384", "-0x4000", "-0o40000", "-0b100000000000000"), - nc(-16383, "-16383", "-0x3fff", "-0o37777", "-0b11111111111111"), - nc(-10001, "-10001", "-0x2711", "-0o23421", "-0b10011100010001"), - nc(-10000, "-10000", "-0x2710", "-0o23420", "-0b10011100010000"), - nc(-9999, "-9999", "-0x270f", "-0o23417", "-0b10011100001111"), - nc(-8193, "-8193", "-0x2001", "-0o20001", "-0b10000000000001"), - nc(-8192, "-8192", "-0x2000", "-0o20000", "-0b10000000000000"), - nc(-8191, "-8191", "-0x1fff", "-0o17777", "-0b1111111111111"), - nc(-4097, "-4097", "-0x1001", "-0o10001", "-0b1000000000001"), - nc(-4096, "-4096", "-0x1000", "-0o10000", "-0b1000000000000"), - nc(-4095, "-4095", "-0xfff", "-0o7777", "-0b111111111111"), - nc(-2147, "-2147", "-0x863", "-0o4143", "-0b100001100011"), - nc(-2049, "-2049", "-0x801", "-0o4001", "-0b100000000001"), - nc(-2048, "-2048", "-0x800", "-0o4000", "-0b100000000000"), - nc(-2047, "-2047", "-0x7ff", "-0o3777", "-0b11111111111"), - nc(-1025, "-1025", "-0x401", "-0o2001", "-0b10000000001"), - nc(-1024, "-1024", "-0x400", "-0o2000", "-0b10000000000"), - nc(-1023, "-1023", "-0x3ff", "-0o1777", "-0b1111111111"), - nc(-1001, "-1001", "-0x3e9", "-0o1751", "-0b1111101001"), - nc(-1000, "-1000", "-0x3e8", "-0o1750", "-0b1111101000"), - nc(-999, "-999", "-0x3e7", "-0o1747", "-0b1111100111"), - nc(-513, "-513", "-0x201", "-0o1001", "-0b1000000001"), - nc(-512, "-512", "-0x200", "-0o1000", "-0b1000000000"), - nc(-511, "-511", "-0x1ff", "-0o777", "-0b111111111"), - nc(-257, "-257", "-0x101", "-0o401", "-0b100000001"), - nc(-256, "-256", "-0x100", "-0o400", "-0b100000000"), - nc(-255, "-255", "-0xff", "-0o377", "-0b11111111"), - nc(-214, "-214", "-0xd6", "-0o326", "-0b11010110"), - nc(-129, "-129", "-0x81", "-0o201", "-0b10000001"), - nc(-128, "-128", "-0x80", "-0o200", "-0b10000000"), - nc(-127, "-127", "-0x7f", "-0o177", "-0b1111111"), - nc(-101, "-101", "-0x65", "-0o145", "-0b1100101"), - nc(-100, "-100", "-0x64", "-0o144", "-0b1100100"), - nc(-99, "-99", "-0x63", "-0o143", "-0b1100011"), - nc(-65, "-65", "-0x41", "-0o101", "-0b1000001"), - nc(-64, "-64", "-0x40", "-0o100", "-0b1000000"), - nc(-63, "-63", "-0x3f", "-0o77", "-0b111111"), - nc(-33, "-33", "-0x21", "-0o41", "-0b100001"), - nc(-32, "-32", "-0x20", "-0o40", "-0b100000"), - nc(-31, "-31", "-0x1f", "-0o37", "-0b11111"), - nc(-21, "-21", "-0x15", "-0o25", "-0b10101"), - nc(-17, "-17", "-0x11", "-0o21", "-0b10001"), - nc(-16, "-16", "-0x10", "-0o20", "-0b10000"), - nc(-15, "-15", "-0xf", "-0o17", "-0b1111"), - nc(-11, "-11", "-0xb", "-0o13", "-0b1011"), - nc(-10, "-10", "-0xa", "-0o12", "-0b1010"), - nc(-9, "-9", "-0x9", "-0o11", "-0b1001"), - nc(-8, "-8", "-0x8", "-0o10", "-0b1000"), - nc(-7, "-7", "-0x7", "-0o7", "-0b111"), - nc(-6, "-6", "-0x6", "-0o6", "-0b110"), - nc(-5, "-5", "-0x5", "-0o5", "-0b101"), - nc(-4, "-4", "-0x4", "-0o4", "-0b100"), - nc(-3, "-3", "-0x3", "-0o3", "-0b11"), - nc(-2, "-2", "-0x2", "-0o2", "-0b10"), - nc(-1, "-1", "-0x1", "-0o1", "-0b1"), - nc(0, "0", "0x0", "0o0", "0b0"), - nc(1, "1", "0x1", "0o1", "0b1"), - nc(2, "2", "0x2", "0o2", "0b10"), - nc(3, "3", "0x3", "0o3", "0b11"), - nc(4, "4", "0x4", "0o4", "0b100"), - nc(5, "5", "0x5", "0o5", "0b101"), - nc(6, "6", "0x6", "0o6", "0b110"), - nc(7, "7", "0x7", "0o7", "0b111"), - nc(8, "8", "0x8", "0o10", "0b1000"), - nc(9, "9", "0x9", "0o11", "0b1001"), - nc(10, "10", "0xa", "0o12", "0b1010"), - nc(11, "11", "0xb", "0o13", "0b1011"), - nc(15, "15", "0xf", "0o17", "0b1111"), - nc(16, "16", "0x10", "0o20", "0b10000"), - nc(17, "17", "0x11", "0o21", "0b10001"), - nc(20, "20", "0x14", "0o24", "0b10100"), - nc(21, "21", "0x15", "0o25", "0b10101"), - nc(22, "22", "0x16", "0o26", "0b10110"), - nc(31, "31", "0x1f", "0o37", "0b11111"), - nc(32, "32", "0x20", "0o40", "0b100000"), - nc(33, "33", "0x21", "0o41", "0b100001"), - nc(63, "63", "0x3f", "0o77", "0b111111"), - nc(64, "64", "0x40", "0o100", "0b1000000"), - nc(65, "65", "0x41", "0o101", "0b1000001"), - nc(99, "99", "0x63", "0o143", "0b1100011"), - nc(100, "100", "0x64", "0o144", "0b1100100"), - nc(101, "101", "0x65", "0o145", "0b1100101"), - nc(127, "127", "0x7f", "0o177", "0b1111111"), - nc(128, "128", "0x80", "0o200", "0b10000000"), - nc(129, "129", "0x81", "0o201", "0b10000001"), - nc(213, "213", "0xd5", "0o325", "0b11010101"), - nc(214, "214", "0xd6", "0o326", "0b11010110"), - nc(215, "215", "0xd7", "0o327", "0b11010111"), - nc(255, "255", "0xff", "0o377", "0b11111111"), - nc(256, "256", "0x100", "0o400", "0b100000000"), - nc(257, "257", "0x101", "0o401", "0b100000001"), - nc(511, "511", "0x1ff", "0o777", "0b111111111"), - nc(512, "512", "0x200", "0o1000", "0b1000000000"), - nc(513, "513", "0x201", "0o1001", "0b1000000001"), - nc(999, "999", "0x3e7", "0o1747", "0b1111100111"), - nc(1000, "1000", "0x3e8", "0o1750", "0b1111101000"), - nc(1001, "1001", "0x3e9", "0o1751", "0b1111101001"), - nc(1023, "1023", "0x3ff", "0o1777", "0b1111111111"), - nc(1024, "1024", "0x400", "0o2000", "0b10000000000"), - nc(1025, "1025", "0x401", "0o2001", "0b10000000001"), - nc(2047, "2047", "0x7ff", "0o3777", "0b11111111111"), - nc(2048, "2048", "0x800", "0o4000", "0b100000000000"), - nc(2049, "2049", "0x801", "0o4001", "0b100000000001"), - nc(2146, "2146", "0x862", "0o4142", "0b100001100010"), - nc(2147, "2147", "0x863", "0o4143", "0b100001100011"), - nc(2148, "2148", "0x864", "0o4144", "0b100001100100"), - nc(4095, "4095", "0xfff", "0o7777", "0b111111111111"), - nc(4096, "4096", "0x1000", "0o10000", "0b1000000000000"), - nc(4097, "4097", "0x1001", "0o10001", "0b1000000000001"), - nc(8191, "8191", "0x1fff", "0o17777", "0b1111111111111"), - nc(8192, "8192", "0x2000", "0o20000", "0b10000000000000"), - nc(8193, "8193", "0x2001", "0o20001", "0b10000000000001"), - nc(9999, "9999", "0x270f", "0o23417", "0b10011100001111"), - nc(10000, "10000", "0x2710", "0o23420", "0b10011100010000"), - nc(10001, "10001", "0x2711", "0o23421", "0b10011100010001"), - nc(16383, "16383", "0x3fff", "0o37777", "0b11111111111111"), - nc(16384, "16384", "0x4000", "0o40000", "0b100000000000000"), - nc(16385, "16385", "0x4001", "0o40001", "0b100000000000001"), - nc(21473, "21473", "0x53e1", "0o51741", "0b101001111100001"), - nc(21474, "21474", "0x53e2", "0o51742", "0b101001111100010"), - nc(21475, "21475", "0x53e3", "0o51743", "0b101001111100011"), - nc(32767, "32767", "0x7fff", "0o77777", "0b111111111111111"), - nc(32768, "32768", "0x8000", "0o100000", "0b1000000000000000"), - nc(32769, "32769", "0x8001", "0o100001", "0b1000000000000001"), - nc(65535, "65535", "0xffff", "0o177777", "0b1111111111111111"), - nc(65536, "65536", "0x10000", "0o200000", "0b10000000000000000"), - nc(65537, "65537", "0x10001", "0o200001", "0b10000000000000001"), - nc(99999, "99999", "0x1869f", "0o303237", "0b11000011010011111"), - nc(100000, "100000", "0x186a0", "0o303240", "0b11000011010100000"), - nc(100001, "100001", "0x186a1", "0o303241", "0b11000011010100001"), - nc(131071, "131071", "0x1ffff", "0o377777", "0b11111111111111111"), - nc(131072, "131072", "0x20000", "0o400000", "0b100000000000000000"), - nc(131073, "131073", "0x20001", "0o400001", "0b100000000000000001"), - nc(214747, "214747", "0x346db", "0o643333", "0b110100011011011011"), - nc(214748, "214748", "0x346dc", "0o643334", "0b110100011011011100"), - nc(214749, "214749", "0x346dd", "0o643335", "0b110100011011011101"), - nc(262143, "262143", "0x3ffff", "0o777777", "0b111111111111111111"), - nc(262144, "262144", "0x40000", "0o1000000", "0b1000000000000000000"), - nc(262145, "262145", "0x40001", "0o1000001", "0b1000000000000000001"), - nc(524287, "524287", "0x7ffff", "0o1777777", "0b1111111111111111111"), - nc(524288, "524288", "0x80000", "0o2000000", "0b10000000000000000000"), - nc(524289, "524289", "0x80001", "0o2000001", "0b10000000000000000001"), - nc(999999, "999999", "0xf423f", "0o3641077", "0b11110100001000111111"), - nc(1000000, "1000000", "0xf4240", "0o3641100", "0b11110100001001000000"), - nc(1000001, "1000001", "0xf4241", "0o3641101", "0b11110100001001000001"), - nc(1048575, "1048575", "0xfffff", "0o3777777", "0b11111111111111111111"), - nc(1048576, "1048576", "0x100000", "0o4000000", "0b100000000000000000000"), - nc(1048577, "1048577", "0x100001", "0o4000001", "0b100000000000000000001"), - nc(2097151, "2097151", "0x1fffff", "0o7777777", "0b111111111111111111111"), - nc(2097152, "2097152", "0x200000", "0o10000000", "0b1000000000000000000000"), - nc(2097153, "2097153", "0x200001", "0o10000001", "0b1000000000000000000001"), - nc(2147482, "2147482", "0x20c49a", "0o10142232", "0b1000001100010010011010"), - nc(2147483, "2147483", "0x20c49b", "0o10142233", "0b1000001100010010011011"), - nc(2147484, "2147484", "0x20c49c", "0o10142234", "0b1000001100010010011100"), - nc(4194303, "4194303", "0x3fffff", "0o17777777", "0b1111111111111111111111"), - nc(4194304, "4194304", "0x400000", "0o20000000", "0b10000000000000000000000"), - nc(4194305, "4194305", "0x400001", "0o20000001", "0b10000000000000000000001"), - nc(8388607, "8388607", "0x7fffff", "0o37777777", "0b11111111111111111111111"), - nc(8388608, "8388608", "0x800000", "0o40000000", "0b100000000000000000000000"), - nc(8388609, "8388609", "0x800001", "0o40000001", "0b100000000000000000000001"), - nc(9999999, "9999999", "0x98967f", "0o46113177", "0b100110001001011001111111"), - nc(10000000, "10000000", "0x989680", "0o46113200", "0b100110001001011010000000"), - nc(10000001, "10000001", "0x989681", "0o46113201", "0b100110001001011010000001"), - nc(16777215, "16777215", "0xffffff", "0o77777777", "0b111111111111111111111111"), - nc(16777216, "16777216", "0x1000000", "0o100000000", "0b1000000000000000000000000"), - nc(16777217, "16777217", "0x1000001", "0o100000001", "0b1000000000000000000000001"), - nc(21474835, "21474835", "0x147ae13", "0o121727023", "0b1010001111010111000010011"), - nc(21474836, "21474836", "0x147ae14", "0o121727024", "0b1010001111010111000010100"), - nc(21474837, "21474837", "0x147ae15", "0o121727025", "0b1010001111010111000010101"), - nc(33554431, "33554431", "0x1ffffff", "0o177777777", "0b1111111111111111111111111"), - nc(33554432, "33554432", "0x2000000", "0o200000000", "0b10000000000000000000000000"), - nc(33554433, "33554433", "0x2000001", "0o200000001", "0b10000000000000000000000001"), - nc(67108863, "67108863", "0x3ffffff", "0o377777777", "0b11111111111111111111111111"), - nc(67108864, "67108864", "0x4000000", "0o400000000", "0b100000000000000000000000000"), - nc(67108865, "67108865", "0x4000001", "0o400000001", "0b100000000000000000000000001"), - nc(99999999, "99999999", "0x5f5e0ff", "0o575360377", "0b101111101011110000011111111"), - nc(100000000, "100000000", "0x5f5e100", "0o575360400", "0b101111101011110000100000000"), - nc(100000001, "100000001", "0x5f5e101", "0o575360401", "0b101111101011110000100000001"), - nc(134217727, "134217727", "0x7ffffff", "0o777777777", "0b111111111111111111111111111"), - nc(134217728, "134217728", "0x8000000", "0o1000000000", "0b1000000000000000000000000000"), - nc(134217729, "134217729", "0x8000001", "0o1000000001", "0b1000000000000000000000000001"), - nc(214748363, "214748363", "0xccccccb", "0o1463146313", "0b1100110011001100110011001011"), - nc(214748364, "214748364", "0xccccccc", "0o1463146314", "0b1100110011001100110011001100"), - nc(214748365, "214748365", "0xccccccd", "0o1463146315", "0b1100110011001100110011001101"), - nc(268435455, "268435455", "0xfffffff", "0o1777777777", "0b1111111111111111111111111111"), - nc(268435456, "268435456", "0x10000000", "0o2000000000", "0b10000000000000000000000000000"), - nc(268435457, "268435457", "0x10000001", "0o2000000001", "0b10000000000000000000000000001"), - nc(536870911, "536870911", "0x1fffffff", "0o3777777777", "0b11111111111111111111111111111"), - nc(536870912, "536870912", "0x20000000", "0o4000000000", "0b100000000000000000000000000000"), - nc(536870913, "536870913", "0x20000001", "0o4000000001", "0b100000000000000000000000000001"), - nc(999999999, "999999999", "0x3b9ac9ff", "0o7346544777", "0b111011100110101100100111111111"), - nc(1000000000, "1000000000", "0x3b9aca00", "0o7346545000", "0b111011100110101100101000000000"), - nc(1000000001, "1000000001", "0x3b9aca01", "0o7346545001", "0b111011100110101100101000000001"), - nc(1073741823, "1073741823", "0x3fffffff", "0o7777777777", "0b111111111111111111111111111111"), - nc(1073741824, "1073741824", "0x40000000", "0o10000000000", "0b1000000000000000000000000000000"), - nc(1073741825, "1073741825", "0x40000001", "0o10000000001", "0b1000000000000000000000000000001"), - nc(2147483642, "2147483642", "0x7ffffffa", "0o17777777772", "0b1111111111111111111111111111010"), - nc(2147483643, "2147483643", "0x7ffffffb", "0o17777777773", "0b1111111111111111111111111111011"), - nc(2147483644, "2147483644", "0x7ffffffc", "0o17777777774", "0b1111111111111111111111111111100"), - nc(2147483645, "2147483645", "0x7ffffffd", "0o17777777775", "0b1111111111111111111111111111101"), - nc(2147483646, "2147483646", "0x7ffffffe", "0o17777777776", "0b1111111111111111111111111111110"), - nc(2147483647, "2147483647", "0x7fffffff", "0o17777777777", "0b1111111111111111111111111111111"), -#undef nc - }; -}; - - -template<> -struct numbers -{ - using value_type = uint32_t; - static C4_INLINE_CONSTEXPR const number_case vals[] = { -#define nc(val, dec, hex, bin, oct) \ - number_case{(value_type)UINT32_C(val), csubstr{dec}, csubstr{hex}, csubstr{bin}, csubstr{oct}} - nc(0, "0", "0x0", "0o0", "0b0"), - nc(1, "1", "0x1", "0o1", "0b1"), - nc(2, "2", "0x2", "0o2", "0b10"), - nc(3, "3", "0x3", "0o3", "0b11"), - nc(4, "4", "0x4", "0o4", "0b100"), - nc(5, "5", "0x5", "0o5", "0b101"), - nc(6, "6", "0x6", "0o6", "0b110"), - nc(7, "7", "0x7", "0o7", "0b111"), - nc(8, "8", "0x8", "0o10", "0b1000"), - nc(9, "9", "0x9", "0o11", "0b1001"), - nc(10, "10", "0xa", "0o12", "0b1010"), - nc(11, "11", "0xb", "0o13", "0b1011"), - nc(15, "15", "0xf", "0o17", "0b1111"), - nc(16, "16", "0x10", "0o20", "0b10000"), - nc(17, "17", "0x11", "0o21", "0b10001"), - nc(31, "31", "0x1f", "0o37", "0b11111"), - nc(32, "32", "0x20", "0o40", "0b100000"), - nc(33, "33", "0x21", "0o41", "0b100001"), - nc(41, "41", "0x29", "0o51", "0b101001"), - nc(42, "42", "0x2a", "0o52", "0b101010"), - nc(43, "43", "0x2b", "0o53", "0b101011"), - nc(63, "63", "0x3f", "0o77", "0b111111"), - nc(64, "64", "0x40", "0o100", "0b1000000"), - nc(65, "65", "0x41", "0o101", "0b1000001"), - nc(99, "99", "0x63", "0o143", "0b1100011"), - nc(100, "100", "0x64", "0o144", "0b1100100"), - nc(101, "101", "0x65", "0o145", "0b1100101"), - nc(127, "127", "0x7f", "0o177", "0b1111111"), - nc(128, "128", "0x80", "0o200", "0b10000000"), - nc(129, "129", "0x81", "0o201", "0b10000001"), - nc(255, "255", "0xff", "0o377", "0b11111111"), - nc(256, "256", "0x100", "0o400", "0b100000000"), - nc(257, "257", "0x101", "0o401", "0b100000001"), - nc(428, "428", "0x1ac", "0o654", "0b110101100"), - nc(429, "429", "0x1ad", "0o655", "0b110101101"), - nc(430, "430", "0x1ae", "0o656", "0b110101110"), - nc(511, "511", "0x1ff", "0o777", "0b111111111"), - nc(512, "512", "0x200", "0o1000", "0b1000000000"), - nc(513, "513", "0x201", "0o1001", "0b1000000001"), - nc(999, "999", "0x3e7", "0o1747", "0b1111100111"), - nc(1000, "1000", "0x3e8", "0o1750", "0b1111101000"), - nc(1001, "1001", "0x3e9", "0o1751", "0b1111101001"), - nc(1023, "1023", "0x3ff", "0o1777", "0b1111111111"), - nc(1024, "1024", "0x400", "0o2000", "0b10000000000"), - nc(1025, "1025", "0x401", "0o2001", "0b10000000001"), - nc(2047, "2047", "0x7ff", "0o3777", "0b11111111111"), - nc(2048, "2048", "0x800", "0o4000", "0b100000000000"), - nc(2049, "2049", "0x801", "0o4001", "0b100000000001"), - nc(4095, "4095", "0xfff", "0o7777", "0b111111111111"), - nc(4096, "4096", "0x1000", "0o10000", "0b1000000000000"), - nc(4097, "4097", "0x1001", "0o10001", "0b1000000000001"), - nc(4293, "4293", "0x10c5", "0o10305", "0b1000011000101"), - nc(4294, "4294", "0x10c6", "0o10306", "0b1000011000110"), - nc(4295, "4295", "0x10c7", "0o10307", "0b1000011000111"), - nc(8191, "8191", "0x1fff", "0o17777", "0b1111111111111"), - nc(8192, "8192", "0x2000", "0o20000", "0b10000000000000"), - nc(8193, "8193", "0x2001", "0o20001", "0b10000000000001"), - nc(9999, "9999", "0x270f", "0o23417", "0b10011100001111"), - nc(10000, "10000", "0x2710", "0o23420", "0b10011100010000"), - nc(10001, "10001", "0x2711", "0o23421", "0b10011100010001"), - nc(16383, "16383", "0x3fff", "0o37777", "0b11111111111111"), - nc(16384, "16384", "0x4000", "0o40000", "0b100000000000000"), - nc(16385, "16385", "0x4001", "0o40001", "0b100000000000001"), - nc(32767, "32767", "0x7fff", "0o77777", "0b111111111111111"), - nc(32768, "32768", "0x8000", "0o100000", "0b1000000000000000"), - nc(32769, "32769", "0x8001", "0o100001", "0b1000000000000001"), - nc(42948, "42948", "0xa7c4", "0o123704", "0b1010011111000100"), - nc(42949, "42949", "0xa7c5", "0o123705", "0b1010011111000101"), - nc(42950, "42950", "0xa7c6", "0o123706", "0b1010011111000110"), - nc(65535, "65535", "0xffff", "0o177777", "0b1111111111111111"), - nc(65536, "65536", "0x10000", "0o200000", "0b10000000000000000"), - nc(65537, "65537", "0x10001", "0o200001", "0b10000000000000001"), - nc(99999, "99999", "0x1869f", "0o303237", "0b11000011010011111"), - nc(100000, "100000", "0x186a0", "0o303240", "0b11000011010100000"), - nc(100001, "100001", "0x186a1", "0o303241", "0b11000011010100001"), - nc(131071, "131071", "0x1ffff", "0o377777", "0b11111111111111111"), - nc(131072, "131072", "0x20000", "0o400000", "0b100000000000000000"), - nc(131073, "131073", "0x20001", "0o400001", "0b100000000000000001"), - nc(262143, "262143", "0x3ffff", "0o777777", "0b111111111111111111"), - nc(262144, "262144", "0x40000", "0o1000000", "0b1000000000000000000"), - nc(262145, "262145", "0x40001", "0o1000001", "0b1000000000000000001"), - nc(429495, "429495", "0x68db7", "0o1506667", "0b1101000110110110111"), - nc(429496, "429496", "0x68db8", "0o1506670", "0b1101000110110111000"), - nc(429497, "429497", "0x68db9", "0o1506671", "0b1101000110110111001"), - nc(524287, "524287", "0x7ffff", "0o1777777", "0b1111111111111111111"), - nc(524288, "524288", "0x80000", "0o2000000", "0b10000000000000000000"), - nc(524289, "524289", "0x80001", "0o2000001", "0b10000000000000000001"), - nc(999999, "999999", "0xf423f", "0o3641077", "0b11110100001000111111"), - nc(1000000, "1000000", "0xf4240", "0o3641100", "0b11110100001001000000"), - nc(1000001, "1000001", "0xf4241", "0o3641101", "0b11110100001001000001"), - nc(1048575, "1048575", "0xfffff", "0o3777777", "0b11111111111111111111"), - nc(1048576, "1048576", "0x100000", "0o4000000", "0b100000000000000000000"), - nc(1048577, "1048577", "0x100001", "0o4000001", "0b100000000000000000001"), - nc(2097151, "2097151", "0x1fffff", "0o7777777", "0b111111111111111111111"), - nc(2097152, "2097152", "0x200000", "0o10000000", "0b1000000000000000000000"), - nc(2097153, "2097153", "0x200001", "0o10000001", "0b1000000000000000000001"), - nc(4194303, "4194303", "0x3fffff", "0o17777777", "0b1111111111111111111111"), - nc(4194304, "4194304", "0x400000", "0o20000000", "0b10000000000000000000000"), - nc(4194305, "4194305", "0x400001", "0o20000001", "0b10000000000000000000001"), - nc(4294966, "4294966", "0x418936", "0o20304466", "0b10000011000100100110110"), - nc(4294967, "4294967", "0x418937", "0o20304467", "0b10000011000100100110111"), - nc(4294968, "4294968", "0x418938", "0o20304470", "0b10000011000100100111000"), - nc(8388607, "8388607", "0x7fffff", "0o37777777", "0b11111111111111111111111"), - nc(8388608, "8388608", "0x800000", "0o40000000", "0b100000000000000000000000"), - nc(8388609, "8388609", "0x800001", "0o40000001", "0b100000000000000000000001"), - nc(9999999, "9999999", "0x98967f", "0o46113177", "0b100110001001011001111111"), - nc(10000000, "10000000", "0x989680", "0o46113200", "0b100110001001011010000000"), - nc(10000001, "10000001", "0x989681", "0o46113201", "0b100110001001011010000001"), - nc(16777215, "16777215", "0xffffff", "0o77777777", "0b111111111111111111111111"), - nc(16777216, "16777216", "0x1000000", "0o100000000", "0b1000000000000000000000000"), - nc(16777217, "16777217", "0x1000001", "0o100000001", "0b1000000000000000000000001"), - nc(33554431, "33554431", "0x1ffffff", "0o177777777", "0b1111111111111111111111111"), - nc(33554432, "33554432", "0x2000000", "0o200000000", "0b10000000000000000000000000"), - nc(33554433, "33554433", "0x2000001", "0o200000001", "0b10000000000000000000000001"), - nc(42949671, "42949671", "0x28f5c27", "0o243656047", "0b10100011110101110000100111"), - nc(42949672, "42949672", "0x28f5c28", "0o243656050", "0b10100011110101110000101000"), - nc(42949673, "42949673", "0x28f5c29", "0o243656051", "0b10100011110101110000101001"), - nc(67108863, "67108863", "0x3ffffff", "0o377777777", "0b11111111111111111111111111"), - nc(67108864, "67108864", "0x4000000", "0o400000000", "0b100000000000000000000000000"), - nc(67108865, "67108865", "0x4000001", "0o400000001", "0b100000000000000000000000001"), - nc(99999999, "99999999", "0x5f5e0ff", "0o575360377", "0b101111101011110000011111111"), - nc(100000000, "100000000", "0x5f5e100", "0o575360400", "0b101111101011110000100000000"), - nc(100000001, "100000001", "0x5f5e101", "0o575360401", "0b101111101011110000100000001"), - nc(134217727, "134217727", "0x7ffffff", "0o777777777", "0b111111111111111111111111111"), - nc(134217728, "134217728", "0x8000000", "0o1000000000", "0b1000000000000000000000000000"), - nc(134217729, "134217729", "0x8000001", "0o1000000001", "0b1000000000000000000000000001"), - nc(268435455, "268435455", "0xfffffff", "0o1777777777", "0b1111111111111111111111111111"), - nc(268435456, "268435456", "0x10000000", "0o2000000000", "0b10000000000000000000000000000"), - nc(268435457, "268435457", "0x10000001", "0o2000000001", "0b10000000000000000000000000001"), - nc(429496728, "429496728", "0x19999998", "0o3146314630", "0b11001100110011001100110011000"), - nc(429496729, "429496729", "0x19999999", "0o3146314631", "0b11001100110011001100110011001"), - nc(429496730, "429496730", "0x1999999a", "0o3146314632", "0b11001100110011001100110011010"), - nc(536870911, "536870911", "0x1fffffff", "0o3777777777", "0b11111111111111111111111111111"), - nc(536870912, "536870912", "0x20000000", "0o4000000000", "0b100000000000000000000000000000"), - nc(536870913, "536870913", "0x20000001", "0o4000000001", "0b100000000000000000000000000001"), - nc(999999999, "999999999", "0x3b9ac9ff", "0o7346544777", "0b111011100110101100100111111111"), - nc(1000000000, "1000000000", "0x3b9aca00", "0o7346545000", "0b111011100110101100101000000000"), - nc(1000000001, "1000000001", "0x3b9aca01", "0o7346545001", "0b111011100110101100101000000001"), - nc(1073741823, "1073741823", "0x3fffffff", "0o7777777777", "0b111111111111111111111111111111"), - nc(1073741824, "1073741824", "0x40000000", "0o10000000000", "0b1000000000000000000000000000000"), - nc(1073741825, "1073741825", "0x40000001", "0o10000000001", "0b1000000000000000000000000000001"), - nc(2147483647, "2147483647", "0x7fffffff", "0o17777777777", "0b1111111111111111111111111111111"), - nc(2147483648, "2147483648", "0x80000000", "0o20000000000", "0b10000000000000000000000000000000"), - nc(2147483649, "2147483649", "0x80000001", "0o20000000001", "0b10000000000000000000000000000001"), - nc(4294967291, "4294967291", "0xfffffffb", "0o37777777773", "0b11111111111111111111111111111011"), - nc(4294967292, "4294967292", "0xfffffffc", "0o37777777774", "0b11111111111111111111111111111100"), - nc(4294967293, "4294967293", "0xfffffffd", "0o37777777775", "0b11111111111111111111111111111101"), - nc(4294967294, "4294967294", "0xfffffffe", "0o37777777776", "0b11111111111111111111111111111110"), - nc(4294967295, "4294967295", "0xffffffff", "0o37777777777", "0b11111111111111111111111111111111"), -#undef nc - }; -}; - - -template<> -struct numbers -{ - using value_type = int64_t; - static C4_INLINE_CONSTEXPR const number_case vals[] = { -#define nc(val, dec, hex, bin, oct) \ - number_case{(value_type)INT64_C(val), csubstr{dec}, csubstr{hex}, csubstr{bin}, csubstr{oct}} -#define ncm1(val, dec, hex, bin, oct) \ - number_case{(value_type)(INT64_C(val)-INT64_C(1)), csubstr{dec}, csubstr{hex}, csubstr{bin}, csubstr{oct}} - ncm1(-9223372036854775807, "-9223372036854775808", "-0x8000000000000000", "-0o1000000000000000000000", "-0b1000000000000000000000000000000000000000000000000000000000000000"), - nc(-9223372036854775807, "-9223372036854775807", "-0x7fffffffffffffff", "-0o777777777777777777777", "-0b111111111111111111111111111111111111111111111111111111111111111"), - nc(-9223372036854775806, "-9223372036854775806", "-0x7ffffffffffffffe", "-0o777777777777777777776", "-0b111111111111111111111111111111111111111111111111111111111111110"), - nc(-9223372036854775805, "-9223372036854775805", "-0x7ffffffffffffffd", "-0o777777777777777777775", "-0b111111111111111111111111111111111111111111111111111111111111101"), - nc(-9223372036854775804, "-9223372036854775804", "-0x7ffffffffffffffc", "-0o777777777777777777774", "-0b111111111111111111111111111111111111111111111111111111111111100"), - nc(-9223372036854775803, "-9223372036854775803", "-0x7ffffffffffffffb", "-0o777777777777777777773", "-0b111111111111111111111111111111111111111111111111111111111111011"), - nc(-4611686018427387905, "-4611686018427387905", "-0x4000000000000001", "-0o400000000000000000001", "-0b100000000000000000000000000000000000000000000000000000000000001"), - nc(-4611686018427387904, "-4611686018427387904", "-0x4000000000000000", "-0o400000000000000000000", "-0b100000000000000000000000000000000000000000000000000000000000000"), - nc(-4611686018427387903, "-4611686018427387903", "-0x3fffffffffffffff", "-0o377777777777777777777", "-0b11111111111111111111111111111111111111111111111111111111111111"), - nc(-2305843009213693953, "-2305843009213693953", "-0x2000000000000001", "-0o200000000000000000001", "-0b10000000000000000000000000000000000000000000000000000000000001"), - nc(-2305843009213693952, "-2305843009213693952", "-0x2000000000000000", "-0o200000000000000000000", "-0b10000000000000000000000000000000000000000000000000000000000000"), - nc(-2305843009213693951, "-2305843009213693951", "-0x1fffffffffffffff", "-0o177777777777777777777", "-0b1111111111111111111111111111111111111111111111111111111111111"), - nc(-1152921504606846977, "-1152921504606846977", "-0x1000000000000001", "-0o100000000000000000001", "-0b1000000000000000000000000000000000000000000000000000000000001"), - nc(-1152921504606846976, "-1152921504606846976", "-0x1000000000000000", "-0o100000000000000000000", "-0b1000000000000000000000000000000000000000000000000000000000000"), - nc(-1152921504606846975, "-1152921504606846975", "-0xfffffffffffffff", "-0o77777777777777777777", "-0b111111111111111111111111111111111111111111111111111111111111"), - nc(-1000000000000000001, "-1000000000000000001", "-0xde0b6b3a7640001", "-0o67405553164731000001", "-0b110111100000101101101011001110100111011001000000000000000001"), - nc(-1000000000000000000, "-1000000000000000000", "-0xde0b6b3a7640000", "-0o67405553164731000000", "-0b110111100000101101101011001110100111011001000000000000000000"), - nc(-999999999999999999, "-999999999999999999", "-0xde0b6b3a763ffff", "-0o67405553164730777777", "-0b110111100000101101101011001110100111011000111111111111111111"), - nc(-922337203685477632, "-922337203685477632", "-0xccccccccccccd00", "-0o63146314631463146400", "-0b110011001100110011001100110011001100110011001100110100000000"), - nc(-576460752303423489, "-576460752303423489", "-0x800000000000001", "-0o40000000000000000001", "-0b100000000000000000000000000000000000000000000000000000000001"), - nc(-576460752303423488, "-576460752303423488", "-0x800000000000000", "-0o40000000000000000000", "-0b100000000000000000000000000000000000000000000000000000000000"), - nc(-576460752303423487, "-576460752303423487", "-0x7ffffffffffffff", "-0o37777777777777777777", "-0b11111111111111111111111111111111111111111111111111111111111"), - nc(-288230376151711745, "-288230376151711745", "-0x400000000000001", "-0o20000000000000000001", "-0b10000000000000000000000000000000000000000000000000000000001"), - nc(-288230376151711744, "-288230376151711744", "-0x400000000000000", "-0o20000000000000000000", "-0b10000000000000000000000000000000000000000000000000000000000"), - nc(-288230376151711743, "-288230376151711743", "-0x3ffffffffffffff", "-0o17777777777777777777", "-0b1111111111111111111111111111111111111111111111111111111111"), - nc(-144115188075855873, "-144115188075855873", "-0x200000000000001", "-0o10000000000000000001", "-0b1000000000000000000000000000000000000000000000000000000001"), - nc(-144115188075855872, "-144115188075855872", "-0x200000000000000", "-0o10000000000000000000", "-0b1000000000000000000000000000000000000000000000000000000000"), - nc(-144115188075855871, "-144115188075855871", "-0x1ffffffffffffff", "-0o7777777777777777777", "-0b111111111111111111111111111111111111111111111111111111111"), - nc(-100000000000000001, "-100000000000000001", "-0x16345785d8a0001", "-0o5432127413542400001", "-0b101100011010001010111100001011101100010100000000000000001"), - nc(-100000000000000000, "-100000000000000000", "-0x16345785d8a0000", "-0o5432127413542400000", "-0b101100011010001010111100001011101100010100000000000000000"), - nc(-99999999999999999, "-99999999999999999", "-0x16345785d89ffff", "-0o5432127413542377777", "-0b101100011010001010111100001011101100010011111111111111111"), - nc(-92233720368547760, "-92233720368547760", "-0x147ae147ae147b0", "-0o5075341217270243660", "-0b101000111101011100001010001111010111000010100011110110000"), - nc(-72057594037927937, "-72057594037927937", "-0x100000000000001", "-0o4000000000000000001", "-0b100000000000000000000000000000000000000000000000000000001"), - nc(-72057594037927936, "-72057594037927936", "-0x100000000000000", "-0o4000000000000000000", "-0b100000000000000000000000000000000000000000000000000000000"), - nc(-72057594037927935, "-72057594037927935", "-0xffffffffffffff", "-0o3777777777777777777", "-0b11111111111111111111111111111111111111111111111111111111"), - nc(-36028797018963969, "-36028797018963969", "-0x80000000000001", "-0o2000000000000000001", "-0b10000000000000000000000000000000000000000000000000000001"), - nc(-36028797018963968, "-36028797018963968", "-0x80000000000000", "-0o2000000000000000000", "-0b10000000000000000000000000000000000000000000000000000000"), - nc(-36028797018963967, "-36028797018963967", "-0x7fffffffffffff", "-0o1777777777777777777", "-0b1111111111111111111111111111111111111111111111111111111"), - nc(-18014398509481985, "-18014398509481985", "-0x40000000000001", "-0o1000000000000000001", "-0b1000000000000000000000000000000000000000000000000000001"), - nc(-18014398509481984, "-18014398509481984", "-0x40000000000000", "-0o1000000000000000000", "-0b1000000000000000000000000000000000000000000000000000000"), - nc(-18014398509481983, "-18014398509481983", "-0x3fffffffffffff", "-0o777777777777777777", "-0b111111111111111111111111111111111111111111111111111111"), - nc(-10000000000000001, "-10000000000000001", "-0x2386f26fc10001", "-0o434157115760200001", "-0b100011100001101111001001101111110000010000000000000001"), - nc(-10000000000000000, "-10000000000000000", "-0x2386f26fc10000", "-0o434157115760200000", "-0b100011100001101111001001101111110000010000000000000000"), - nc(-9999999999999999, "-9999999999999999", "-0x2386f26fc0ffff", "-0o434157115760177777", "-0b100011100001101111001001101111110000001111111111111111"), - nc(-9223372036854776, "-9223372036854776", "-0x20c49ba5e353f8", "-0o406111564570651770", "-0b100000110001001001101110100101111000110101001111111000"), - nc(-9007199254740993, "-9007199254740993", "-0x20000000000001", "-0o400000000000000001", "-0b100000000000000000000000000000000000000000000000000001"), - nc(-9007199254740992, "-9007199254740992", "-0x20000000000000", "-0o400000000000000000", "-0b100000000000000000000000000000000000000000000000000000"), - nc(-9007199254740991, "-9007199254740991", "-0x1fffffffffffff", "-0o377777777777777777", "-0b11111111111111111111111111111111111111111111111111111"), - nc(-4503599627370497, "-4503599627370497", "-0x10000000000001", "-0o200000000000000001", "-0b10000000000000000000000000000000000000000000000000001"), - nc(-4503599627370496, "-4503599627370496", "-0x10000000000000", "-0o200000000000000000", "-0b10000000000000000000000000000000000000000000000000000"), - nc(-4503599627370495, "-4503599627370495", "-0xfffffffffffff", "-0o177777777777777777", "-0b1111111111111111111111111111111111111111111111111111"), - nc(-2251799813685249, "-2251799813685249", "-0x8000000000001", "-0o100000000000000001", "-0b1000000000000000000000000000000000000000000000000001"), - nc(-2251799813685248, "-2251799813685248", "-0x8000000000000", "-0o100000000000000000", "-0b1000000000000000000000000000000000000000000000000000"), - nc(-2251799813685247, "-2251799813685247", "-0x7ffffffffffff", "-0o77777777777777777", "-0b111111111111111111111111111111111111111111111111111"), - nc(-1125899906842625, "-1125899906842625", "-0x4000000000001", "-0o40000000000000001", "-0b100000000000000000000000000000000000000000000000001"), - nc(-1125899906842624, "-1125899906842624", "-0x4000000000000", "-0o40000000000000000", "-0b100000000000000000000000000000000000000000000000000"), - nc(-1125899906842623, "-1125899906842623", "-0x3ffffffffffff", "-0o37777777777777777", "-0b11111111111111111111111111111111111111111111111111"), - nc(-1000000000000001, "-1000000000000001", "-0x38d7ea4c68001", "-0o34327724461500001", "-0b11100011010111111010100100110001101000000000000001"), - nc(-1000000000000000, "-1000000000000000", "-0x38d7ea4c68000", "-0o34327724461500000", "-0b11100011010111111010100100110001101000000000000000"), - nc(-999999999999999, "-999999999999999", "-0x38d7ea4c67fff", "-0o34327724461477777", "-0b11100011010111111010100100110001100111111111111111"), - nc(-922337203685477, "-922337203685477", "-0x346dc5d638865", "-0o32155613530704145", "-0b11010001101101110001011101011000111000100001100101"), - nc(-562949953421313, "-562949953421313", "-0x2000000000001", "-0o20000000000000001", "-0b10000000000000000000000000000000000000000000000001"), - nc(-562949953421312, "-562949953421312", "-0x2000000000000", "-0o20000000000000000", "-0b10000000000000000000000000000000000000000000000000"), - nc(-562949953421311, "-562949953421311", "-0x1ffffffffffff", "-0o17777777777777777", "-0b1111111111111111111111111111111111111111111111111"), - nc(-281474976710657, "-281474976710657", "-0x1000000000001", "-0o10000000000000001", "-0b1000000000000000000000000000000000000000000000001"), - nc(-281474976710656, "-281474976710656", "-0x1000000000000", "-0o10000000000000000", "-0b1000000000000000000000000000000000000000000000000"), - nc(-281474976710655, "-281474976710655", "-0xffffffffffff", "-0o7777777777777777", "-0b111111111111111111111111111111111111111111111111"), - nc(-140737488355329, "-140737488355329", "-0x800000000001", "-0o4000000000000001", "-0b100000000000000000000000000000000000000000000001"), - nc(-140737488355328, "-140737488355328", "-0x800000000000", "-0o4000000000000000", "-0b100000000000000000000000000000000000000000000000"), - nc(-140737488355327, "-140737488355327", "-0x7fffffffffff", "-0o3777777777777777", "-0b11111111111111111111111111111111111111111111111"), - nc(-100000000000001, "-100000000000001", "-0x5af3107a4001", "-0o2657142036440001", "-0b10110101111001100010000011110100100000000000001"), - nc(-100000000000000, "-100000000000000", "-0x5af3107a4000", "-0o2657142036440000", "-0b10110101111001100010000011110100100000000000000"), - nc(-99999999999999, "-99999999999999", "-0x5af3107a3fff", "-0o2657142036437777", "-0b10110101111001100010000011110100011111111111111"), - nc(-92233720368547, "-92233720368547", "-0x53e2d6238da3", "-0o2476132610706643", "-0b10100111110001011010110001000111000110110100011"), - nc(-70368744177665, "-70368744177665", "-0x400000000001", "-0o2000000000000001", "-0b10000000000000000000000000000000000000000000001"), - nc(-70368744177664, "-70368744177664", "-0x400000000000", "-0o2000000000000000", "-0b10000000000000000000000000000000000000000000000"), - nc(-70368744177663, "-70368744177663", "-0x3fffffffffff", "-0o1777777777777777", "-0b1111111111111111111111111111111111111111111111"), - nc(-35184372088833, "-35184372088833", "-0x200000000001", "-0o1000000000000001", "-0b1000000000000000000000000000000000000000000001"), - nc(-35184372088832, "-35184372088832", "-0x200000000000", "-0o1000000000000000", "-0b1000000000000000000000000000000000000000000000"), - nc(-35184372088831, "-35184372088831", "-0x1fffffffffff", "-0o777777777777777", "-0b111111111111111111111111111111111111111111111"), - nc(-17592186044417, "-17592186044417", "-0x100000000001", "-0o400000000000001", "-0b100000000000000000000000000000000000000000001"), - nc(-17592186044416, "-17592186044416", "-0x100000000000", "-0o400000000000000", "-0b100000000000000000000000000000000000000000000"), - nc(-17592186044415, "-17592186044415", "-0xfffffffffff", "-0o377777777777777", "-0b11111111111111111111111111111111111111111111"), - nc(-10000000000001, "-10000000000001", "-0x9184e72a001", "-0o221411634520001", "-0b10010001100001001110011100101010000000000001"), - nc(-10000000000000, "-10000000000000", "-0x9184e72a000", "-0o221411634520000", "-0b10010001100001001110011100101010000000000000"), - nc(-9999999999999, "-9999999999999", "-0x9184e729fff", "-0o221411634517777", "-0b10010001100001001110011100101001111111111111"), - nc(-9223372036854, "-9223372036854", "-0x8637bd05af6", "-0o206157364055366", "-0b10000110001101111011110100000101101011110110"), - nc(-8796093022209, "-8796093022209", "-0x80000000001", "-0o200000000000001", "-0b10000000000000000000000000000000000000000001"), - nc(-8796093022208, "-8796093022208", "-0x80000000000", "-0o200000000000000", "-0b10000000000000000000000000000000000000000000"), - nc(-8796093022207, "-8796093022207", "-0x7ffffffffff", "-0o177777777777777", "-0b1111111111111111111111111111111111111111111"), - nc(-4398046511105, "-4398046511105", "-0x40000000001", "-0o100000000000001", "-0b1000000000000000000000000000000000000000001"), - nc(-4398046511104, "-4398046511104", "-0x40000000000", "-0o100000000000000", "-0b1000000000000000000000000000000000000000000"), - nc(-4398046511103, "-4398046511103", "-0x3ffffffffff", "-0o77777777777777", "-0b111111111111111111111111111111111111111111"), - nc(-2199023255553, "-2199023255553", "-0x20000000001", "-0o40000000000001", "-0b100000000000000000000000000000000000000001"), - nc(-2199023255552, "-2199023255552", "-0x20000000000", "-0o40000000000000", "-0b100000000000000000000000000000000000000000"), - nc(-2199023255551, "-2199023255551", "-0x1ffffffffff", "-0o37777777777777", "-0b11111111111111111111111111111111111111111"), - nc(-1099511627777, "-1099511627777", "-0x10000000001", "-0o20000000000001", "-0b10000000000000000000000000000000000000001"), - nc(-1099511627776, "-1099511627776", "-0x10000000000", "-0o20000000000000", "-0b10000000000000000000000000000000000000000"), - nc(-1099511627775, "-1099511627775", "-0xffffffffff", "-0o17777777777777", "-0b1111111111111111111111111111111111111111"), - nc(-1000000000001, "-1000000000001", "-0xe8d4a51001", "-0o16432451210001", "-0b1110100011010100101001010001000000000001"), - nc(-1000000000000, "-1000000000000", "-0xe8d4a51000", "-0o16432451210000", "-0b1110100011010100101001010001000000000000"), - nc(-999999999999, "-999999999999", "-0xe8d4a50fff", "-0o16432451207777", "-0b1110100011010100101001010000111111111111"), - nc(-922337203685, "-922337203685", "-0xd6bf94d5e5", "-0o15327745152745", "-0b1101011010111111100101001101010111100101"), - nc(-549755813889, "-549755813889", "-0x8000000001", "-0o10000000000001", "-0b1000000000000000000000000000000000000001"), - nc(-549755813888, "-549755813888", "-0x8000000000", "-0o10000000000000", "-0b1000000000000000000000000000000000000000"), - nc(-549755813887, "-549755813887", "-0x7fffffffff", "-0o7777777777777", "-0b111111111111111111111111111111111111111"), - nc(-274877906945, "-274877906945", "-0x4000000001", "-0o4000000000001", "-0b100000000000000000000000000000000000001"), - nc(-274877906944, "-274877906944", "-0x4000000000", "-0o4000000000000", "-0b100000000000000000000000000000000000000"), - nc(-274877906943, "-274877906943", "-0x3fffffffff", "-0o3777777777777", "-0b11111111111111111111111111111111111111"), - nc(-137438953473, "-137438953473", "-0x2000000001", "-0o2000000000001", "-0b10000000000000000000000000000000000001"), - nc(-137438953472, "-137438953472", "-0x2000000000", "-0o2000000000000", "-0b10000000000000000000000000000000000000"), - nc(-137438953471, "-137438953471", "-0x1fffffffff", "-0o1777777777777", "-0b1111111111111111111111111111111111111"), - nc(-100000000001, "-100000000001", "-0x174876e801", "-0o1351035564001", "-0b1011101001000011101101110100000000001"), - nc(-100000000000, "-100000000000", "-0x174876e800", "-0o1351035564000", "-0b1011101001000011101101110100000000000"), - nc(-99999999999, "-99999999999", "-0x174876e7ff", "-0o1351035563777", "-0b1011101001000011101101110011111111111"), - nc(-92233720368, "-92233720368", "-0x15798ee230", "-0o1257143561060", "-0b1010101111001100011101110001000110000"), - nc(-68719476737, "-68719476737", "-0x1000000001", "-0o1000000000001", "-0b1000000000000000000000000000000000001"), - nc(-68719476736, "-68719476736", "-0x1000000000", "-0o1000000000000", "-0b1000000000000000000000000000000000000"), - nc(-68719476735, "-68719476735", "-0xfffffffff", "-0o777777777777", "-0b111111111111111111111111111111111111"), - nc(-34359738369, "-34359738369", "-0x800000001", "-0o400000000001", "-0b100000000000000000000000000000000001"), - nc(-34359738368, "-34359738368", "-0x800000000", "-0o400000000000", "-0b100000000000000000000000000000000000"), - nc(-34359738367, "-34359738367", "-0x7ffffffff", "-0o377777777777", "-0b11111111111111111111111111111111111"), - nc(-17179869185, "-17179869185", "-0x400000001", "-0o200000000001", "-0b10000000000000000000000000000000001"), - nc(-17179869184, "-17179869184", "-0x400000000", "-0o200000000000", "-0b10000000000000000000000000000000000"), - nc(-17179869183, "-17179869183", "-0x3ffffffff", "-0o177777777777", "-0b1111111111111111111111111111111111"), - nc(-10000000001, "-10000000001", "-0x2540be401", "-0o112402762001", "-0b1001010100000010111110010000000001"), - nc(-10000000000, "-10000000000", "-0x2540be400", "-0o112402762000", "-0b1001010100000010111110010000000000"), - nc(-9999999999, "-9999999999", "-0x2540be3ff", "-0o112402761777", "-0b1001010100000010111110001111111111"), - nc(-9223372036, "-9223372036", "-0x225c17d04", "-0o104560276404", "-0b1000100101110000010111110100000100"), - nc(-8589934593, "-8589934593", "-0x200000001", "-0o100000000001", "-0b1000000000000000000000000000000001"), - nc(-8589934592, "-8589934592", "-0x200000000", "-0o100000000000", "-0b1000000000000000000000000000000000"), - nc(-8589934591, "-8589934591", "-0x1ffffffff", "-0o77777777777", "-0b111111111111111111111111111111111"), - nc(-4294967297, "-4294967297", "-0x100000001", "-0o40000000001", "-0b100000000000000000000000000000001"), - nc(-4294967296, "-4294967296", "-0x100000000", "-0o40000000000", "-0b100000000000000000000000000000000"), - nc(-4294967295, "-4294967295", "-0xffffffff", "-0o37777777777", "-0b11111111111111111111111111111111"), - nc(-2147483649, "-2147483649", "-0x80000001", "-0o20000000001", "-0b10000000000000000000000000000001"), - nc(-2147483648, "-2147483648", "-0x80000000", "-0o20000000000", "-0b10000000000000000000000000000000"), - nc(-2147483647, "-2147483647", "-0x7fffffff", "-0o17777777777", "-0b1111111111111111111111111111111"), - nc(-1073741825, "-1073741825", "-0x40000001", "-0o10000000001", "-0b1000000000000000000000000000001"), - nc(-1073741824, "-1073741824", "-0x40000000", "-0o10000000000", "-0b1000000000000000000000000000000"), - nc(-1073741823, "-1073741823", "-0x3fffffff", "-0o7777777777", "-0b111111111111111111111111111111"), - nc(-1000000001, "-1000000001", "-0x3b9aca01", "-0o7346545001", "-0b111011100110101100101000000001"), - nc(-1000000000, "-1000000000", "-0x3b9aca00", "-0o7346545000", "-0b111011100110101100101000000000"), - nc(-999999999, "-999999999", "-0x3b9ac9ff", "-0o7346544777", "-0b111011100110101100100111111111"), - nc(-922337203, "-922337203", "-0x36f9bfb3", "-0o6676337663", "-0b110110111110011011111110110011"), - nc(-536870913, "-536870913", "-0x20000001", "-0o4000000001", "-0b100000000000000000000000000001"), - nc(-536870912, "-536870912", "-0x20000000", "-0o4000000000", "-0b100000000000000000000000000000"), - nc(-536870911, "-536870911", "-0x1fffffff", "-0o3777777777", "-0b11111111111111111111111111111"), - nc(-268435457, "-268435457", "-0x10000001", "-0o2000000001", "-0b10000000000000000000000000001"), - nc(-268435456, "-268435456", "-0x10000000", "-0o2000000000", "-0b10000000000000000000000000000"), - nc(-268435455, "-268435455", "-0xfffffff", "-0o1777777777", "-0b1111111111111111111111111111"), - nc(-134217729, "-134217729", "-0x8000001", "-0o1000000001", "-0b1000000000000000000000000001"), - nc(-134217728, "-134217728", "-0x8000000", "-0o1000000000", "-0b1000000000000000000000000000"), - nc(-134217727, "-134217727", "-0x7ffffff", "-0o777777777", "-0b111111111111111111111111111"), - nc(-100000001, "-100000001", "-0x5f5e101", "-0o575360401", "-0b101111101011110000100000001"), - nc(-100000000, "-100000000", "-0x5f5e100", "-0o575360400", "-0b101111101011110000100000000"), - nc(-99999999, "-99999999", "-0x5f5e0ff", "-0o575360377", "-0b101111101011110000011111111"), - nc(-92233720, "-92233720", "-0x57f5ff8", "-0o537657770", "-0b101011111110101111111111000"), - nc(-67108865, "-67108865", "-0x4000001", "-0o400000001", "-0b100000000000000000000000001"), - nc(-67108864, "-67108864", "-0x4000000", "-0o400000000", "-0b100000000000000000000000000"), - nc(-67108863, "-67108863", "-0x3ffffff", "-0o377777777", "-0b11111111111111111111111111"), - nc(-33554433, "-33554433", "-0x2000001", "-0o200000001", "-0b10000000000000000000000001"), - nc(-33554432, "-33554432", "-0x2000000", "-0o200000000", "-0b10000000000000000000000000"), - nc(-33554431, "-33554431", "-0x1ffffff", "-0o177777777", "-0b1111111111111111111111111"), - nc(-16777217, "-16777217", "-0x1000001", "-0o100000001", "-0b1000000000000000000000001"), - nc(-16777216, "-16777216", "-0x1000000", "-0o100000000", "-0b1000000000000000000000000"), - nc(-16777215, "-16777215", "-0xffffff", "-0o77777777", "-0b111111111111111111111111"), - nc(-10000001, "-10000001", "-0x989681", "-0o46113201", "-0b100110001001011010000001"), - nc(-10000000, "-10000000", "-0x989680", "-0o46113200", "-0b100110001001011010000000"), - nc(-9999999, "-9999999", "-0x98967f", "-0o46113177", "-0b100110001001011001111111"), - nc(-9223372, "-9223372", "-0x8cbccc", "-0o43136314", "-0b100011001011110011001100"), - nc(-8388609, "-8388609", "-0x800001", "-0o40000001", "-0b100000000000000000000001"), - nc(-8388608, "-8388608", "-0x800000", "-0o40000000", "-0b100000000000000000000000"), - nc(-8388607, "-8388607", "-0x7fffff", "-0o37777777", "-0b11111111111111111111111"), - nc(-4194305, "-4194305", "-0x400001", "-0o20000001", "-0b10000000000000000000001"), - nc(-4194304, "-4194304", "-0x400000", "-0o20000000", "-0b10000000000000000000000"), - nc(-4194303, "-4194303", "-0x3fffff", "-0o17777777", "-0b1111111111111111111111"), - nc(-2097153, "-2097153", "-0x200001", "-0o10000001", "-0b1000000000000000000001"), - nc(-2097152, "-2097152", "-0x200000", "-0o10000000", "-0b1000000000000000000000"), - nc(-2097151, "-2097151", "-0x1fffff", "-0o7777777", "-0b111111111111111111111"), - nc(-1048577, "-1048577", "-0x100001", "-0o4000001", "-0b100000000000000000001"), - nc(-1048576, "-1048576", "-0x100000", "-0o4000000", "-0b100000000000000000000"), - nc(-1048575, "-1048575", "-0xfffff", "-0o3777777", "-0b11111111111111111111"), - nc(-1000001, "-1000001", "-0xf4241", "-0o3641101", "-0b11110100001001000001"), - nc(-1000000, "-1000000", "-0xf4240", "-0o3641100", "-0b11110100001001000000"), - nc(-999999, "-999999", "-0xf423f", "-0o3641077", "-0b11110100001000111111"), - nc(-922337, "-922337", "-0xe12e1", "-0o3411341", "-0b11100001001011100001"), - nc(-524289, "-524289", "-0x80001", "-0o2000001", "-0b10000000000000000001"), - nc(-524288, "-524288", "-0x80000", "-0o2000000", "-0b10000000000000000000"), - nc(-524287, "-524287", "-0x7ffff", "-0o1777777", "-0b1111111111111111111"), - nc(-262145, "-262145", "-0x40001", "-0o1000001", "-0b1000000000000000001"), - nc(-262144, "-262144", "-0x40000", "-0o1000000", "-0b1000000000000000000"), - nc(-262143, "-262143", "-0x3ffff", "-0o777777", "-0b111111111111111111"), - nc(-131073, "-131073", "-0x20001", "-0o400001", "-0b100000000000000001"), - nc(-131072, "-131072", "-0x20000", "-0o400000", "-0b100000000000000000"), - nc(-131071, "-131071", "-0x1ffff", "-0o377777", "-0b11111111111111111"), - nc(-100001, "-100001", "-0x186a1", "-0o303241", "-0b11000011010100001"), - nc(-100000, "-100000", "-0x186a0", "-0o303240", "-0b11000011010100000"), - nc(-99999, "-99999", "-0x1869f", "-0o303237", "-0b11000011010011111"), - nc(-92233, "-92233", "-0x16849", "-0o264111", "-0b10110100001001001"), - nc(-65537, "-65537", "-0x10001", "-0o200001", "-0b10000000000000001"), - nc(-65536, "-65536", "-0x10000", "-0o200000", "-0b10000000000000000"), - nc(-65535, "-65535", "-0xffff", "-0o177777", "-0b1111111111111111"), - nc(-32769, "-32769", "-0x8001", "-0o100001", "-0b1000000000000001"), - nc(-32768, "-32768", "-0x8000", "-0o100000", "-0b1000000000000000"), - nc(-32767, "-32767", "-0x7fff", "-0o77777", "-0b111111111111111"), - nc(-16385, "-16385", "-0x4001", "-0o40001", "-0b100000000000001"), - nc(-16384, "-16384", "-0x4000", "-0o40000", "-0b100000000000000"), - nc(-16383, "-16383", "-0x3fff", "-0o37777", "-0b11111111111111"), - nc(-10001, "-10001", "-0x2711", "-0o23421", "-0b10011100010001"), - nc(-10000, "-10000", "-0x2710", "-0o23420", "-0b10011100010000"), - nc(-9999, "-9999", "-0x270f", "-0o23417", "-0b10011100001111"), - nc(-9223, "-9223", "-0x2407", "-0o22007", "-0b10010000000111"), - nc(-8193, "-8193", "-0x2001", "-0o20001", "-0b10000000000001"), - nc(-8192, "-8192", "-0x2000", "-0o20000", "-0b10000000000000"), - nc(-8191, "-8191", "-0x1fff", "-0o17777", "-0b1111111111111"), - nc(-4097, "-4097", "-0x1001", "-0o10001", "-0b1000000000001"), - nc(-4096, "-4096", "-0x1000", "-0o10000", "-0b1000000000000"), - nc(-4095, "-4095", "-0xfff", "-0o7777", "-0b111111111111"), - nc(-2049, "-2049", "-0x801", "-0o4001", "-0b100000000001"), - nc(-2048, "-2048", "-0x800", "-0o4000", "-0b100000000000"), - nc(-2047, "-2047", "-0x7ff", "-0o3777", "-0b11111111111"), - nc(-1025, "-1025", "-0x401", "-0o2001", "-0b10000000001"), - nc(-1024, "-1024", "-0x400", "-0o2000", "-0b10000000000"), - nc(-1023, "-1023", "-0x3ff", "-0o1777", "-0b1111111111"), - nc(-1001, "-1001", "-0x3e9", "-0o1751", "-0b1111101001"), - nc(-1000, "-1000", "-0x3e8", "-0o1750", "-0b1111101000"), - nc(-999, "-999", "-0x3e7", "-0o1747", "-0b1111100111"), - nc(-922, "-922", "-0x39a", "-0o1632", "-0b1110011010"), - nc(-513, "-513", "-0x201", "-0o1001", "-0b1000000001"), - nc(-512, "-512", "-0x200", "-0o1000", "-0b1000000000"), - nc(-511, "-511", "-0x1ff", "-0o777", "-0b111111111"), - nc(-257, "-257", "-0x101", "-0o401", "-0b100000001"), - nc(-256, "-256", "-0x100", "-0o400", "-0b100000000"), - nc(-255, "-255", "-0xff", "-0o377", "-0b11111111"), - nc(-129, "-129", "-0x81", "-0o201", "-0b10000001"), - nc(-128, "-128", "-0x80", "-0o200", "-0b10000000"), - nc(-127, "-127", "-0x7f", "-0o177", "-0b1111111"), - nc(-101, "-101", "-0x65", "-0o145", "-0b1100101"), - nc(-100, "-100", "-0x64", "-0o144", "-0b1100100"), - nc(-99, "-99", "-0x63", "-0o143", "-0b1100011"), - nc(-92, "-92", "-0x5c", "-0o134", "-0b1011100"), - nc(-65, "-65", "-0x41", "-0o101", "-0b1000001"), - nc(-64, "-64", "-0x40", "-0o100", "-0b1000000"), - nc(-63, "-63", "-0x3f", "-0o77", "-0b111111"), - nc(-33, "-33", "-0x21", "-0o41", "-0b100001"), - nc(-32, "-32", "-0x20", "-0o40", "-0b100000"), - nc(-31, "-31", "-0x1f", "-0o37", "-0b11111"), - nc(-17, "-17", "-0x11", "-0o21", "-0b10001"), - nc(-16, "-16", "-0x10", "-0o20", "-0b10000"), - nc(-15, "-15", "-0xf", "-0o17", "-0b1111"), - nc(-11, "-11", "-0xb", "-0o13", "-0b1011"), - nc(-10, "-10", "-0xa", "-0o12", "-0b1010"), - nc(-9, "-9", "-0x9", "-0o11", "-0b1001"), - nc(-8, "-8", "-0x8", "-0o10", "-0b1000"), - nc(-7, "-7", "-0x7", "-0o7", "-0b111"), - nc(-6, "-6", "-0x6", "-0o6", "-0b110"), - nc(-5, "-5", "-0x5", "-0o5", "-0b101"), - nc(-4, "-4", "-0x4", "-0o4", "-0b100"), - nc(-3, "-3", "-0x3", "-0o3", "-0b11"), - nc(-2, "-2", "-0x2", "-0o2", "-0b10"), - nc(-1, "-1", "-0x1", "-0o1", "-0b1"), - nc(0, "0", "0x0", "0o0", "0b0"), - nc(1, "1", "0x1", "0o1", "0b1"), - nc(2, "2", "0x2", "0o2", "0b10"), - nc(3, "3", "0x3", "0o3", "0b11"), - nc(4, "4", "0x4", "0o4", "0b100"), - nc(5, "5", "0x5", "0o5", "0b101"), - nc(6, "6", "0x6", "0o6", "0b110"), - nc(7, "7", "0x7", "0o7", "0b111"), - nc(8, "8", "0x8", "0o10", "0b1000"), - nc(9, "9", "0x9", "0o11", "0b1001"), - nc(10, "10", "0xa", "0o12", "0b1010"), - nc(11, "11", "0xb", "0o13", "0b1011"), - nc(15, "15", "0xf", "0o17", "0b1111"), - nc(16, "16", "0x10", "0o20", "0b10000"), - nc(17, "17", "0x11", "0o21", "0b10001"), - nc(31, "31", "0x1f", "0o37", "0b11111"), - nc(32, "32", "0x20", "0o40", "0b100000"), - nc(33, "33", "0x21", "0o41", "0b100001"), - nc(63, "63", "0x3f", "0o77", "0b111111"), - nc(64, "64", "0x40", "0o100", "0b1000000"), - nc(65, "65", "0x41", "0o101", "0b1000001"), - nc(91, "91", "0x5b", "0o133", "0b1011011"), - nc(92, "92", "0x5c", "0o134", "0b1011100"), - nc(93, "93", "0x5d", "0o135", "0b1011101"), - nc(99, "99", "0x63", "0o143", "0b1100011"), - nc(100, "100", "0x64", "0o144", "0b1100100"), - nc(101, "101", "0x65", "0o145", "0b1100101"), - nc(127, "127", "0x7f", "0o177", "0b1111111"), - nc(128, "128", "0x80", "0o200", "0b10000000"), - nc(129, "129", "0x81", "0o201", "0b10000001"), - nc(255, "255", "0xff", "0o377", "0b11111111"), - nc(256, "256", "0x100", "0o400", "0b100000000"), - nc(257, "257", "0x101", "0o401", "0b100000001"), - nc(511, "511", "0x1ff", "0o777", "0b111111111"), - nc(512, "512", "0x200", "0o1000", "0b1000000000"), - nc(513, "513", "0x201", "0o1001", "0b1000000001"), - nc(921, "921", "0x399", "0o1631", "0b1110011001"), - nc(922, "922", "0x39a", "0o1632", "0b1110011010"), - nc(923, "923", "0x39b", "0o1633", "0b1110011011"), - nc(999, "999", "0x3e7", "0o1747", "0b1111100111"), - nc(1000, "1000", "0x3e8", "0o1750", "0b1111101000"), - nc(1001, "1001", "0x3e9", "0o1751", "0b1111101001"), - nc(1023, "1023", "0x3ff", "0o1777", "0b1111111111"), - nc(1024, "1024", "0x400", "0o2000", "0b10000000000"), - nc(1025, "1025", "0x401", "0o2001", "0b10000000001"), - nc(2047, "2047", "0x7ff", "0o3777", "0b11111111111"), - nc(2048, "2048", "0x800", "0o4000", "0b100000000000"), - nc(2049, "2049", "0x801", "0o4001", "0b100000000001"), - nc(4095, "4095", "0xfff", "0o7777", "0b111111111111"), - nc(4096, "4096", "0x1000", "0o10000", "0b1000000000000"), - nc(4097, "4097", "0x1001", "0o10001", "0b1000000000001"), - nc(8191, "8191", "0x1fff", "0o17777", "0b1111111111111"), - nc(8192, "8192", "0x2000", "0o20000", "0b10000000000000"), - nc(8193, "8193", "0x2001", "0o20001", "0b10000000000001"), - nc(9222, "9222", "0x2406", "0o22006", "0b10010000000110"), - nc(9223, "9223", "0x2407", "0o22007", "0b10010000000111"), - nc(9224, "9224", "0x2408", "0o22010", "0b10010000001000"), - nc(9999, "9999", "0x270f", "0o23417", "0b10011100001111"), - nc(10000, "10000", "0x2710", "0o23420", "0b10011100010000"), - nc(10001, "10001", "0x2711", "0o23421", "0b10011100010001"), - nc(16383, "16383", "0x3fff", "0o37777", "0b11111111111111"), - nc(16384, "16384", "0x4000", "0o40000", "0b100000000000000"), - nc(16385, "16385", "0x4001", "0o40001", "0b100000000000001"), - nc(32767, "32767", "0x7fff", "0o77777", "0b111111111111111"), - nc(32768, "32768", "0x8000", "0o100000", "0b1000000000000000"), - nc(32769, "32769", "0x8001", "0o100001", "0b1000000000000001"), - nc(65535, "65535", "0xffff", "0o177777", "0b1111111111111111"), - nc(65536, "65536", "0x10000", "0o200000", "0b10000000000000000"), - nc(65537, "65537", "0x10001", "0o200001", "0b10000000000000001"), - nc(92232, "92232", "0x16848", "0o264110", "0b10110100001001000"), - nc(92233, "92233", "0x16849", "0o264111", "0b10110100001001001"), - nc(92234, "92234", "0x1684a", "0o264112", "0b10110100001001010"), - nc(99999, "99999", "0x1869f", "0o303237", "0b11000011010011111"), - nc(100000, "100000", "0x186a0", "0o303240", "0b11000011010100000"), - nc(100001, "100001", "0x186a1", "0o303241", "0b11000011010100001"), - nc(131071, "131071", "0x1ffff", "0o377777", "0b11111111111111111"), - nc(131072, "131072", "0x20000", "0o400000", "0b100000000000000000"), - nc(131073, "131073", "0x20001", "0o400001", "0b100000000000000001"), - nc(262143, "262143", "0x3ffff", "0o777777", "0b111111111111111111"), - nc(262144, "262144", "0x40000", "0o1000000", "0b1000000000000000000"), - nc(262145, "262145", "0x40001", "0o1000001", "0b1000000000000000001"), - nc(524287, "524287", "0x7ffff", "0o1777777", "0b1111111111111111111"), - nc(524288, "524288", "0x80000", "0o2000000", "0b10000000000000000000"), - nc(524289, "524289", "0x80001", "0o2000001", "0b10000000000000000001"), - nc(922336, "922336", "0xe12e0", "0o3411340", "0b11100001001011100000"), - nc(922337, "922337", "0xe12e1", "0o3411341", "0b11100001001011100001"), - nc(922338, "922338", "0xe12e2", "0o3411342", "0b11100001001011100010"), - nc(999999, "999999", "0xf423f", "0o3641077", "0b11110100001000111111"), - nc(1000000, "1000000", "0xf4240", "0o3641100", "0b11110100001001000000"), - nc(1000001, "1000001", "0xf4241", "0o3641101", "0b11110100001001000001"), - nc(1048575, "1048575", "0xfffff", "0o3777777", "0b11111111111111111111"), - nc(1048576, "1048576", "0x100000", "0o4000000", "0b100000000000000000000"), - nc(1048577, "1048577", "0x100001", "0o4000001", "0b100000000000000000001"), - nc(2097151, "2097151", "0x1fffff", "0o7777777", "0b111111111111111111111"), - nc(2097152, "2097152", "0x200000", "0o10000000", "0b1000000000000000000000"), - nc(2097153, "2097153", "0x200001", "0o10000001", "0b1000000000000000000001"), - nc(4194303, "4194303", "0x3fffff", "0o17777777", "0b1111111111111111111111"), - nc(4194304, "4194304", "0x400000", "0o20000000", "0b10000000000000000000000"), - nc(4194305, "4194305", "0x400001", "0o20000001", "0b10000000000000000000001"), - nc(8388607, "8388607", "0x7fffff", "0o37777777", "0b11111111111111111111111"), - nc(8388608, "8388608", "0x800000", "0o40000000", "0b100000000000000000000000"), - nc(8388609, "8388609", "0x800001", "0o40000001", "0b100000000000000000000001"), - nc(9223371, "9223371", "0x8cbccb", "0o43136313", "0b100011001011110011001011"), - nc(9223372, "9223372", "0x8cbccc", "0o43136314", "0b100011001011110011001100"), - nc(9223373, "9223373", "0x8cbccd", "0o43136315", "0b100011001011110011001101"), - nc(9999999, "9999999", "0x98967f", "0o46113177", "0b100110001001011001111111"), - nc(10000000, "10000000", "0x989680", "0o46113200", "0b100110001001011010000000"), - nc(10000001, "10000001", "0x989681", "0o46113201", "0b100110001001011010000001"), - nc(16777215, "16777215", "0xffffff", "0o77777777", "0b111111111111111111111111"), - nc(16777216, "16777216", "0x1000000", "0o100000000", "0b1000000000000000000000000"), - nc(16777217, "16777217", "0x1000001", "0o100000001", "0b1000000000000000000000001"), - nc(33554431, "33554431", "0x1ffffff", "0o177777777", "0b1111111111111111111111111"), - nc(33554432, "33554432", "0x2000000", "0o200000000", "0b10000000000000000000000000"), - nc(33554433, "33554433", "0x2000001", "0o200000001", "0b10000000000000000000000001"), - nc(67108863, "67108863", "0x3ffffff", "0o377777777", "0b11111111111111111111111111"), - nc(67108864, "67108864", "0x4000000", "0o400000000", "0b100000000000000000000000000"), - nc(67108865, "67108865", "0x4000001", "0o400000001", "0b100000000000000000000000001"), - nc(92233719, "92233719", "0x57f5ff7", "0o537657767", "0b101011111110101111111110111"), - nc(92233720, "92233720", "0x57f5ff8", "0o537657770", "0b101011111110101111111111000"), - nc(92233721, "92233721", "0x57f5ff9", "0o537657771", "0b101011111110101111111111001"), - nc(99999999, "99999999", "0x5f5e0ff", "0o575360377", "0b101111101011110000011111111"), - nc(100000000, "100000000", "0x5f5e100", "0o575360400", "0b101111101011110000100000000"), - nc(100000001, "100000001", "0x5f5e101", "0o575360401", "0b101111101011110000100000001"), - nc(134217727, "134217727", "0x7ffffff", "0o777777777", "0b111111111111111111111111111"), - nc(134217728, "134217728", "0x8000000", "0o1000000000", "0b1000000000000000000000000000"), - nc(134217729, "134217729", "0x8000001", "0o1000000001", "0b1000000000000000000000000001"), - nc(268435455, "268435455", "0xfffffff", "0o1777777777", "0b1111111111111111111111111111"), - nc(268435456, "268435456", "0x10000000", "0o2000000000", "0b10000000000000000000000000000"), - nc(268435457, "268435457", "0x10000001", "0o2000000001", "0b10000000000000000000000000001"), - nc(536870911, "536870911", "0x1fffffff", "0o3777777777", "0b11111111111111111111111111111"), - nc(536870912, "536870912", "0x20000000", "0o4000000000", "0b100000000000000000000000000000"), - nc(536870913, "536870913", "0x20000001", "0o4000000001", "0b100000000000000000000000000001"), - nc(922337202, "922337202", "0x36f9bfb2", "0o6676337662", "0b110110111110011011111110110010"), - nc(922337203, "922337203", "0x36f9bfb3", "0o6676337663", "0b110110111110011011111110110011"), - nc(922337204, "922337204", "0x36f9bfb4", "0o6676337664", "0b110110111110011011111110110100"), - nc(999999999, "999999999", "0x3b9ac9ff", "0o7346544777", "0b111011100110101100100111111111"), - nc(1000000000, "1000000000", "0x3b9aca00", "0o7346545000", "0b111011100110101100101000000000"), - nc(1000000001, "1000000001", "0x3b9aca01", "0o7346545001", "0b111011100110101100101000000001"), - nc(1073741823, "1073741823", "0x3fffffff", "0o7777777777", "0b111111111111111111111111111111"), - nc(1073741824, "1073741824", "0x40000000", "0o10000000000", "0b1000000000000000000000000000000"), - nc(1073741825, "1073741825", "0x40000001", "0o10000000001", "0b1000000000000000000000000000001"), - nc(2147483647, "2147483647", "0x7fffffff", "0o17777777777", "0b1111111111111111111111111111111"), - nc(2147483648, "2147483648", "0x80000000", "0o20000000000", "0b10000000000000000000000000000000"), - nc(2147483649, "2147483649", "0x80000001", "0o20000000001", "0b10000000000000000000000000000001"), - nc(4294967295, "4294967295", "0xffffffff", "0o37777777777", "0b11111111111111111111111111111111"), - nc(4294967296, "4294967296", "0x100000000", "0o40000000000", "0b100000000000000000000000000000000"), - nc(4294967297, "4294967297", "0x100000001", "0o40000000001", "0b100000000000000000000000000000001"), - nc(8589934591, "8589934591", "0x1ffffffff", "0o77777777777", "0b111111111111111111111111111111111"), - nc(8589934592, "8589934592", "0x200000000", "0o100000000000", "0b1000000000000000000000000000000000"), - nc(8589934593, "8589934593", "0x200000001", "0o100000000001", "0b1000000000000000000000000000000001"), - nc(9223372035, "9223372035", "0x225c17d03", "0o104560276403", "0b1000100101110000010111110100000011"), - nc(9223372036, "9223372036", "0x225c17d04", "0o104560276404", "0b1000100101110000010111110100000100"), - nc(9223372037, "9223372037", "0x225c17d05", "0o104560276405", "0b1000100101110000010111110100000101"), - nc(9999999999, "9999999999", "0x2540be3ff", "0o112402761777", "0b1001010100000010111110001111111111"), - nc(10000000000, "10000000000", "0x2540be400", "0o112402762000", "0b1001010100000010111110010000000000"), - nc(10000000001, "10000000001", "0x2540be401", "0o112402762001", "0b1001010100000010111110010000000001"), - nc(17179869183, "17179869183", "0x3ffffffff", "0o177777777777", "0b1111111111111111111111111111111111"), - nc(17179869184, "17179869184", "0x400000000", "0o200000000000", "0b10000000000000000000000000000000000"), - nc(17179869185, "17179869185", "0x400000001", "0o200000000001", "0b10000000000000000000000000000000001"), - nc(34359738367, "34359738367", "0x7ffffffff", "0o377777777777", "0b11111111111111111111111111111111111"), - nc(34359738368, "34359738368", "0x800000000", "0o400000000000", "0b100000000000000000000000000000000000"), - nc(34359738369, "34359738369", "0x800000001", "0o400000000001", "0b100000000000000000000000000000000001"), - nc(68719476735, "68719476735", "0xfffffffff", "0o777777777777", "0b111111111111111111111111111111111111"), - nc(68719476736, "68719476736", "0x1000000000", "0o1000000000000", "0b1000000000000000000000000000000000000"), - nc(68719476737, "68719476737", "0x1000000001", "0o1000000000001", "0b1000000000000000000000000000000000001"), - nc(92233720367, "92233720367", "0x15798ee22f", "0o1257143561057", "0b1010101111001100011101110001000101111"), - nc(92233720368, "92233720368", "0x15798ee230", "0o1257143561060", "0b1010101111001100011101110001000110000"), - nc(92233720369, "92233720369", "0x15798ee231", "0o1257143561061", "0b1010101111001100011101110001000110001"), - nc(99999999999, "99999999999", "0x174876e7ff", "0o1351035563777", "0b1011101001000011101101110011111111111"), - nc(100000000000, "100000000000", "0x174876e800", "0o1351035564000", "0b1011101001000011101101110100000000000"), - nc(100000000001, "100000000001", "0x174876e801", "0o1351035564001", "0b1011101001000011101101110100000000001"), - nc(137438953471, "137438953471", "0x1fffffffff", "0o1777777777777", "0b1111111111111111111111111111111111111"), - nc(137438953472, "137438953472", "0x2000000000", "0o2000000000000", "0b10000000000000000000000000000000000000"), - nc(137438953473, "137438953473", "0x2000000001", "0o2000000000001", "0b10000000000000000000000000000000000001"), - nc(274877906943, "274877906943", "0x3fffffffff", "0o3777777777777", "0b11111111111111111111111111111111111111"), - nc(274877906944, "274877906944", "0x4000000000", "0o4000000000000", "0b100000000000000000000000000000000000000"), - nc(274877906945, "274877906945", "0x4000000001", "0o4000000000001", "0b100000000000000000000000000000000000001"), - nc(549755813887, "549755813887", "0x7fffffffff", "0o7777777777777", "0b111111111111111111111111111111111111111"), - nc(549755813888, "549755813888", "0x8000000000", "0o10000000000000", "0b1000000000000000000000000000000000000000"), - nc(549755813889, "549755813889", "0x8000000001", "0o10000000000001", "0b1000000000000000000000000000000000000001"), - nc(922337203684, "922337203684", "0xd6bf94d5e4", "0o15327745152744", "0b1101011010111111100101001101010111100100"), - nc(922337203685, "922337203685", "0xd6bf94d5e5", "0o15327745152745", "0b1101011010111111100101001101010111100101"), - nc(922337203686, "922337203686", "0xd6bf94d5e6", "0o15327745152746", "0b1101011010111111100101001101010111100110"), - nc(999999999999, "999999999999", "0xe8d4a50fff", "0o16432451207777", "0b1110100011010100101001010000111111111111"), - nc(1000000000000, "1000000000000", "0xe8d4a51000", "0o16432451210000", "0b1110100011010100101001010001000000000000"), - nc(1000000000001, "1000000000001", "0xe8d4a51001", "0o16432451210001", "0b1110100011010100101001010001000000000001"), - nc(1099511627775, "1099511627775", "0xffffffffff", "0o17777777777777", "0b1111111111111111111111111111111111111111"), - nc(1099511627776, "1099511627776", "0x10000000000", "0o20000000000000", "0b10000000000000000000000000000000000000000"), - nc(1099511627777, "1099511627777", "0x10000000001", "0o20000000000001", "0b10000000000000000000000000000000000000001"), - nc(2199023255551, "2199023255551", "0x1ffffffffff", "0o37777777777777", "0b11111111111111111111111111111111111111111"), - nc(2199023255552, "2199023255552", "0x20000000000", "0o40000000000000", "0b100000000000000000000000000000000000000000"), - nc(2199023255553, "2199023255553", "0x20000000001", "0o40000000000001", "0b100000000000000000000000000000000000000001"), - nc(4398046511103, "4398046511103", "0x3ffffffffff", "0o77777777777777", "0b111111111111111111111111111111111111111111"), - nc(4398046511104, "4398046511104", "0x40000000000", "0o100000000000000", "0b1000000000000000000000000000000000000000000"), - nc(4398046511105, "4398046511105", "0x40000000001", "0o100000000000001", "0b1000000000000000000000000000000000000000001"), - nc(8796093022207, "8796093022207", "0x7ffffffffff", "0o177777777777777", "0b1111111111111111111111111111111111111111111"), - nc(8796093022208, "8796093022208", "0x80000000000", "0o200000000000000", "0b10000000000000000000000000000000000000000000"), - nc(8796093022209, "8796093022209", "0x80000000001", "0o200000000000001", "0b10000000000000000000000000000000000000000001"), - nc(9223372036853, "9223372036853", "0x8637bd05af5", "0o206157364055365", "0b10000110001101111011110100000101101011110101"), - nc(9223372036854, "9223372036854", "0x8637bd05af6", "0o206157364055366", "0b10000110001101111011110100000101101011110110"), - nc(9223372036855, "9223372036855", "0x8637bd05af7", "0o206157364055367", "0b10000110001101111011110100000101101011110111"), - nc(9999999999999, "9999999999999", "0x9184e729fff", "0o221411634517777", "0b10010001100001001110011100101001111111111111"), - nc(10000000000000, "10000000000000", "0x9184e72a000", "0o221411634520000", "0b10010001100001001110011100101010000000000000"), - nc(10000000000001, "10000000000001", "0x9184e72a001", "0o221411634520001", "0b10010001100001001110011100101010000000000001"), - nc(17592186044415, "17592186044415", "0xfffffffffff", "0o377777777777777", "0b11111111111111111111111111111111111111111111"), - nc(17592186044416, "17592186044416", "0x100000000000", "0o400000000000000", "0b100000000000000000000000000000000000000000000"), - nc(17592186044417, "17592186044417", "0x100000000001", "0o400000000000001", "0b100000000000000000000000000000000000000000001"), - nc(35184372088831, "35184372088831", "0x1fffffffffff", "0o777777777777777", "0b111111111111111111111111111111111111111111111"), - nc(35184372088832, "35184372088832", "0x200000000000", "0o1000000000000000", "0b1000000000000000000000000000000000000000000000"), - nc(35184372088833, "35184372088833", "0x200000000001", "0o1000000000000001", "0b1000000000000000000000000000000000000000000001"), - nc(70368744177663, "70368744177663", "0x3fffffffffff", "0o1777777777777777", "0b1111111111111111111111111111111111111111111111"), - nc(70368744177664, "70368744177664", "0x400000000000", "0o2000000000000000", "0b10000000000000000000000000000000000000000000000"), - nc(70368744177665, "70368744177665", "0x400000000001", "0o2000000000000001", "0b10000000000000000000000000000000000000000000001"), - nc(92233720368546, "92233720368546", "0x53e2d6238da2", "0o2476132610706642", "0b10100111110001011010110001000111000110110100010"), - nc(92233720368547, "92233720368547", "0x53e2d6238da3", "0o2476132610706643", "0b10100111110001011010110001000111000110110100011"), - nc(92233720368548, "92233720368548", "0x53e2d6238da4", "0o2476132610706644", "0b10100111110001011010110001000111000110110100100"), - nc(99999999999999, "99999999999999", "0x5af3107a3fff", "0o2657142036437777", "0b10110101111001100010000011110100011111111111111"), - nc(100000000000000, "100000000000000", "0x5af3107a4000", "0o2657142036440000", "0b10110101111001100010000011110100100000000000000"), - nc(100000000000001, "100000000000001", "0x5af3107a4001", "0o2657142036440001", "0b10110101111001100010000011110100100000000000001"), - nc(140737488355327, "140737488355327", "0x7fffffffffff", "0o3777777777777777", "0b11111111111111111111111111111111111111111111111"), - nc(140737488355328, "140737488355328", "0x800000000000", "0o4000000000000000", "0b100000000000000000000000000000000000000000000000"), - nc(140737488355329, "140737488355329", "0x800000000001", "0o4000000000000001", "0b100000000000000000000000000000000000000000000001"), - nc(281474976710655, "281474976710655", "0xffffffffffff", "0o7777777777777777", "0b111111111111111111111111111111111111111111111111"), - nc(281474976710656, "281474976710656", "0x1000000000000", "0o10000000000000000", "0b1000000000000000000000000000000000000000000000000"), - nc(281474976710657, "281474976710657", "0x1000000000001", "0o10000000000000001", "0b1000000000000000000000000000000000000000000000001"), - nc(562949953421311, "562949953421311", "0x1ffffffffffff", "0o17777777777777777", "0b1111111111111111111111111111111111111111111111111"), - nc(562949953421312, "562949953421312", "0x2000000000000", "0o20000000000000000", "0b10000000000000000000000000000000000000000000000000"), - nc(562949953421313, "562949953421313", "0x2000000000001", "0o20000000000000001", "0b10000000000000000000000000000000000000000000000001"), - nc(922337203685476, "922337203685476", "0x346dc5d638864", "0o32155613530704144", "0b11010001101101110001011101011000111000100001100100"), - nc(922337203685477, "922337203685477", "0x346dc5d638865", "0o32155613530704145", "0b11010001101101110001011101011000111000100001100101"), - nc(922337203685478, "922337203685478", "0x346dc5d638866", "0o32155613530704146", "0b11010001101101110001011101011000111000100001100110"), - nc(999999999999999, "999999999999999", "0x38d7ea4c67fff", "0o34327724461477777", "0b11100011010111111010100100110001100111111111111111"), - nc(1000000000000000, "1000000000000000", "0x38d7ea4c68000", "0o34327724461500000", "0b11100011010111111010100100110001101000000000000000"), - nc(1000000000000001, "1000000000000001", "0x38d7ea4c68001", "0o34327724461500001", "0b11100011010111111010100100110001101000000000000001"), - nc(1125899906842623, "1125899906842623", "0x3ffffffffffff", "0o37777777777777777", "0b11111111111111111111111111111111111111111111111111"), - nc(1125899906842624, "1125899906842624", "0x4000000000000", "0o40000000000000000", "0b100000000000000000000000000000000000000000000000000"), - nc(1125899906842625, "1125899906842625", "0x4000000000001", "0o40000000000000001", "0b100000000000000000000000000000000000000000000000001"), - nc(2251799813685247, "2251799813685247", "0x7ffffffffffff", "0o77777777777777777", "0b111111111111111111111111111111111111111111111111111"), - nc(2251799813685248, "2251799813685248", "0x8000000000000", "0o100000000000000000", "0b1000000000000000000000000000000000000000000000000000"), - nc(2251799813685249, "2251799813685249", "0x8000000000001", "0o100000000000000001", "0b1000000000000000000000000000000000000000000000000001"), - nc(4503599627370495, "4503599627370495", "0xfffffffffffff", "0o177777777777777777", "0b1111111111111111111111111111111111111111111111111111"), - nc(4503599627370496, "4503599627370496", "0x10000000000000", "0o200000000000000000", "0b10000000000000000000000000000000000000000000000000000"), - nc(4503599627370497, "4503599627370497", "0x10000000000001", "0o200000000000000001", "0b10000000000000000000000000000000000000000000000000001"), - nc(9007199254740991, "9007199254740991", "0x1fffffffffffff", "0o377777777777777777", "0b11111111111111111111111111111111111111111111111111111"), - nc(9007199254740992, "9007199254740992", "0x20000000000000", "0o400000000000000000", "0b100000000000000000000000000000000000000000000000000000"), - nc(9007199254740993, "9007199254740993", "0x20000000000001", "0o400000000000000001", "0b100000000000000000000000000000000000000000000000000001"), - nc(9223372036854775, "9223372036854775", "0x20c49ba5e353f7", "0o406111564570651767", "0b100000110001001001101110100101111000110101001111110111"), - nc(9223372036854776, "9223372036854776", "0x20c49ba5e353f8", "0o406111564570651770", "0b100000110001001001101110100101111000110101001111111000"), - nc(9223372036854777, "9223372036854777", "0x20c49ba5e353f9", "0o406111564570651771", "0b100000110001001001101110100101111000110101001111111001"), - nc(9999999999999999, "9999999999999999", "0x2386f26fc0ffff", "0o434157115760177777", "0b100011100001101111001001101111110000001111111111111111"), - nc(10000000000000000, "10000000000000000", "0x2386f26fc10000", "0o434157115760200000", "0b100011100001101111001001101111110000010000000000000000"), - nc(10000000000000001, "10000000000000001", "0x2386f26fc10001", "0o434157115760200001", "0b100011100001101111001001101111110000010000000000000001"), - nc(18014398509481983, "18014398509481983", "0x3fffffffffffff", "0o777777777777777777", "0b111111111111111111111111111111111111111111111111111111"), - nc(18014398509481984, "18014398509481984", "0x40000000000000", "0o1000000000000000000", "0b1000000000000000000000000000000000000000000000000000000"), - nc(18014398509481985, "18014398509481985", "0x40000000000001", "0o1000000000000000001", "0b1000000000000000000000000000000000000000000000000000001"), - nc(36028797018963967, "36028797018963967", "0x7fffffffffffff", "0o1777777777777777777", "0b1111111111111111111111111111111111111111111111111111111"), - nc(36028797018963968, "36028797018963968", "0x80000000000000", "0o2000000000000000000", "0b10000000000000000000000000000000000000000000000000000000"), - nc(36028797018963969, "36028797018963969", "0x80000000000001", "0o2000000000000000001", "0b10000000000000000000000000000000000000000000000000000001"), - nc(72057594037927935, "72057594037927935", "0xffffffffffffff", "0o3777777777777777777", "0b11111111111111111111111111111111111111111111111111111111"), - nc(72057594037927936, "72057594037927936", "0x100000000000000", "0o4000000000000000000", "0b100000000000000000000000000000000000000000000000000000000"), - nc(72057594037927937, "72057594037927937", "0x100000000000001", "0o4000000000000000001", "0b100000000000000000000000000000000000000000000000000000001"), - nc(92233720368547759, "92233720368547759", "0x147ae147ae147af", "0o5075341217270243657", "0b101000111101011100001010001111010111000010100011110101111"), - nc(92233720368547760, "92233720368547760", "0x147ae147ae147b0", "0o5075341217270243660", "0b101000111101011100001010001111010111000010100011110110000"), - nc(92233720368547761, "92233720368547761", "0x147ae147ae147b1", "0o5075341217270243661", "0b101000111101011100001010001111010111000010100011110110001"), - nc(99999999999999999, "99999999999999999", "0x16345785d89ffff", "0o5432127413542377777", "0b101100011010001010111100001011101100010011111111111111111"), - nc(100000000000000000, "100000000000000000", "0x16345785d8a0000", "0o5432127413542400000", "0b101100011010001010111100001011101100010100000000000000000"), - nc(100000000000000001, "100000000000000001", "0x16345785d8a0001", "0o5432127413542400001", "0b101100011010001010111100001011101100010100000000000000001"), - nc(144115188075855871, "144115188075855871", "0x1ffffffffffffff", "0o7777777777777777777", "0b111111111111111111111111111111111111111111111111111111111"), - nc(144115188075855872, "144115188075855872", "0x200000000000000", "0o10000000000000000000", "0b1000000000000000000000000000000000000000000000000000000000"), - nc(144115188075855873, "144115188075855873", "0x200000000000001", "0o10000000000000000001", "0b1000000000000000000000000000000000000000000000000000000001"), - nc(288230376151711743, "288230376151711743", "0x3ffffffffffffff", "0o17777777777777777777", "0b1111111111111111111111111111111111111111111111111111111111"), - nc(288230376151711744, "288230376151711744", "0x400000000000000", "0o20000000000000000000", "0b10000000000000000000000000000000000000000000000000000000000"), - nc(288230376151711745, "288230376151711745", "0x400000000000001", "0o20000000000000000001", "0b10000000000000000000000000000000000000000000000000000000001"), - nc(576460752303423487, "576460752303423487", "0x7ffffffffffffff", "0o37777777777777777777", "0b11111111111111111111111111111111111111111111111111111111111"), - nc(576460752303423488, "576460752303423488", "0x800000000000000", "0o40000000000000000000", "0b100000000000000000000000000000000000000000000000000000000000"), - nc(576460752303423489, "576460752303423489", "0x800000000000001", "0o40000000000000000001", "0b100000000000000000000000000000000000000000000000000000000001"), - nc(922337203685477631, "922337203685477631", "0xcccccccccccccff", "0o63146314631463146377", "0b110011001100110011001100110011001100110011001100110011111111"), - nc(922337203685477632, "922337203685477632", "0xccccccccccccd00", "0o63146314631463146400", "0b110011001100110011001100110011001100110011001100110100000000"), - nc(922337203685477633, "922337203685477633", "0xccccccccccccd01", "0o63146314631463146401", "0b110011001100110011001100110011001100110011001100110100000001"), - nc(999999999999999999, "999999999999999999", "0xde0b6b3a763ffff", "0o67405553164730777777", "0b110111100000101101101011001110100111011000111111111111111111"), - nc(1000000000000000000, "1000000000000000000", "0xde0b6b3a7640000", "0o67405553164731000000", "0b110111100000101101101011001110100111011001000000000000000000"), - nc(1000000000000000001, "1000000000000000001", "0xde0b6b3a7640001", "0o67405553164731000001", "0b110111100000101101101011001110100111011001000000000000000001"), - nc(1152921504606846975, "1152921504606846975", "0xfffffffffffffff", "0o77777777777777777777", "0b111111111111111111111111111111111111111111111111111111111111"), - nc(1152921504606846976, "1152921504606846976", "0x1000000000000000", "0o100000000000000000000", "0b1000000000000000000000000000000000000000000000000000000000000"), - nc(1152921504606846977, "1152921504606846977", "0x1000000000000001", "0o100000000000000000001", "0b1000000000000000000000000000000000000000000000000000000000001"), - nc(2305843009213693951, "2305843009213693951", "0x1fffffffffffffff", "0o177777777777777777777", "0b1111111111111111111111111111111111111111111111111111111111111"), - nc(2305843009213693952, "2305843009213693952", "0x2000000000000000", "0o200000000000000000000", "0b10000000000000000000000000000000000000000000000000000000000000"), - nc(2305843009213693953, "2305843009213693953", "0x2000000000000001", "0o200000000000000000001", "0b10000000000000000000000000000000000000000000000000000000000001"), - nc(4611686018427387903, "4611686018427387903", "0x3fffffffffffffff", "0o377777777777777777777", "0b11111111111111111111111111111111111111111111111111111111111111"), - nc(4611686018427387904, "4611686018427387904", "0x4000000000000000", "0o400000000000000000000", "0b100000000000000000000000000000000000000000000000000000000000000"), - nc(4611686018427387905, "4611686018427387905", "0x4000000000000001", "0o400000000000000000001", "0b100000000000000000000000000000000000000000000000000000000000001"), - nc(9223372036854775802, "9223372036854775802", "0x7ffffffffffffffa", "0o777777777777777777772", "0b111111111111111111111111111111111111111111111111111111111111010"), - nc(9223372036854775803, "9223372036854775803", "0x7ffffffffffffffb", "0o777777777777777777773", "0b111111111111111111111111111111111111111111111111111111111111011"), - nc(9223372036854775804, "9223372036854775804", "0x7ffffffffffffffc", "0o777777777777777777774", "0b111111111111111111111111111111111111111111111111111111111111100"), - nc(9223372036854775805, "9223372036854775805", "0x7ffffffffffffffd", "0o777777777777777777775", "0b111111111111111111111111111111111111111111111111111111111111101"), - nc(9223372036854775806, "9223372036854775806", "0x7ffffffffffffffe", "0o777777777777777777776", "0b111111111111111111111111111111111111111111111111111111111111110"), - nc(9223372036854775807, "9223372036854775807", "0x7fffffffffffffff", "0o777777777777777777777", "0b111111111111111111111111111111111111111111111111111111111111111"), -#undef nc - }; -}; - - -template<> -struct numbers -{ - using value_type = uint64_t; - static C4_INLINE_CONSTEXPR const number_case vals[] = { -#define nc(val, dec, hex, bin, oct) \ - number_case{UINT64_C(val), csubstr{dec}, csubstr{hex}, csubstr{bin}, csubstr{oct}} - nc(0, "0", "0x0", "0o0", "0b0"), - nc(1, "1", "0x1", "0o1", "0b1"), - nc(2, "2", "0x2", "0o2", "0b10"), - nc(3, "3", "0x3", "0o3", "0b11"), - nc(4, "4", "0x4", "0o4", "0b100"), - nc(5, "5", "0x5", "0o5", "0b101"), - nc(6, "6", "0x6", "0o6", "0b110"), - nc(7, "7", "0x7", "0o7", "0b111"), - nc(8, "8", "0x8", "0o10", "0b1000"), - nc(9, "9", "0x9", "0o11", "0b1001"), - nc(10, "10", "0xa", "0o12", "0b1010"), - nc(11, "11", "0xb", "0o13", "0b1011"), - nc(15, "15", "0xf", "0o17", "0b1111"), - nc(16, "16", "0x10", "0o20", "0b10000"), - nc(17, "17", "0x11", "0o21", "0b10001"), - nc(18, "18", "0x12", "0o22", "0b10010"), - nc(19, "19", "0x13", "0o23", "0b10011"), - nc(31, "31", "0x1f", "0o37", "0b11111"), - nc(32, "32", "0x20", "0o40", "0b100000"), - nc(33, "33", "0x21", "0o41", "0b100001"), - nc(63, "63", "0x3f", "0o77", "0b111111"), - nc(64, "64", "0x40", "0o100", "0b1000000"), - nc(65, "65", "0x41", "0o101", "0b1000001"), - nc(99, "99", "0x63", "0o143", "0b1100011"), - nc(100, "100", "0x64", "0o144", "0b1100100"), - nc(101, "101", "0x65", "0o145", "0b1100101"), - nc(127, "127", "0x7f", "0o177", "0b1111111"), - nc(128, "128", "0x80", "0o200", "0b10000000"), - nc(129, "129", "0x81", "0o201", "0b10000001"), - nc(183, "183", "0xb7", "0o267", "0b10110111"), - nc(184, "184", "0xb8", "0o270", "0b10111000"), - nc(185, "185", "0xb9", "0o271", "0b10111001"), - nc(255, "255", "0xff", "0o377", "0b11111111"), - nc(256, "256", "0x100", "0o400", "0b100000000"), - nc(257, "257", "0x101", "0o401", "0b100000001"), - nc(511, "511", "0x1ff", "0o777", "0b111111111"), - nc(512, "512", "0x200", "0o1000", "0b1000000000"), - nc(513, "513", "0x201", "0o1001", "0b1000000001"), - nc(999, "999", "0x3e7", "0o1747", "0b1111100111"), - nc(1000, "1000", "0x3e8", "0o1750", "0b1111101000"), - nc(1001, "1001", "0x3e9", "0o1751", "0b1111101001"), - nc(1023, "1023", "0x3ff", "0o1777", "0b1111111111"), - nc(1024, "1024", "0x400", "0o2000", "0b10000000000"), - nc(1025, "1025", "0x401", "0o2001", "0b10000000001"), - nc(1843, "1843", "0x733", "0o3463", "0b11100110011"), - nc(1844, "1844", "0x734", "0o3464", "0b11100110100"), - nc(1845, "1845", "0x735", "0o3465", "0b11100110101"), - nc(2047, "2047", "0x7ff", "0o3777", "0b11111111111"), - nc(2048, "2048", "0x800", "0o4000", "0b100000000000"), - nc(2049, "2049", "0x801", "0o4001", "0b100000000001"), - nc(4095, "4095", "0xfff", "0o7777", "0b111111111111"), - nc(4096, "4096", "0x1000", "0o10000", "0b1000000000000"), - nc(4097, "4097", "0x1001", "0o10001", "0b1000000000001"), - nc(8191, "8191", "0x1fff", "0o17777", "0b1111111111111"), - nc(8192, "8192", "0x2000", "0o20000", "0b10000000000000"), - nc(8193, "8193", "0x2001", "0o20001", "0b10000000000001"), - nc(9999, "9999", "0x270f", "0o23417", "0b10011100001111"), - nc(10000, "10000", "0x2710", "0o23420", "0b10011100010000"), - nc(10001, "10001", "0x2711", "0o23421", "0b10011100010001"), - nc(16383, "16383", "0x3fff", "0o37777", "0b11111111111111"), - nc(16384, "16384", "0x4000", "0o40000", "0b100000000000000"), - nc(16385, "16385", "0x4001", "0o40001", "0b100000000000001"), - nc(18445, "18445", "0x480d", "0o44015", "0b100100000001101"), - nc(18446, "18446", "0x480e", "0o44016", "0b100100000001110"), - nc(18447, "18447", "0x480f", "0o44017", "0b100100000001111"), - nc(32767, "32767", "0x7fff", "0o77777", "0b111111111111111"), - nc(32768, "32768", "0x8000", "0o100000", "0b1000000000000000"), - nc(32769, "32769", "0x8001", "0o100001", "0b1000000000000001"), - nc(65535, "65535", "0xffff", "0o177777", "0b1111111111111111"), - nc(65536, "65536", "0x10000", "0o200000", "0b10000000000000000"), - nc(65537, "65537", "0x10001", "0o200001", "0b10000000000000001"), - nc(99999, "99999", "0x1869f", "0o303237", "0b11000011010011111"), - nc(100000, "100000", "0x186a0", "0o303240", "0b11000011010100000"), - nc(100001, "100001", "0x186a1", "0o303241", "0b11000011010100001"), - nc(131071, "131071", "0x1ffff", "0o377777", "0b11111111111111111"), - nc(131072, "131072", "0x20000", "0o400000", "0b100000000000000000"), - nc(131073, "131073", "0x20001", "0o400001", "0b100000000000000001"), - nc(184466, "184466", "0x2d092", "0o550222", "0b101101000010010010"), - nc(184467, "184467", "0x2d093", "0o550223", "0b101101000010010011"), - nc(184468, "184468", "0x2d094", "0o550224", "0b101101000010010100"), - nc(262143, "262143", "0x3ffff", "0o777777", "0b111111111111111111"), - nc(262144, "262144", "0x40000", "0o1000000", "0b1000000000000000000"), - nc(262145, "262145", "0x40001", "0o1000001", "0b1000000000000000001"), - nc(524287, "524287", "0x7ffff", "0o1777777", "0b1111111111111111111"), - nc(524288, "524288", "0x80000", "0o2000000", "0b10000000000000000000"), - nc(524289, "524289", "0x80001", "0o2000001", "0b10000000000000000001"), - nc(999999, "999999", "0xf423f", "0o3641077", "0b11110100001000111111"), - nc(1000000, "1000000", "0xf4240", "0o3641100", "0b11110100001001000000"), - nc(1000001, "1000001", "0xf4241", "0o3641101", "0b11110100001001000001"), - nc(1048575, "1048575", "0xfffff", "0o3777777", "0b11111111111111111111"), - nc(1048576, "1048576", "0x100000", "0o4000000", "0b100000000000000000000"), - nc(1048577, "1048577", "0x100001", "0o4000001", "0b100000000000000000001"), - nc(1844673, "1844673", "0x1c25c1", "0o7022701", "0b111000010010111000001"), - nc(1844674, "1844674", "0x1c25c2", "0o7022702", "0b111000010010111000010"), - nc(1844675, "1844675", "0x1c25c3", "0o7022703", "0b111000010010111000011"), - nc(2097151, "2097151", "0x1fffff", "0o7777777", "0b111111111111111111111"), - nc(2097152, "2097152", "0x200000", "0o10000000", "0b1000000000000000000000"), - nc(2097153, "2097153", "0x200001", "0o10000001", "0b1000000000000000000001"), - nc(4194303, "4194303", "0x3fffff", "0o17777777", "0b1111111111111111111111"), - nc(4194304, "4194304", "0x400000", "0o20000000", "0b10000000000000000000000"), - nc(4194305, "4194305", "0x400001", "0o20000001", "0b10000000000000000000001"), - nc(8388607, "8388607", "0x7fffff", "0o37777777", "0b11111111111111111111111"), - nc(8388608, "8388608", "0x800000", "0o40000000", "0b100000000000000000000000"), - nc(8388609, "8388609", "0x800001", "0o40000001", "0b100000000000000000000001"), - nc(9999999, "9999999", "0x98967f", "0o46113177", "0b100110001001011001111111"), - nc(10000000, "10000000", "0x989680", "0o46113200", "0b100110001001011010000000"), - nc(10000001, "10000001", "0x989681", "0o46113201", "0b100110001001011010000001"), - nc(16777215, "16777215", "0xffffff", "0o77777777", "0b111111111111111111111111"), - nc(16777216, "16777216", "0x1000000", "0o100000000", "0b1000000000000000000000000"), - nc(16777217, "16777217", "0x1000001", "0o100000001", "0b1000000000000000000000001"), - nc(18446743, "18446743", "0x1197997", "0o106274627", "0b1000110010111100110010111"), - nc(18446744, "18446744", "0x1197998", "0o106274630", "0b1000110010111100110011000"), - nc(18446745, "18446745", "0x1197999", "0o106274631", "0b1000110010111100110011001"), - nc(33554431, "33554431", "0x1ffffff", "0o177777777", "0b1111111111111111111111111"), - nc(33554432, "33554432", "0x2000000", "0o200000000", "0b10000000000000000000000000"), - nc(33554433, "33554433", "0x2000001", "0o200000001", "0b10000000000000000000000001"), - nc(67108863, "67108863", "0x3ffffff", "0o377777777", "0b11111111111111111111111111"), - nc(67108864, "67108864", "0x4000000", "0o400000000", "0b100000000000000000000000000"), - nc(67108865, "67108865", "0x4000001", "0o400000001", "0b100000000000000000000000001"), - nc(99999999, "99999999", "0x5f5e0ff", "0o575360377", "0b101111101011110000011111111"), - nc(100000000, "100000000", "0x5f5e100", "0o575360400", "0b101111101011110000100000000"), - nc(100000001, "100000001", "0x5f5e101", "0o575360401", "0b101111101011110000100000001"), - nc(134217727, "134217727", "0x7ffffff", "0o777777777", "0b111111111111111111111111111"), - nc(134217728, "134217728", "0x8000000", "0o1000000000", "0b1000000000000000000000000000"), - nc(134217729, "134217729", "0x8000001", "0o1000000001", "0b1000000000000000000000000001"), - nc(184467439, "184467439", "0xafebfef", "0o1277537757", "0b1010111111101011111111101111"), - nc(184467440, "184467440", "0xafebff0", "0o1277537760", "0b1010111111101011111111110000"), - nc(184467441, "184467441", "0xafebff1", "0o1277537761", "0b1010111111101011111111110001"), - nc(268435455, "268435455", "0xfffffff", "0o1777777777", "0b1111111111111111111111111111"), - nc(268435456, "268435456", "0x10000000", "0o2000000000", "0b10000000000000000000000000000"), - nc(268435457, "268435457", "0x10000001", "0o2000000001", "0b10000000000000000000000000001"), - nc(536870911, "536870911", "0x1fffffff", "0o3777777777", "0b11111111111111111111111111111"), - nc(536870912, "536870912", "0x20000000", "0o4000000000", "0b100000000000000000000000000000"), - nc(536870913, "536870913", "0x20000001", "0o4000000001", "0b100000000000000000000000000001"), - nc(999999999, "999999999", "0x3b9ac9ff", "0o7346544777", "0b111011100110101100100111111111"), - nc(1000000000, "1000000000", "0x3b9aca00", "0o7346545000", "0b111011100110101100101000000000"), - nc(1000000001, "1000000001", "0x3b9aca01", "0o7346545001", "0b111011100110101100101000000001"), - nc(1073741823, "1073741823", "0x3fffffff", "0o7777777777", "0b111111111111111111111111111111"), - nc(1073741824, "1073741824", "0x40000000", "0o10000000000", "0b1000000000000000000000000000000"), - nc(1073741825, "1073741825", "0x40000001", "0o10000000001", "0b1000000000000000000000000000001"), - nc(1844674406, "1844674406", "0x6df37f66", "0o15574677546", "0b1101101111100110111111101100110"), - nc(1844674407, "1844674407", "0x6df37f67", "0o15574677547", "0b1101101111100110111111101100111"), - nc(1844674408, "1844674408", "0x6df37f68", "0o15574677550", "0b1101101111100110111111101101000"), - nc(2147483647, "2147483647", "0x7fffffff", "0o17777777777", "0b1111111111111111111111111111111"), - nc(2147483648, "2147483648", "0x80000000", "0o20000000000", "0b10000000000000000000000000000000"), - nc(2147483649, "2147483649", "0x80000001", "0o20000000001", "0b10000000000000000000000000000001"), - nc(4294967295, "4294967295", "0xffffffff", "0o37777777777", "0b11111111111111111111111111111111"), - nc(4294967296, "4294967296", "0x100000000", "0o40000000000", "0b100000000000000000000000000000000"), - nc(4294967297, "4294967297", "0x100000001", "0o40000000001", "0b100000000000000000000000000000001"), - nc(8589934591, "8589934591", "0x1ffffffff", "0o77777777777", "0b111111111111111111111111111111111"), - nc(8589934592, "8589934592", "0x200000000", "0o100000000000", "0b1000000000000000000000000000000000"), - nc(8589934593, "8589934593", "0x200000001", "0o100000000001", "0b1000000000000000000000000000000001"), - nc(9999999999, "9999999999", "0x2540be3ff", "0o112402761777", "0b1001010100000010111110001111111111"), - nc(10000000000, "10000000000", "0x2540be400", "0o112402762000", "0b1001010100000010111110010000000000"), - nc(10000000001, "10000000001", "0x2540be401", "0o112402762001", "0b1001010100000010111110010000000001"), - nc(17179869183, "17179869183", "0x3ffffffff", "0o177777777777", "0b1111111111111111111111111111111111"), - nc(17179869184, "17179869184", "0x400000000", "0o200000000000", "0b10000000000000000000000000000000000"), - nc(17179869185, "17179869185", "0x400000001", "0o200000000001", "0b10000000000000000000000000000000001"), - nc(18446744072, "18446744072", "0x44b82fa08", "0o211340575010", "0b10001001011100000101111101000001000"), - nc(18446744073, "18446744073", "0x44b82fa09", "0o211340575011", "0b10001001011100000101111101000001001"), - nc(18446744074, "18446744074", "0x44b82fa0a", "0o211340575012", "0b10001001011100000101111101000001010"), - nc(34359738367, "34359738367", "0x7ffffffff", "0o377777777777", "0b11111111111111111111111111111111111"), - nc(34359738368, "34359738368", "0x800000000", "0o400000000000", "0b100000000000000000000000000000000000"), - nc(34359738369, "34359738369", "0x800000001", "0o400000000001", "0b100000000000000000000000000000000001"), - nc(68719476735, "68719476735", "0xfffffffff", "0o777777777777", "0b111111111111111111111111111111111111"), - nc(68719476736, "68719476736", "0x1000000000", "0o1000000000000", "0b1000000000000000000000000000000000000"), - nc(68719476737, "68719476737", "0x1000000001", "0o1000000000001", "0b1000000000000000000000000000000000001"), - nc(99999999999, "99999999999", "0x174876e7ff", "0o1351035563777", "0b1011101001000011101101110011111111111"), - nc(100000000000, "100000000000", "0x174876e800", "0o1351035564000", "0b1011101001000011101101110100000000000"), - nc(100000000001, "100000000001", "0x174876e801", "0o1351035564001", "0b1011101001000011101101110100000000001"), - nc(137438953471, "137438953471", "0x1fffffffff", "0o1777777777777", "0b1111111111111111111111111111111111111"), - nc(137438953472, "137438953472", "0x2000000000", "0o2000000000000", "0b10000000000000000000000000000000000000"), - nc(137438953473, "137438953473", "0x2000000001", "0o2000000000001", "0b10000000000000000000000000000000000001"), - nc(184467440736, "184467440736", "0x2af31dc460", "0o2536307342140", "0b10101011110011000111011100010001100000"), - nc(184467440737, "184467440737", "0x2af31dc461", "0o2536307342141", "0b10101011110011000111011100010001100001"), - nc(184467440738, "184467440738", "0x2af31dc462", "0o2536307342142", "0b10101011110011000111011100010001100010"), - nc(274877906943, "274877906943", "0x3fffffffff", "0o3777777777777", "0b11111111111111111111111111111111111111"), - nc(274877906944, "274877906944", "0x4000000000", "0o4000000000000", "0b100000000000000000000000000000000000000"), - nc(274877906945, "274877906945", "0x4000000001", "0o4000000000001", "0b100000000000000000000000000000000000001"), - nc(549755813887, "549755813887", "0x7fffffffff", "0o7777777777777", "0b111111111111111111111111111111111111111"), - nc(549755813888, "549755813888", "0x8000000000", "0o10000000000000", "0b1000000000000000000000000000000000000000"), - nc(549755813889, "549755813889", "0x8000000001", "0o10000000000001", "0b1000000000000000000000000000000000000001"), - nc(999999999999, "999999999999", "0xe8d4a50fff", "0o16432451207777", "0b1110100011010100101001010000111111111111"), - nc(1000000000000, "1000000000000", "0xe8d4a51000", "0o16432451210000", "0b1110100011010100101001010001000000000000"), - nc(1000000000001, "1000000000001", "0xe8d4a51001", "0o16432451210001", "0b1110100011010100101001010001000000000001"), - nc(1099511627775, "1099511627775", "0xffffffffff", "0o17777777777777", "0b1111111111111111111111111111111111111111"), - nc(1099511627776, "1099511627776", "0x10000000000", "0o20000000000000", "0b10000000000000000000000000000000000000000"), - nc(1099511627777, "1099511627777", "0x10000000001", "0o20000000000001", "0b10000000000000000000000000000000000000001"), - nc(1844674407369, "1844674407369", "0x1ad7f29abc9", "0o32657712325711", "0b11010110101111111001010011010101111001001"), - nc(1844674407370, "1844674407370", "0x1ad7f29abca", "0o32657712325712", "0b11010110101111111001010011010101111001010"), - nc(1844674407371, "1844674407371", "0x1ad7f29abcb", "0o32657712325713", "0b11010110101111111001010011010101111001011"), - nc(2199023255551, "2199023255551", "0x1ffffffffff", "0o37777777777777", "0b11111111111111111111111111111111111111111"), - nc(2199023255552, "2199023255552", "0x20000000000", "0o40000000000000", "0b100000000000000000000000000000000000000000"), - nc(2199023255553, "2199023255553", "0x20000000001", "0o40000000000001", "0b100000000000000000000000000000000000000001"), - nc(4398046511103, "4398046511103", "0x3ffffffffff", "0o77777777777777", "0b111111111111111111111111111111111111111111"), - nc(4398046511104, "4398046511104", "0x40000000000", "0o100000000000000", "0b1000000000000000000000000000000000000000000"), - nc(4398046511105, "4398046511105", "0x40000000001", "0o100000000000001", "0b1000000000000000000000000000000000000000001"), - nc(8796093022207, "8796093022207", "0x7ffffffffff", "0o177777777777777", "0b1111111111111111111111111111111111111111111"), - nc(8796093022208, "8796093022208", "0x80000000000", "0o200000000000000", "0b10000000000000000000000000000000000000000000"), - nc(8796093022209, "8796093022209", "0x80000000001", "0o200000000000001", "0b10000000000000000000000000000000000000000001"), - nc(9999999999999, "9999999999999", "0x9184e729fff", "0o221411634517777", "0b10010001100001001110011100101001111111111111"), - nc(10000000000000, "10000000000000", "0x9184e72a000", "0o221411634520000", "0b10010001100001001110011100101010000000000000"), - nc(10000000000001, "10000000000001", "0x9184e72a001", "0o221411634520001", "0b10010001100001001110011100101010000000000001"), - nc(17592186044415, "17592186044415", "0xfffffffffff", "0o377777777777777", "0b11111111111111111111111111111111111111111111"), - nc(17592186044416, "17592186044416", "0x100000000000", "0o400000000000000", "0b100000000000000000000000000000000000000000000"), - nc(17592186044417, "17592186044417", "0x100000000001", "0o400000000000001", "0b100000000000000000000000000000000000000000001"), - nc(18446744073708, "18446744073708", "0x10c6f7a0b5ec", "0o414336750132754", "0b100001100011011110111101000001011010111101100"), - nc(18446744073709, "18446744073709", "0x10c6f7a0b5ed", "0o414336750132755", "0b100001100011011110111101000001011010111101101"), - nc(18446744073710, "18446744073710", "0x10c6f7a0b5ee", "0o414336750132756", "0b100001100011011110111101000001011010111101110"), - nc(35184372088831, "35184372088831", "0x1fffffffffff", "0o777777777777777", "0b111111111111111111111111111111111111111111111"), - nc(35184372088832, "35184372088832", "0x200000000000", "0o1000000000000000", "0b1000000000000000000000000000000000000000000000"), - nc(35184372088833, "35184372088833", "0x200000000001", "0o1000000000000001", "0b1000000000000000000000000000000000000000000001"), - nc(70368744177663, "70368744177663", "0x3fffffffffff", "0o1777777777777777", "0b1111111111111111111111111111111111111111111111"), - nc(70368744177664, "70368744177664", "0x400000000000", "0o2000000000000000", "0b10000000000000000000000000000000000000000000000"), - nc(70368744177665, "70368744177665", "0x400000000001", "0o2000000000000001", "0b10000000000000000000000000000000000000000000001"), - nc(99999999999999, "99999999999999", "0x5af3107a3fff", "0o2657142036437777", "0b10110101111001100010000011110100011111111111111"), - nc(100000000000000, "100000000000000", "0x5af3107a4000", "0o2657142036440000", "0b10110101111001100010000011110100100000000000000"), - nc(100000000000001, "100000000000001", "0x5af3107a4001", "0o2657142036440001", "0b10110101111001100010000011110100100000000000001"), - nc(140737488355327, "140737488355327", "0x7fffffffffff", "0o3777777777777777", "0b11111111111111111111111111111111111111111111111"), - nc(140737488355328, "140737488355328", "0x800000000000", "0o4000000000000000", "0b100000000000000000000000000000000000000000000000"), - nc(140737488355329, "140737488355329", "0x800000000001", "0o4000000000000001", "0b100000000000000000000000000000000000000000000001"), - nc(184467440737094, "184467440737094", "0xa7c5ac471b46", "0o5174265421615506", "0b101001111100010110101100010001110001101101000110"), - nc(184467440737095, "184467440737095", "0xa7c5ac471b47", "0o5174265421615507", "0b101001111100010110101100010001110001101101000111"), - nc(184467440737096, "184467440737096", "0xa7c5ac471b48", "0o5174265421615510", "0b101001111100010110101100010001110001101101001000"), - nc(281474976710655, "281474976710655", "0xffffffffffff", "0o7777777777777777", "0b111111111111111111111111111111111111111111111111"), - nc(281474976710656, "281474976710656", "0x1000000000000", "0o10000000000000000", "0b1000000000000000000000000000000000000000000000000"), - nc(281474976710657, "281474976710657", "0x1000000000001", "0o10000000000000001", "0b1000000000000000000000000000000000000000000000001"), - nc(562949953421311, "562949953421311", "0x1ffffffffffff", "0o17777777777777777", "0b1111111111111111111111111111111111111111111111111"), - nc(562949953421312, "562949953421312", "0x2000000000000", "0o20000000000000000", "0b10000000000000000000000000000000000000000000000000"), - nc(562949953421313, "562949953421313", "0x2000000000001", "0o20000000000000001", "0b10000000000000000000000000000000000000000000000001"), - nc(999999999999999, "999999999999999", "0x38d7ea4c67fff", "0o34327724461477777", "0b11100011010111111010100100110001100111111111111111"), - nc(1000000000000000, "1000000000000000", "0x38d7ea4c68000", "0o34327724461500000", "0b11100011010111111010100100110001101000000000000000"), - nc(1000000000000001, "1000000000000001", "0x38d7ea4c68001", "0o34327724461500001", "0b11100011010111111010100100110001101000000000000001"), - nc(1125899906842623, "1125899906842623", "0x3ffffffffffff", "0o37777777777777777", "0b11111111111111111111111111111111111111111111111111"), - nc(1125899906842624, "1125899906842624", "0x4000000000000", "0o40000000000000000", "0b100000000000000000000000000000000000000000000000000"), - nc(1125899906842625, "1125899906842625", "0x4000000000001", "0o40000000000000001", "0b100000000000000000000000000000000000000000000000001"), - nc(1844674407370954, "1844674407370954", "0x68db8bac710ca", "0o64333427261610312", "0b110100011011011100010111010110001110001000011001010"), - nc(1844674407370955, "1844674407370955", "0x68db8bac710cb", "0o64333427261610313", "0b110100011011011100010111010110001110001000011001011"), - nc(1844674407370956, "1844674407370956", "0x68db8bac710cc", "0o64333427261610314", "0b110100011011011100010111010110001110001000011001100"), - nc(2251799813685247, "2251799813685247", "0x7ffffffffffff", "0o77777777777777777", "0b111111111111111111111111111111111111111111111111111"), - nc(2251799813685248, "2251799813685248", "0x8000000000000", "0o100000000000000000", "0b1000000000000000000000000000000000000000000000000000"), - nc(2251799813685249, "2251799813685249", "0x8000000000001", "0o100000000000000001", "0b1000000000000000000000000000000000000000000000000001"), - nc(4503599627370495, "4503599627370495", "0xfffffffffffff", "0o177777777777777777", "0b1111111111111111111111111111111111111111111111111111"), - nc(4503599627370496, "4503599627370496", "0x10000000000000", "0o200000000000000000", "0b10000000000000000000000000000000000000000000000000000"), - nc(4503599627370497, "4503599627370497", "0x10000000000001", "0o200000000000000001", "0b10000000000000000000000000000000000000000000000000001"), - nc(9007199254740991, "9007199254740991", "0x1fffffffffffff", "0o377777777777777777", "0b11111111111111111111111111111111111111111111111111111"), - nc(9007199254740992, "9007199254740992", "0x20000000000000", "0o400000000000000000", "0b100000000000000000000000000000000000000000000000000000"), - nc(9007199254740993, "9007199254740993", "0x20000000000001", "0o400000000000000001", "0b100000000000000000000000000000000000000000000000000001"), - nc(9999999999999999, "9999999999999999", "0x2386f26fc0ffff", "0o434157115760177777", "0b100011100001101111001001101111110000001111111111111111"), - nc(10000000000000000, "10000000000000000", "0x2386f26fc10000", "0o434157115760200000", "0b100011100001101111001001101111110000010000000000000000"), - nc(10000000000000001, "10000000000000001", "0x2386f26fc10001", "0o434157115760200001", "0b100011100001101111001001101111110000010000000000000001"), - nc(18014398509481983, "18014398509481983", "0x3fffffffffffff", "0o777777777777777777", "0b111111111111111111111111111111111111111111111111111111"), - nc(18014398509481984, "18014398509481984", "0x40000000000000", "0o1000000000000000000", "0b1000000000000000000000000000000000000000000000000000000"), - nc(18014398509481985, "18014398509481985", "0x40000000000001", "0o1000000000000000001", "0b1000000000000000000000000000000000000000000000000000001"), - nc(18446744073709551, "18446744073709551", "0x4189374bc6a7ef", "0o1014223351361523757", "0b1000001100010010011011101001011110001101010011111101111"), - nc(18446744073709552, "18446744073709552", "0x4189374bc6a7f0", "0o1014223351361523760", "0b1000001100010010011011101001011110001101010011111110000"), - nc(18446744073709553, "18446744073709553", "0x4189374bc6a7f1", "0o1014223351361523761", "0b1000001100010010011011101001011110001101010011111110001"), - nc(36028797018963967, "36028797018963967", "0x7fffffffffffff", "0o1777777777777777777", "0b1111111111111111111111111111111111111111111111111111111"), - nc(36028797018963968, "36028797018963968", "0x80000000000000", "0o2000000000000000000", "0b10000000000000000000000000000000000000000000000000000000"), - nc(36028797018963969, "36028797018963969", "0x80000000000001", "0o2000000000000000001", "0b10000000000000000000000000000000000000000000000000000001"), - nc(72057594037927935, "72057594037927935", "0xffffffffffffff", "0o3777777777777777777", "0b11111111111111111111111111111111111111111111111111111111"), - nc(72057594037927936, "72057594037927936", "0x100000000000000", "0o4000000000000000000", "0b100000000000000000000000000000000000000000000000000000000"), - nc(72057594037927937, "72057594037927937", "0x100000000000001", "0o4000000000000000001", "0b100000000000000000000000000000000000000000000000000000001"), - nc(99999999999999999, "99999999999999999", "0x16345785d89ffff", "0o5432127413542377777", "0b101100011010001010111100001011101100010011111111111111111"), - nc(100000000000000000, "100000000000000000", "0x16345785d8a0000", "0o5432127413542400000", "0b101100011010001010111100001011101100010100000000000000000"), - nc(100000000000000001, "100000000000000001", "0x16345785d8a0001", "0o5432127413542400001", "0b101100011010001010111100001011101100010100000000000000001"), - nc(144115188075855871, "144115188075855871", "0x1ffffffffffffff", "0o7777777777777777777", "0b111111111111111111111111111111111111111111111111111111111"), - nc(144115188075855872, "144115188075855872", "0x200000000000000", "0o10000000000000000000", "0b1000000000000000000000000000000000000000000000000000000000"), - nc(144115188075855873, "144115188075855873", "0x200000000000001", "0o10000000000000000001", "0b1000000000000000000000000000000000000000000000000000000001"), - nc(184467440737095519, "184467440737095519", "0x28f5c28f5c28f5f", "0o12172702436560507537", "0b1010001111010111000010100011110101110000101000111101011111"), - nc(184467440737095520, "184467440737095520", "0x28f5c28f5c28f60", "0o12172702436560507540", "0b1010001111010111000010100011110101110000101000111101100000"), - nc(184467440737095521, "184467440737095521", "0x28f5c28f5c28f61", "0o12172702436560507541", "0b1010001111010111000010100011110101110000101000111101100001"), - nc(288230376151711743, "288230376151711743", "0x3ffffffffffffff", "0o17777777777777777777", "0b1111111111111111111111111111111111111111111111111111111111"), - nc(288230376151711744, "288230376151711744", "0x400000000000000", "0o20000000000000000000", "0b10000000000000000000000000000000000000000000000000000000000"), - nc(288230376151711745, "288230376151711745", "0x400000000000001", "0o20000000000000000001", "0b10000000000000000000000000000000000000000000000000000000001"), - nc(576460752303423487, "576460752303423487", "0x7ffffffffffffff", "0o37777777777777777777", "0b11111111111111111111111111111111111111111111111111111111111"), - nc(576460752303423488, "576460752303423488", "0x800000000000000", "0o40000000000000000000", "0b100000000000000000000000000000000000000000000000000000000000"), - nc(576460752303423489, "576460752303423489", "0x800000000000001", "0o40000000000000000001", "0b100000000000000000000000000000000000000000000000000000000001"), - nc(999999999999999999, "999999999999999999", "0xde0b6b3a763ffff", "0o67405553164730777777", "0b110111100000101101101011001110100111011000111111111111111111"), - nc(1000000000000000000, "1000000000000000000", "0xde0b6b3a7640000", "0o67405553164731000000", "0b110111100000101101101011001110100111011001000000000000000000"), - nc(1000000000000000001, "1000000000000000001", "0xde0b6b3a7640001", "0o67405553164731000001", "0b110111100000101101101011001110100111011001000000000000000001"), - nc(1152921504606846975, "1152921504606846975", "0xfffffffffffffff", "0o77777777777777777777", "0b111111111111111111111111111111111111111111111111111111111111"), - nc(1152921504606846976, "1152921504606846976", "0x1000000000000000", "0o100000000000000000000", "0b1000000000000000000000000000000000000000000000000000000000000"), - nc(1152921504606846977, "1152921504606846977", "0x1000000000000001", "0o100000000000000000001", "0b1000000000000000000000000000000000000000000000000000000000001"), - nc(1844674407370955263, "1844674407370955263", "0x19999999999999ff", "0o146314631463146314777", "0b1100110011001100110011001100110011001100110011001100111111111"), - nc(1844674407370955264, "1844674407370955264", "0x1999999999999a00", "0o146314631463146315000", "0b1100110011001100110011001100110011001100110011001101000000000"), - nc(1844674407370955265, "1844674407370955265", "0x1999999999999a01", "0o146314631463146315001", "0b1100110011001100110011001100110011001100110011001101000000001"), - nc(2305843009213693951, "2305843009213693951", "0x1fffffffffffffff", "0o177777777777777777777", "0b1111111111111111111111111111111111111111111111111111111111111"), - nc(2305843009213693952, "2305843009213693952", "0x2000000000000000", "0o200000000000000000000", "0b10000000000000000000000000000000000000000000000000000000000000"), - nc(2305843009213693953, "2305843009213693953", "0x2000000000000001", "0o200000000000000000001", "0b10000000000000000000000000000000000000000000000000000000000001"), - nc(4611686018427387903, "4611686018427387903", "0x3fffffffffffffff", "0o377777777777777777777", "0b11111111111111111111111111111111111111111111111111111111111111"), - nc(4611686018427387904, "4611686018427387904", "0x4000000000000000", "0o400000000000000000000", "0b100000000000000000000000000000000000000000000000000000000000000"), - nc(4611686018427387905, "4611686018427387905", "0x4000000000000001", "0o400000000000000000001", "0b100000000000000000000000000000000000000000000000000000000000001"), - nc(9223372036854775807, "9223372036854775807", "0x7fffffffffffffff", "0o777777777777777777777", "0b111111111111111111111111111111111111111111111111111111111111111"), - nc(9223372036854775808, "9223372036854775808", "0x8000000000000000", "0o1000000000000000000000", "0b1000000000000000000000000000000000000000000000000000000000000000"), - nc(9223372036854775809, "9223372036854775809", "0x8000000000000001", "0o1000000000000000000001", "0b1000000000000000000000000000000000000000000000000000000000000001"), - nc(9999999999999999999, "9999999999999999999", "0x8ac7230489e7ffff", "0o1053071060221171777777", "0b1000101011000111001000110000010010001001111001111111111111111111"), - nc(10000000000000000000, "10000000000000000000", "0x8ac7230489e80000", "0o1053071060221172000000", "0b1000101011000111001000110000010010001001111010000000000000000000"), - nc(10000000000000000001, "10000000000000000001", "0x8ac7230489e80001", "0o1053071060221172000001", "0b1000101011000111001000110000010010001001111010000000000000000001"), - nc(18446744073709551611, "18446744073709551611", "0xfffffffffffffffb", "0o1777777777777777777773", "0b1111111111111111111111111111111111111111111111111111111111111011"), - nc(18446744073709551612, "18446744073709551612", "0xfffffffffffffffc", "0o1777777777777777777774", "0b1111111111111111111111111111111111111111111111111111111111111100"), - nc(18446744073709551613, "18446744073709551613", "0xfffffffffffffffd", "0o1777777777777777777775", "0b1111111111111111111111111111111111111111111111111111111111111101"), - nc(18446744073709551614, "18446744073709551614", "0xfffffffffffffffe", "0o1777777777777777777776", "0b1111111111111111111111111111111111111111111111111111111111111110"), - nc(18446744073709551615, "18446744073709551615", "0xffffffffffffffff", "0o1777777777777777777777", "0b1111111111111111111111111111111111111111111111111111111111111111"), -#undef nc - }; -}; - -C4_INLINE_CONSTEXPR const number_case numbers::vals[]; -C4_INLINE_CONSTEXPR const number_case numbers::vals[]; - -C4_INLINE_CONSTEXPR const number_case numbers::vals[]; -C4_INLINE_CONSTEXPR const number_case numbers::vals[]; - -C4_INLINE_CONSTEXPR const number_case numbers::vals[]; -C4_INLINE_CONSTEXPR const number_case numbers::vals[]; - -C4_INLINE_CONSTEXPR const number_case numbers::vals[]; -C4_INLINE_CONSTEXPR const number_case numbers::vals[]; - -C4_SUPPRESS_WARNING_MSVC_POP - -} // namespace c4 diff --git a/thirdparty/ryml/ext/c4core/test/test_preprocessor.cpp b/thirdparty/ryml/ext/c4core/test/test_preprocessor.cpp deleted file mode 100644 index bd2619ae4..000000000 --- a/thirdparty/ryml/ext/c4core/test/test_preprocessor.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef C4CORE_SINGLE_HEADER -#include "c4/preprocessor.hpp" -#include "c4/language.hpp" -#endif - -#ifdef WE_LL_GET_THERE___MSVC_CANT_HANDLE_THE_FOREACH_MACRO___NEEDS_TO_BE_FIXED -#include -#include - -struct SomeStruct -{ - int32_t a; - int32_t b; - int32_t c; - int32_t d; -}; - -TEST(TestForEach, print_offsets) -{ -#define M_OFFS_(structure, field) m[#field] = offsetof(structure, field) -#define M_OFFS(field) M_OFFS_(SomeStruct, field) - - std::map< std::string, size_t > m; - - C4_FOR_EACH(M_OFFS, a, b, c); - C4_FOR_EACH(M_OFFS, d); - - EXPECT_EQ(m["a"], 0); - EXPECT_EQ(m["b"], 4); - EXPECT_EQ(m["c"], 8); - EXPECT_EQ(m["d"], 12); -} - -//----------------------------------------------------------------------------- -// C4_BEGIN_NAMESPACE()/C4_END_NAMESPACE() are implemented with C4_FOR_EACH(). -// Test these here too. - -namespace a, b, c { -int a_var = 0; -} // namespace c, b -int var = 1; // a::var -namespace b { -int var = 2; // a::b::var -namespace c { -int var = 3; // a::b::c::var -} // namespace c, b, a - -TEST(TestForEach, begin_end_namespace) -{ - EXPECT_EQ(a::b::c::a_var, 0); - EXPECT_EQ(a::var, 1); - EXPECT_EQ(a::b::var, 2); - EXPECT_EQ(a::b::c::var, 3); -} -#endif diff --git a/thirdparty/ryml/ext/c4core/test/test_singleheader/libc4core_singleheader.cpp b/thirdparty/ryml/ext/c4core/test/test_singleheader/libc4core_singleheader.cpp deleted file mode 100644 index 078c77d1e..000000000 --- a/thirdparty/ryml/ext/c4core/test/test_singleheader/libc4core_singleheader.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#define C4CORE_SINGLE_HDR_DEFINE_NOW -#include diff --git a/thirdparty/ryml/ext/c4core/test/test_span.cpp b/thirdparty/ryml/ext/c4core/test/test_span.cpp deleted file mode 100644 index c492013d7..000000000 --- a/thirdparty/ryml/ext/c4core/test/test_span.cpp +++ /dev/null @@ -1,944 +0,0 @@ -#ifndef C4CORE_SINGLE_HEADER -#include "c4/span.hpp" -#endif - -#include "c4/libtest/supprwarn_push.hpp" - -#include - -namespace c4 { - -//----------------------------------------------------------------------------- -TEST_CASE_TEMPLATE("span.default_init", SpanClass, span, spanrs, spanrsl) -{ - SpanClass s; - CHECK_EQ(s.size(), 0); - CHECK_EQ(s.capacity(), 0); - CHECK_EQ(s.data(), nullptr); -} - - -template class Span, class T, class I> -Span cvt_to_const(Span const& s) -{ - Span ret = s; - return ret; -} - -TEST_CASE_TEMPLATE("span.convert_to_const", SpanClass, span, spanrs, spanrsl) -{ - SpanClass s; - auto cs = cvt_to_const(s); - CHECK_EQ(s.size(), cs.size()); - CHECK_EQ(s.data(), cs.data()); - CHECK_EQ(s.end(), cs.end()); -} - - -//----------------------------------------------------------------------------- -TEST_CASE("span.empty_init") -{ - int arr[10]; - span s(arr, 0); - CHECK_EQ(s.size(), 0); - CHECK_EQ(s.capacity(), 0); - CHECK_NE(s.data(), nullptr); -} - -TEST_CASE("spanrs.empty_init") -{ - int arr[10]; - - { - spanrs s(arr, 0); - CHECK_EQ(s.size(), 0); - CHECK_EQ(s.capacity(), 0); - CHECK_EQ(s.data(), arr); - } - - { - spanrs s(arr, 0, C4_COUNTOF(arr)); - CHECK_EQ(s.size(), 0); - CHECK_EQ(s.capacity(), 10); - CHECK_EQ(s.data(), arr); - } -} - -TEST_CASE("spanrsl.empty_init") -{ - int arr[10]; - - { - spanrsl s(arr, 0); - CHECK_EQ(s.size(), 0); - CHECK_EQ(s.capacity(), 0); - CHECK_EQ(s.data(), arr); - CHECK_EQ(s.offset(), 0); - } - - { - spanrsl s(arr, 0, C4_COUNTOF(arr)); - CHECK_EQ(s.size(), 0); - CHECK_EQ(s.capacity(), 10); - CHECK_EQ(s.data(), arr); - CHECK_EQ(s.offset(), 0); - } -} - -//----------------------------------------------------------------------------- - -TEST_CASE_TEMPLATE("span.fromArray", SpanClass, - span, span, span, - spanrs, spanrs, spanrs, - spanrsl, spanrsl, spanrsl - ) -{ - using ConstSpanClass = typename SpanClass::const_type; - using T = typename SpanClass::value_type; - T arr1[10]; - T arr2[20]; - - T a = 0; - for(auto &v : arr1) { v = a; ++a; } - for(auto &v : arr2) { v = a; ++a; } - - { - SpanClass s(arr1); - CHECK_EQ(s.size(), C4_COUNTOF(arr1)); - CHECK_EQ(s.capacity(), C4_COUNTOF(arr1)); - CHECK_EQ(s.data(), arr1); - } - - { - ConstSpanClass s(arr1); - CHECK_EQ(s.size(), C4_COUNTOF(arr1)); - CHECK_EQ(s.capacity(), C4_COUNTOF(arr1)); - CHECK_EQ(s.data(), arr1); - } - - { - SpanClass s = arr1; - CHECK_EQ(s.size(), C4_COUNTOF(arr1)); - CHECK_EQ(s.capacity(), C4_COUNTOF(arr1)); - CHECK_EQ(s.data(), arr1); - } - - { - ConstSpanClass s = arr1; - CHECK_EQ(s.size(), C4_COUNTOF(arr1)); - CHECK_EQ(s.capacity(), C4_COUNTOF(arr1)); - CHECK_EQ(s.data(), arr1); - } - - { - SpanClass s = arr1; - CHECK_EQ(s.size(), C4_COUNTOF(arr1)); - CHECK_EQ(s.capacity(), C4_COUNTOF(arr1)); - CHECK_EQ(s.data(), arr1); - s = arr2; - CHECK_EQ(s.size(), C4_COUNTOF(arr2)); - CHECK_EQ(s.capacity(), C4_COUNTOF(arr2)); - CHECK_EQ(s.data(), arr2); - } - - { - ConstSpanClass s = arr1; - CHECK_EQ(s.size(), C4_COUNTOF(arr1)); - CHECK_EQ(s.capacity(), C4_COUNTOF(arr1)); - CHECK_EQ(s.data(), arr1); - s = arr2; - CHECK_EQ(s.size(), C4_COUNTOF(arr2)); - CHECK_EQ(s.capacity(), C4_COUNTOF(arr2)); - CHECK_EQ(s.data(), arr2); - } -} - - -//----------------------------------------------------------------------------- -TEST_CASE("span.subspan") -{ - int arr[10]; - span s(arr); - C4_STATIC_ASSERT((std::is_same::value)); - - { - auto ss = s.subspan(0, 5); - CHECK_EQ(ss.size(), 5); - CHECK_EQ(ss.capacity(), 5); - CHECK_EQ(ss.data(), arr); - - ss = s.subspan(5); - CHECK_EQ(ss.size(), 5); - CHECK_EQ(ss.capacity(), 5); - CHECK_EQ(ss.data(), &arr[5]); - - // fine to obtain an empty span at the end - ss = s.subspan(10); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.capacity(), 0); - CHECK_EQ(ss.data(), std::end(arr)); - // fine to obtain an empty span at the end - ss = s.subspan(10, 0); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.capacity(), 0); - CHECK_EQ(ss.data(), std::end(arr)); - } - { - int buf10[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - int buf_5[] = {-1, 0, 1, 2, 3, 4}; - int *buf5 = buf_5 + 1; // to make sure that one does not immediately follow the other in memory - - span n(buf10); - span m(buf5, 5); - - auto ss = n.subspan(0); - CHECK_EQ(ss.data(), buf10); - CHECK_EQ(ss.size(), 10); - ss = m.subspan(0); - CHECK_EQ(ss.data(), buf5); - CHECK_EQ(ss.size(), 5); - ss = n.subspan(0, 0); - CHECK_NE(ss.data(), nullptr); - CHECK_EQ(ss.data(), &buf10[0]); - CHECK_EQ(ss.size(), 0); - ss = m.subspan(0, 0); - CHECK_NE(ss.data(), nullptr); - CHECK_EQ(ss.data(), &buf5[0]); - CHECK_EQ(ss.size(), 0); - } -} -TEST_CASE("spanrs.subspan") -{ - int arr[10]; - spanrs s(arr); - C4_STATIC_ASSERT((std::is_same::value)); - - auto ss = s.subspan(0, 5); - CHECK_EQ(ss.size(), 5); - CHECK_EQ(ss.capacity(), 10); - CHECK_EQ(ss.data(), arr); - - ss = s.subspan(5); - CHECK_EQ(ss.size(), 5); - CHECK_EQ(ss.capacity(), 5); - CHECK_EQ(ss.data(), &arr[5]); - - // fine to obtain an empty span at the end - ss = s.subspan(10); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.capacity(), 0); - CHECK_EQ(ss.data(), std::end(arr)); - // fine to obtain an empty span at the end - ss = s.subspan(10, 0); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.capacity(), 0); - CHECK_EQ(ss.data(), std::end(arr)); -} -TEST_CASE("spanrsl.subspan") -{ - int arr[10]; - spanrsl s(arr); - C4_STATIC_ASSERT((std::is_same::value)); - - auto ss = s.subspan(0, 5); - CHECK_EQ(ss.size(), 5); - CHECK_EQ(ss.capacity(), 10); - CHECK_EQ(ss.data(), arr); - CHECK_EQ(ss.offset(), 0); - - ss = ss.original(); - CHECK_EQ(ss.size(), 10); - CHECK_EQ(ss.capacity(), 10); - CHECK_EQ(ss.data(), arr); - CHECK_EQ(ss.offset(), 0); - - ss = s.subspan(5); - CHECK_EQ(ss.size(), 5); - CHECK_EQ(ss.capacity(), 5); - CHECK_EQ(ss.data(), &arr[5]); - CHECK_EQ(ss.offset(), 5); - - ss = ss.original(); - CHECK_EQ(ss.size(), 10); - CHECK_EQ(ss.capacity(), 10); - CHECK_EQ(ss.data(), arr); - CHECK_EQ(ss.offset(), 0); - - // fine to obtain an empty span at the end - ss = s.subspan(10); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.capacity(), 0); - CHECK_EQ(ss.data(), std::end(arr)); - // fine to obtain an empty span at the end - ss = s.subspan(10, 0); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.capacity(), 0); - CHECK_EQ(ss.data(), std::end(arr)); -} - -//----------------------------------------------------------------------------- -TEST_CASE("span.range") -{ - int arr[10]; - span s(arr); - C4_STATIC_ASSERT((std::is_same::value)); - - auto ss = s.range(0, 5); - CHECK_EQ(ss.size(), 5); - CHECK_EQ(ss.capacity(), 5); - CHECK_EQ(ss.data(), arr); - - ss = s.range(5); - CHECK_EQ(ss.size(), 5); - CHECK_EQ(ss.capacity(), 5); - CHECK_EQ(ss.data(), &arr[5]); - - ss = s.range(5, 10); - CHECK_EQ(ss.size(), 5); - CHECK_EQ(ss.capacity(), 5); - CHECK_EQ(ss.data(), &arr[5]); - - ss = s.range(10, 10); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.capacity(), 0); - CHECK_EQ(ss.data(), std::end(arr)); - - SUBCASE("empty_span") - { - s = {}; - ss = s.range(0, 0); - CHECK(ss.empty()); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.data(), nullptr); - s = arr; - ss = s.range(0, 0); - CHECK(ss.empty()); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.data(), arr); - ss = s.range(10, 10); - CHECK(ss.empty()); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.data(), arr + 10); - ss = s.range(10); - CHECK(ss.empty()); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.data(), arr + 10); - } -} -TEST_CASE("spanrs.range") -{ - int arr[10]; - spanrs s(arr); - C4_STATIC_ASSERT((std::is_same::value)); - - auto ss = s.range(0, 5); - CHECK_EQ(ss.size(), 5); - CHECK_EQ(ss.capacity(), 10); - CHECK_EQ(ss.data(), arr); - - ss = s.range(5); - CHECK_EQ(ss.size(), 5); - CHECK_EQ(ss.capacity(), 5); - CHECK_EQ(ss.data(), &arr[5]); - - ss = s.range(5, 10); - CHECK_EQ(ss.size(), 5); - CHECK_EQ(ss.capacity(), 5); - CHECK_EQ(ss.data(), &arr[5]); - - ss = s.range(10, 10); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.capacity(), 0); - CHECK_EQ(ss.data(), std::end(arr)); - - SUBCASE("empty_span") - { - s = {}; - ss = s.range(0, 0); - CHECK(ss.empty()); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.data(), nullptr); - s = arr; - ss = s.range(0, 0); - CHECK(ss.empty()); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.data(), arr); - ss = s.range(10, 10); - CHECK(ss.empty()); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.data(), arr + 10); - ss = s.range(10); - CHECK(ss.empty()); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.data(), arr + 10); - } -} -TEST_CASE("spanrsl.range") -{ - int arr[10]; - spanrsl s(arr); - C4_STATIC_ASSERT((std::is_same::value)); - - auto ss = s.range(0, 5); - CHECK_EQ(ss.size(), 5); - CHECK_EQ(ss.capacity(), 10); - CHECK_EQ(ss.data(), arr); - - ss = ss.original(); - CHECK_EQ(ss.size(), 10); - CHECK_EQ(ss.capacity(), 10); - CHECK_EQ(ss.data(), arr); - - ss = s.range(5); - CHECK_EQ(ss.size(), 5); - CHECK_EQ(ss.capacity(), 5); - CHECK_EQ(ss.data(), &arr[5]); - - ss = s.range(5, 10); - CHECK_EQ(ss.size(), 5); - CHECK_EQ(ss.capacity(), 5); - CHECK_EQ(ss.data(), &arr[5]); - - ss = ss.original(); - CHECK_EQ(ss.size(), 10); - CHECK_EQ(ss.capacity(), 10); - CHECK_EQ(ss.data(), arr); - - ss = s.range(10, 10); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.capacity(), 0); - CHECK_EQ(ss.data(), std::end(arr)); - - SUBCASE("empty_span") - { - s = {}; - ss = s.range(0, 0); - CHECK(ss.empty()); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.data(), nullptr); - s = arr; - ss = s.range(0, 0); - CHECK(ss.empty()); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.data(), arr); - ss = s.range(10, 10); - CHECK(ss.empty()); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.data(), arr + 10); - ss = s.range(10); - CHECK(ss.empty()); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.data(), arr + 10); - } -} - -//----------------------------------------------------------------------------- -TEST_CASE("span.first") -{ - int arr[10]; - span s(arr); - C4_STATIC_ASSERT((std::is_same::value)); - - auto ss = s.first(0); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.capacity(), 0); - CHECK_EQ(ss.data(), arr); - - ss = s.first(5); - CHECK_EQ(ss.size(), 5); - CHECK_EQ(ss.capacity(), 5); - CHECK_EQ(ss.data(), arr); - - SUBCASE("empty") - { - s = {}; - ss = s.first(0); - CHECK(ss.empty()); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.data(), nullptr); - s = arr; - ss = s.first(0); - CHECK(ss.empty()); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.data(), arr); - } -} -TEST_CASE("spanrs.first") -{ - int arr[10]; - spanrs s(arr); - C4_STATIC_ASSERT((std::is_same::value)); - - auto ss = s.first(0); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.capacity(), 10); - CHECK_EQ(ss.data(), arr); - - ss = s.first(5); - CHECK_EQ(ss.size(), 5); - CHECK_EQ(ss.capacity(), 10); - CHECK_EQ(ss.data(), arr); - - SUBCASE("empty") - { - s = {}; - ss = s.first(0); - CHECK(ss.empty()); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.data(), nullptr); - s = arr; - ss = s.first(0); - CHECK(ss.empty()); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.data(), arr); - } -} -TEST_CASE("spanrsl.first") -{ - int arr[10]; - spanrsl s(arr); - C4_STATIC_ASSERT((std::is_same::value)); - - auto ss = s.first(0); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.capacity(), 10); - CHECK_EQ(ss.data(), arr); - - ss = ss.original(); - CHECK_EQ(ss.size(), 10); - CHECK_EQ(ss.capacity(), 10); - CHECK_EQ(ss.data(), arr); - - ss = s.first(5); - CHECK_EQ(ss.size(), 5); - CHECK_EQ(ss.capacity(), 10); - CHECK_EQ(ss.data(), arr); - - ss = ss.original(); - CHECK_EQ(ss.size(), 10); - CHECK_EQ(ss.capacity(), 10); - CHECK_EQ(ss.data(), arr); - - SUBCASE("empty") - { - s = {}; - ss = s.first(0); - CHECK(ss.empty()); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.data(), nullptr); - s = arr; - ss = s.first(0); - CHECK(ss.empty()); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.data(), arr); - } -} - -//----------------------------------------------------------------------------- -TEST_CASE("span.last") -{ - int arr[10]; - span s(arr); - C4_STATIC_ASSERT((std::is_same::value)); - - auto ss = s.last(0); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.capacity(), 0); - CHECK_EQ(ss.data(), arr + s.size()); - - ss = s.last(5); - CHECK_EQ(ss.size(), 5); - CHECK_EQ(ss.capacity(), 5); - CHECK_EQ(ss.data(), arr + 5); - - SUBCASE("empty") - { - s = {}; - ss = s.last(0); - CHECK(ss.empty()); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.data(), nullptr); - s = arr; - ss = s.last(0); - CHECK(ss.empty()); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.data(), arr + 10); - } -} -TEST_CASE("spanrs.last") -{ - int arr[10]; - spanrs s(arr); - C4_STATIC_ASSERT((std::is_same::value)); - - auto ss = s.last(0); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.capacity(), 0); - CHECK_EQ(ss.data(), arr + s.size()); - - ss = s.last(5); - CHECK_EQ(ss.size(), 5); - CHECK_EQ(ss.capacity(), 5); - CHECK_EQ(ss.data(), arr + 5); - - SUBCASE("empty") - { - s = {}; - ss = s.last(0); - CHECK(ss.empty()); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.data(), nullptr); - s = arr; - ss = s.last(0); - CHECK(ss.empty()); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.data(), arr + 10); - } -} -TEST_CASE("spanrsl.last") -{ - int arr[10]; - spanrsl s(arr); - C4_STATIC_ASSERT((std::is_same::value)); - - auto ss = s.last(0); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.capacity(), 0); - CHECK_EQ(ss.data(), arr + s.size()); - - ss = ss.original(); - CHECK_EQ(ss.size(), 10); - CHECK_EQ(ss.capacity(), 10); - CHECK_EQ(ss.data(), arr); - - ss = s.last(5); - CHECK_EQ(ss.size(), 5); - CHECK_EQ(ss.capacity(), 5); - CHECK_EQ(ss.data(), arr + 5); - - ss = ss.original(); - CHECK_EQ(ss.size(), 10); - CHECK_EQ(ss.capacity(), 10); - CHECK_EQ(ss.data(), arr); - - SUBCASE("empty") - { - s = {}; - ss = s.last(0); - CHECK(ss.empty()); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.data(), nullptr); - s = arr; - ss = s.last(0); - CHECK(ss.empty()); - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.data(), arr + 10); - } -} - - -//----------------------------------------------------------------------------- -TEST_CASE_TEMPLATE("span.is_subspan", SpanClass, span, spanrs, spanrsl) -{ - int buf10[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - int buf_5[] = {-1, 0, 1, 2, 3, 4}; - int *buf5 = buf_5 + 1; // to make sure that one does not immediately follow the other in memory - - SpanClass n(buf10); - SpanClass m(buf5, 5); - - CHECK_EQ(n.data(), buf10); - CHECK_EQ(m.data(), buf5); - - CHECK_UNARY(n.is_subspan(n.subspan(0 ))); - CHECK_UNARY(n.is_subspan(n.subspan(0, 3))); - CHECK_UNARY(n.is_subspan(n.subspan(0, 0))); - - CHECK_FALSE(n.is_subspan(m.subspan(0 ))); - CHECK_FALSE(n.is_subspan(m.subspan(0, 3))); - CHECK_FALSE(n.is_subspan(m.subspan(0, 0))); -} - -//----------------------------------------------------------------------------- -TEST_CASE_TEMPLATE("span.compll", SpanClass, span, spanrs, spanrsl) -{ - int buf10[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - - SpanClass n(buf10); - - CHECK_EQ(n.compll(n.subspan(0)), n.subspan(0, 0)); - CHECK_EQ(n.is_subspan(n.compll(n.subspan(0))), true); - CHECK_EQ(n.compll(n.subspan(0, 0)), n.subspan(0, 0)); - CHECK_EQ(n.is_subspan(n.compll(n.subspan(0, 0))), true); - - CHECK_EQ(n.compll(n.subspan(0, 1)), n.subspan(0, 0)); - CHECK_EQ(n.compll(n.subspan(0, 3)), n.subspan(0, 0)); - - CHECK_EQ(n.compll(n.range(5, 10)), n.subspan(0, 5)); - CHECK_EQ(n.compll(n.range(5, 5)), n.subspan(0, 5)); - - CHECK_EQ(n.compll(n.subspan(n.size(), 0)), n); - CHECK_EQ(n.compll(n.range(n.size(), n.size())), n); -} - - -//----------------------------------------------------------------------------- - -TEST_CASE_TEMPLATE("span.complr", SpanClass, span, spanrs, spanrsl) -{ - int buf10[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - - SpanClass n(buf10); - - CHECK_EQ(n.complr(n.subspan(0)), n.subspan(0, 0)); - CHECK_EQ(n.is_subspan(n.complr(n.subspan(0))), true); - CHECK_EQ(n.complr(n.subspan(0, 0)), n.subspan(0)); - CHECK_EQ(n.is_subspan(n.complr(n.subspan(0, 0))), true); - - CHECK_EQ(n.complr(n.subspan(0, 1)), n.subspan(1)); - CHECK_EQ(n.complr(n.subspan(0, 3)), n.subspan(3)); - - CHECK_EQ(n.complr(n.subspan(5)), n.subspan(0, 0)); - CHECK_EQ(n.complr(n.range(5, 10)), n.subspan(0, 0)); - - CHECK_EQ(n.complr(n.subspan(5, 0)), n.subspan(5)); - CHECK_EQ(n.complr(n.range(5, 5)), n.subspan(5)); - - CHECK_EQ(n.complr(n.subspan(0, 0)), n); - CHECK_EQ(n.complr(n.range(0, 0)), n); -} - - -//----------------------------------------------------------------------------- -TEST_CASE("span.rtrim") -{ - int arr[10]; - span s(arr); - auto ss = s; - - ss.rtrim(0); - CHECK_EQ(ss.size(), s.size()); - CHECK_EQ(ss.capacity(), s.capacity()); - CHECK_EQ(ss.data(), arr); - - ss.rtrim(5); - CHECK_EQ(ss.size(), s.size() - 5); - CHECK_EQ(ss.capacity(), s.capacity() - 5); - CHECK_EQ(ss.data(), arr); -} -TEST_CASE("spanrs.rtrim") -{ - int arr[10]; - spanrs s(arr); - auto ss = s; - - ss.rtrim(0); - CHECK_EQ(ss.size(), s.size()); - CHECK_EQ(ss.capacity(), s.capacity()); - CHECK_EQ(ss.data(), arr); - - ss.rtrim(5); - CHECK_EQ(ss.size(), s.size() - 5); - CHECK_EQ(ss.capacity(), s.capacity()); - CHECK_EQ(ss.data(), arr); -} -TEST_CASE("spanrsl.rtrim") -{ - int arr[10]; - spanrsl s(arr); - auto ss = s; - - ss.rtrim(0); - CHECK_EQ(ss.size(), s.size()); - CHECK_EQ(ss.capacity(), s.capacity()); - CHECK_EQ(ss.data(), arr); - - ss = ss.original(); - CHECK_EQ(ss.size(), 10); - CHECK_EQ(ss.capacity(), 10); - CHECK_EQ(ss.data(), arr); - - ss.rtrim(5); - CHECK_EQ(ss.size(), s.size() - 5); - CHECK_EQ(ss.capacity(), s.capacity()); - CHECK_EQ(ss.data(), arr); - - ss = ss.original(); - CHECK_EQ(ss.size(), 10); - CHECK_EQ(ss.capacity(), 10); - CHECK_EQ(ss.data(), arr); -} - -//----------------------------------------------------------------------------- -TEST_CASE("span.ltrim") -{ - int arr[10]; - span s(arr); - auto ss = s; - - ss.ltrim(0); - CHECK_EQ(ss.size(), s.size()); - CHECK_EQ(ss.capacity(), s.capacity()); - CHECK_EQ(ss.data(), arr); - - ss.ltrim(5); - CHECK_EQ(ss.size(), s.size() - 5); - CHECK_EQ(ss.capacity(), s.capacity() - 5); - CHECK_EQ(ss.data(), arr + 5); -} -TEST_CASE("spanrs.ltrim") -{ - int arr[10]; - spanrs s(arr); - auto ss = s; - - ss.ltrim(0); - CHECK_EQ(ss.size(), s.size()); - CHECK_EQ(ss.capacity(), ss.capacity()); - CHECK_EQ(ss.data(), arr); - - ss.ltrim(5); - CHECK_EQ(ss.size(), s.size() - 5); - CHECK_EQ(ss.capacity(), s.size() - 5); - CHECK_EQ(ss.data(), arr + 5); -} -TEST_CASE("spanrsl.ltrim") -{ - int arr[10]; - spanrsl s(arr); - auto ss = s; - - ss.ltrim(0); - CHECK_EQ(ss.size(), s.size()); - CHECK_EQ(ss.capacity(), ss.capacity()); - CHECK_EQ(ss.data(), arr); - - ss = ss.original(); - CHECK_EQ(ss.size(), 10); - CHECK_EQ(ss.capacity(), 10); - CHECK_EQ(ss.data(), arr); - - ss.ltrim(5); - CHECK_EQ(ss.size(), s.size() - 5); - CHECK_EQ(ss.capacity(), s.size() - 5); - CHECK_EQ(ss.data(), arr + 5); - - ss = ss.original(); - CHECK_EQ(ss.size(), 10); - CHECK_EQ(ss.capacity(), 10); - CHECK_EQ(ss.data(), arr); -} - -//----------------------------------------------------------------------------- -const char larrc[11] = "0123456789"; -const char rarrc[11] = "1234567890"; -const int larri[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; -const int rarri[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}; -TEST_CASE("span.reverse_iter") -{ - cspan s(larri); - REQUIRE_EQ(s.data(), larri); - REQUIRE_EQ(s.begin(), std::begin(larri)); - REQUIRE_EQ(s.end(), std::end(larri)); - REQUIRE_EQ(&*s.rbegin(), s.end()-1); - using rit = cspan::const_reverse_iterator; - int pos = szconv(s.size()) - 1; - size_t count = 0; - //for(rit b = s.rbegin(), e = s.rend(); b != e; ++b) // BUG: b != e is never true on arm-eabi-g++-7 - for(rit b = s.rbegin(), e = s.rend(); b < e; ++b) - { - CHECK_EQ(&(*b), s.data() + pos); - auto spos = szconv(pos); - REQUIRE_EQ(&*b, &s[spos]); - REQUIRE_GE(pos, 0); - REQUIRE_LT(pos, szconv(s.size())); - REQUIRE_LT(count, s.size()); - CHECK_EQ(*b, s[spos]); - --pos; - ++count; - } - CHECK_EQ(pos, -1); - CHECK_EQ(count, s.size()); -} - -//----------------------------------------------------------------------------- -TEST_CASE("span_impl.eq") -{ - CHECK_EQ(cspan (larrc), cspan (larrc)); - CHECK_EQ(cspanrs(larrc), cspan (larrc)); - CHECK_EQ(cspan (larrc), cspanrs(larrc)); - CHECK_EQ(cspanrs(larrc), cspanrs(larrc)); - - CHECK_EQ(cspan (larri) , cspan (larri)); - CHECK_EQ(cspanrs(larri) , cspan (larri)); - CHECK_EQ(cspan (larri) , cspanrs(larri)); - CHECK_EQ(cspanrs(larri) , cspanrs(larri)); -} - -TEST_CASE("span_impl.lt") -{ - CHECK_LT(cspan (larrc), cspan (rarrc)); - CHECK_LT(cspanrs(larrc), cspan (rarrc)); - CHECK_LT(cspan (larrc), cspanrs(rarrc)); - CHECK_LT(cspanrs(larrc), cspanrs(rarrc)); - - CHECK_LT(cspan (larri) , cspan (rarri)); - CHECK_LT(cspanrs(larri) , cspan (rarri)); - CHECK_LT(cspan (larri) , cspanrs(rarri)); - CHECK_LT(cspanrs(larri) , cspanrs(rarri)); -} -TEST_CASE("span_impl.gt") -{ - CHECK_GT(cspan (rarrc), cspan (larrc)); - CHECK_GT(cspan (rarrc), cspanrs(larrc)); - CHECK_GT(cspanrs(rarrc), cspan (larrc)); - CHECK_GT(cspanrs(rarrc), cspanrs(larrc)); - - CHECK_GT(cspan (rarri) , cspan (larri)); - CHECK_GT(cspan (rarri) , cspanrs(larri)); - CHECK_GT(cspanrs(rarri) , cspan (larri)); - CHECK_GT(cspanrs(rarri) , cspanrs(larri)); -} - -TEST_CASE("span_impl.ge") -{ - CHECK_GE(cspan (rarrc), cspan (larrc)); - CHECK_GE(cspan (rarrc), cspanrs(larrc)); - CHECK_GE(cspanrs(rarrc), cspan (larrc)); - CHECK_GE(cspanrs(rarrc), cspanrs(larrc)); - CHECK_GE(cspan (larrc), cspan (larrc)); - CHECK_GE(cspan (larrc), cspanrs(larrc)); - CHECK_GE(cspanrs(larrc), cspan (larrc)); - CHECK_GE(cspanrs(larrc), cspanrs(larrc)); - CHECK_GE(cspan (rarri) , cspan (larri)); - CHECK_GE(cspan (rarri) , cspanrs(larri)); - CHECK_GE(cspanrs(rarri) , cspan (larri)); - CHECK_GE(cspanrs(rarri) , cspanrs(larri)); - CHECK_GE(cspan (larri) , cspan (larri)); - CHECK_GE(cspan (larri) , cspanrs(larri)); - CHECK_GE(cspanrs(larri) , cspan (larri)); - CHECK_GE(cspanrs(larri) , cspanrs(larri)); -} -TEST_CASE("span_impl.le") -{ - CHECK_LE(cspan (larrc), cspan (rarrc)); - CHECK_LE(cspanrs(larrc), cspan (rarrc)); - CHECK_LE(cspan (larrc), cspanrs(rarrc)); - CHECK_LE(cspanrs(larrc), cspanrs(rarrc)); - CHECK_LE(cspan (larrc), cspan (larrc)); - CHECK_LE(cspanrs(larrc), cspan (larrc)); - CHECK_LE(cspan (larrc), cspanrs(larrc)); - CHECK_LE(cspanrs(larrc), cspanrs(larrc)); - CHECK_LE(cspan (larri) , cspan (rarri)); - CHECK_LE(cspanrs(larri) , cspan (rarri)); - CHECK_LE(cspan (larri) , cspanrs(rarri)); - CHECK_LE(cspanrs(larri) , cspanrs(rarri)); - CHECK_LE(cspan (larri) , cspan (larri)); - CHECK_LE(cspanrs(larri) , cspan (larri)); - CHECK_LE(cspan (larri) , cspanrs(larri)); - CHECK_LE(cspanrs(larri) , cspanrs(larri)); -} - -} // namespace c4 - -#include "c4/libtest/supprwarn_pop.hpp" diff --git a/thirdparty/ryml/ext/c4core/test/test_std_string.cpp b/thirdparty/ryml/ext/c4core/test/test_std_string.cpp deleted file mode 100644 index de5b3739b..000000000 --- a/thirdparty/ryml/ext/c4core/test/test_std_string.cpp +++ /dev/null @@ -1,125 +0,0 @@ -#include "c4/test.hpp" -#ifndef C4CORE_SINGLE_HEADER -#include "c4/std/string_fwd.hpp" -#include "c4/std/string.hpp" -#endif - -namespace c4 { - -TEST_CASE("std_string.to_substr") -{ - std::string s("barnabe"); - substr ss = to_substr(s); - CHECK_EQ(ss.str, s.data()); - CHECK_EQ(ss.len, s.size()); - s[0] = 'B'; - CHECK_EQ(ss[0], 'B'); - ss[0] = 'b'; - CHECK_EQ(s[0], 'b'); -} - -TEST_CASE("std_string.to_csubstr") -{ - std::string s("barnabe"); - csubstr ss = to_csubstr(s); - CHECK_EQ(ss.str, s.data()); - CHECK_EQ(ss.len, s.size()); - s[0] = 'B'; - CHECK_EQ(ss[0], 'B'); -} - -TEST_CASE("std_string.compare_csubstr") -{ - std::string s0 = "000"; - std::string s1 = "111"; - csubstr ss0 = "000"; - csubstr ss1 = "111"; - CHECK_NE(s0.data(), ss0.data()); - CHECK_NE(s1.data(), ss1.data()); - // - CHECK_EQ(s0, ss0); - CHECK_EQ(s1, ss1); - CHECK_EQ(ss0, s0); - CHECK_EQ(ss1, s1); - // - CHECK_NE(s1, ss0); - CHECK_NE(s0, ss1); - CHECK_NE(ss1, s0); - CHECK_NE(ss0, s1); - // - CHECK_GE(s0, ss0); - CHECK_LE(s1, ss1); - CHECK_GE(ss0, s0); - CHECK_LE(ss1, s1); - CHECK_GE(s1, ss0); - CHECK_LE(s0, ss1); - CHECK_GE(ss1, s0); - CHECK_LE(ss0, s1); - // - CHECK_GT(s1, ss0); - CHECK_LT(s0, ss1); - CHECK_GT(ss1, s0); - CHECK_LT(ss0, s1); -} - -TEST_CASE("std_string.compare_substr") -{ - std::string s0 = "000"; - std::string s1 = "111"; - char buf0[] = "000"; - char buf1[] = "111"; - substr ss0 = buf0; - substr ss1 = buf1; - CHECK_NE(s0.data(), ss0.data()); - CHECK_NE(s1.data(), ss1.data()); - // - CHECK_EQ(s0, ss0); - CHECK_EQ(s1, ss1); - CHECK_EQ(ss0, s0); - CHECK_EQ(ss1, s1); - // - CHECK_NE(s1, ss0); - CHECK_NE(s0, ss1); - CHECK_NE(ss1, s0); - CHECK_NE(ss0, s1); - // - CHECK_GE(s0, ss0); - CHECK_LE(s1, ss1); - CHECK_GE(ss0, s0); - CHECK_LE(ss1, s1); - CHECK_GE(s1, ss0); - CHECK_LE(s0, ss1); - CHECK_GE(ss1, s0); - CHECK_LE(ss0, s1); - // - CHECK_GT(s1, ss0); - CHECK_LT(s0, ss1); - CHECK_GT(ss1, s0); - CHECK_LT(ss0, s1); -} - -TEST_CASE("std_string.to_chars") -{ - const std::string s0 = "000"; - char buf_[100] = {}; - substr buf = buf_; - CHECK_NE(buf.data(), s0.data()); - size_t ret = to_chars({}, s0); - CHECK_EQ(ret, s0.size()); - CHECK_NE(buf.first(ret), s0); - ret = to_chars(buf, s0); - CHECK_EQ(ret, s0.size()); - CHECK_EQ(buf.first(ret), s0); -} - -TEST_CASE("std_string.from_chars") -{ - std::string s0; - csubstr buf = "0123456798"; - CHECK_NE(buf.data(), s0.data()); - bool ok = from_chars(buf, &s0); - CHECK(ok); - CHECK_EQ(buf, s0); -} - -} // namespace c4 diff --git a/thirdparty/ryml/ext/c4core/test/test_std_vector.cpp b/thirdparty/ryml/ext/c4core/test/test_std_vector.cpp deleted file mode 100644 index 1cfe54f94..000000000 --- a/thirdparty/ryml/ext/c4core/test/test_std_vector.cpp +++ /dev/null @@ -1,133 +0,0 @@ -#include "c4/test.hpp" -#ifndef C4CORE_SINGLE_HEADER -#include "c4/std/vector_fwd.hpp" -#include "c4/std/vector.hpp" -#endif - -namespace c4 { - -template -std::vector ctor(const char (&s)[N]) -{ - return std::vector(s, s+N-1); -} - -TEST_CASE("std_vector.to_csubstr") -{ - std::vector s = ctor("barnabe"); - csubstr ss = to_csubstr(s); - CHECK_EQ(ss, csubstr("barnabe")); - CHECK_EQ(ss.str, s.data()); - CHECK_EQ(ss.len, s.size()); -} - -TEST_CASE("std_vector.to_substr") -{ - std::vector s = ctor("barnabe"); - substr ss = to_substr(s); - CHECK_EQ(ss, csubstr("barnabe")); - CHECK_EQ(ss.str, s.data()); - CHECK_EQ(ss.len, s.size()); - // - CHECK_EQ(s[0], 'b'); - ss[0] = 'B'; - CHECK_EQ(s[0], 'B'); - ss[0] = 'A'; - CHECK_EQ(s[0], 'A'); -} - -TEST_CASE("std_vector.compare_csubstr") -{ - std::vector s0 = ctor("000"); - std::vector s1 = ctor("111"); - csubstr ss0 = "000"; - csubstr ss1 = "111"; - CHECK_NE(s0.data(), ss0.data()); - CHECK_NE(s1.data(), ss1.data()); - // - CHECK_EQ(s0, ss0); - CHECK_EQ(s1, ss1); - CHECK_EQ(ss0, s0); - CHECK_EQ(ss1, s1); - // - CHECK_NE(s1, ss0); - CHECK_NE(s0, ss1); - CHECK_NE(ss1, s0); - CHECK_NE(ss0, s1); - // - CHECK_GE(s0, ss0); - CHECK_LE(s1, ss1); - CHECK_GE(ss0, s0); - CHECK_LE(ss1, s1); - CHECK_GE(s1, ss0); - CHECK_LE(s0, ss1); - CHECK_GE(ss1, s0); - CHECK_LE(ss0, s1); - // - CHECK_GT(s1, ss0); - CHECK_LT(s0, ss1); - CHECK_GT(ss1, s0); - CHECK_LT(ss0, s1); -} - -TEST_CASE("std_vector.compare_substr") -{ - std::vector s0 = ctor("000"); - std::vector s1 = ctor("111"); - char buf0[] = "000"; - char buf1[] = "111"; - substr ss0 = buf0; - substr ss1 = buf1; - CHECK_NE(s0.data(), ss0.data()); - CHECK_NE(s1.data(), ss1.data()); - // - CHECK_EQ(s0, ss0); - CHECK_EQ(s1, ss1); - CHECK_EQ(ss0, s0); - CHECK_EQ(ss1, s1); - // - CHECK_NE(s1, ss0); - CHECK_NE(s0, ss1); - CHECK_NE(ss1, s0); - CHECK_NE(ss0, s1); - // - CHECK_GE(s0, ss0); - CHECK_LE(s1, ss1); - CHECK_GE(ss0, s0); - CHECK_LE(ss1, s1); - CHECK_GE(s1, ss0); - CHECK_LE(s0, ss1); - CHECK_GE(ss1, s0); - CHECK_LE(ss0, s1); - // - CHECK_GT(s1, ss0); - CHECK_LT(s0, ss1); - CHECK_GT(ss1, s0); - CHECK_LT(ss0, s1); -} - -TEST_CASE("std_vector.to_chars") -{ - const std::vector s0 = ctor("000"); - char buf_[100] = {}; - substr buf = buf_; - CHECK_NE(buf.data(), s0.data()); - size_t ret = to_chars({}, s0); - CHECK_EQ(ret, s0.size()); - CHECK_NE(buf.first(ret), s0); - ret = to_chars(buf, s0); - CHECK_EQ(ret, s0.size()); - CHECK_EQ(buf.first(ret), s0); -} - -TEST_CASE("std_vector.from_chars") -{ - std::vector s0; - csubstr buf = "0123456798"; - CHECK_NE(buf.data(), s0.data()); - bool ok = from_chars(buf, &s0); - CHECK(ok); - CHECK_EQ(buf, s0); -} - -} // namespace c4 diff --git a/thirdparty/ryml/ext/c4core/test/test_substr.cpp b/thirdparty/ryml/ext/c4core/test/test_substr.cpp deleted file mode 100644 index 777b4b4b0..000000000 --- a/thirdparty/ryml/ext/c4core/test/test_substr.cpp +++ /dev/null @@ -1,4507 +0,0 @@ -#ifndef C4CORE_SINGLE_HEADER -#include "c4/std/std.hpp" -#include "c4/substr.hpp" -#endif - -#include - -#include "c4/libtest/supprwarn_push.hpp" -#include - -namespace c4 { - -TEST_CASE("substr.ctor_from_char") -{ - char buf1[] = "{foo: 1}"; - char buf2[] = "{foo: 2}"; - substr s(buf1); - CHECK_EQ(s, "{foo: 1}"); - s = buf2; - CHECK_EQ(s, "{foo: 2}"); -} - -TEST_CASE("csubstr.ctor_from_char") -{ - char buf1[] = "{foo: 1}"; - char buf2[] = "{foo: 2}"; - csubstr s(buf1); - CHECK_EQ(s, "{foo: 1}"); - s = buf2; - CHECK_EQ(s, "{foo: 2}"); -} - -TEST_CASE("csubstr.empty_vs_null") -{ - csubstr s; - CHECK_UNARY(s.empty()); - CHECK_UNARY(s.len == 0); - CHECK_UNARY(s.str == nullptr); - CHECK_UNARY(s == nullptr); - - s = ""; - CHECK_UNARY(s.empty()); - CHECK_UNARY(s.len == 0); - CHECK_UNARY(s.str != nullptr); - CHECK_UNARY(s != nullptr); - - s = nullptr; - CHECK_UNARY(s.empty()); - CHECK_UNARY(s.len == 0); - CHECK_UNARY(s.str == nullptr); - CHECK_UNARY(s == nullptr); - - s = ""; - CHECK_UNARY(s.empty()); - CHECK_UNARY(s.len == 0); - CHECK_UNARY(s.str != nullptr); - CHECK_UNARY(s != nullptr); - - s = {}; - CHECK_UNARY(s.empty()); - CHECK_UNARY(s.len == 0); - CHECK_UNARY(s.str == nullptr); - CHECK_UNARY(s == nullptr); - - csubstr pp(nullptr); - CHECK_UNARY(pp.empty()); - CHECK_UNARY(pp.len == 0); - CHECK_UNARY(pp.str == nullptr); - CHECK_UNARY(pp == nullptr); -} - -TEST_CASE("substr.is_sub") -{ - csubstr buf = "0123456789"; - - // ref - csubstr s; - csubstr ref = buf.select("345"); - CHECK_EQ(ref, "345"); - CHECK_UNARY(buf.is_super(ref)); - CHECK_UNARY(ref.is_sub(buf)); - CHECK_FALSE(ref.is_super(buf)); - CHECK_FALSE(buf.is_sub(ref)); - - buf.clear(); - ref.clear(); - CHECK_FALSE(buf.is_super(ref)); - CHECK_FALSE(ref.is_super(buf)); - CHECK_FALSE(ref.is_sub(buf)); - CHECK_FALSE(buf.is_sub(ref)); - - buf = ""; - ref = buf; - CHECK_FALSE(buf.is_super("a")); - CHECK_UNARY(buf.is_super(ref)); -} - -TEST_CASE("substr.overlaps") -{ - csubstr buf = "0123456789"; - - // ref - csubstr s; - csubstr ref = buf.select("345"); - CHECK_EQ(ref.len, 3); - CHECK_EQ(ref, "345"); - - // all_left - s = buf.sub(0, 2); - CHECK_EQ(s, "01"); - CHECK_FALSE(ref.overlaps(s)); - CHECK_FALSE(s.overlaps(ref)); - - // all_left_tight - s = buf.sub(0, 3); - CHECK_EQ(s, "012"); - CHECK_FALSE(ref.overlaps(s)); - CHECK_FALSE(s.overlaps(ref)); - - // overlap_left - s = buf.sub(0, 4); - CHECK_EQ(s, "0123"); - CHECK_UNARY(ref.overlaps(s)); - CHECK_UNARY(s.overlaps(ref)); - - // inside_tight_left - s = buf.sub(3, 1); - CHECK_EQ(s, "3"); - CHECK_UNARY(ref.overlaps(s)); - CHECK_UNARY(s.overlaps(ref)); - s = buf.sub(3, 2); - CHECK_EQ(s, "34"); - CHECK_UNARY(ref.overlaps(s)); - CHECK_UNARY(s.overlaps(ref)); - - // all_inside_tight - s = buf.sub(4, 1); - CHECK_EQ(s, "4"); - CHECK_UNARY(ref.overlaps(s)); - CHECK_UNARY(s.overlaps(ref)); - s = buf.sub(3, 3); - CHECK_EQ(s, "345"); - CHECK_UNARY(ref.overlaps(s)); - CHECK_UNARY(s.overlaps(ref)); - - // inside_tight_right - s = buf.sub(4, 2); - CHECK_EQ(s, "45"); - CHECK_UNARY(ref.overlaps(s)); - CHECK_UNARY(s.overlaps(ref)); - s = buf.sub(5, 1); - CHECK_EQ(s, "5"); - CHECK_UNARY(ref.overlaps(s)); - CHECK_UNARY(s.overlaps(ref)); - - // overlap_right - s = buf.sub(5, 2); - CHECK_EQ(s, "56"); - CHECK_UNARY(ref.overlaps(s)); - CHECK_UNARY(s.overlaps(ref)); - s = buf.sub(5, 3); - CHECK_EQ(s, "567"); - CHECK_UNARY(ref.overlaps(s)); - CHECK_UNARY(s.overlaps(ref)); - - // all_right_tight - s = buf.sub(6, 1); - CHECK_EQ(s, "6"); - CHECK_FALSE(ref.overlaps(s)); - CHECK_FALSE(s.overlaps(ref)); - s = buf.sub(6, 2); - CHECK_EQ(s, "67"); - CHECK_FALSE(ref.overlaps(s)); - CHECK_FALSE(s.overlaps(ref)); - - // all_right - s = buf.sub(7, 1); - CHECK_EQ(s, "7"); - CHECK_FALSE(ref.overlaps(s)); - CHECK_FALSE(s.overlaps(ref)); - s = buf.sub(7, 2); - CHECK_EQ(s, "78"); - CHECK_FALSE(ref.overlaps(s)); - CHECK_FALSE(s.overlaps(ref)); - - // null vs null - csubstr n1, n2; - CHECK_EQ(n1.str, nullptr); - CHECK_EQ(n2.str, nullptr); - CHECK_EQ(n1.len, 0); - CHECK_EQ(n2.len, 0); - CHECK_FALSE(n1.overlaps(n2)); - CHECK_FALSE(n2.overlaps(n1)); -} - -TEST_CASE("substr.sub") -{ - CHECK_EQ(csubstr("10]").sub(0, 2), "10"); -} - -TEST_CASE("substr.range") -{ - csubstr s = "0123456789"; - CHECK_EQ(s.range(0, 10), "0123456789"); - CHECK_EQ(s.range(0 ), "0123456789"); - CHECK_EQ(s.range(1, 10), "123456789"); - CHECK_EQ(s.range(1 ), "123456789"); - CHECK_EQ(s.range(2, 10), "23456789"); - CHECK_EQ(s.range(2 ), "23456789"); - CHECK_EQ(s.range(3, 10), "3456789"); - CHECK_EQ(s.range(3 ), "3456789"); - CHECK_EQ(s.range(4, 10), "456789"); - CHECK_EQ(s.range(4 ), "456789"); - CHECK_EQ(s.range(5, 10), "56789"); - CHECK_EQ(s.range(5 ), "56789"); - CHECK_EQ(s.range(6, 10), "6789"); - CHECK_EQ(s.range(6 ), "6789"); - CHECK_EQ(s.range(7, 10), "789"); - CHECK_EQ(s.range(7 ), "789"); - CHECK_EQ(s.range(8, 10), "89"); - CHECK_EQ(s.range(8 ), "89"); - CHECK_EQ(s.range(9, 10), "9"); - CHECK_EQ(s.range(9 ), "9"); - CHECK_EQ(s.range(10, 10), ""); - CHECK_EQ(s.range(10 ), ""); - - CHECK_EQ(s.range(0 , 9), "012345678"); - CHECK_EQ(s.range(1 , 9), "12345678"); - CHECK_EQ(s.range(2 , 9), "2345678"); - CHECK_EQ(s.range(3 , 9), "345678"); - CHECK_EQ(s.range(4 , 9), "45678"); - CHECK_EQ(s.range(5 , 9), "5678"); - CHECK_EQ(s.range(6 , 9), "678"); - CHECK_EQ(s.range(7 , 9), "78"); - CHECK_EQ(s.range(8 , 9), "8"); - CHECK_EQ(s.range(9 , 9), ""); - - CHECK_EQ(s.range(0 , 7), "0123456"); - CHECK_EQ(s.range(1 , 7), "123456"); - CHECK_EQ(s.range(2 , 7), "23456"); - CHECK_EQ(s.range(3 , 7), "3456"); - CHECK_EQ(s.range(4 , 7), "456"); - CHECK_EQ(s.range(5 , 7), "56"); - CHECK_EQ(s.range(6 , 7), "6"); - CHECK_EQ(s.range(7 , 7), ""); - - CHECK_EQ(s.range(0 , 5), "01234"); - CHECK_EQ(s.range(1 , 5), "1234"); - CHECK_EQ(s.range(2 , 5), "234"); - CHECK_EQ(s.range(3 , 5), "34"); - CHECK_EQ(s.range(4 , 5), "4"); - CHECK_EQ(s.range(5 , 5), ""); - - CHECK_EQ(s.range(0 , 3), "012"); - CHECK_EQ(s.range(1 , 3), "12"); - CHECK_EQ(s.range(2 , 3), "2"); - CHECK_EQ(s.range(3 , 3), ""); - - CHECK_EQ(s.range(0 , 2), "01"); - CHECK_EQ(s.range(1 , 2), "1"); - CHECK_EQ(s.range(2 , 2), ""); - - CHECK_EQ(s.range(0 , 1), "0"); - CHECK_EQ(s.range(1 , 1), ""); -} - -TEST_CASE("substr.first") -{ - csubstr s = "0123456789"; - - CHECK_EQ(s.first(csubstr::npos), s); - - CHECK_EQ(s.first(10), "0123456789"); - CHECK_EQ(s.first(9), "012345678"); - CHECK_EQ(s.first(8), "01234567"); - CHECK_EQ(s.first(7), "0123456"); - CHECK_EQ(s.first(6), "012345"); - CHECK_EQ(s.first(5), "01234"); - CHECK_EQ(s.first(4), "0123"); - CHECK_EQ(s.first(3), "012"); - CHECK_EQ(s.first(2), "01"); - CHECK_EQ(s.first(1), "0"); - CHECK_EQ(s.first(0), ""); -} - -TEST_CASE("substr.last") -{ - csubstr s = "0123456789"; - - CHECK_EQ(s.last(csubstr::npos), s); - - CHECK_EQ(s.last(10), "0123456789"); - CHECK_EQ(s.last(9), "123456789"); - CHECK_EQ(s.last(8), "23456789"); - CHECK_EQ(s.last(7), "3456789"); - CHECK_EQ(s.last(6), "456789"); - CHECK_EQ(s.last(5), "56789"); - CHECK_EQ(s.last(4), "6789"); - CHECK_EQ(s.last(3), "789"); - CHECK_EQ(s.last(2), "89"); - CHECK_EQ(s.last(1), "9"); - CHECK_EQ(s.last(0), ""); -} - -TEST_CASE("substr.offs") -{ - csubstr s = "0123456789"; - - CHECK_EQ(s.offs(0, 0), s); - - CHECK_EQ(s.offs(1, 0), "123456789"); - CHECK_EQ(s.offs(0, 1), "012345678"); - CHECK_EQ(s.offs(1, 1), "12345678"); - - CHECK_EQ(s.offs(1, 2), "1234567"); - CHECK_EQ(s.offs(2, 1), "2345678"); - CHECK_EQ(s.offs(2, 2), "234567"); - - CHECK_EQ(s.offs(2, 3), "23456"); - CHECK_EQ(s.offs(3, 2), "34567"); - CHECK_EQ(s.offs(3, 3), "3456"); - - CHECK_EQ(s.offs(3, 4), "345"); - CHECK_EQ(s.offs(4, 3), "456"); - CHECK_EQ(s.offs(4, 4), "45"); - - CHECK_EQ(s.offs(4, 5), "4"); - CHECK_EQ(s.offs(5, 4), "5"); - CHECK_EQ(s.offs(5, 5), ""); -} - -TEST_CASE("substr.count") -{ - csubstr buf = "0123456789"; - - CHECK_EQ(buf.count('0'), 1); - CHECK_EQ(buf.count('0', 0), 1); - CHECK_EQ(buf.count('0', 1), 0); - CHECK_EQ(buf.count('0', buf.len), 0); - - CHECK_EQ(buf.count("01"), 1); - CHECK_EQ(buf.count("01", 0), 1); - CHECK_EQ(buf.count("01", 1), 0); - CHECK_EQ(buf.count("01", buf.len), 0); - - CHECK_EQ(buf.count('1'), 1); - CHECK_EQ(buf.count('1', 0), 1); - CHECK_EQ(buf.count('1', 1), 1); - CHECK_EQ(buf.count('1', 2), 0); - CHECK_EQ(buf.count('1', buf.len), 0); - - CHECK_EQ(buf.count("12"), 1); - CHECK_EQ(buf.count("12", 0), 1); - CHECK_EQ(buf.count("12", 1), 1); - CHECK_EQ(buf.count("12", 2), 0); - CHECK_EQ(buf.count("12", buf.len), 0); - - CHECK_EQ(buf.count('2'), 1); - CHECK_EQ(buf.count('2', 0), 1); - CHECK_EQ(buf.count('2', 1), 1); - CHECK_EQ(buf.count('2', 2), 1); - CHECK_EQ(buf.count('2', 3), 0); - CHECK_EQ(buf.count('2', buf.len), 0); - - CHECK_EQ(buf.count("23"), 1); - CHECK_EQ(buf.count("23", 0), 1); - CHECK_EQ(buf.count("23", 1), 1); - CHECK_EQ(buf.count("23", 2), 1); - CHECK_EQ(buf.count("23", 3), 0); - CHECK_EQ(buf.count("23", buf.len), 0); - - CHECK_EQ(buf.count('3'), 1); - CHECK_EQ(buf.count('3', 0), 1); - CHECK_EQ(buf.count('3', 1), 1); - CHECK_EQ(buf.count('3', 2), 1); - CHECK_EQ(buf.count('3', 3), 1); - CHECK_EQ(buf.count('3', 4), 0); - CHECK_EQ(buf.count('3', buf.len), 0); - - CHECK_EQ(buf.count("34"), 1); - CHECK_EQ(buf.count("34", 0), 1); - CHECK_EQ(buf.count("34", 1), 1); - CHECK_EQ(buf.count("34", 2), 1); - CHECK_EQ(buf.count("34", 3), 1); - CHECK_EQ(buf.count("34", 4), 0); - CHECK_EQ(buf.count("34", buf.len), 0); - - CHECK_EQ(buf.count('4'), 1); - CHECK_EQ(buf.count('4', 0), 1); - CHECK_EQ(buf.count('4', 1), 1); - CHECK_EQ(buf.count('4', 2), 1); - CHECK_EQ(buf.count('4', 3), 1); - CHECK_EQ(buf.count('4', 4), 1); - CHECK_EQ(buf.count('4', 5), 0); - CHECK_EQ(buf.count('4', buf.len), 0); - - CHECK_EQ(buf.count("45"), 1); - CHECK_EQ(buf.count("45", 0), 1); - CHECK_EQ(buf.count("45", 1), 1); - CHECK_EQ(buf.count("45", 2), 1); - CHECK_EQ(buf.count("45", 3), 1); - CHECK_EQ(buf.count("45", 4), 1); - CHECK_EQ(buf.count("45", 5), 0); - CHECK_EQ(buf.count("45", buf.len), 0); - - CHECK_EQ(buf.count('5'), 1); - CHECK_EQ(buf.count('5', 0), 1); - CHECK_EQ(buf.count('5', 1), 1); - CHECK_EQ(buf.count('5', 2), 1); - CHECK_EQ(buf.count('5', 3), 1); - CHECK_EQ(buf.count('5', 4), 1); - CHECK_EQ(buf.count('5', 5), 1); - CHECK_EQ(buf.count('5', 6), 0); - CHECK_EQ(buf.count('5', buf.len), 0); - - CHECK_EQ(buf.count("56"), 1); - CHECK_EQ(buf.count("56", 0), 1); - CHECK_EQ(buf.count("56", 1), 1); - CHECK_EQ(buf.count("56", 2), 1); - CHECK_EQ(buf.count("56", 3), 1); - CHECK_EQ(buf.count("56", 4), 1); - CHECK_EQ(buf.count("56", 5), 1); - CHECK_EQ(buf.count("56", 6), 0); - CHECK_EQ(buf.count("56", buf.len), 0); - - CHECK_EQ(buf.count('a'), 0); - CHECK_EQ(buf.count('a', 0), 0); - CHECK_EQ(buf.count('a', 1), 0); - CHECK_EQ(buf.count('a', 2), 0); - CHECK_EQ(buf.count('a', 3), 0); - CHECK_EQ(buf.count('a', 4), 0); - CHECK_EQ(buf.count('a', 5), 0); - CHECK_EQ(buf.count('a', 6), 0); - CHECK_EQ(buf.count('a', buf.len), 0); - - CHECK_EQ(buf.count("ab"), 0); - CHECK_EQ(buf.count("ab", 0), 0); - CHECK_EQ(buf.count("ab", 1), 0); - CHECK_EQ(buf.count("ab", 2), 0); - CHECK_EQ(buf.count("ab", 3), 0); - CHECK_EQ(buf.count("ab", 4), 0); - CHECK_EQ(buf.count("ab", 5), 0); - CHECK_EQ(buf.count("ab", 6), 0); - CHECK_EQ(buf.count("ab", buf.len), 0); - - buf = "00110022003300440055"; - CHECK_EQ(buf.count('0', 0), 10); - CHECK_EQ(buf.count('0', 1), 9); - CHECK_EQ(buf.count('0', 2), 8); - CHECK_EQ(buf.count('0', 3), 8); - CHECK_EQ(buf.count('0', 4), 8); - CHECK_EQ(buf.count('0', 5), 7); - CHECK_EQ(buf.count('0', 6), 6); - CHECK_EQ(buf.count('0', 7), 6); - CHECK_EQ(buf.count('0', 8), 6); - CHECK_EQ(buf.count('0', 9), 5); - CHECK_EQ(buf.count('0', 10), 4); - CHECK_EQ(buf.count('0', 11), 4); - CHECK_EQ(buf.count('0', 12), 4); - CHECK_EQ(buf.count('0', 13), 3); - CHECK_EQ(buf.count('0', 14), 2); - CHECK_EQ(buf.count('0', 15), 2); - CHECK_EQ(buf.count('0', 16), 2); - CHECK_EQ(buf.count('0', 17), 1); - CHECK_EQ(buf.count('0', 18), 0); - CHECK_EQ(buf.count('0', 19), 0); - CHECK_EQ(buf.count('0', 20), 0); - - CHECK_EQ(buf.count('1', 0), 2); - CHECK_EQ(buf.count('1', 1), 2); - CHECK_EQ(buf.count('1', 2), 2); - CHECK_EQ(buf.count('1', 3), 1); - CHECK_EQ(buf.count('1', 4), 0); - CHECK_EQ(buf.count('1', 5), 0); - - CHECK_EQ(buf.count("01" ), 1); - CHECK_EQ(buf.count("01", 2), 0); - CHECK_EQ(buf.count("10" ), 1); - CHECK_EQ(buf.count("10", 4), 0); - CHECK_EQ(buf.count("00", 0), 5); - CHECK_EQ(buf.count("00", 1), 4); - CHECK_EQ(buf.count("00", 2), 4); - CHECK_EQ(buf.count("00", 3), 4); - CHECK_EQ(buf.count("00", 4), 4); - CHECK_EQ(buf.count("00", 5), 3); - CHECK_EQ(buf.count("00", 6), 3); - CHECK_EQ(buf.count("00", 7), 3); - CHECK_EQ(buf.count("00", 8), 3); - CHECK_EQ(buf.count("00", 9), 2); - CHECK_EQ(buf.count("00", 10), 2); - CHECK_EQ(buf.count("00", 11), 2); - CHECK_EQ(buf.count("00", 12), 2); - CHECK_EQ(buf.count("00", 13), 1); - CHECK_EQ(buf.count("00", 14), 1); - CHECK_EQ(buf.count("00", 15), 1); - CHECK_EQ(buf.count("00", 16), 1); - CHECK_EQ(buf.count("00", 17), 0); - CHECK_EQ(buf.count("00", 18), 0); - CHECK_EQ(buf.count("00", 19), 0); - CHECK_EQ(buf.count("00", 20), 0); -} - -TEST_CASE("substr.select") -{ - csubstr buf = "0123456789"; - - CHECK_EQ(buf.select('0'), "0"); - CHECK_EQ(buf.select('1'), "1"); - CHECK_EQ(buf.select('2'), "2"); - CHECK_EQ(buf.select('8'), "8"); - CHECK_EQ(buf.select('9'), "9"); - - CHECK_EQ(buf.select('a').str, nullptr); - CHECK_EQ(buf.select('a').len, 0); - CHECK_EQ(buf.select('a'), ""); - - CHECK_EQ(buf.select("a").str, nullptr); - CHECK_EQ(buf.select("a").len, 0); - CHECK_EQ(buf.select("a"), ""); - - CHECK_EQ(buf.select("0"), "0"); - CHECK_EQ(buf.select("0").str, buf.str+0); - CHECK_EQ(buf.select("0").len, 1); - - CHECK_EQ(buf.select("1"), "1"); - CHECK_EQ(buf.select("1").str, buf.str+1); - CHECK_EQ(buf.select("1").len, 1); - - CHECK_EQ(buf.select("2"), "2"); - CHECK_EQ(buf.select("2").str, buf.str+2); - CHECK_EQ(buf.select("2").len, 1); - - CHECK_EQ(buf.select("9"), "9"); - CHECK_EQ(buf.select("9").str, buf.str+9); - CHECK_EQ(buf.select("9").len, 1); - - CHECK_EQ(buf.select("012"), "012"); - CHECK_EQ(buf.select("012").str, buf.str+0); - CHECK_EQ(buf.select("012").len, 3); - - CHECK_EQ(buf.select("345"), "345"); - CHECK_EQ(buf.select("345").str, buf.str+3); - CHECK_EQ(buf.select("345").len, 3); - - CHECK_EQ(buf.select("789"), "789"); - CHECK_EQ(buf.select("789").str, buf.str+7); - CHECK_EQ(buf.select("789").len, 3); - - CHECK_EQ(buf.select("89a"), ""); - CHECK_EQ(buf.select("89a").str, nullptr); - CHECK_EQ(buf.select("89a").len, 0); -} - -TEST_CASE("substr.begins_with") -{ - CHECK (csubstr(": ").begins_with(":" )); - CHECK (csubstr(": ").begins_with(':' )); - CHECK_FALSE(csubstr(":") .begins_with(": ")); - - CHECK (csubstr( "1234").begins_with('0', 0)); - CHECK (csubstr( "01234").begins_with('0', 1)); - CHECK_FALSE(csubstr( "01234").begins_with('0', 2)); - CHECK (csubstr( "001234").begins_with('0', 1)); - CHECK (csubstr( "001234").begins_with('0', 2)); - CHECK_FALSE(csubstr( "001234").begins_with('0', 3)); - CHECK (csubstr( "0001234").begins_with('0', 1)); - CHECK (csubstr( "0001234").begins_with('0', 2)); - CHECK (csubstr( "0001234").begins_with('0', 3)); - CHECK_FALSE(csubstr( "0001234").begins_with('0', 4)); - CHECK (csubstr("00001234").begins_with('0', 1)); - CHECK (csubstr("00001234").begins_with('0', 2)); - CHECK (csubstr("00001234").begins_with('0', 3)); - CHECK (csubstr("00001234").begins_with('0', 4)); - CHECK_FALSE(csubstr("00001234").begins_with('0', 5)); -} - -TEST_CASE("substr.ends_with") -{ - CHECK_UNARY(csubstr("{% if foo %}bar{% endif %}").ends_with("{% endif %}")); - - CHECK (csubstr("1234" ).ends_with('0', 0)); - CHECK (csubstr("12340" ).ends_with('0', 1)); - CHECK_FALSE(csubstr("12340" ).ends_with('0', 2)); - CHECK (csubstr("123400" ).ends_with('0', 1)); - CHECK (csubstr("123400" ).ends_with('0', 2)); - CHECK_FALSE(csubstr("123400" ).ends_with('0', 3)); - CHECK (csubstr("1234000" ).ends_with('0', 1)); - CHECK (csubstr("1234000" ).ends_with('0', 2)); - CHECK (csubstr("1234000" ).ends_with('0', 3)); - CHECK_FALSE(csubstr("1234000" ).ends_with('0', 4)); - CHECK (csubstr("12340000").ends_with('0', 1)); - CHECK (csubstr("12340000").ends_with('0', 2)); - CHECK (csubstr("12340000").ends_with('0', 3)); - CHECK (csubstr("12340000").ends_with('0', 4)); - CHECK_FALSE(csubstr("12340000").ends_with('0', 5)); -} - -TEST_CASE("substr.find") -{ - csubstr s012345 = "012345"; - CHECK(s012345.find('a') == csubstr::npos); - CHECK(s012345.find('0' ) == 0u); - CHECK(s012345.find('0', 1u) == csubstr::npos); - CHECK(s012345.find('1' ) == 1u); - CHECK(s012345.find('1', 2u) == csubstr::npos); - CHECK(s012345.find('2' ) == 2u); - CHECK(s012345.find('2', 3u) == csubstr::npos); - CHECK(s012345.find('3' ) == 3u); - CHECK(s012345.find('3', 4u) == csubstr::npos); - CHECK(s012345.find("ab" ) == csubstr::npos); - CHECK(s012345.find("01" ) == 0u); - CHECK(s012345.find("01", 1u) == csubstr::npos); - CHECK(s012345.find("12" ) == 1u); - CHECK(s012345.find("12", 2u) == csubstr::npos); - CHECK(s012345.find("23" ) == 2u); - CHECK(s012345.find("23", 3u) == csubstr::npos); -} - -TEST_CASE("substr.first_of") -{ - size_t npos = csubstr::npos; - - CHECK_EQ(csubstr("012345").first_of('a'), npos); - CHECK_EQ(csubstr("012345").first_of("ab"), npos); - - CHECK_EQ(csubstr("012345").first_of('0'), 0u); - CHECK_EQ(csubstr("012345").first_of("0"), 0u); - CHECK_EQ(csubstr("012345").first_of("01"), 0u); - CHECK_EQ(csubstr("012345").first_of("10"), 0u); - CHECK_EQ(csubstr("012345").first_of("012"), 0u); - CHECK_EQ(csubstr("012345").first_of("210"), 0u); - CHECK_EQ(csubstr("012345").first_of("0123"), 0u); - CHECK_EQ(csubstr("012345").first_of("3210"), 0u); - CHECK_EQ(csubstr("012345").first_of("01234"), 0u); - CHECK_EQ(csubstr("012345").first_of("43210"), 0u); - CHECK_EQ(csubstr("012345").first_of("012345"), 0u); - CHECK_EQ(csubstr("012345").first_of("543210"), 0u); - - CHECK_EQ(csubstr("012345").first_of('0', 2u), npos); - CHECK_EQ(csubstr("012345").first_of("0", 2u), npos); - CHECK_EQ(csubstr("012345").first_of("01", 2u), npos); - CHECK_EQ(csubstr("012345").first_of("10", 2u), npos); - CHECK_EQ(csubstr("012345").first_of("012", 2u), 2u); - CHECK_EQ(csubstr("012345").first_of("210", 2u), 2u); - CHECK_EQ(csubstr("012345").first_of("0123", 2u), 2u); - CHECK_EQ(csubstr("012345").first_of("3210", 2u), 2u); - CHECK_EQ(csubstr("012345").first_of("01234", 2u), 2u); - CHECK_EQ(csubstr("012345").first_of("43210", 2u), 2u); - CHECK_EQ(csubstr("012345").first_of("012345", 2u), 2u); - CHECK_EQ(csubstr("012345").first_of("543210", 2u), 2u); - - CHECK_EQ(csubstr("012345").first_of('5'), 5u); - CHECK_EQ(csubstr("012345").first_of("5"), 5u); - CHECK_EQ(csubstr("012345").first_of("45"), 4u); - CHECK_EQ(csubstr("012345").first_of("54"), 4u); - CHECK_EQ(csubstr("012345").first_of("345"), 3u); - CHECK_EQ(csubstr("012345").first_of("543"), 3u); - CHECK_EQ(csubstr("012345").first_of("2345"), 2u); - CHECK_EQ(csubstr("012345").first_of("5432"), 2u); - CHECK_EQ(csubstr("012345").first_of("12345"), 1u); - CHECK_EQ(csubstr("012345").first_of("54321"), 1u); - CHECK_EQ(csubstr("012345").first_of("012345"), 0u); - CHECK_EQ(csubstr("012345").first_of("543210"), 0u); - - CHECK_EQ(csubstr("012345").first_of('5', 2u), 5u); - CHECK_EQ(csubstr("012345").first_of("5", 2u), 5u); - CHECK_EQ(csubstr("012345").first_of("45", 2u), 4u); - CHECK_EQ(csubstr("012345").first_of("54", 2u), 4u); - CHECK_EQ(csubstr("012345").first_of("345", 2u), 3u); - CHECK_EQ(csubstr("012345").first_of("543", 2u), 3u); - CHECK_EQ(csubstr("012345").first_of("2345", 2u), 2u); - CHECK_EQ(csubstr("012345").first_of("5432", 2u), 2u); - CHECK_EQ(csubstr("012345").first_of("12345", 2u), 2u); - CHECK_EQ(csubstr("012345").first_of("54321", 2u), 2u); - CHECK_EQ(csubstr("012345").first_of("012345", 2u), 2u); - CHECK_EQ(csubstr("012345").first_of("543210", 2u), 2u); - - CHECK_EQ(csubstr{}.first_of('0'), npos); - CHECK_EQ(csubstr{}.first_of('0', 0u), npos); - CHECK_EQ(csubstr("012345").first_of('0', 6u), npos); - CHECK_EQ(csubstr("012345").first_of('5', 6u), npos); - CHECK_EQ(csubstr("012345").first_of("012345", 6u), npos); -} - -TEST_CASE("substr.last_of") -{ - size_t npos = csubstr::npos; - - CHECK_EQ(csubstr("012345").last_of('a'), npos); - CHECK_EQ(csubstr("012345").last_of("ab"), npos); - - CHECK_EQ(csubstr("012345").last_of('0'), 0u); - CHECK_EQ(csubstr("012345").last_of("0"), 0u); - CHECK_EQ(csubstr("012345").last_of("01"), 1u); - CHECK_EQ(csubstr("012345").last_of("10"), 1u); - CHECK_EQ(csubstr("012345").last_of("012"), 2u); - CHECK_EQ(csubstr("012345").last_of("210"), 2u); - CHECK_EQ(csubstr("012345").last_of("0123"), 3u); - CHECK_EQ(csubstr("012345").last_of("3210"), 3u); - CHECK_EQ(csubstr("012345").last_of("01234"), 4u); - CHECK_EQ(csubstr("012345").last_of("43210"), 4u); - CHECK_EQ(csubstr("012345").last_of("012345"), 5u); - CHECK_EQ(csubstr("012345").last_of("543210"), 5u); - - CHECK_EQ(csubstr("012345").last_of('0', 2u), 0u); - CHECK_EQ(csubstr("012345").last_of("0", 2u), 0u); - CHECK_EQ(csubstr("012345").last_of("01", 2u), 1u); - CHECK_EQ(csubstr("012345").last_of("10", 2u), 1u); - CHECK_EQ(csubstr("012345").last_of("012", 2u), 1u); - CHECK_EQ(csubstr("012345").last_of("210", 2u), 1u); - CHECK_EQ(csubstr("012345").last_of("0123", 2u), 1u); - CHECK_EQ(csubstr("012345").last_of("3210", 2u), 1u); - CHECK_EQ(csubstr("012345").last_of("01234", 2u), 1u); - CHECK_EQ(csubstr("012345").last_of("43210", 2u), 1u); - CHECK_EQ(csubstr("012345").last_of("012345", 2u), 1u); - CHECK_EQ(csubstr("012345").last_of("543210", 2u), 1u); - - CHECK_EQ(csubstr("012345").last_of('5'), 5u); - CHECK_EQ(csubstr("012345").last_of("5"), 5u); - CHECK_EQ(csubstr("012345").last_of("45"), 5u); - CHECK_EQ(csubstr("012345").last_of("54"), 5u); - CHECK_EQ(csubstr("012345").last_of("345"), 5u); - CHECK_EQ(csubstr("012345").last_of("543"), 5u); - CHECK_EQ(csubstr("012345").last_of("2345"), 5u); - CHECK_EQ(csubstr("012345").last_of("5432"), 5u); - CHECK_EQ(csubstr("012345").last_of("12345"), 5u); - CHECK_EQ(csubstr("012345").last_of("54321"), 5u); - CHECK_EQ(csubstr("012345").last_of("012345"), 5u); - CHECK_EQ(csubstr("012345").last_of("543210"), 5u); - - CHECK_EQ(csubstr("012345").last_of('5', 2u), npos); - CHECK_EQ(csubstr("012345").last_of("5", 2u), npos); - CHECK_EQ(csubstr("012345").last_of("45", 2u), npos); - CHECK_EQ(csubstr("012345").last_of("54", 2u), npos); - CHECK_EQ(csubstr("012345").last_of("345", 2u), npos); - CHECK_EQ(csubstr("012345").last_of("543", 2u), npos); - CHECK_EQ(csubstr("012345").last_of("2345", 2u), npos); - CHECK_EQ(csubstr("012345").last_of("5432", 2u), npos); - CHECK_EQ(csubstr("012345").last_of("12345", 2u), 1u); - CHECK_EQ(csubstr("012345").last_of("54321", 2u), 1u); - CHECK_EQ(csubstr("012345").last_of("012345", 2u), 1u); - CHECK_EQ(csubstr("012345").last_of("543210", 2u), 1u); - - CHECK_EQ(csubstr{}.last_of('?'), npos); - CHECK_EQ(csubstr("012345").last_of('0', 6u), 0u); - CHECK_EQ(csubstr("012345").last_of('5', 6u), 5u); - CHECK_EQ(csubstr("012345").last_of("012345", 6u), 5u); -} - -TEST_CASE("substr.first_not_of") -{ - size_t npos = csubstr::npos; - - CHECK_EQ(csubstr("012345").first_not_of('a'), 0u); - CHECK_EQ(csubstr("012345").first_not_of("ab"), 0u); - - CHECK_EQ(csubstr("012345").first_not_of('0'), 1u); - CHECK_EQ(csubstr("012345").first_not_of("0"), 1u); - CHECK_EQ(csubstr("012345").first_not_of("01"), 2u); - CHECK_EQ(csubstr("012345").first_not_of("10"), 2u); - CHECK_EQ(csubstr("012345").first_not_of("012"), 3u); - CHECK_EQ(csubstr("012345").first_not_of("210"), 3u); - CHECK_EQ(csubstr("012345").first_not_of("0123"), 4u); - CHECK_EQ(csubstr("012345").first_not_of("3210"), 4u); - CHECK_EQ(csubstr("012345").first_not_of("01234"), 5u); - CHECK_EQ(csubstr("012345").first_not_of("43210"), 5u); - CHECK_EQ(csubstr("012345").first_not_of("012345"), npos); - CHECK_EQ(csubstr("012345").first_not_of("543210"), npos); - - CHECK_EQ(csubstr("012345").first_not_of('0', 2u), 2u); - CHECK_EQ(csubstr("012345").first_not_of("0", 2u), 2u); - CHECK_EQ(csubstr("012345").first_not_of("01", 2u), 2u); - CHECK_EQ(csubstr("012345").first_not_of("10", 2u), 2u); - CHECK_EQ(csubstr("012345").first_not_of("012", 2u), 3u); - CHECK_EQ(csubstr("012345").first_not_of("210", 2u), 3u); - CHECK_EQ(csubstr("012345").first_not_of("0123", 2u), 4u); - CHECK_EQ(csubstr("012345").first_not_of("3210", 2u), 4u); - CHECK_EQ(csubstr("012345").first_not_of("01234", 2u), 5u); - CHECK_EQ(csubstr("012345").first_not_of("43210", 2u), 5u); - CHECK_EQ(csubstr("012345").first_not_of("012345", 2u), npos); - CHECK_EQ(csubstr("012345").first_not_of("543210", 2u), npos); - - CHECK_EQ(csubstr("012345").first_not_of('5'), 0u); - CHECK_EQ(csubstr("012345").first_not_of("5"), 0u); - CHECK_EQ(csubstr("012345").first_not_of("45"), 0u); - CHECK_EQ(csubstr("012345").first_not_of("54"), 0u); - CHECK_EQ(csubstr("012345").first_not_of("345"), 0u); - CHECK_EQ(csubstr("012345").first_not_of("543"), 0u); - CHECK_EQ(csubstr("012345").first_not_of("2345"), 0u); - CHECK_EQ(csubstr("012345").first_not_of("5432"), 0u); - CHECK_EQ(csubstr("012345").first_not_of("12345"), 0u); - CHECK_EQ(csubstr("012345").first_not_of("54321"), 0u); - CHECK_EQ(csubstr("012345").first_not_of("012345"), npos); - CHECK_EQ(csubstr("012345").first_not_of("543210"), npos); - - CHECK_EQ(csubstr("012345").first_not_of('5', 2u), 2u); - CHECK_EQ(csubstr("012345").first_not_of("5", 2u), 2u); - CHECK_EQ(csubstr("012345").first_not_of("45", 2u), 2u); - CHECK_EQ(csubstr("012345").first_not_of("54", 2u), 2u); - CHECK_EQ(csubstr("012345").first_not_of("345", 2u), 2u); - CHECK_EQ(csubstr("012345").first_not_of("543", 2u), 2u); - CHECK_EQ(csubstr("012345").first_not_of("2345", 2u), npos); - CHECK_EQ(csubstr("012345").first_not_of("5432", 2u), npos); - CHECK_EQ(csubstr("012345").first_not_of("12345", 2u), npos); - CHECK_EQ(csubstr("012345").first_not_of("54321", 2u), npos); - CHECK_EQ(csubstr("012345").first_not_of("012345", 2u), npos); - CHECK_EQ(csubstr("012345").first_not_of("543210", 2u), npos); - - CHECK_EQ(csubstr("").first_not_of('0', 0u), npos); - CHECK_EQ(csubstr("012345").first_not_of('5', 6u), npos); - CHECK_EQ(csubstr("012345").first_not_of("012345", 6u), npos); -} - -TEST_CASE("substr.last_not_of") -{ - size_t npos = csubstr::npos; - - CHECK_EQ(csubstr("012345").last_not_of('a'), 5u); - CHECK_EQ(csubstr("012345").last_not_of("ab"), 5u); - - CHECK_EQ(csubstr("012345").last_not_of('5'), 4u); - CHECK_EQ(csubstr("012345").last_not_of("5"), 4u); - CHECK_EQ(csubstr("012345").last_not_of("45"), 3u); - CHECK_EQ(csubstr("012345").last_not_of("54"), 3u); - CHECK_EQ(csubstr("012345").last_not_of("345"), 2u); - CHECK_EQ(csubstr("012345").last_not_of("543"), 2u); - CHECK_EQ(csubstr("012345").last_not_of("2345"), 1u); - CHECK_EQ(csubstr("012345").last_not_of("5432"), 1u); - CHECK_EQ(csubstr("012345").last_not_of("12345"), 0u); - CHECK_EQ(csubstr("012345").last_not_of("54321"), 0u); - CHECK_EQ(csubstr("012345").last_not_of("012345"), npos); - CHECK_EQ(csubstr("012345").last_not_of("543210"), npos); - - CHECK_EQ(csubstr("012345").last_not_of('5', 2u), 1u); - CHECK_EQ(csubstr("012345").last_not_of("5", 2u), 1u); - CHECK_EQ(csubstr("012345").last_not_of("45", 2u), 1u); - CHECK_EQ(csubstr("012345").last_not_of("54", 2u), 1u); - CHECK_EQ(csubstr("012345").last_not_of("345", 2u), 1u); - CHECK_EQ(csubstr("012345").last_not_of("543", 2u), 1u); - CHECK_EQ(csubstr("012345").last_not_of("2345", 2u), 1u); - CHECK_EQ(csubstr("012345").last_not_of("5432", 2u), 1u); - CHECK_EQ(csubstr("012345").last_not_of("12345", 2u), 0u); - CHECK_EQ(csubstr("012345").last_not_of("54321", 2u), 0u); - CHECK_EQ(csubstr("012345").last_not_of("012345", 2u), npos); - CHECK_EQ(csubstr("012345").last_not_of("543210", 2u), npos); - - CHECK_EQ(csubstr("012345").last_not_of('0'), 5u); - CHECK_EQ(csubstr("012345").last_not_of("0"), 5u); - CHECK_EQ(csubstr("012345").last_not_of("01"), 5u); - CHECK_EQ(csubstr("012345").last_not_of("10"), 5u); - CHECK_EQ(csubstr("012345").last_not_of("012"), 5u); - CHECK_EQ(csubstr("012345").last_not_of("210"), 5u); - CHECK_EQ(csubstr("012345").last_not_of("0123"), 5u); - CHECK_EQ(csubstr("012345").last_not_of("3210"), 5u); - CHECK_EQ(csubstr("012345").last_not_of("01234"), 5u); - CHECK_EQ(csubstr("012345").last_not_of("43210"), 5u); - CHECK_EQ(csubstr("012345").last_not_of("012345"), npos); - CHECK_EQ(csubstr("012345").last_not_of("543210"), npos); - - CHECK_EQ(csubstr("012345").last_not_of('0', 2u), 1u); - CHECK_EQ(csubstr("012345").last_not_of("0", 2u), 1u); - CHECK_EQ(csubstr("012345").last_not_of("01", 2u), npos); - CHECK_EQ(csubstr("012345").last_not_of("10", 2u), npos); - CHECK_EQ(csubstr("012345").last_not_of("012", 2u), npos); - CHECK_EQ(csubstr("012345").last_not_of("210", 2u), npos); - CHECK_EQ(csubstr("012345").last_not_of("0123", 2u), npos); - CHECK_EQ(csubstr("012345").last_not_of("3210", 2u), npos); - CHECK_EQ(csubstr("012345").last_not_of("01234", 2u), npos); - CHECK_EQ(csubstr("012345").last_not_of("43210", 2u), npos); - CHECK_EQ(csubstr("012345").last_not_of("012345", 2u), npos); - CHECK_EQ(csubstr("012345").last_not_of("543210", 2u), npos); - - CHECK_EQ(csubstr("").last_not_of('0', 0u), npos); - CHECK_EQ(csubstr("012345").last_not_of('5', 6u), 4u); -} - -TEST_CASE("substr.left_of") -{ - csubstr s = "012345"; - - CHECK_EQ(s.left_of(csubstr::npos), s); - CHECK_EQ(s.left_of(csubstr::npos, /*include_pos*/false), s); - CHECK_EQ(s.left_of(csubstr::npos, /*include_pos*/true), s); - - - CHECK_EQ(s.left_of(0), ""); - CHECK_EQ(s.left_of(1), "0"); - CHECK_EQ(s.left_of(2), "01"); - CHECK_EQ(s.left_of(3), "012"); - CHECK_EQ(s.left_of(4), "0123"); - CHECK_EQ(s.left_of(5), "01234"); - CHECK_EQ(s.left_of(6), "012345"); - - CHECK_EQ(s.left_of(0, /*include_pos*/false), ""); - CHECK_EQ(s.left_of(1, /*include_pos*/false), "0"); - CHECK_EQ(s.left_of(2, /*include_pos*/false), "01"); - CHECK_EQ(s.left_of(3, /*include_pos*/false), "012"); - CHECK_EQ(s.left_of(4, /*include_pos*/false), "0123"); - CHECK_EQ(s.left_of(5, /*include_pos*/false), "01234"); - CHECK_EQ(s.left_of(6, /*include_pos*/false), "012345"); - - CHECK_UNARY(s.is_super(s.left_of(0, /*include_pos*/false))); - CHECK_UNARY(s.is_super(s.left_of(1, /*include_pos*/false))); - CHECK_UNARY(s.is_super(s.left_of(2, /*include_pos*/false))); - CHECK_UNARY(s.is_super(s.left_of(3, /*include_pos*/false))); - CHECK_UNARY(s.is_super(s.left_of(4, /*include_pos*/false))); - - - CHECK_EQ(s.left_of(0, /*include_pos*/true), "0"); - CHECK_EQ(s.left_of(1, /*include_pos*/true), "01"); - CHECK_EQ(s.left_of(2, /*include_pos*/true), "012"); - CHECK_EQ(s.left_of(3, /*include_pos*/true), "0123"); - CHECK_EQ(s.left_of(4, /*include_pos*/true), "01234"); - CHECK_EQ(s.left_of(5, /*include_pos*/true), "012345"); - - CHECK_UNARY(s.is_super(s.left_of(0, /*include_pos*/true))); - CHECK_UNARY(s.is_super(s.left_of(1, /*include_pos*/true))); - CHECK_UNARY(s.is_super(s.left_of(2, /*include_pos*/true))); - CHECK_UNARY(s.is_super(s.left_of(3, /*include_pos*/true))); - CHECK_UNARY(s.is_super(s.left_of(4, /*include_pos*/true))); - - - CHECK_EQ(s.sub(5), "5"); - CHECK_EQ(s.sub(4), "45"); - CHECK_EQ(s.sub(3), "345"); - CHECK_EQ(s.sub(2), "2345"); - CHECK_EQ(s.sub(1), "12345"); - CHECK_EQ(s.sub(0), "012345"); - - CHECK_EQ(s.left_of(s.sub(5)), "01234"); - CHECK_EQ(s.left_of(s.sub(4)), "0123"); - CHECK_EQ(s.left_of(s.sub(3)), "012"); - CHECK_EQ(s.left_of(s.sub(2)), "01"); - CHECK_EQ(s.left_of(s.sub(1)), "0"); - CHECK_EQ(s.left_of(s.sub(0)), ""); - - CHECK_UNARY(s.is_super(s.left_of(s.sub(5)))); - CHECK_UNARY(s.is_super(s.left_of(s.sub(4)))); - CHECK_UNARY(s.is_super(s.left_of(s.sub(3)))); - CHECK_UNARY(s.is_super(s.left_of(s.sub(2)))); - CHECK_UNARY(s.is_super(s.left_of(s.sub(1)))); - CHECK_UNARY(s.is_super(s.left_of(s.sub(0)))); -} - -TEST_CASE("substr.right_of") -{ - csubstr s = "012345"; - - CHECK_EQ(s.right_of(csubstr::npos), ""); - CHECK_EQ(s.right_of(csubstr::npos), ""); - - CHECK_EQ(s.right_of(csubstr::npos, /*include_pos*/false), ""); - CHECK_EQ(s.right_of(csubstr::npos, /*include_pos*/true), ""); - - - CHECK_EQ(s.right_of(0), "12345"); - CHECK_EQ(s.right_of(1), "2345"); - CHECK_EQ(s.right_of(2), "345"); - CHECK_EQ(s.right_of(3), "45"); - CHECK_EQ(s.right_of(4), "5"); - CHECK_EQ(s.right_of(5), ""); - - CHECK_EQ(s.right_of(0, /*include_pos*/false), "12345"); - CHECK_EQ(s.right_of(1, /*include_pos*/false), "2345"); - CHECK_EQ(s.right_of(2, /*include_pos*/false), "345"); - CHECK_EQ(s.right_of(3, /*include_pos*/false), "45"); - CHECK_EQ(s.right_of(4, /*include_pos*/false), "5"); - CHECK_EQ(s.right_of(5, /*include_pos*/false), ""); - - CHECK_UNARY(s.is_super(s.right_of(0))); - CHECK_UNARY(s.is_super(s.right_of(1))); - CHECK_UNARY(s.is_super(s.right_of(2))); - CHECK_UNARY(s.is_super(s.right_of(3))); - CHECK_UNARY(s.is_super(s.right_of(4))); - CHECK_UNARY(s.is_super(s.right_of(5))); - - CHECK_UNARY(s.is_super(s.right_of(0, /*include_pos*/false))); - CHECK_UNARY(s.is_super(s.right_of(1, /*include_pos*/false))); - CHECK_UNARY(s.is_super(s.right_of(2, /*include_pos*/false))); - CHECK_UNARY(s.is_super(s.right_of(3, /*include_pos*/false))); - CHECK_UNARY(s.is_super(s.right_of(4, /*include_pos*/false))); - CHECK_UNARY(s.is_super(s.right_of(5, /*include_pos*/false))); - - - CHECK_EQ(s.right_of(0, /*include_pos*/true), "012345"); - CHECK_EQ(s.right_of(1, /*include_pos*/true), "12345"); - CHECK_EQ(s.right_of(2, /*include_pos*/true), "2345"); - CHECK_EQ(s.right_of(3, /*include_pos*/true), "345"); - CHECK_EQ(s.right_of(4, /*include_pos*/true), "45"); - CHECK_EQ(s.right_of(5, /*include_pos*/true), "5"); - CHECK_EQ(s.right_of(6, /*include_pos*/true), ""); - - CHECK_UNARY(s.is_super(s.right_of(0, /*include_pos*/true))); - CHECK_UNARY(s.is_super(s.right_of(1, /*include_pos*/true))); - CHECK_UNARY(s.is_super(s.right_of(2, /*include_pos*/true))); - CHECK_UNARY(s.is_super(s.right_of(3, /*include_pos*/true))); - CHECK_UNARY(s.is_super(s.right_of(4, /*include_pos*/true))); - CHECK_UNARY(s.is_super(s.right_of(5, /*include_pos*/true))); - CHECK_UNARY(s.is_super(s.right_of(6, /*include_pos*/true))); - - - CHECK_EQ(s.sub(0, 0), ""); - CHECK_EQ(s.sub(0, 1), "0"); - CHECK_EQ(s.sub(0, 2), "01"); - CHECK_EQ(s.sub(0, 3), "012"); - CHECK_EQ(s.sub(0, 4), "0123"); - CHECK_EQ(s.sub(0, 5), "01234"); - CHECK_EQ(s.sub(0, 6), "012345"); - - CHECK_EQ(s.right_of(s.sub(0, 0)), "012345"); - CHECK_EQ(s.right_of(s.sub(0, 1)), "12345"); - CHECK_EQ(s.right_of(s.sub(0, 2)), "2345"); - CHECK_EQ(s.right_of(s.sub(0, 3)), "345"); - CHECK_EQ(s.right_of(s.sub(0, 4)), "45"); - CHECK_EQ(s.right_of(s.sub(0, 5)), "5"); - CHECK_EQ(s.right_of(s.sub(0, 6)), ""); - - CHECK_UNARY(s.is_super(s.right_of(s.sub(0, 0)))); - CHECK_UNARY(s.is_super(s.right_of(s.sub(0, 1)))); - CHECK_UNARY(s.is_super(s.right_of(s.sub(0, 2)))); - CHECK_UNARY(s.is_super(s.right_of(s.sub(0, 3)))); - CHECK_UNARY(s.is_super(s.right_of(s.sub(0, 4)))); - CHECK_UNARY(s.is_super(s.right_of(s.sub(0, 5)))); - CHECK_UNARY(s.is_super(s.right_of(s.sub(0, 6)))); -} - -TEST_CASE("substr.compare_different_length") -{ - const char s1[] = "one empty doc"; - const char s2[] = "one empty doc, explicit termination"; - csubstr c1(s1), c2(s2); - CHECK_NE(c1, c2); - CHECK_NE(c1, s2); - CHECK_NE(s1, c2); - CHECK_LT(c1, c2); - CHECK_LT(c1, s2); - CHECK_LT(s1, c2); - CHECK_GT(c2, c1); - CHECK_GT(c2, s1); - CHECK_GT(s2, c1); - CHECK_NE((c1 > c2), (c1 < c2)); - CHECK_NE((c1 > s2), (c1 < s2)); - CHECK_NE((s1 > c2), (s1 < c2)); - CHECK_NE((c2 > c1), (c2 < c1)); - CHECK_NE((c2 > s1), (c2 < s1)); - CHECK_NE((s2 > c1), (s2 < c1)); - CHECK_NE((c1 == c2), (c1 != c2)); - CHECK_NE((c1 == s2), (c1 != s2)); - CHECK_NE((s1 == c2), (s1 != c2)); - CHECK_NE((c2 == c1), (c2 != c1)); - CHECK_NE((c2 == s1), (c2 != s1)); - CHECK_NE((s2 == c1), (s2 != c1)); -} - -TEST_CASE("substr.compare_null") -{ - csubstr s1, s2, sp(" "); - CHECK_EQ(s1, ""); - CHECK_EQ(s1, s2); - CHECK(!(s1 > s2)); - CHECK(!(s1 < s2)); - CHECK((s1 <= s2)); - CHECK((s1 >= s2)); - CHECK(!(s1 != s2)); - CHECK_EQ(s1.compare('-'), -1); - CHECK_EQ(sp.compare(' '), 0); - CHECK_EQ(s1.compare("-", 1u), -1); - CHECK_EQ(s1.compare("-", 0u), 0); - CHECK_EQ(s1.compare((const char*)0, 0u), 0); - CHECK_EQ(sp.compare((const char*)0, 0u), 1); - CHECK_EQ(sp.compare(" ", 0u), 1); - CHECK_EQ(sp.compare(" ", 1u), 0); -} - -TEST_CASE("substr.compare_vs_char") -{ - CHECK_EQ(csubstr().compare('1'), -1); // str==null, len==0 - CHECK_EQ(csubstr("0123").first(0).compare('1'), -1); // str!=null, len==0 - CHECK_EQ(csubstr("0123").first(1).compare('1'), -1); - - CHECK_EQ(csubstr("-"), '-'); - CHECK_NE(csubstr("+"), '-'); - - CHECK_NE(csubstr("---"), '-'); - CHECK_NE(csubstr("---"), "-"); - - CHECK_NE(csubstr("aaa"), 'a'); - CHECK_NE(csubstr("aaa"), "a"); - - CHECK_NE(csubstr("aaa"), 'b'); - CHECK_NE(csubstr("aaa"), "b"); - - CHECK_LT(csubstr("aaa"), 'b'); - CHECK_LT(csubstr("aaa"), "b"); - - CHECK_LE(csubstr("aaa"), 'b'); - CHECK_LE(csubstr("aaa"), "b"); - - CHECK_NE(csubstr("bbb"), 'a'); - CHECK_NE(csubstr("bbb"), "a"); - - CHECK_GT(csubstr("bbb"), 'a'); - CHECK_GT(csubstr("bbb"), "a"); - - CHECK_GE(csubstr("bbb"), 'a'); - CHECK_GE(csubstr("bbb"), "a"); -} - -TEST_CASE("substr.mixed_cmp") -{ - // c++20 introduced new comparison rules and clang10 fails: - // - // error: ISO C++20 considers use of overloaded operator '==' (with operand - // types 'const c4::basic_substring' and 'const - // c4::basic_substring') to be ambiguous despite there being a unique - // best viable function [-Werror,-Wambiguous-reversed-operator] - - char sa_[] = "a"; - char sb_[] = "b"; - csubstr csa = "a"; substr sa = sa_; - csubstr csb = "b"; substr sb = sb_; - - CHECK_EQ(csa, csa); - CHECK_EQ(sa, sa); // this fails - CHECK_EQ(csa, sa); - CHECK_EQ(sa, csa); - - CHECK_NE(sa, sb); - CHECK_NE(csa, csb); - CHECK_NE(csa, sb); - CHECK_NE(sa, csb); - - CHECK_LT(sa, sb); - CHECK_LT(csa, csb); - CHECK_LT(csa, sb); - CHECK_LT(sa, csb); - - CHECK_LE(sa, sb); - CHECK_LE(csa, csb); - CHECK_LE(csa, sb); - CHECK_LE(sa, csb); - - CHECK_LE(sa, sa); - CHECK_LE(csa, csa); - CHECK_LE(csa, sa); - CHECK_LE(sa, csa); - - CHECK_GT(sb, sa); - CHECK_GT(csb, csa); - CHECK_GT(csb, sa); - CHECK_GT( sb, csa); - - CHECK_GE(sb, sa); - CHECK_GE(csb, csa); - CHECK_GE(csb, sa); - CHECK_GE( sb, csa); - - CHECK_GE(sb, sb); - CHECK_GE(csb, csb); - CHECK_GE(csb, sb); - CHECK_GE( sb, csb); -} - -TEST_CASE("substr.eqne") -{ - char buf[128]; - for(size_t i = 0; i < 5; ++i) buf[i] = (char)('0' + i); - csubstr cmp(buf, 5); - - CHECK_EQ(csubstr("01234"), cmp); - CHECK_EQ( "01234" , cmp); - CHECK_EQ( cmp, "01234"); - CHECK_NE(csubstr("0123"), cmp); - CHECK_NE( "0123" , cmp); - CHECK_NE( cmp, "0123"); - CHECK_NE(csubstr("012345"), cmp); - CHECK_NE( "012345" , cmp); - CHECK_NE( cmp, "012345"); -} - -TEST_CASE("substr.substr2csubstr") -{ - char b[] = "some string"; - substr s(b); - csubstr sc = s; - CHECK_EQ(sc, s); - const substr cs(b); - const csubstr csc(b); -} - -template -void test_first_of_any(csubstr input, bool true_or_false, size_t which, size_t pos, Args... args) -{ - csubstr::first_of_any_result r = input.first_of_any(to_csubstr(args)...); - //std::cout << input << ": " << (bool(r) ? "true" : "false") << "/which:" << r.which << "/pos:" << r.pos << "\n"; - CHECK_EQ(r, true_or_false); - if(true_or_false) - { - CHECK_UNARY(r); - } - else - { - CHECK_FALSE(r); - } - CHECK_EQ(r.which, which); - CHECK_EQ(r.pos, pos); -} - -TEST_CASE("substr.first_of_any") -{ - size_t NONE = csubstr::NONE; - size_t npos = csubstr::npos; - - test_first_of_any("foobar" , true , 0u , 3u, "bar", "barbell", "bark", "barff"); - test_first_of_any("foobar" , false, NONE, npos, "barbell", "bark", "barff"); - test_first_of_any("foobart" , false, NONE, npos, "barbell", "bark", "barff"); - - test_first_of_any("10" , false, NONE, npos, "0x", "0X", "-0x", "-0X"); - test_first_of_any("10]" , false, NONE, npos, "0x", "0X", "-0x", "-0X"); - test_first_of_any(csubstr("10]").first(2), false, NONE, npos, "0x", "0X", "-0x", "-0X"); - - - test_first_of_any("baz{% endif %}", true, 0u, 3u, "{% endif %}", "{% if " , "{% elif bar %}" , "{% else %}" ); - test_first_of_any("baz{% endif %}", true, 1u, 3u, "{% if " , "{% endif %}" , "{% elif bar %}" , "{% else %}" ); - test_first_of_any("baz{% endif %}", true, 2u, 3u, "{% if " , "{% elif bar %}" , "{% endif %}" , "{% else %}" ); - test_first_of_any("baz{% endif %}", true, 3u, 3u, "{% if " , "{% elif bar %}" , "{% else %}" , "{% endif %}"); - - test_first_of_any("baz{% e..if %}", false, NONE, npos, "{% endif %}", "{% if " , "{% elif bar %}" , "{% else %}" ); - test_first_of_any("baz{% e..if %}", false, NONE, npos, "{% if " , "{% endif %}" , "{% elif bar %}" , "{% else %}" ); - test_first_of_any("baz{% e..if %}", false, NONE, npos, "{% if " , "{% elif bar %}" , "{% endif %}" , "{% else %}" ); - test_first_of_any("baz{% e..if %}", false, NONE, npos, "{% if " , "{% elif bar %}" , "{% else %}" , "{% endif %}"); - - - test_first_of_any("bar{% else %}baz{% endif %}", true, 0u, 3u, "{% else %}" , "{% if " , "{% elif bar %}" , "{% endif %}"); - test_first_of_any("bar{% else %}baz{% endif %}", true, 1u, 3u, "{% if " , "{% else %}" , "{% elif bar %}" , "{% endif %}"); - test_first_of_any("bar{% else %}baz{% endif %}", true, 2u, 3u, "{% if " , "{% elif bar %}" , "{% else %}" , "{% endif %}"); - test_first_of_any("bar{% else %}baz{% endif %}", true, 3u, 3u, "{% if " , "{% elif bar %}" , "{% endif %}" , "{% else %}" ); - - test_first_of_any("bar{% e..e %}baz{% e..if %}", false, NONE, npos, "{% else %}" , "{% if " , "{% elif bar %}" , "{% endif %}"); - test_first_of_any("bar{% e..e %}baz{% e..if %}", false, NONE, npos, "{% if " , "{% else %}" , "{% elif bar %}" , "{% endif %}"); - test_first_of_any("bar{% e..e %}baz{% e..if %}", false, NONE, npos, "{% if " , "{% elif bar %}" , "{% else %}" , "{% endif %}"); - test_first_of_any("bar{% e..e %}baz{% e..if %}", false, NONE, npos, "{% if " , "{% elif bar %}" , "{% endif %}" , "{% else %}" ); - - - test_first_of_any("foo{% elif bar %}bar{% else %}baz{% endif %}", true, 0u, 3u, "{% elif bar %}" , "{% if " , "{% else %}" , "{% endif %}" ); - test_first_of_any("foo{% elif bar %}bar{% else %}baz{% endif %}", true, 1u, 3u, "{% if " , "{% elif bar %}" , "{% else %}" , "{% endif %}" ); - test_first_of_any("foo{% elif bar %}bar{% else %}baz{% endif %}", true, 2u, 3u, "{% if " , "{% else %}" , "{% elif bar %}" , "{% endif %}" ); - test_first_of_any("foo{% elif bar %}bar{% else %}baz{% endif %}", true, 3u, 3u, "{% if " , "{% else %}" , "{% endif %}" , "{% elif bar %}"); - - test_first_of_any("foo{% e..f bar %}bar{% e..e %}baz{% e..if %}", false, NONE, npos, "{% elif bar %}" , "{% if " , "{% else %}" , "{% endif %}" ); - test_first_of_any("foo{% e..f bar %}bar{% e..e %}baz{% e..if %}", false, NONE, npos, "{% if " , "{% elif bar %}" , "{% else %}" , "{% endif %}" ); - test_first_of_any("foo{% e..f bar %}bar{% e..e %}baz{% e..if %}", false, NONE, npos, "{% if " , "{% else %}" , "{% elif bar %}" , "{% endif %}" ); - test_first_of_any("foo{% e..f bar %}bar{% e..e %}baz{% e..if %}", false, NONE, npos, "{% if " , "{% else %}" , "{% endif %}" , "{% elif bar %}"); - - - test_first_of_any("{% if foo %}foo{% elif bar %}bar{% else %}baz{% endif %}", true, 0u, 0u, "{% if " , "{% elif bar %}" , "{% else %}" , "{% endif %}" ); - test_first_of_any("{% if foo %}foo{% elif bar %}bar{% else %}baz{% endif %}", true, 1u, 0u, "{% elif bar %}" , "{% if " , "{% else %}" , "{% endif %}" ); - test_first_of_any("{% if foo %}foo{% elif bar %}bar{% else %}baz{% endif %}", true, 2u, 0u, "{% elif bar %}" , "{% else %}" , "{% if " , "{% endif %}" ); - test_first_of_any("{% if foo %}foo{% elif bar %}bar{% else %}baz{% endif %}", true, 3u, 0u, "{% elif bar %}" , "{% else %}" , "{% endif %}", "{% if " ); - - test_first_of_any("{% .. foo %}foo{% e..f bar %}bar{% e..e %}baz{% e..if %}", false, NONE, npos, "{% if " , "{% elif bar %}" , "{% else %}" , "{% endif %}" ); - test_first_of_any("{% .. foo %}foo{% e..f bar %}bar{% e..e %}baz{% e..if %}", false, NONE, npos, "{% elif bar %}" , "{% if " , "{% else %}" , "{% endif %}" ); - test_first_of_any("{% .. foo %}foo{% e..f bar %}bar{% e..e %}baz{% e..if %}", false, NONE, npos, "{% elif bar %}" , "{% else %}" , "{% if " , "{% endif %}" ); - test_first_of_any("{% .. foo %}foo{% e..f bar %}bar{% e..e %}baz{% e..if %}", false, NONE, npos, "{% elif bar %}" , "{% else %}" , "{% endif %}", "{% if " ); -} - - -TEST_CASE("substr.pair_range_esc") -{ - const char q = '\''; - CHECK_EQ(csubstr("").pair_range_esc(q), ""); - CHECK_EQ(csubstr("'").pair_range_esc(q), ""); - CHECK_EQ(csubstr("''").pair_range_esc(q), "''"); - CHECK_EQ(csubstr("'\\'\\''").pair_range_esc(q), "'\\'\\''"); - CHECK_EQ(csubstr("asdasdasd''asdasd").pair_range_esc(q), "''"); - CHECK_EQ(csubstr("asdasdasd'abc'asdasda").pair_range_esc(q), "'abc'"); -} - -TEST_CASE("substr.pair_range") -{ - CHECK_EQ(csubstr("").pair_range('{', '}'), ""); - CHECK_EQ(csubstr("{").pair_range('{', '}'), ""); - CHECK_EQ(csubstr("}").pair_range('{', '}'), ""); - CHECK_EQ(csubstr("{}").pair_range('{', '}'), "{}"); - CHECK_EQ(csubstr("{abc}").pair_range('{', '}'), "{abc}"); - CHECK_EQ(csubstr("123{abc}456").pair_range('{', '}'), "{abc}"); -} - -TEST_CASE("substr.pair_range_nested") -{ - CHECK_EQ(csubstr("").pair_range_nested('{', '}'), ""); - CHECK_EQ(csubstr("{").pair_range_nested('{', '}'), ""); - CHECK_EQ(csubstr("}").pair_range_nested('{', '}'), ""); - CHECK_EQ(csubstr("{}").pair_range_nested('{', '}'), "{}"); - CHECK_EQ(csubstr("{abc}").pair_range_nested('{', '}'), "{abc}"); - CHECK_EQ(csubstr("123{abc}456").pair_range_nested('{', '}'), "{abc}"); - CHECK_EQ(csubstr("123{abc}456{def}").pair_range_nested('{', '}'), "{abc}"); - CHECK_EQ(csubstr( "{{}}").pair_range_nested('{', '}'), "{{}}"); - CHECK_EQ(csubstr("123{{}}456").pair_range_nested('{', '}'), "{{}}"); - CHECK_EQ(csubstr( "{a{}b{}c}").pair_range_nested('{', '}'), "{a{}b{}c}"); - CHECK_EQ(csubstr("123{a{}b{}c}456").pair_range_nested('{', '}'), "{a{}b{}c}"); - CHECK_EQ(csubstr( "{a{{}}b{{}}c}").pair_range_nested('{', '}'), "{a{{}}b{{}}c}"); - CHECK_EQ(csubstr("123{a{{}}b{{}}c}456").pair_range_nested('{', '}'), "{a{{}}b{{}}c}"); - CHECK_EQ(csubstr( "{{{}}a{{}}b{{}}c{{}}}").pair_range_nested('{', '}'), "{{{}}a{{}}b{{}}c{{}}}"); - CHECK_EQ(csubstr("123{{{}}a{{}}b{{}}c{{}}}456").pair_range_nested('{', '}'), "{{{}}a{{}}b{{}}c{{}}}"); -} - -TEST_CASE("substr.unquoted") -{ - CHECK_EQ(csubstr("").unquoted(), ""); - - CHECK_EQ(csubstr("''").unquoted(), ""); - CHECK_EQ(csubstr("\"\"").unquoted(), ""); - - CHECK_EQ(csubstr("'\''").unquoted(), "'"); - - CHECK_EQ(csubstr("aa").unquoted(), "aa"); - CHECK_EQ(csubstr("'aa'").unquoted(), "aa"); - CHECK_EQ(csubstr("\"aa\"").unquoted(), "aa"); - CHECK_EQ(csubstr("'aa\''").unquoted(), "aa'"); -} - - -TEST_CASE("substr.first_non_empty_span") -{ - CHECK_EQ(csubstr("foo bar").first_non_empty_span(), "foo"); - CHECK_EQ(csubstr(" foo bar").first_non_empty_span(), "foo"); - CHECK_EQ(csubstr("\n \r \t foo bar").first_non_empty_span(), "foo"); - CHECK_EQ(csubstr("\n \r \t foo\n\r\t bar").first_non_empty_span(), "foo"); - CHECK_EQ(csubstr("\n \r \t foo\n\r\t bar").first_non_empty_span(), "foo"); - CHECK_EQ(csubstr(",\n \r \t foo\n\r\t bar").first_non_empty_span(), ","); -} - -TEST_CASE("substr.first_uint_span") -{ - CHECK_EQ(csubstr("1234").first_uint_span(), "1234"); - CHECK_EQ(csubstr("+1234").first_uint_span(), "+1234"); - CHECK_EQ(csubstr("-1234").first_uint_span(), ""); - CHECK_EQ(csubstr("1234 asdkjh").first_uint_span(), "1234"); - CHECK_EQ(csubstr("1234\rasdkjh").first_uint_span(), "1234"); - CHECK_EQ(csubstr("1234\tasdkjh").first_uint_span(), "1234"); - CHECK_EQ(csubstr("1234\nasdkjh").first_uint_span(), "1234"); - CHECK_EQ(csubstr("1234]asdkjh").first_uint_span(), "1234"); - CHECK_EQ(csubstr("1234)asdkjh").first_uint_span(), "1234"); - CHECK_EQ(csubstr("1234gasdkjh").first_uint_span(), ""); - CHECK_EQ(csubstr("1").first_uint_span(), "1"); - CHECK_EQ(csubstr("+1").first_uint_span(), "+1"); - CHECK_EQ(csubstr("-1").first_uint_span(), ""); - CHECK_EQ(csubstr("-0").first_uint_span(), ""); - CHECK_EQ(csubstr("0").first_uint_span(), "0"); - CHECK_EQ(csubstr("+0").first_uint_span(), "+0"); - CHECK_EQ(csubstr("-0").first_uint_span(), ""); - CHECK_EQ(csubstr("1234 abc").first_uint_span(), "1234"); - CHECK_EQ(csubstr("abc 1234 abc").first_uint_span(), ""); - CHECK_EQ(csubstr("+0x1234 abc").first_uint_span(), "+0x1234"); - CHECK_EQ(csubstr("-0x1234 abc").first_uint_span(), ""); - CHECK_EQ(csubstr("0x1234 abc").first_uint_span(), "0x1234"); - CHECK_EQ(csubstr("0x1234\rabc").first_uint_span(), "0x1234"); - CHECK_EQ(csubstr("0x1234\nabc").first_uint_span(), "0x1234"); - CHECK_EQ(csubstr("0x1234\tabc").first_uint_span(), "0x1234"); - CHECK_EQ(csubstr("0x1234]abc").first_uint_span(), "0x1234"); - CHECK_EQ(csubstr("0x1234)abc").first_uint_span(), "0x1234"); - CHECK_EQ(csubstr("0x1234g").first_uint_span(), ""); - CHECK_EQ(csubstr("0b01").first_uint_span(), "0b01"); - CHECK_EQ(csubstr("+0b01").first_uint_span(), "+0b01"); - CHECK_EQ(csubstr("-0b01").first_uint_span(), ""); - CHECK_EQ(csubstr("0b01 asdasd").first_uint_span(), "0b01"); - CHECK_EQ(csubstr("0b01\rasdasd").first_uint_span(), "0b01"); - CHECK_EQ(csubstr("0b01\tasdasd").first_uint_span(), "0b01"); - CHECK_EQ(csubstr("0b01\nasdasd").first_uint_span(), "0b01"); - CHECK_EQ(csubstr("0b01]asdasd").first_uint_span(), "0b01"); - CHECK_EQ(csubstr("0b01)asdasd").first_uint_span(), "0b01"); - CHECK_EQ(csubstr("0b01hasdasd").first_uint_span(), ""); - CHECK_EQ(csubstr("+").first_uint_span(), ""); - CHECK_EQ(csubstr("-").first_uint_span(), ""); -} - -TEST_CASE("substr.first_int_span") -{ - CHECK_EQ(csubstr("1234").first_int_span(), "1234"); - CHECK_EQ(csubstr("+1234").first_int_span(), "+1234"); - CHECK_EQ(csubstr("-1234").first_int_span(), "-1234"); - CHECK_EQ(csubstr("-1234 asdkjh").first_int_span(), "-1234"); - CHECK_EQ(csubstr("-1234\rasdkjh").first_int_span(), "-1234"); - CHECK_EQ(csubstr("-1234\tasdkjh").first_int_span(), "-1234"); - CHECK_EQ(csubstr("-1234\nasdkjh").first_int_span(), "-1234"); - CHECK_EQ(csubstr("-1234]asdkjh").first_int_span(), "-1234"); - CHECK_EQ(csubstr("-1234)asdkjh").first_int_span(), "-1234"); - CHECK_EQ(csubstr("-1234gasdkjh").first_int_span(), ""); - CHECK_EQ(csubstr("1").first_int_span(), "1"); - CHECK_EQ(csubstr("+1").first_int_span(), "+1"); - CHECK_EQ(csubstr("-1").first_int_span(), "-1"); - CHECK_EQ(csubstr("-0").first_int_span(), "-0"); - CHECK_EQ(csubstr("0").first_int_span(), "0"); - CHECK_EQ(csubstr("+0").first_int_span(), "+0"); - CHECK_EQ(csubstr("-0").first_int_span(), "-0"); - CHECK_EQ(csubstr("1234 abc").first_int_span(), "1234"); - CHECK_EQ(csubstr("abc 1234 abc").first_int_span(), ""); - CHECK_EQ(csubstr("+0x1234 abc").first_int_span(), "+0x1234"); - CHECK_EQ(csubstr("-0x1234 abc").first_int_span(), "-0x1234"); - CHECK_EQ(csubstr("0x1234 abc").first_int_span(), "0x1234"); - CHECK_EQ(csubstr("0x1234\rabc").first_int_span(), "0x1234"); - CHECK_EQ(csubstr("0x1234\nabc").first_int_span(), "0x1234"); - CHECK_EQ(csubstr("0x1234\tabc").first_int_span(), "0x1234"); - CHECK_EQ(csubstr("0x1234]abc").first_int_span(), "0x1234"); - CHECK_EQ(csubstr("0x1234)abc").first_int_span(), "0x1234"); - CHECK_EQ(csubstr("0x1234gabc").first_int_span(), ""); - CHECK_EQ(csubstr("0b01").first_int_span(), "0b01"); - CHECK_EQ(csubstr("+0b01").first_int_span(), "+0b01"); - CHECK_EQ(csubstr("-0b01").first_int_span(), "-0b01"); - CHECK_EQ(csubstr("0b01 asdasd").first_int_span(), "0b01"); - CHECK_EQ(csubstr("0b01\rasdasd").first_int_span(), "0b01"); - CHECK_EQ(csubstr("0b01\tasdasd").first_int_span(), "0b01"); - CHECK_EQ(csubstr("0b01\nasdasd").first_int_span(), "0b01"); - CHECK_EQ(csubstr("0b01]asdasd").first_int_span(), "0b01"); - CHECK_EQ(csubstr("0b01)asdasd").first_int_span(), "0b01"); - CHECK_EQ(csubstr("0b01gasdasd").first_int_span(), ""); -} - -TEST_CASE("substr.first_real_span") -{ - // all integers are reals - CHECK_EQ(csubstr("1234").first_real_span(), "1234"); - CHECK_EQ(csubstr("+1234").first_real_span(), "+1234"); - CHECK_EQ(csubstr("-1234").first_real_span(), "-1234"); - CHECK_EQ(csubstr("-1234 asdkjh").first_real_span(), "-1234"); - CHECK_EQ(csubstr("-1234\rasdkjh").first_real_span(), "-1234"); - CHECK_EQ(csubstr("-1234\tasdkjh").first_real_span(), "-1234"); - CHECK_EQ(csubstr("-1234\nasdkjh").first_real_span(), "-1234"); - CHECK_EQ(csubstr("-1234]asdkjh").first_real_span(), "-1234"); - CHECK_EQ(csubstr("-1234)asdkjh").first_real_span(), "-1234"); - CHECK_EQ(csubstr("-1234gasdkjh").first_real_span(), ""); - CHECK_EQ(csubstr("1").first_real_span(), "1"); - CHECK_EQ(csubstr("+1").first_real_span(), "+1"); - CHECK_EQ(csubstr("-1").first_real_span(), "-1"); - CHECK_EQ(csubstr("-0").first_real_span(), "-0"); - CHECK_EQ(csubstr("0").first_real_span(), "0"); - CHECK_EQ(csubstr("+0").first_real_span(), "+0"); - CHECK_EQ(csubstr("-0").first_real_span(), "-0"); - CHECK_EQ(csubstr("1234 abc").first_real_span(), "1234"); - CHECK_EQ(csubstr("abc 1234 abc").first_real_span(), ""); - CHECK_EQ(csubstr("+0x1234 abc").first_real_span(), "+0x1234"); - CHECK_EQ(csubstr("-0x1234 abc").first_real_span(), "-0x1234"); - CHECK_EQ(csubstr("0x1234 abc").first_real_span(), "0x1234"); - CHECK_EQ(csubstr("0x1234\rabc").first_real_span(), "0x1234"); - CHECK_EQ(csubstr("0x1234\nabc").first_real_span(), "0x1234"); - CHECK_EQ(csubstr("0x1234\tabc").first_real_span(), "0x1234"); - CHECK_EQ(csubstr("0x1234]abc").first_real_span(), "0x1234"); - CHECK_EQ(csubstr("0x1234)abc").first_real_span(), "0x1234"); - CHECK_EQ(csubstr("0x1234gabc").first_real_span(), ""); - CHECK_EQ(csubstr("0b01").first_real_span(), "0b01"); - CHECK_EQ(csubstr("+0b01").first_real_span(), "+0b01"); - CHECK_EQ(csubstr("-0b01").first_real_span(), "-0b01"); - CHECK_EQ(csubstr("0b01 asdasd").first_real_span(), "0b01"); - CHECK_EQ(csubstr("0b01\rasdasd").first_real_span(), "0b01"); - CHECK_EQ(csubstr("0b01\tasdasd").first_real_span(), "0b01"); - CHECK_EQ(csubstr("0b01\nasdasd").first_real_span(), "0b01"); - CHECK_EQ(csubstr("0b01]asdasd").first_real_span(), "0b01"); - CHECK_EQ(csubstr("0b01)asdasd").first_real_span(), "0b01"); - CHECK_EQ(csubstr("0b01gasdasd").first_real_span(), ""); - CHECK_EQ(csubstr("0b1.01 asdasd").first_real_span(), "0b1.01"); - CHECK_EQ(csubstr("0b1.01\rasdasd").first_real_span(), "0b1.01"); - CHECK_EQ(csubstr("0b1.01\tasdasd").first_real_span(), "0b1.01"); - CHECK_EQ(csubstr("0b1.01\nasdasd").first_real_span(), "0b1.01"); - CHECK_EQ(csubstr("0b1.01]asdasd").first_real_span(), "0b1.01"); - CHECK_EQ(csubstr("0b1.01)asdasd").first_real_span(), "0b1.01"); - CHECK_EQ(csubstr("0b1.01gasdasd").first_real_span(), ""); - CHECK_EQ(csubstr("0b1.02 asdasd").first_real_span(), ""); - CHECK_EQ(csubstr("0b1.02\rasdasd").first_real_span(), ""); - CHECK_EQ(csubstr("0b1.02\tasdasd").first_real_span(), ""); - CHECK_EQ(csubstr("0b1.02\nasdasd").first_real_span(), ""); - CHECK_EQ(csubstr("0b1.02]asdasd").first_real_span(), ""); - CHECK_EQ(csubstr("0b1.02)asdasd").first_real_span(), ""); - CHECK_EQ(csubstr("0b1.02gasdasd").first_real_span(), ""); - CHECK_EQ(csubstr("+").first_real_span(), ""); - CHECK_EQ(csubstr("-").first_real_span(), ""); - CHECK_EQ(csubstr("+0x").first_real_span(), ""); - CHECK_EQ(csubstr("-0x").first_real_span(), ""); - CHECK_EQ(csubstr("+0b").first_real_span(), ""); - CHECK_EQ(csubstr("-0b").first_real_span(), ""); - CHECK_EQ(csubstr("+0o").first_real_span(), ""); - CHECK_EQ(csubstr("-0o").first_real_span(), ""); - CHECK_EQ(csubstr("-1.234 asdkjh").first_real_span(), "-1.234"); -// CHECK_EQ(csubstr("-1.234e5 asdkjh").first_real_span(), "-1.234e5"); - CHECK_EQ(csubstr("-1.234e+5 asdkjh").first_real_span(), "-1.234e+5"); - CHECK_EQ(csubstr("-1.234e-5 asdkjh").first_real_span(), "-1.234e-5"); - CHECK_EQ(csubstr("0x1.e8480p+19 asdkjh").first_real_span(), "0x1.e8480p+19"); - CHECK_EQ(csubstr("0x1.e8480p-19 asdkjh").first_real_span(), "0x1.e8480p-19"); - CHECK_EQ(csubstr("-0x1.e8480p+19 asdkjh").first_real_span(), "-0x1.e8480p+19"); - CHECK_EQ(csubstr("-0x1.e8480p-19 asdkjh").first_real_span(), "-0x1.e8480p-19"); - CHECK_EQ(csubstr("+0x1.e8480p+19 asdkjh").first_real_span(), "+0x1.e8480p+19"); - CHECK_EQ(csubstr("+0x1.e8480p-19 asdkjh").first_real_span(), "+0x1.e8480p-19"); - CHECK_EQ(csubstr("infinity").first_real_span(), "infinity"); - CHECK_EQ(csubstr(" infinity").first_real_span(), "infinity"); - CHECK_EQ(csubstr("-infinity").first_real_span(), "-infinity"); - CHECK_EQ(csubstr(" -infinity").first_real_span(), "-infinity"); - CHECK_EQ(csubstr("+infinity").first_real_span(), "+infinity"); - CHECK_EQ(csubstr(" +infinity").first_real_span(), "+infinity"); - CHECK_EQ(csubstr("infinity ").first_real_span(), "infinity"); - CHECK_EQ(csubstr(" infinity ").first_real_span(), "infinity"); - CHECK_EQ(csubstr("-infinity ").first_real_span(), "-infinity"); - CHECK_EQ(csubstr(" -infinity ").first_real_span(), "-infinity"); - CHECK_EQ(csubstr("+infinity ").first_real_span(), "+infinity"); - CHECK_EQ(csubstr(" +infinity ").first_real_span(), "+infinity"); - CHECK_EQ(csubstr("infinity1").first_real_span(), ""); - CHECK_EQ(csubstr(" infinity1").first_real_span(), ""); - CHECK_EQ(csubstr("-infinity1").first_real_span(), ""); - CHECK_EQ(csubstr(" -infinity1").first_real_span(), ""); - CHECK_EQ(csubstr("+infinity1").first_real_span(), ""); - CHECK_EQ(csubstr(" +infinity1").first_real_span(), ""); - CHECK_EQ(csubstr("infin").first_real_span(), ""); - CHECK_EQ(csubstr(" infin").first_real_span(), ""); - CHECK_EQ(csubstr("-infin").first_real_span(), ""); - CHECK_EQ(csubstr(" -infin").first_real_span(), ""); - CHECK_EQ(csubstr("+infin").first_real_span(), ""); - CHECK_EQ(csubstr(" +infin").first_real_span(), ""); - CHECK_EQ(csubstr("inflated").first_real_span(), ""); - CHECK_EQ(csubstr(" inflated").first_real_span(), ""); - CHECK_EQ(csubstr("-inflated").first_real_span(), ""); - CHECK_EQ(csubstr(" -inflated").first_real_span(), ""); - CHECK_EQ(csubstr("+inflated").first_real_span(), ""); - CHECK_EQ(csubstr(" +inflated").first_real_span(), ""); - CHECK_EQ(csubstr("inf").first_real_span(), "inf"); - CHECK_EQ(csubstr(" inf").first_real_span(), "inf"); - CHECK_EQ(csubstr("-inf").first_real_span(), "-inf"); - CHECK_EQ(csubstr(" -inf").first_real_span(), "-inf"); - CHECK_EQ(csubstr("+inf").first_real_span(), "+inf"); - CHECK_EQ(csubstr(" +inf").first_real_span(), "+inf"); - CHECK_EQ(csubstr("inf ").first_real_span(), "inf"); - CHECK_EQ(csubstr(" inf ").first_real_span(), "inf"); - CHECK_EQ(csubstr("-inf ").first_real_span(), "-inf"); - CHECK_EQ(csubstr(" -inf ").first_real_span(), "-inf"); - CHECK_EQ(csubstr("+inf ").first_real_span(), "+inf"); - CHECK_EQ(csubstr(" +inf ").first_real_span(), "+inf"); - CHECK_EQ(csubstr("inf1").first_real_span(), ""); - CHECK_EQ(csubstr(" inf1").first_real_span(), ""); - CHECK_EQ(csubstr("-inf1").first_real_span(), ""); - CHECK_EQ(csubstr(" -inf1").first_real_span(), ""); - CHECK_EQ(csubstr("+inf1").first_real_span(), ""); - CHECK_EQ(csubstr(" +inf1").first_real_span(), ""); - CHECK_EQ(csubstr("nan").first_real_span(), "nan"); - CHECK_EQ(csubstr(" nan").first_real_span(), "nan"); - CHECK_EQ(csubstr("-nan").first_real_span(), "-nan"); - CHECK_EQ(csubstr(" -nan").first_real_span(), "-nan"); - CHECK_EQ(csubstr("+nan").first_real_span(), "+nan"); - CHECK_EQ(csubstr(" +nan").first_real_span(), "+nan"); - CHECK_EQ(csubstr("nan ").first_real_span(), "nan"); - CHECK_EQ(csubstr(" nan ").first_real_span(), "nan"); - CHECK_EQ(csubstr("-nan ").first_real_span(), "-nan"); - CHECK_EQ(csubstr(" -nan ").first_real_span(), "-nan"); - CHECK_EQ(csubstr("+nan ").first_real_span(), "+nan"); - CHECK_EQ(csubstr(" +nan ").first_real_span(), "+nan"); - CHECK_EQ(csubstr("nan1").first_real_span(), ""); - CHECK_EQ(csubstr(" nan1").first_real_span(), ""); - CHECK_EQ(csubstr("-nan1").first_real_span(), ""); - CHECK_EQ(csubstr(" -nan1").first_real_span(), ""); - CHECK_EQ(csubstr("+nan1").first_real_span(), ""); - CHECK_EQ(csubstr(" +nan1").first_real_span(), ""); -} - -// start with some obvious direct tests -TEST_CASE("substr.is_unsigned_integer") -{ - SUBCASE("empty_string") - { - CHECK_FALSE(csubstr().is_unsigned_integer()); - CHECK_FALSE(csubstr("").is_unsigned_integer()); - } - SUBCASE("signs") - { - CHECK_FALSE(csubstr("-").is_unsigned_integer()); - CHECK_FALSE(csubstr("+").is_unsigned_integer()); - CHECK_FALSE(csubstr("-1").is_unsigned_integer()); - CHECK_UNARY(csubstr("+1").is_unsigned_integer()); - } - SUBCASE("whitespace_before") - { - CHECK_FALSE(csubstr(" 0").is_unsigned_integer()); - CHECK_FALSE(csubstr(" 1").is_unsigned_integer()); - CHECK_FALSE(csubstr(" -1").is_unsigned_integer()); - CHECK_FALSE(csubstr(" 0.1").is_unsigned_integer()); - CHECK_FALSE(csubstr(" -0.1").is_unsigned_integer()); - } - SUBCASE("whitespace_after") - { - CHECK_FALSE(csubstr("0 ").is_unsigned_integer()); - CHECK_FALSE(csubstr("1 ").is_unsigned_integer()); - CHECK_FALSE(csubstr("-1 ").is_unsigned_integer()); - CHECK_FALSE(csubstr("0.1 ").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0.1 ").is_unsigned_integer()); - } - SUBCASE("whitespace_only") - { - CHECK_FALSE(csubstr(" ").is_unsigned_integer()); - CHECK_FALSE(csubstr("\t\t\t\t").is_unsigned_integer()); - CHECK_FALSE(csubstr("\n\n\n\n").is_unsigned_integer()); - CHECK_FALSE(csubstr("\r\r\r\r").is_unsigned_integer()); - } - SUBCASE("decimal") - { - CHECK_UNARY(csubstr("0").is_unsigned_integer()); - CHECK_UNARY(csubstr("1").is_unsigned_integer()); - CHECK_FALSE(csubstr("-1").is_unsigned_integer()); - CHECK_FALSE(csubstr("0.1").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0.1").is_unsigned_integer()); - } - SUBCASE("hexadecimal") - { - CHECK_FALSE(csubstr("0x").is_unsigned_integer()); - CHECK_FALSE(csubstr("0X").is_unsigned_integer()); - CHECK_UNARY(csubstr("0x1").is_unsigned_integer()); - CHECK_UNARY(csubstr("0X1").is_unsigned_integer()); - CHECK_UNARY(csubstr("0x0").is_unsigned_integer()); - CHECK_UNARY(csubstr("0X0").is_unsigned_integer()); - CHECK_UNARY(csubstr("0xa").is_unsigned_integer()); - CHECK_UNARY(csubstr("0Xa").is_unsigned_integer()); - CHECK_UNARY(csubstr("0xb").is_unsigned_integer()); - CHECK_UNARY(csubstr("0Xb").is_unsigned_integer()); - CHECK_UNARY(csubstr("0xc").is_unsigned_integer()); - CHECK_UNARY(csubstr("0Xc").is_unsigned_integer()); - CHECK_UNARY(csubstr("0xd").is_unsigned_integer()); - CHECK_UNARY(csubstr("0Xd").is_unsigned_integer()); - CHECK_UNARY(csubstr("0xe").is_unsigned_integer()); - CHECK_UNARY(csubstr("0Xe").is_unsigned_integer()); - CHECK_UNARY(csubstr("0xf").is_unsigned_integer()); - CHECK_UNARY(csubstr("0Xf").is_unsigned_integer()); - CHECK_UNARY(csubstr("0xA").is_unsigned_integer()); - CHECK_UNARY(csubstr("0XA").is_unsigned_integer()); - CHECK_UNARY(csubstr("0xB").is_unsigned_integer()); - CHECK_UNARY(csubstr("0XB").is_unsigned_integer()); - CHECK_UNARY(csubstr("0xC").is_unsigned_integer()); - CHECK_UNARY(csubstr("0XC").is_unsigned_integer()); - CHECK_UNARY(csubstr("0xD").is_unsigned_integer()); - CHECK_UNARY(csubstr("0XD").is_unsigned_integer()); - CHECK_UNARY(csubstr("0xE").is_unsigned_integer()); - CHECK_UNARY(csubstr("0XE").is_unsigned_integer()); - CHECK_UNARY(csubstr("0xF").is_unsigned_integer()); - CHECK_UNARY(csubstr("0XF").is_unsigned_integer()); - CHECK_FALSE(csubstr("0xg").is_unsigned_integer()); - CHECK_FALSE(csubstr("0Xg").is_unsigned_integer()); - CHECK_FALSE(csubstr("0xG").is_unsigned_integer()); - CHECK_FALSE(csubstr("0XG").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0x1").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0X1").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0x0").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0X0").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0xa").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0Xa").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0xb").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0Xb").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0xc").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0Xc").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0xd").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0Xd").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0xe").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0Xe").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0xf").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0Xf").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0xA").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0XA").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0xB").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0XB").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0xC").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0XC").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0xD").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0XD").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0xE").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0XE").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0xF").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0XF").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0xg").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0Xg").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0xG").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0XG").is_unsigned_integer()); - } - SUBCASE("binary") - { - CHECK_FALSE(csubstr("0b").is_unsigned_integer()); - CHECK_FALSE(csubstr("0B").is_unsigned_integer()); - CHECK_UNARY(csubstr("0b0").is_unsigned_integer()); - CHECK_UNARY(csubstr("0B0").is_unsigned_integer()); - CHECK_UNARY(csubstr("0b1").is_unsigned_integer()); - CHECK_UNARY(csubstr("0B1").is_unsigned_integer()); - CHECK_FALSE(csubstr("0b2").is_unsigned_integer()); - CHECK_FALSE(csubstr("0B2").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0b0").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0B0").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0b1").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0B1").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0b2").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0B2").is_unsigned_integer()); - } - SUBCASE("octal") - { - CHECK_FALSE(csubstr("0o").is_unsigned_integer()); - CHECK_FALSE(csubstr("0O").is_unsigned_integer()); - CHECK_UNARY(csubstr("0o0").is_unsigned_integer()); - CHECK_UNARY(csubstr("0O0").is_unsigned_integer()); - CHECK_UNARY(csubstr("0o1").is_unsigned_integer()); - CHECK_UNARY(csubstr("0O1").is_unsigned_integer()); - CHECK_UNARY(csubstr("0o6").is_unsigned_integer()); - CHECK_UNARY(csubstr("0O6").is_unsigned_integer()); - CHECK_UNARY(csubstr("0o6").is_unsigned_integer()); - CHECK_UNARY(csubstr("0O6").is_unsigned_integer()); - CHECK_UNARY(csubstr("0o7").is_unsigned_integer()); - CHECK_UNARY(csubstr("0O7").is_unsigned_integer()); - CHECK_FALSE(csubstr("0o8").is_unsigned_integer()); - CHECK_FALSE(csubstr("0O8").is_unsigned_integer()); - CHECK_FALSE(csubstr("0o9").is_unsigned_integer()); - CHECK_FALSE(csubstr("0O9").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0o0").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0O0").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0o1").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0O1").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0o6").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0O6").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0o6").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0O6").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0o7").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0O7").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0o8").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0O8").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0o9").is_unsigned_integer()); - CHECK_FALSE(csubstr("-0O9").is_unsigned_integer()); - } -} - -TEST_CASE("substr.is_integer") -{ - SUBCASE("empty_string") - { - CHECK_FALSE(csubstr().is_integer()); - CHECK_FALSE(csubstr("").is_integer()); - } - SUBCASE("signs") - { - CHECK_FALSE(csubstr("-").is_integer()); - CHECK_FALSE(csubstr("+").is_integer()); - CHECK_UNARY(csubstr("-1").is_integer()); - CHECK_UNARY(csubstr("+1").is_integer()); - } - SUBCASE("whitespace_before") - { - CHECK_FALSE(csubstr(" 0").is_integer()); - CHECK_FALSE(csubstr(" 1").is_integer()); - CHECK_FALSE(csubstr(" -1").is_integer()); - CHECK_FALSE(csubstr(" 0.1").is_integer()); - CHECK_FALSE(csubstr(" -0.1").is_integer()); - } - SUBCASE("whitespace_after") - { - CHECK_FALSE(csubstr("0 ").is_integer()); - CHECK_FALSE(csubstr("1 ").is_integer()); - CHECK_FALSE(csubstr("-1 ").is_integer()); - CHECK_FALSE(csubstr("0.1 ").is_integer()); - CHECK_FALSE(csubstr("-0.1 ").is_integer()); - } - SUBCASE("whitespace_only") - { - CHECK_FALSE(csubstr(" ").is_integer()); - CHECK_FALSE(csubstr("\t\t\t\t").is_integer()); - CHECK_FALSE(csubstr("\n\n\n\n").is_integer()); - CHECK_FALSE(csubstr("\r\r\r\r").is_integer()); - } - SUBCASE("decimal") - { - CHECK_UNARY(csubstr("0").is_integer()); - CHECK_UNARY(csubstr("1").is_integer()); - CHECK_UNARY(csubstr("-1").is_integer()); - CHECK_FALSE(csubstr("0.1").is_integer()); - CHECK_FALSE(csubstr("-0.1").is_integer()); - } - SUBCASE("hexadecimal") - { - CHECK_FALSE(csubstr("0x").is_integer()); - CHECK_FALSE(csubstr("0X").is_integer()); - CHECK_UNARY(csubstr("0x1").is_integer()); - CHECK_UNARY(csubstr("0X1").is_integer()); - CHECK_UNARY(csubstr("0x0").is_integer()); - CHECK_UNARY(csubstr("0X0").is_integer()); - CHECK_UNARY(csubstr("0xa").is_integer()); - CHECK_UNARY(csubstr("0Xa").is_integer()); - CHECK_UNARY(csubstr("0xb").is_integer()); - CHECK_UNARY(csubstr("0Xb").is_integer()); - CHECK_UNARY(csubstr("0xc").is_integer()); - CHECK_UNARY(csubstr("0Xc").is_integer()); - CHECK_UNARY(csubstr("0xd").is_integer()); - CHECK_UNARY(csubstr("0Xd").is_integer()); - CHECK_UNARY(csubstr("0xe").is_integer()); - CHECK_UNARY(csubstr("0Xe").is_integer()); - CHECK_UNARY(csubstr("0xf").is_integer()); - CHECK_UNARY(csubstr("0Xf").is_integer()); - CHECK_UNARY(csubstr("0xA").is_integer()); - CHECK_UNARY(csubstr("0XA").is_integer()); - CHECK_UNARY(csubstr("0xB").is_integer()); - CHECK_UNARY(csubstr("0XB").is_integer()); - CHECK_UNARY(csubstr("0xC").is_integer()); - CHECK_UNARY(csubstr("0XC").is_integer()); - CHECK_UNARY(csubstr("0xD").is_integer()); - CHECK_UNARY(csubstr("0XD").is_integer()); - CHECK_UNARY(csubstr("0xE").is_integer()); - CHECK_UNARY(csubstr("0XE").is_integer()); - CHECK_UNARY(csubstr("0xF").is_integer()); - CHECK_UNARY(csubstr("0XF").is_integer()); - CHECK_FALSE(csubstr("0xg").is_integer()); - CHECK_FALSE(csubstr("0Xg").is_integer()); - CHECK_FALSE(csubstr("0xG").is_integer()); - CHECK_FALSE(csubstr("0XG").is_integer()); - CHECK_UNARY(csubstr("-0x1").is_integer()); - CHECK_UNARY(csubstr("-0X1").is_integer()); - CHECK_UNARY(csubstr("-0x0").is_integer()); - CHECK_UNARY(csubstr("-0X0").is_integer()); - CHECK_UNARY(csubstr("-0xa").is_integer()); - CHECK_UNARY(csubstr("-0Xa").is_integer()); - CHECK_UNARY(csubstr("-0xb").is_integer()); - CHECK_UNARY(csubstr("-0Xb").is_integer()); - CHECK_UNARY(csubstr("-0xc").is_integer()); - CHECK_UNARY(csubstr("-0Xc").is_integer()); - CHECK_UNARY(csubstr("-0xd").is_integer()); - CHECK_UNARY(csubstr("-0Xd").is_integer()); - CHECK_UNARY(csubstr("-0xe").is_integer()); - CHECK_UNARY(csubstr("-0Xe").is_integer()); - CHECK_UNARY(csubstr("-0xf").is_integer()); - CHECK_UNARY(csubstr("-0Xf").is_integer()); - CHECK_UNARY(csubstr("-0xA").is_integer()); - CHECK_UNARY(csubstr("-0XA").is_integer()); - CHECK_UNARY(csubstr("-0xB").is_integer()); - CHECK_UNARY(csubstr("-0XB").is_integer()); - CHECK_UNARY(csubstr("-0xC").is_integer()); - CHECK_UNARY(csubstr("-0XC").is_integer()); - CHECK_UNARY(csubstr("-0xD").is_integer()); - CHECK_UNARY(csubstr("-0XD").is_integer()); - CHECK_UNARY(csubstr("-0xE").is_integer()); - CHECK_UNARY(csubstr("-0XE").is_integer()); - CHECK_UNARY(csubstr("-0xF").is_integer()); - CHECK_UNARY(csubstr("-0XF").is_integer()); - CHECK_FALSE(csubstr("-0xg").is_integer()); - CHECK_FALSE(csubstr("-0Xg").is_integer()); - CHECK_FALSE(csubstr("-0xG").is_integer()); - CHECK_FALSE(csubstr("-0XG").is_integer()); - } - SUBCASE("binary") - { - CHECK_FALSE(csubstr("0b").is_integer()); - CHECK_FALSE(csubstr("0B").is_integer()); - CHECK_UNARY(csubstr("0b0").is_integer()); - CHECK_UNARY(csubstr("0B0").is_integer()); - CHECK_UNARY(csubstr("0b1").is_integer()); - CHECK_UNARY(csubstr("0B1").is_integer()); - CHECK_FALSE(csubstr("0b2").is_integer()); - CHECK_FALSE(csubstr("0B2").is_integer()); - CHECK_UNARY(csubstr("-0b0").is_integer()); - CHECK_UNARY(csubstr("-0B0").is_integer()); - CHECK_UNARY(csubstr("-0b1").is_integer()); - CHECK_UNARY(csubstr("-0B1").is_integer()); - CHECK_FALSE(csubstr("-0b2").is_integer()); - CHECK_FALSE(csubstr("-0B2").is_integer()); - } - SUBCASE("octal") - { - CHECK_FALSE(csubstr("0o").is_integer()); - CHECK_FALSE(csubstr("0O").is_integer()); - CHECK_UNARY(csubstr("0o0").is_integer()); - CHECK_UNARY(csubstr("0O0").is_integer()); - CHECK_UNARY(csubstr("0o1").is_integer()); - CHECK_UNARY(csubstr("0O1").is_integer()); - CHECK_UNARY(csubstr("0o6").is_integer()); - CHECK_UNARY(csubstr("0O6").is_integer()); - CHECK_UNARY(csubstr("0o6").is_integer()); - CHECK_UNARY(csubstr("0O6").is_integer()); - CHECK_UNARY(csubstr("0o7").is_integer()); - CHECK_UNARY(csubstr("0O7").is_integer()); - CHECK_FALSE(csubstr("0o8").is_integer()); - CHECK_FALSE(csubstr("0O8").is_integer()); - CHECK_FALSE(csubstr("0o9").is_integer()); - CHECK_FALSE(csubstr("0O9").is_integer()); - CHECK_UNARY(csubstr("-0o0").is_integer()); - CHECK_UNARY(csubstr("-0O0").is_integer()); - CHECK_UNARY(csubstr("-0o1").is_integer()); - CHECK_UNARY(csubstr("-0O1").is_integer()); - CHECK_UNARY(csubstr("-0o6").is_integer()); - CHECK_UNARY(csubstr("-0O6").is_integer()); - CHECK_UNARY(csubstr("-0o6").is_integer()); - CHECK_UNARY(csubstr("-0O6").is_integer()); - CHECK_UNARY(csubstr("-0o7").is_integer()); - CHECK_UNARY(csubstr("-0O7").is_integer()); - CHECK_FALSE(csubstr("-0o8").is_integer()); - CHECK_FALSE(csubstr("-0O8").is_integer()); - CHECK_FALSE(csubstr("-0o9").is_integer()); - CHECK_FALSE(csubstr("-0O9").is_integer()); - } -} - -TEST_CASE("substr.is_real") -{ - SUBCASE("empty_string") - { - CHECK_FALSE(csubstr().is_real()); - CHECK_FALSE(csubstr("").is_real()); - } - SUBCASE("signs") - { - CHECK_FALSE(csubstr("-").is_real()); - CHECK_FALSE(csubstr("+").is_real()); - CHECK_UNARY(csubstr("-1").is_real()); - CHECK_UNARY(csubstr("+1").is_real()); - } - SUBCASE("whitespace_before") - { - CHECK_FALSE(csubstr(" 0").is_real()); - CHECK_FALSE(csubstr(" 1").is_real()); - CHECK_FALSE(csubstr(" -1").is_real()); - CHECK_FALSE(csubstr(" 0.1").is_real()); - CHECK_FALSE(csubstr(" -0.1").is_real()); - } - SUBCASE("whitespace_after") - { - CHECK_FALSE(csubstr("0 ").is_real()); - CHECK_FALSE(csubstr("1 ").is_real()); - CHECK_FALSE(csubstr("-1 ").is_real()); - CHECK_FALSE(csubstr("0.1 ").is_real()); - CHECK_FALSE(csubstr("-0.1 ").is_real()); - } - SUBCASE("whitespace_only") - { - CHECK_FALSE(csubstr(" ").is_real()); - CHECK_FALSE(csubstr("\t\t\t\t").is_real()); - CHECK_FALSE(csubstr("\n\n\n\n").is_real()); - CHECK_FALSE(csubstr("\r\r\r\r").is_real()); - } - SUBCASE("decimal") - { - CHECK_UNARY(csubstr("0").is_real()); - CHECK_UNARY(csubstr("1").is_real()); - CHECK_UNARY(csubstr("-1").is_real()); - CHECK_UNARY(csubstr("0.1").is_real()); - CHECK_UNARY(csubstr("-0.1").is_real()); - } - SUBCASE("hexadecimal") - { - CHECK_FALSE(csubstr("0x").is_real()); - CHECK_FALSE(csubstr("0X").is_real()); - CHECK_UNARY(csubstr("0x1").is_real()); - CHECK_UNARY(csubstr("0X1").is_real()); - CHECK_UNARY(csubstr("0x0").is_real()); - CHECK_UNARY(csubstr("0X0").is_real()); - CHECK_UNARY(csubstr("0xa").is_real()); - CHECK_UNARY(csubstr("0Xa").is_real()); - CHECK_UNARY(csubstr("0xb").is_real()); - CHECK_UNARY(csubstr("0Xb").is_real()); - CHECK_UNARY(csubstr("0xc").is_real()); - CHECK_UNARY(csubstr("0Xc").is_real()); - CHECK_UNARY(csubstr("0xd").is_real()); - CHECK_UNARY(csubstr("0Xd").is_real()); - CHECK_UNARY(csubstr("0xe").is_real()); - CHECK_UNARY(csubstr("0Xe").is_real()); - CHECK_UNARY(csubstr("0xf").is_real()); - CHECK_UNARY(csubstr("0Xf").is_real()); - CHECK_UNARY(csubstr("0xA").is_real()); - CHECK_UNARY(csubstr("0XA").is_real()); - CHECK_UNARY(csubstr("0xB").is_real()); - CHECK_UNARY(csubstr("0XB").is_real()); - CHECK_UNARY(csubstr("0xC").is_real()); - CHECK_UNARY(csubstr("0XC").is_real()); - CHECK_UNARY(csubstr("0xD").is_real()); - CHECK_UNARY(csubstr("0XD").is_real()); - CHECK_UNARY(csubstr("0xE").is_real()); - CHECK_UNARY(csubstr("0XE").is_real()); - CHECK_UNARY(csubstr("0xF").is_real()); - CHECK_UNARY(csubstr("0XF").is_real()); - CHECK_FALSE(csubstr("0xg").is_real()); - CHECK_FALSE(csubstr("0Xg").is_real()); - CHECK_FALSE(csubstr("0xG").is_real()); - CHECK_FALSE(csubstr("0XG").is_real()); - CHECK_UNARY(csubstr("-0x1").is_real()); - CHECK_UNARY(csubstr("-0X1").is_real()); - CHECK_UNARY(csubstr("-0x0").is_real()); - CHECK_UNARY(csubstr("-0X0").is_real()); - CHECK_UNARY(csubstr("-0xa").is_real()); - CHECK_UNARY(csubstr("-0Xa").is_real()); - CHECK_UNARY(csubstr("-0xb").is_real()); - CHECK_UNARY(csubstr("-0Xb").is_real()); - CHECK_UNARY(csubstr("-0xc").is_real()); - CHECK_UNARY(csubstr("-0Xc").is_real()); - CHECK_UNARY(csubstr("-0xd").is_real()); - CHECK_UNARY(csubstr("-0Xd").is_real()); - CHECK_UNARY(csubstr("-0xe").is_real()); - CHECK_UNARY(csubstr("-0Xe").is_real()); - CHECK_UNARY(csubstr("-0xf").is_real()); - CHECK_UNARY(csubstr("-0Xf").is_real()); - CHECK_UNARY(csubstr("-0xA").is_real()); - CHECK_UNARY(csubstr("-0XA").is_real()); - CHECK_UNARY(csubstr("-0xB").is_real()); - CHECK_UNARY(csubstr("-0XB").is_real()); - CHECK_UNARY(csubstr("-0xC").is_real()); - CHECK_UNARY(csubstr("-0XC").is_real()); - CHECK_UNARY(csubstr("-0xD").is_real()); - CHECK_UNARY(csubstr("-0XD").is_real()); - CHECK_UNARY(csubstr("-0xE").is_real()); - CHECK_UNARY(csubstr("-0XE").is_real()); - CHECK_UNARY(csubstr("-0xF").is_real()); - CHECK_UNARY(csubstr("-0XF").is_real()); - CHECK_FALSE(csubstr("-0xg").is_real()); - CHECK_FALSE(csubstr("-0Xg").is_real()); - CHECK_FALSE(csubstr("-0xG").is_real()); - CHECK_FALSE(csubstr("-0XG").is_real()); - CHECK_UNARY(csubstr("0x1.e8480p+19").is_real()); - CHECK_UNARY(csubstr("0X1.e8480P+19").is_real()); - CHECK_UNARY(csubstr("0x1.e8480P+19").is_real()); - CHECK_UNARY(csubstr("0X1.e8480p+19").is_real()); - CHECK_UNARY(csubstr("-0x1.e8480p+19").is_real()); - CHECK_UNARY(csubstr("-0X1.e8480P+19").is_real()); - CHECK_UNARY(csubstr("-0x1.e8480P+19").is_real()); - CHECK_UNARY(csubstr("-0X1.e8480p+19").is_real()); - } - SUBCASE("binary") - { - CHECK_FALSE(csubstr("0b").is_real()); - CHECK_FALSE(csubstr("0B").is_real()); - CHECK_UNARY(csubstr("0b0").is_real()); - CHECK_UNARY(csubstr("0B0").is_real()); - CHECK_UNARY(csubstr("0b1").is_real()); - CHECK_UNARY(csubstr("0B1").is_real()); - CHECK_FALSE(csubstr("0b2").is_real()); - CHECK_FALSE(csubstr("0B2").is_real()); - CHECK_UNARY(csubstr("-0b0").is_real()); - CHECK_UNARY(csubstr("-0B0").is_real()); - CHECK_UNARY(csubstr("-0b1").is_real()); - CHECK_UNARY(csubstr("-0B1").is_real()); - CHECK_FALSE(csubstr("-0b2").is_real()); - CHECK_FALSE(csubstr("-0B2").is_real()); - } - SUBCASE("octal") - { - CHECK_FALSE(csubstr("0o").is_real()); - CHECK_FALSE(csubstr("0O").is_real()); - CHECK_UNARY(csubstr("0o0").is_real()); - CHECK_UNARY(csubstr("0O0").is_real()); - CHECK_UNARY(csubstr("0o1").is_real()); - CHECK_UNARY(csubstr("0O1").is_real()); - CHECK_UNARY(csubstr("0o6").is_real()); - CHECK_UNARY(csubstr("0O6").is_real()); - CHECK_UNARY(csubstr("0o6").is_real()); - CHECK_UNARY(csubstr("0O6").is_real()); - CHECK_UNARY(csubstr("0o7").is_real()); - CHECK_UNARY(csubstr("0O7").is_real()); - CHECK_FALSE(csubstr("0o8").is_real()); - CHECK_FALSE(csubstr("0O8").is_real()); - CHECK_FALSE(csubstr("0o9").is_real()); - CHECK_FALSE(csubstr("0O9").is_real()); - CHECK_UNARY(csubstr("-0o0").is_real()); - CHECK_UNARY(csubstr("-0O0").is_real()); - CHECK_UNARY(csubstr("-0o1").is_real()); - CHECK_UNARY(csubstr("-0O1").is_real()); - CHECK_UNARY(csubstr("-0o6").is_real()); - CHECK_UNARY(csubstr("-0O6").is_real()); - CHECK_UNARY(csubstr("-0o6").is_real()); - CHECK_UNARY(csubstr("-0O6").is_real()); - CHECK_UNARY(csubstr("-0o7").is_real()); - CHECK_UNARY(csubstr("-0O7").is_real()); - CHECK_FALSE(csubstr("-0o8").is_real()); - CHECK_FALSE(csubstr("-0O8").is_real()); - CHECK_FALSE(csubstr("-0o9").is_real()); - CHECK_FALSE(csubstr("-0O9").is_real()); - } - SUBCASE("infinity") - { - CHECK_UNARY(csubstr("infinity").is_real()); - CHECK_FALSE(csubstr(" infinity").is_real()); - CHECK_UNARY(csubstr("-infinity").is_real()); - CHECK_FALSE(csubstr(" -infinity").is_real()); - CHECK_UNARY(csubstr("+infinity").is_real()); - CHECK_FALSE(csubstr(" +infinity").is_real()); - CHECK_FALSE(csubstr("infinity ").is_real()); - CHECK_FALSE(csubstr(" infinity ").is_real()); - CHECK_FALSE(csubstr("-infinity ").is_real()); - CHECK_FALSE(csubstr(" -infinity ").is_real()); - CHECK_FALSE(csubstr("+infinity ").is_real()); - CHECK_FALSE(csubstr(" +infinity ").is_real()); - CHECK_FALSE(csubstr("infinity1").is_real()); - CHECK_FALSE(csubstr(" infinity1").is_real()); - CHECK_FALSE(csubstr("-infinity1").is_real()); - CHECK_FALSE(csubstr(" -infinity1").is_real()); - CHECK_FALSE(csubstr("+infinity1").is_real()); - CHECK_FALSE(csubstr(" +infinity1").is_real()); - CHECK_FALSE(csubstr("infin").is_real()); - CHECK_FALSE(csubstr(" infin").is_real()); - CHECK_FALSE(csubstr("-infin").is_real()); - CHECK_FALSE(csubstr(" -infin").is_real()); - CHECK_FALSE(csubstr("+infin").is_real()); - CHECK_FALSE(csubstr(" +infin").is_real()); - CHECK_FALSE(csubstr("inflated").is_real()); - CHECK_FALSE(csubstr(" inflated").is_real()); - CHECK_FALSE(csubstr("-inflated").is_real()); - CHECK_FALSE(csubstr(" -inflated").is_real()); - CHECK_FALSE(csubstr("+inflated").is_real()); - CHECK_FALSE(csubstr(" +inflated").is_real()); - } - SUBCASE("inf") - { - CHECK_UNARY(csubstr("inf").is_real()); - CHECK_FALSE(csubstr(" inf").is_real()); - CHECK_UNARY(csubstr("-inf").is_real()); - CHECK_FALSE(csubstr(" -inf").is_real()); - CHECK_UNARY(csubstr("+inf").is_real()); - CHECK_FALSE(csubstr(" +inf").is_real()); - CHECK_FALSE(csubstr("inf ").is_real()); - CHECK_FALSE(csubstr(" inf ").is_real()); - CHECK_FALSE(csubstr("-inf ").is_real()); - CHECK_FALSE(csubstr(" -inf ").is_real()); - CHECK_FALSE(csubstr("+inf ").is_real()); - CHECK_FALSE(csubstr(" +inf ").is_real()); - CHECK_FALSE(csubstr("inf1").is_real()); - CHECK_FALSE(csubstr(" inf1").is_real()); - CHECK_FALSE(csubstr("-inf1").is_real()); - CHECK_FALSE(csubstr(" -inf1").is_real()); - CHECK_FALSE(csubstr("+inf1").is_real()); - CHECK_FALSE(csubstr(" +inf1").is_real()); - } - SUBCASE("nan") - { - CHECK_UNARY(csubstr("nan").is_real()); - CHECK_FALSE(csubstr(" nan").is_real()); - CHECK_UNARY(csubstr("-nan").is_real()); - CHECK_FALSE(csubstr(" -nan").is_real()); - CHECK_UNARY(csubstr("+nan").is_real()); - CHECK_FALSE(csubstr(" +nan").is_real()); - CHECK_FALSE(csubstr("nan ").is_real()); - CHECK_FALSE(csubstr(" nan ").is_real()); - CHECK_FALSE(csubstr("-nan ").is_real()); - CHECK_FALSE(csubstr(" -nan ").is_real()); - CHECK_FALSE(csubstr("+nan ").is_real()); - CHECK_FALSE(csubstr(" +nan ").is_real()); - CHECK_FALSE(csubstr("nan1").is_real()); - CHECK_FALSE(csubstr(" nan1").is_real()); - CHECK_FALSE(csubstr("-nan1").is_real()); - CHECK_FALSE(csubstr(" -nan1").is_real()); - CHECK_FALSE(csubstr("+nan1").is_real()); - CHECK_FALSE(csubstr(" +nan1").is_real()); - } -} - -typedef enum : uint8_t { kIsNone = 0, kIsUint = 1, kIsInt = 3, kIsReal = 7 } NumberClass; -struct number -{ - csubstr num; - NumberClass cls; - - template - number(const char (&n)[N], NumberClass c) : num(n), cls(c) {} - number(csubstr n, NumberClass c) : num(n), cls(c) {} - - void test(csubstr ref={}) - { - if(ref.empty()) - ref = num; - INFO("num=" << num); - INFO("ref=" << ref); - switch(cls) - { - case kIsUint: - { - INFO("uint"); - CHECK_EQ(num.first_uint_span(), ref); - CHECK_EQ(num.first_int_span(), ref); - CHECK_EQ(num.first_real_span(), ref); - CHECK_UNARY(num.first_uint_span().is_unsigned_integer()); - CHECK_UNARY(num.first_uint_span().is_integer()); - CHECK_UNARY(num.first_uint_span().is_number()); - break; - } - case kIsInt: - { - INFO("int"); - CHECK_EQ(num.first_uint_span(), ""); - CHECK_EQ(num.first_int_span(), ref); - CHECK_EQ(num.first_real_span(), ref); - CHECK_FALSE(num.first_int_span().is_unsigned_integer()); - CHECK_UNARY(num.first_int_span().is_integer()); - CHECK_UNARY(num.first_int_span().is_number()); - break; - } - case kIsReal: - { - INFO("real"); - CHECK_EQ(num.first_uint_span(), ""); - CHECK_EQ(num.first_int_span(), ""); - CHECK_EQ(num.first_real_span(), ref); - CHECK_FALSE(num.first_real_span().is_unsigned_integer()); - CHECK_FALSE(num.first_real_span().is_integer()); - CHECK_UNARY(num .first_real_span().is_number()); - break; - } - case kIsNone: - { - INFO("none"); - CHECK_EQ(num.first_uint_span(), ""); - CHECK_EQ(num.first_int_span(), ""); - CHECK_EQ(num.first_real_span(), ""); - CHECK_FALSE(num.is_unsigned_integer()); - CHECK_FALSE(num.is_integer()); - CHECK_FALSE(num.is_number()); - break; - } - default: - { - CHECK_UNARY(false);//FAIL(); - break; - } - } - } -}; - -const number numbers[] = { - {"", kIsNone}, - {"0x", kIsNone}, - {"0b", kIsNone}, - {"0o", kIsNone}, - {".", kIsNone}, - {"0x.", kIsNone}, - {"0b.", kIsNone}, - {"0o.", kIsNone}, - {"-", kIsNone}, - {"0x-", kIsNone}, - {"0b-", kIsNone}, - {"0o-", kIsNone}, - {"+", kIsNone}, - {"0x+", kIsNone}, - {"0b+", kIsNone}, - {"0o+", kIsNone}, - {".e", kIsNone}, - {".e+", kIsNone}, - {".e-", kIsNone}, - {"0x.p", kIsNone}, - {"0x.p+", kIsNone}, - {"0x.p-", kIsNone}, - {"0b.p", kIsNone}, - {"0b.p+", kIsNone}, - {"0b.p-", kIsNone}, - {"0o.p", kIsNone}, - {"0o.p+", kIsNone}, - {"0o.p-", kIsNone}, - {"0x.p+", kIsNone}, - {"0x0.p+", kIsNone}, - {"0x.0p+", kIsNone}, - {"0x.p+0", kIsNone}, - {"0x.p+00", kIsNone}, - {"0x0.0p+", kIsNone}, - {"0x.0p+0", kIsReal}, - {"0x0.p+0", kIsReal}, - {"0x0.0p+0", kIsReal}, - {"0x0.0p+00", kIsReal}, - {"0x00.00p+00", kIsReal}, - {"0x0p0.00p+00", kIsNone}, - {"0x00.0p0p+00", kIsNone}, - {"0x00.00p+0p0", kIsNone}, - {"0x00.00p+00p", kIsNone}, - {"0b.p+", kIsNone}, - {"0b0.p+", kIsNone}, - {"0b.0p+", kIsNone}, - {"0b.p+0", kIsNone}, - {"0b.p+00", kIsNone}, - {"0b0.0p+", kIsNone}, - {"0b.0p+0", kIsReal}, - {"0b0.p+0", kIsReal}, - {"0b0.0p+0", kIsReal}, - {"0b0.0p+00", kIsReal}, - {"0b00.00p+00", kIsReal}, - {"0b0p0.00p+00", kIsNone}, - {"0b00.0p0p+00", kIsNone}, - {"0b00.00p+0p0", kIsNone}, - {"0b00.00p+00p", kIsNone}, - {"0o.p+", kIsNone}, - {"0o0.p+", kIsNone}, - {"0o.0p+", kIsNone}, - {"0o.p+0", kIsNone}, - {"0o.p+00", kIsNone}, - {"0o0.0p+", kIsNone}, - {"0o.0p+0", kIsReal}, - {"0o0.p+0", kIsReal}, - {"0o0.0p+0", kIsReal}, - {"0o0.0p+00", kIsReal}, - {"0o00.00p+00", kIsReal}, - {"0o0p0.00p+00", kIsNone}, - {"0o00.0p0p+00", kIsNone}, - {"0o00.00p+0p0", kIsNone}, - {"0o00.00p+00p", kIsNone}, - {".e+", kIsNone}, - {"0.e+", kIsNone}, - {".0e+", kIsNone}, - {".e+0", kIsNone}, - {".e+00", kIsNone}, - {"0.0e+", kIsNone}, - {".0e+0", kIsReal}, - {"0.e+0", kIsReal}, - {"0.0e+0", kIsReal}, - {"0.0e+00", kIsReal}, - {"00.00e+00", kIsReal}, - {"0e0.00e+00", kIsNone}, - {"00.0e0e+00", kIsNone}, - {"00.00e+0e0", kIsNone}, - {"00.00e+00e", kIsNone}, - {"0x1234.", kIsReal}, - {"+0x1234.", kIsReal}, - {"-0x1234.", kIsReal}, - {"0x.1234", kIsReal}, - {"0x0.1.2.3", kIsNone}, - {"0o0.1.2.3", kIsNone}, - {"0b0.1.0.1", kIsNone}, - {"a", kIsNone}, - {"b", kIsNone}, - {"?", kIsNone}, - {"0.0.1", kIsNone}, - {"0.0.9", kIsNone}, - {"0.0.10", kIsNone}, - {"0.1.0", kIsNone}, - {"0.9.0", kIsNone}, - {"0.10.0", kIsNone}, - {"1.0.0", kIsNone}, - {"9.0.0", kIsNone}, - {"10.0.0", kIsNone}, - {".0", kIsReal}, - {"0.", kIsReal}, - {"0.0", kIsReal}, - {"1234", kIsUint}, - {"+1234", kIsUint}, - {"-1234", kIsInt}, - {"1234.0", kIsReal}, - {"+1234.0", kIsReal}, - {"-1234.0", kIsReal}, - {"0000", kIsUint}, - {"0123", kIsUint}, - {"0", kIsUint}, - {"1", kIsUint}, - {"1.", kIsReal}, - {".1", kIsReal}, - {"0x1234", kIsUint}, - {"+0x1234", kIsUint}, - {"-0x1234", kIsInt}, - {"0b01", kIsUint}, - {"1e+1", kIsReal}, - {"1e-1", kIsReal}, - {"1.e-1", kIsReal}, - {"1.e+1", kIsReal}, - {"1.0e-1", kIsReal}, - {"1.0e+1", kIsReal}, - {"1e+123", kIsReal}, - {"1e-123", kIsReal}, - {"1.e-123", kIsReal}, - {"1.e+123", kIsReal}, - {"1.0e123", kIsReal}, - {"1.0e-123", kIsReal}, - {"1.0e+123", kIsReal}, - {"0x1.e8480p+19", kIsReal}, - {"0x1.g8480p+19", kIsNone}, - {"0xg.e8480p+19", kIsNone}, - {"0b101.011p+19", kIsReal}, - {"0b101.012p+19", kIsNone}, - {"0b102.011p+19", kIsNone}, - {"0o173.045p+19", kIsReal}, - {"0o173.048p+19", kIsNone}, - {"0o178.045p+19", kIsNone}, - {"infinity", kIsReal}, - {"inf", kIsReal}, - {"nan", kIsReal}, -}; - -TEST_CASE("substr.is_number") -{ - SUBCASE("basic.hex") - { - CHECK_EQ(csubstr("0x.0p+0").first_real_span(), csubstr("0x.0p+0")); - CHECK_EQ(csubstr("0x)sdkjhsdfkju").first_int_span(), csubstr{}); - CHECK_EQ(csubstr("0x)sdkjhsdfkju").first_uint_span(), csubstr{}); - CHECK_EQ(csubstr("0x)sdkjhsdfkju").first_real_span(), csubstr{}); - CHECK_EQ(csubstr("0x0)sdkjhsdfkju").first_int_span(), csubstr("0x0")); - CHECK_EQ(csubstr("0x0)sdkjhsdfkju").first_uint_span(), csubstr("0x0")); - CHECK_EQ(csubstr("0x0)sdkjhsdfkju").first_real_span(), csubstr("0x0")); - } - SUBCASE("basic.dec") - { - CHECK_EQ(csubstr("+infinity").first_real_span(), csubstr("+infinity")); - CHECK_EQ(csubstr("-infinity").first_real_span(), csubstr("-infinity")); - CHECK_EQ(csubstr("+inf").first_real_span(), csubstr("+inf")); - CHECK_EQ(csubstr("-inf").first_real_span(), csubstr("-inf")); - CHECK_EQ(csubstr("0.e+0").first_real_span(), csubstr("0.e+0")); - CHECK_EQ(csubstr("0.e-0").first_real_span(), csubstr("0.e-0")); - } - SUBCASE("plain") - { - for(number n : numbers) - { - n.test(); - } - } - char buf[128]; - SUBCASE("leading+") - { - for(number n : numbers) - { - INFO("orig=" << n.num); - substr withplus = cat_sub(buf, '+', n.num); - NumberClass cls = n.cls; - if(withplus.begins_with("+-") || withplus.begins_with("++")) - cls = kIsNone; - number cp(withplus, cls); - cp.test(); - } - } - SUBCASE("leading-") - { - for(number n : numbers) - { - INFO("orig=" << n.num); - substr withminus = cat_sub(buf, '-', n.num); - NumberClass cls = n.cls; - if(cls == kIsUint) - cls = kIsInt; - if(withminus.begins_with("--") || withminus.begins_with("-+")) - cls = kIsNone; - number cp(withminus, cls); - cp.test(); - } - } - SUBCASE("capital_e") - { - for(number n : numbers) - { - INFO("orig=" << n.num); - substr replaced = cat_sub(buf, n.num); - replaced.replace('e', 'E'); - number cp(replaced, n.cls); - cp.test(); - } - } - SUBCASE("capital_p") - { - for(number n : numbers) - { - INFO("orig=" << n.num); - substr replaced = cat_sub(buf, n.num); - replaced.replace('p', 'P'); - number cp(replaced, n.cls); - cp.test(); - } - } - SUBCASE("capital_0x") - { - for(number n : numbers) - { - INFO("orig=" << n.num); - substr replaced = cat_sub(buf, n.num); - replaced.replace('x', 'X'); - number cp(replaced, n.cls); - cp.test(); - } - } - SUBCASE("capital_0b") - { - for(number n : numbers) - { - INFO("orig=" << n.num); - substr replaced = cat_sub(buf, n.num); - replaced.replace('b', 'B'); - number cp(replaced, n.cls); - cp.test(); - } - } - SUBCASE("capital_0o") - { - for(number n : numbers) - { - INFO("orig=" << n.num); - substr replaced = cat_sub(buf, n.num); - replaced.replace('o', 'O'); - number cp(replaced, n.cls); - cp.test(); - } - } - SUBCASE("numbers before") - { - char numbuf_[16] = {}; - substr numbuf = numbuf_; - for(number n : numbers) - { - INFO("orig=" << n.num); - for(char c : {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}) - { - numbuf.fill(c); - substr result = cat_sub(buf, numbuf, n.num); - number cp(result.sub(numbuf.len), n.cls); - cp.test(); - } - } - } - SUBCASE("numbers after") - { - char numbuf_[16] = {}; - substr numbuf = numbuf_; - for(number n : numbers) - { - INFO("orig=" << n.num); - for(char c : {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}) - { - numbuf.fill(c); - substr result = cat_sub(buf, n.num, numbuf); - number cp(result.first(n.num.len), n.cls); - cp.test(); - } - } - } - SUBCASE("delimiter after") - { - for(number n : numbers) - { - INFO("orig=" << n.num); - for(char c : {' ', '\n', ']', ')', '}', ',', ';', '\r', '\t','\0'}) - { - INFO("delimiter='" << c << "'"); - substr result = cat_sub(buf, n.num, c); - number cp(result, n.cls); - cp.test(n.num); - } - } - } - csubstr garbage = "sdkjhsdfkju"; - SUBCASE("prepend") - { - // adding anything before the number will make it not be a number - for(number n : numbers) - { - if(n.num.empty()) - continue; - INFO("orig=" << n.num); - for(int i = 0; i < 127; ++i) - { - char c = (char)i; - csubstr fmtd = cat_sub(buf, garbage, c, n.num); - number cp(fmtd, kIsNone); - cp.test(); - } - } - } - SUBCASE("append") - { - // adding after may or may not make it a number - for(number const& n : numbers) - { - INFO("orig=" << n.num); - for(int i = 0; i < 127; ++i) - { - number cp = n; - char c = (char)i; - cp.num = cat_sub(buf, n.num, c, garbage); - if(!csubstr::_is_delim_char(c)) - { - cp.cls = kIsNone; - } - cp.test(n.num); - } - } - } -} - -TEST_CASE("substr.triml") -{ - using S = csubstr; - - CHECK_EQ(S("aaabbb" ).triml('a' ), "bbb"); - CHECK_EQ(S("aaabbb" ).triml('b' ), "aaabbb"); - CHECK_EQ(S("aaabbb" ).triml('c' ), "aaabbb"); - CHECK_EQ(S("aaabbb" ).triml("ab"), ""); - CHECK_EQ(S("aaabbb" ).triml("ba"), ""); - CHECK_EQ(S("aaabbb" ).triml("cd"), "aaabbb"); - CHECK_EQ(S("aaa...bbb").triml('a' ), "...bbb"); - CHECK_EQ(S("aaa...bbb").triml('b' ), "aaa...bbb"); - CHECK_EQ(S("aaa...bbb").triml('c' ), "aaa...bbb"); - CHECK_EQ(S("aaa...bbb").triml("ab"), "...bbb"); - CHECK_EQ(S("aaa...bbb").triml("ba"), "...bbb"); - CHECK_EQ(S("aaa...bbb").triml("ab."), ""); - CHECK_EQ(S("aaa...bbb").triml("a."), "bbb"); - CHECK_EQ(S("aaa...bbb").triml(".a"), "bbb"); - CHECK_EQ(S("aaa...bbb").triml("b."), "aaa...bbb"); - CHECK_EQ(S("aaa...bbb").triml(".b"), "aaa...bbb"); - CHECK_EQ(S("aaa...bbb").triml("cd"), "aaa...bbb"); - - CHECK_EQ(S("ab" ).triml('a' ), "b"); - CHECK_EQ(S("ab" ).triml('b' ), "ab"); - CHECK_EQ(S("ab" ).triml('c' ), "ab"); - CHECK_EQ(S("ab" ).triml("ab"), ""); - CHECK_EQ(S("ab" ).triml("ba"), ""); - CHECK_EQ(S("ab" ).triml("cd"), "ab"); - CHECK_EQ(S("a...b").triml('a' ), "...b"); - CHECK_EQ(S("a...b").triml('b' ), "a...b"); - CHECK_EQ(S("a...b").triml('c' ), "a...b"); - CHECK_EQ(S("a...b").triml("ab"), "...b"); - CHECK_EQ(S("a...b").triml("ba"), "...b"); - CHECK_EQ(S("a...b").triml("ab."), ""); - CHECK_EQ(S("a...b").triml("a."), "b"); - CHECK_EQ(S("a...b").triml(".a"), "b"); - CHECK_EQ(S("a...b").triml("b."), "a...b"); - CHECK_EQ(S("a...b").triml(".b"), "a...b"); - CHECK_EQ(S("a...b").triml("cd"), "a...b"); -} - -TEST_CASE("substr.trimr") -{ - using S = csubstr; - - CHECK_EQ(S("aaabbb" ).trimr('a' ), "aaabbb"); - CHECK_EQ(S("aaabbb" ).trimr('b' ), "aaa"); - CHECK_EQ(S("aaabbb" ).trimr('c' ), "aaabbb"); - CHECK_EQ(S("aaabbb" ).trimr("ab"), ""); - CHECK_EQ(S("aaabbb" ).trimr("ba"), ""); - CHECK_EQ(S("aaabbb" ).trimr("cd"), "aaabbb"); - CHECK_EQ(S("aaa...bbb").trimr('a' ), "aaa...bbb"); - CHECK_EQ(S("aaa...bbb").trimr('b' ), "aaa..."); - CHECK_EQ(S("aaa...bbb").trimr('c' ), "aaa...bbb"); - CHECK_EQ(S("aaa...bbb").trimr("ab"), "aaa..."); - CHECK_EQ(S("aaa...bbb").trimr("ba"), "aaa..."); - CHECK_EQ(S("aaa...bbb").trimr("ab."), ""); - CHECK_EQ(S("aaa...bbb").trimr("a."), "aaa...bbb"); - CHECK_EQ(S("aaa...bbb").trimr(".a"), "aaa...bbb"); - CHECK_EQ(S("aaa...bbb").trimr("b."), "aaa"); - CHECK_EQ(S("aaa...bbb").trimr(".b"), "aaa"); - CHECK_EQ(S("aaa...bbb").trimr("cd"), "aaa...bbb"); - - CHECK_EQ(S("ab" ).trimr('a' ), "ab"); - CHECK_EQ(S("ab" ).trimr('b' ), "a"); - CHECK_EQ(S("ab" ).trimr('c' ), "ab"); - CHECK_EQ(S("ab" ).trimr("ab"), ""); - CHECK_EQ(S("ab" ).trimr("ba"), ""); - CHECK_EQ(S("ab" ).trimr("cd"), "ab"); - CHECK_EQ(S("a...b").trimr('a' ), "a...b"); - CHECK_EQ(S("a...b").trimr('b' ), "a..."); - CHECK_EQ(S("a...b").trimr('c' ), "a...b"); - CHECK_EQ(S("a...b").trimr("ab"), "a..."); - CHECK_EQ(S("a...b").trimr("ba"), "a..."); - CHECK_EQ(S("a...b").trimr("ab."), ""); - CHECK_EQ(S("a...b").trimr("a."), "a...b"); - CHECK_EQ(S("a...b").trimr(".a"), "a...b"); - CHECK_EQ(S("a...b").trimr("b."), "a"); - CHECK_EQ(S("a...b").trimr(".b"), "a"); - CHECK_EQ(S("a...b").trimr("cd"), "a...b"); -} - -TEST_CASE("substr.trim") -{ - using S = csubstr; - - CHECK_EQ(S("aaabbb" ).trim('a' ), "bbb"); - CHECK_EQ(S("aaabbb" ).trim('b' ), "aaa"); - CHECK_EQ(S("aaabbb" ).trim('c' ), "aaabbb"); - CHECK_EQ(S("aaabbb" ).trim("ab"), ""); - CHECK_EQ(S("aaabbb" ).trim("ba"), ""); - CHECK_EQ(S("aaabbb" ).trim("cd"), "aaabbb"); - CHECK_EQ(S("aaa...bbb").trim('a' ), "...bbb"); - CHECK_EQ(S("aaa...bbb").trim('b' ), "aaa..."); - CHECK_EQ(S("aaa...bbb").trim('c' ), "aaa...bbb"); - CHECK_EQ(S("aaa...bbb").trim("ab"), "..."); - CHECK_EQ(S("aaa...bbb").trim("ba"), "..."); - CHECK_EQ(S("aaa...bbb").trim('c' ), "aaa...bbb"); - CHECK_EQ(S("aaa...bbb").trim("ab."), ""); - CHECK_EQ(S("aaa...bbb").trim("." ), "aaa...bbb"); - CHECK_EQ(S("aaa...bbb").trim("a."), "bbb"); - CHECK_EQ(S("aaa...bbb").trim(".a"), "bbb"); - CHECK_EQ(S("aaa...bbb").trim("b."), "aaa"); - CHECK_EQ(S("aaa...bbb").trim(".b"), "aaa"); - CHECK_EQ(S("aaa...bbb").trim("cd"), "aaa...bbb"); - - CHECK_EQ(S("ab" ).trim('a' ), "b"); - CHECK_EQ(S("ab" ).trim('b' ), "a"); - CHECK_EQ(S("ab" ).trim('c' ), "ab"); - CHECK_EQ(S("ab" ).trim("ab"), ""); - CHECK_EQ(S("ab" ).trim("ba"), ""); - CHECK_EQ(S("ab" ).trim("cd"), "ab"); - CHECK_EQ(S("a...b").trim('a' ), "...b"); - CHECK_EQ(S("a...b").trim('b' ), "a..."); - CHECK_EQ(S("a...b").trim('c' ), "a...b"); - CHECK_EQ(S("a...b").trim("ab"), "..."); - CHECK_EQ(S("a...b").trim("ba"), "..."); - CHECK_EQ(S("a...b").trim('c' ), "a...b"); - CHECK_EQ(S("a...b").trim("ab."), ""); - CHECK_EQ(S("a...b").trim("." ), "a...b"); - CHECK_EQ(S("a...b").trim("a."), "b"); - CHECK_EQ(S("a...b").trim(".a"), "b"); - CHECK_EQ(S("a...b").trim("b."), "a"); - CHECK_EQ(S("a...b").trim(".b"), "a"); - CHECK_EQ(S("a...b").trim("cd"), "a...b"); -} - -TEST_CASE("substr.pop_right") -{ - using S = csubstr; - - CHECK_EQ(S("0/1/2" ).pop_right('/' ), "2"); - CHECK_EQ(S("0/1/2" ).pop_right('/', true), "2"); - CHECK_EQ(S("0/1/2/" ).pop_right('/' ), ""); - CHECK_EQ(S("0/1/2/" ).pop_right('/', true), "2/"); - CHECK_EQ(S("0/1/2///" ).pop_right('/' ), ""); - CHECK_EQ(S("0/1/2///" ).pop_right('/', true), "2///"); - - CHECK_EQ(S("0/1//2" ).pop_right('/' ), "2"); - CHECK_EQ(S("0/1//2" ).pop_right('/', true), "2"); - CHECK_EQ(S("0/1//2/" ).pop_right('/' ), ""); - CHECK_EQ(S("0/1//2/" ).pop_right('/', true), "2/"); - CHECK_EQ(S("0/1//2///" ).pop_right('/' ), ""); - CHECK_EQ(S("0/1//2///" ).pop_right('/', true), "2///"); - - CHECK_EQ(S("0/1///2" ).pop_right('/' ), "2"); - CHECK_EQ(S("0/1///2" ).pop_right('/', true), "2"); - CHECK_EQ(S("0/1///2/" ).pop_right('/' ), ""); - CHECK_EQ(S("0/1///2/" ).pop_right('/', true), "2/"); - CHECK_EQ(S("0/1///2///" ).pop_right('/' ), ""); - CHECK_EQ(S("0/1///2///" ).pop_right('/', true), "2///"); - - CHECK_EQ(S("/0/1/2" ).pop_right('/' ), "2"); - CHECK_EQ(S("/0/1/2" ).pop_right('/', true), "2"); - CHECK_EQ(S("/0/1/2/" ).pop_right('/' ), ""); - CHECK_EQ(S("/0/1/2/" ).pop_right('/', true), "2/"); - CHECK_EQ(S("/0/1/2///").pop_right('/' ), ""); - CHECK_EQ(S("/0/1/2///").pop_right('/', true), "2///"); - - CHECK_EQ(S("0" ).pop_right('/' ), "0"); - CHECK_EQ(S("0" ).pop_right('/', true), "0"); - CHECK_EQ(S("0/" ).pop_right('/' ), ""); - CHECK_EQ(S("0/" ).pop_right('/', true), "0/"); - CHECK_EQ(S("0///" ).pop_right('/' ), ""); - CHECK_EQ(S("0///" ).pop_right('/', true), "0///"); - - CHECK_EQ(S("/0" ).pop_right('/' ), "0"); - CHECK_EQ(S("/0" ).pop_right('/', true), "0"); - CHECK_EQ(S("/0/" ).pop_right('/' ), ""); - CHECK_EQ(S("/0/" ).pop_right('/', true), "0/"); - CHECK_EQ(S("/0///" ).pop_right('/' ), ""); - CHECK_EQ(S("/0///" ).pop_right('/', true), "0///"); - - CHECK_EQ(S("/" ).pop_right('/' ), ""); - CHECK_EQ(S("/" ).pop_right('/', true), ""); - CHECK_EQ(S("///" ).pop_right('/' ), ""); - CHECK_EQ(S("///" ).pop_right('/', true), ""); - - CHECK_EQ(S("" ).pop_right('/' ), ""); - CHECK_EQ(S("" ).pop_right('/', true), ""); - - CHECK_EQ(S("0-1-2" ).pop_right('-' ), "2"); - CHECK_EQ(S("0-1-2" ).pop_right('-', true), "2"); - CHECK_EQ(S("0-1-2-" ).pop_right('-' ), ""); - CHECK_EQ(S("0-1-2-" ).pop_right('-', true), "2-"); - CHECK_EQ(S("0-1-2---" ).pop_right('-' ), ""); - CHECK_EQ(S("0-1-2---" ).pop_right('-', true), "2---"); - - CHECK_EQ(S("0-1--2" ).pop_right('-' ), "2"); - CHECK_EQ(S("0-1--2" ).pop_right('-', true), "2"); - CHECK_EQ(S("0-1--2-" ).pop_right('-' ), ""); - CHECK_EQ(S("0-1--2-" ).pop_right('-', true), "2-"); - CHECK_EQ(S("0-1--2---" ).pop_right('-' ), ""); - CHECK_EQ(S("0-1--2---" ).pop_right('-', true), "2---"); - - CHECK_EQ(S("0-1---2" ).pop_right('-' ), "2"); - CHECK_EQ(S("0-1---2" ).pop_right('-', true), "2"); - CHECK_EQ(S("0-1---2-" ).pop_right('-' ), ""); - CHECK_EQ(S("0-1---2-" ).pop_right('-', true), "2-"); - CHECK_EQ(S("0-1---2---" ).pop_right('-' ), ""); - CHECK_EQ(S("0-1---2---" ).pop_right('-', true), "2---"); - - CHECK_EQ(S("-0-1-2" ).pop_right('-' ), "2"); - CHECK_EQ(S("-0-1-2" ).pop_right('-', true), "2"); - CHECK_EQ(S("-0-1-2-" ).pop_right('-' ), ""); - CHECK_EQ(S("-0-1-2-" ).pop_right('-', true), "2-"); - CHECK_EQ(S("-0-1-2---").pop_right('-' ), ""); - CHECK_EQ(S("-0-1-2---").pop_right('-', true), "2---"); - - CHECK_EQ(S("0" ).pop_right('-' ), "0"); - CHECK_EQ(S("0" ).pop_right('-', true), "0"); - CHECK_EQ(S("0-" ).pop_right('-' ), ""); - CHECK_EQ(S("0-" ).pop_right('-', true), "0-"); - CHECK_EQ(S("0---" ).pop_right('-' ), ""); - CHECK_EQ(S("0---" ).pop_right('-', true), "0---"); - - CHECK_EQ(S("-0" ).pop_right('-' ), "0"); - CHECK_EQ(S("-0" ).pop_right('-', true), "0"); - CHECK_EQ(S("-0-" ).pop_right('-' ), ""); - CHECK_EQ(S("-0-" ).pop_right('-', true), "0-"); - CHECK_EQ(S("-0---" ).pop_right('-' ), ""); - CHECK_EQ(S("-0---" ).pop_right('-', true), "0---"); - - CHECK_EQ(S("-" ).pop_right('-' ), ""); - CHECK_EQ(S("-" ).pop_right('-', true), ""); - CHECK_EQ(S("---" ).pop_right('-' ), ""); - CHECK_EQ(S("---" ).pop_right('-', true), ""); - - CHECK_EQ(S("" ).pop_right('-' ), ""); - CHECK_EQ(S("" ).pop_right('-', true), ""); -} - -TEST_CASE("substr.pop_left") -{ - using S = csubstr; - - CHECK_EQ(S("0/1/2" ).pop_left('/' ), "0"); - CHECK_EQ(S("0/1/2" ).pop_left('/', true), "0"); - CHECK_EQ(S("0/1/2/" ).pop_left('/' ), "0"); - CHECK_EQ(S("0/1/2/" ).pop_left('/', true), "0"); - CHECK_EQ(S("0/1/2///" ).pop_left('/' ), "0"); - CHECK_EQ(S("0/1/2///" ).pop_left('/', true), "0"); - - CHECK_EQ(S("0//1/2" ).pop_left('/' ), "0"); - CHECK_EQ(S("0//1/2" ).pop_left('/', true), "0"); - CHECK_EQ(S("0//1/2/" ).pop_left('/' ), "0"); - CHECK_EQ(S("0//1/2/" ).pop_left('/', true), "0"); - CHECK_EQ(S("0//1/2///" ).pop_left('/' ), "0"); - CHECK_EQ(S("0//1/2///" ).pop_left('/', true), "0"); - - CHECK_EQ(S("0///1/2" ).pop_left('/' ), "0"); - CHECK_EQ(S("0///1/2" ).pop_left('/', true), "0"); - CHECK_EQ(S("0///1/2/" ).pop_left('/' ), "0"); - CHECK_EQ(S("0///1/2/" ).pop_left('/', true), "0"); - CHECK_EQ(S("0///1/2///" ).pop_left('/' ), "0"); - CHECK_EQ(S("0///1/2///" ).pop_left('/', true), "0"); - - CHECK_EQ(S("/0/1/2" ).pop_left('/' ), ""); - CHECK_EQ(S("/0/1/2" ).pop_left('/', true), "/0"); - CHECK_EQ(S("/0/1/2/" ).pop_left('/' ), ""); - CHECK_EQ(S("/0/1/2/" ).pop_left('/', true), "/0"); - CHECK_EQ(S("/0/1/2///").pop_left('/' ), ""); - CHECK_EQ(S("/0/1/2///").pop_left('/', true), "/0"); - CHECK_EQ(S("///0/1/2" ).pop_left('/' ), ""); - CHECK_EQ(S("///0/1/2" ).pop_left('/', true), "///0"); - CHECK_EQ(S("///0/1/2/").pop_left('/' ), ""); - CHECK_EQ(S("///0/1/2/").pop_left('/', true), "///0"); - CHECK_EQ(S("///0/1/2/").pop_left('/' ), ""); - CHECK_EQ(S("///0/1/2/").pop_left('/', true), "///0"); - - CHECK_EQ(S("0" ).pop_left('/' ), "0"); - CHECK_EQ(S("0" ).pop_left('/', true), "0"); - CHECK_EQ(S("0/" ).pop_left('/' ), "0"); - CHECK_EQ(S("0/" ).pop_left('/', true), "0"); - CHECK_EQ(S("0///" ).pop_left('/' ), "0"); - CHECK_EQ(S("0///" ).pop_left('/', true), "0"); - - CHECK_EQ(S("/0" ).pop_left('/' ), ""); - CHECK_EQ(S("/0" ).pop_left('/', true), "/0"); - CHECK_EQ(S("/0/" ).pop_left('/' ), ""); - CHECK_EQ(S("/0/" ).pop_left('/', true), "/0"); - CHECK_EQ(S("/0///" ).pop_left('/' ), ""); - CHECK_EQ(S("/0///" ).pop_left('/', true), "/0"); - CHECK_EQ(S("///0///" ).pop_left('/' ), ""); - CHECK_EQ(S("///0///" ).pop_left('/', true), "///0"); - - CHECK_EQ(S("/" ).pop_left('/' ), ""); - CHECK_EQ(S("/" ).pop_left('/', true), ""); - CHECK_EQ(S("///" ).pop_left('/' ), ""); - CHECK_EQ(S("///" ).pop_left('/', true), ""); - - CHECK_EQ(S("" ).pop_left('/' ), ""); - CHECK_EQ(S("" ).pop_left('/', true), ""); - - CHECK_EQ(S("0-1-2" ).pop_left('-' ), "0"); - CHECK_EQ(S("0-1-2" ).pop_left('-', true), "0"); - CHECK_EQ(S("0-1-2-" ).pop_left('-' ), "0"); - CHECK_EQ(S("0-1-2-" ).pop_left('-', true), "0"); - CHECK_EQ(S("0-1-2---" ).pop_left('-' ), "0"); - CHECK_EQ(S("0-1-2---" ).pop_left('-', true), "0"); - - CHECK_EQ(S("0--1-2" ).pop_left('-' ), "0"); - CHECK_EQ(S("0--1-2" ).pop_left('-', true), "0"); - CHECK_EQ(S("0--1-2-" ).pop_left('-' ), "0"); - CHECK_EQ(S("0--1-2-" ).pop_left('-', true), "0"); - CHECK_EQ(S("0--1-2---" ).pop_left('-' ), "0"); - CHECK_EQ(S("0--1-2---" ).pop_left('-', true), "0"); - - CHECK_EQ(S("0---1-2" ).pop_left('-' ), "0"); - CHECK_EQ(S("0---1-2" ).pop_left('-', true), "0"); - CHECK_EQ(S("0---1-2-" ).pop_left('-' ), "0"); - CHECK_EQ(S("0---1-2-" ).pop_left('-', true), "0"); - CHECK_EQ(S("0---1-2---" ).pop_left('-' ), "0"); - CHECK_EQ(S("0---1-2---" ).pop_left('-', true), "0"); - - CHECK_EQ(S("-0-1-2" ).pop_left('-' ), ""); - CHECK_EQ(S("-0-1-2" ).pop_left('-', true), "-0"); - CHECK_EQ(S("-0-1-2-" ).pop_left('-' ), ""); - CHECK_EQ(S("-0-1-2-" ).pop_left('-', true), "-0"); - CHECK_EQ(S("-0-1-2---").pop_left('-' ), ""); - CHECK_EQ(S("-0-1-2---").pop_left('-', true), "-0"); - CHECK_EQ(S("---0-1-2" ).pop_left('-' ), ""); - CHECK_EQ(S("---0-1-2" ).pop_left('-', true), "---0"); - CHECK_EQ(S("---0-1-2-").pop_left('-' ), ""); - CHECK_EQ(S("---0-1-2-").pop_left('-', true), "---0"); - CHECK_EQ(S("---0-1-2-").pop_left('-' ), ""); - CHECK_EQ(S("---0-1-2-").pop_left('-', true), "---0"); - - CHECK_EQ(S("0" ).pop_left('-' ), "0"); - CHECK_EQ(S("0" ).pop_left('-', true), "0"); - CHECK_EQ(S("0-" ).pop_left('-' ), "0"); - CHECK_EQ(S("0-" ).pop_left('-', true), "0"); - CHECK_EQ(S("0---" ).pop_left('-' ), "0"); - CHECK_EQ(S("0---" ).pop_left('-', true), "0"); - - CHECK_EQ(S("-0" ).pop_left('-' ), ""); - CHECK_EQ(S("-0" ).pop_left('-', true), "-0"); - CHECK_EQ(S("-0-" ).pop_left('-' ), ""); - CHECK_EQ(S("-0-" ).pop_left('-', true), "-0"); - CHECK_EQ(S("-0---" ).pop_left('-' ), ""); - CHECK_EQ(S("-0---" ).pop_left('-', true), "-0"); - CHECK_EQ(S("---0---" ).pop_left('-' ), ""); - CHECK_EQ(S("---0---" ).pop_left('-', true), "---0"); - - CHECK_EQ(S("-" ).pop_left('-' ), ""); - CHECK_EQ(S("-" ).pop_left('-', true), ""); - CHECK_EQ(S("---" ).pop_left('-' ), ""); - CHECK_EQ(S("---" ).pop_left('-', true), ""); - - CHECK_EQ(S("" ).pop_left('-' ), ""); - CHECK_EQ(S("" ).pop_left('-', true), ""); -} - -TEST_CASE("substr.gpop_left") -{ - using S = csubstr; - - CHECK_EQ(S("0/1/2" ).gpop_left('/' ), "0/1"); - CHECK_EQ(S("0/1/2" ).gpop_left('/', true), "0/1"); - CHECK_EQ(S("0/1/2/" ).gpop_left('/' ), "0/1/2"); - CHECK_EQ(S("0/1/2/" ).gpop_left('/', true), "0/1"); - CHECK_EQ(S("0/1/2//" ).gpop_left('/' ), "0/1/2/"); - CHECK_EQ(S("0/1/2//" ).gpop_left('/', true), "0/1"); - CHECK_EQ(S("0/1/2///" ).gpop_left('/' ), "0/1/2//"); - CHECK_EQ(S("0/1/2///" ).gpop_left('/', true), "0/1"); - - CHECK_EQ(S("0/1//2" ).gpop_left('/' ), "0/1/"); - CHECK_EQ(S("0/1//2" ).gpop_left('/', true), "0/1"); - CHECK_EQ(S("0/1//2/" ).gpop_left('/' ), "0/1//2"); - CHECK_EQ(S("0/1//2/" ).gpop_left('/', true), "0/1"); - CHECK_EQ(S("0/1//2//" ).gpop_left('/' ), "0/1//2/"); - CHECK_EQ(S("0/1//2//" ).gpop_left('/', true), "0/1"); - CHECK_EQ(S("0/1//2///" ).gpop_left('/' ), "0/1//2//"); - CHECK_EQ(S("0/1//2///" ).gpop_left('/', true), "0/1"); - - CHECK_EQ(S("0/1///2" ).gpop_left('/' ), "0/1//"); - CHECK_EQ(S("0/1///2" ).gpop_left('/', true), "0/1"); - CHECK_EQ(S("0/1///2/" ).gpop_left('/' ), "0/1///2"); - CHECK_EQ(S("0/1///2/" ).gpop_left('/', true), "0/1"); - CHECK_EQ(S("0/1///2//" ).gpop_left('/' ), "0/1///2/"); - CHECK_EQ(S("0/1///2//" ).gpop_left('/', true), "0/1"); - CHECK_EQ(S("0/1///2///" ).gpop_left('/' ), "0/1///2//"); - CHECK_EQ(S("0/1///2///" ).gpop_left('/', true), "0/1"); - - CHECK_EQ(S("/0/1/2" ).gpop_left('/' ), "/0/1"); - CHECK_EQ(S("/0/1/2" ).gpop_left('/', true), "/0/1"); - CHECK_EQ(S("/0/1/2/" ).gpop_left('/' ), "/0/1/2"); - CHECK_EQ(S("/0/1/2/" ).gpop_left('/', true), "/0/1"); - CHECK_EQ(S("/0/1/2//" ).gpop_left('/' ), "/0/1/2/"); - CHECK_EQ(S("/0/1/2//" ).gpop_left('/', true), "/0/1"); - CHECK_EQ(S("/0/1/2///" ).gpop_left('/' ), "/0/1/2//"); - CHECK_EQ(S("/0/1/2///" ).gpop_left('/', true), "/0/1"); - - CHECK_EQ(S("//0/1/2" ).gpop_left('/' ), "//0/1"); - CHECK_EQ(S("//0/1/2" ).gpop_left('/', true), "//0/1"); - CHECK_EQ(S("//0/1/2/" ).gpop_left('/' ), "//0/1/2"); - CHECK_EQ(S("//0/1/2/" ).gpop_left('/', true), "//0/1"); - CHECK_EQ(S("//0/1/2//" ).gpop_left('/' ), "//0/1/2/"); - CHECK_EQ(S("//0/1/2//" ).gpop_left('/', true), "//0/1"); - CHECK_EQ(S("//0/1/2///" ).gpop_left('/' ), "//0/1/2//"); - CHECK_EQ(S("//0/1/2///" ).gpop_left('/', true), "//0/1"); - - CHECK_EQ(S("///0/1/2" ).gpop_left('/' ), "///0/1"); - CHECK_EQ(S("///0/1/2" ).gpop_left('/', true), "///0/1"); - CHECK_EQ(S("///0/1/2/" ).gpop_left('/' ), "///0/1/2"); - CHECK_EQ(S("///0/1/2/" ).gpop_left('/', true), "///0/1"); - CHECK_EQ(S("///0/1/2//" ).gpop_left('/' ), "///0/1/2/"); - CHECK_EQ(S("///0/1/2//" ).gpop_left('/', true), "///0/1"); - CHECK_EQ(S("///0/1/2///").gpop_left('/' ), "///0/1/2//"); - CHECK_EQ(S("///0/1/2///").gpop_left('/', true), "///0/1"); - - - CHECK_EQ(S("0/1" ).gpop_left('/' ), "0"); - CHECK_EQ(S("0/1" ).gpop_left('/', true), "0"); - CHECK_EQ(S("0/1/" ).gpop_left('/' ), "0/1"); - CHECK_EQ(S("0/1/" ).gpop_left('/', true), "0"); - CHECK_EQ(S("0/1//" ).gpop_left('/' ), "0/1/"); - CHECK_EQ(S("0/1//" ).gpop_left('/', true), "0"); - CHECK_EQ(S("0/1///" ).gpop_left('/' ), "0/1//"); - CHECK_EQ(S("0/1///" ).gpop_left('/', true), "0"); - - CHECK_EQ(S("0//1" ).gpop_left('/' ), "0/"); - CHECK_EQ(S("0//1" ).gpop_left('/', true), "0"); - CHECK_EQ(S("0//1/" ).gpop_left('/' ), "0//1"); - CHECK_EQ(S("0//1/" ).gpop_left('/', true), "0"); - CHECK_EQ(S("0//1//" ).gpop_left('/' ), "0//1/"); - CHECK_EQ(S("0//1//" ).gpop_left('/', true), "0"); - CHECK_EQ(S("0//1///" ).gpop_left('/' ), "0//1//"); - CHECK_EQ(S("0//1///" ).gpop_left('/', true), "0"); - - CHECK_EQ(S("0///1" ).gpop_left('/' ), "0//"); - CHECK_EQ(S("0///1" ).gpop_left('/', true), "0"); - CHECK_EQ(S("0///1/" ).gpop_left('/' ), "0///1"); - CHECK_EQ(S("0///1/" ).gpop_left('/', true), "0"); - CHECK_EQ(S("0///1//" ).gpop_left('/' ), "0///1/"); - CHECK_EQ(S("0///1//" ).gpop_left('/', true), "0"); - CHECK_EQ(S("0///1///" ).gpop_left('/' ), "0///1//"); - CHECK_EQ(S("0///1///" ).gpop_left('/', true), "0"); - - CHECK_EQ(S("/0/1" ).gpop_left('/' ), "/0"); - CHECK_EQ(S("/0/1" ).gpop_left('/', true), "/0"); - CHECK_EQ(S("/0/1/" ).gpop_left('/' ), "/0/1"); - CHECK_EQ(S("/0/1/" ).gpop_left('/', true), "/0"); - CHECK_EQ(S("/0/1//" ).gpop_left('/' ), "/0/1/"); - CHECK_EQ(S("/0/1//" ).gpop_left('/', true), "/0"); - CHECK_EQ(S("/0/1///" ).gpop_left('/' ), "/0/1//"); - CHECK_EQ(S("/0/1///" ).gpop_left('/', true), "/0"); - - CHECK_EQ(S("/0//1" ).gpop_left('/' ), "/0/"); - CHECK_EQ(S("/0//1" ).gpop_left('/', true), "/0"); - CHECK_EQ(S("/0//1/" ).gpop_left('/' ), "/0//1"); - CHECK_EQ(S("/0//1/" ).gpop_left('/', true), "/0"); - CHECK_EQ(S("/0//1//" ).gpop_left('/' ), "/0//1/"); - CHECK_EQ(S("/0//1//" ).gpop_left('/', true), "/0"); - CHECK_EQ(S("/0//1///" ).gpop_left('/' ), "/0//1//"); - CHECK_EQ(S("/0//1///" ).gpop_left('/', true), "/0"); - - CHECK_EQ(S("/0///1" ).gpop_left('/' ), "/0//"); - CHECK_EQ(S("/0///1" ).gpop_left('/', true), "/0"); - CHECK_EQ(S("/0///1/" ).gpop_left('/' ), "/0///1"); - CHECK_EQ(S("/0///1/" ).gpop_left('/', true), "/0"); - CHECK_EQ(S("/0///1//" ).gpop_left('/' ), "/0///1/"); - CHECK_EQ(S("/0///1//" ).gpop_left('/', true), "/0"); - CHECK_EQ(S("/0///1///" ).gpop_left('/' ), "/0///1//"); - CHECK_EQ(S("/0///1///" ).gpop_left('/', true), "/0"); - - CHECK_EQ(S("//0/1" ).gpop_left('/' ), "//0"); - CHECK_EQ(S("//0/1" ).gpop_left('/', true), "//0"); - CHECK_EQ(S("//0/1/" ).gpop_left('/' ), "//0/1"); - CHECK_EQ(S("//0/1/" ).gpop_left('/', true), "//0"); - CHECK_EQ(S("//0/1//" ).gpop_left('/' ), "//0/1/"); - CHECK_EQ(S("//0/1//" ).gpop_left('/', true), "//0"); - CHECK_EQ(S("//0/1///" ).gpop_left('/' ), "//0/1//"); - CHECK_EQ(S("//0/1///" ).gpop_left('/', true), "//0"); - - CHECK_EQ(S("//0//1" ).gpop_left('/' ), "//0/"); - CHECK_EQ(S("//0//1" ).gpop_left('/', true), "//0"); - CHECK_EQ(S("//0//1/" ).gpop_left('/' ), "//0//1"); - CHECK_EQ(S("//0//1/" ).gpop_left('/', true), "//0"); - CHECK_EQ(S("//0//1//" ).gpop_left('/' ), "//0//1/"); - CHECK_EQ(S("//0//1//" ).gpop_left('/', true), "//0"); - CHECK_EQ(S("//0//1///" ).gpop_left('/' ), "//0//1//"); - CHECK_EQ(S("//0//1///" ).gpop_left('/', true), "//0"); - - CHECK_EQ(S("//0///1" ).gpop_left('/' ), "//0//"); - CHECK_EQ(S("//0///1" ).gpop_left('/', true), "//0"); - CHECK_EQ(S("//0///1/" ).gpop_left('/' ), "//0///1"); - CHECK_EQ(S("//0///1/" ).gpop_left('/', true), "//0"); - CHECK_EQ(S("//0///1//" ).gpop_left('/' ), "//0///1/"); - CHECK_EQ(S("//0///1//" ).gpop_left('/', true), "//0"); - CHECK_EQ(S("//0///1///" ).gpop_left('/' ), "//0///1//"); - CHECK_EQ(S("//0///1///" ).gpop_left('/', true), "//0"); - - CHECK_EQ(S("0" ).gpop_left('/' ), ""); - CHECK_EQ(S("0" ).gpop_left('/', true), ""); - CHECK_EQ(S("0/" ).gpop_left('/' ), "0"); - CHECK_EQ(S("0/" ).gpop_left('/', true), ""); - CHECK_EQ(S("0//" ).gpop_left('/' ), "0/"); - CHECK_EQ(S("0//" ).gpop_left('/', true), ""); - CHECK_EQ(S("0///" ).gpop_left('/' ), "0//"); - CHECK_EQ(S("0///" ).gpop_left('/', true), ""); - - CHECK_EQ(S("/0" ).gpop_left('/' ), ""); - CHECK_EQ(S("/0" ).gpop_left('/', true), ""); - CHECK_EQ(S("/0/" ).gpop_left('/' ), "/0"); - CHECK_EQ(S("/0/" ).gpop_left('/', true), ""); - CHECK_EQ(S("/0//" ).gpop_left('/' ), "/0/"); - CHECK_EQ(S("/0//" ).gpop_left('/', true), ""); - CHECK_EQ(S("/0///" ).gpop_left('/' ), "/0//"); - CHECK_EQ(S("/0///" ).gpop_left('/', true), ""); - - CHECK_EQ(S("//0" ).gpop_left('/' ), "/"); - CHECK_EQ(S("//0" ).gpop_left('/', true), ""); - CHECK_EQ(S("//0/" ).gpop_left('/' ), "//0"); - CHECK_EQ(S("//0/" ).gpop_left('/', true), ""); - CHECK_EQ(S("//0//" ).gpop_left('/' ), "//0/"); - CHECK_EQ(S("//0//" ).gpop_left('/', true), ""); - CHECK_EQ(S("//0///" ).gpop_left('/' ), "//0//"); - CHECK_EQ(S("//0///" ).gpop_left('/', true), ""); - - CHECK_EQ(S("///0" ).gpop_left('/' ), "//"); - CHECK_EQ(S("///0" ).gpop_left('/', true), ""); - CHECK_EQ(S("///0/" ).gpop_left('/' ), "///0"); - CHECK_EQ(S("///0/" ).gpop_left('/', true), ""); - CHECK_EQ(S("///0//" ).gpop_left('/' ), "///0/"); - CHECK_EQ(S("///0//" ).gpop_left('/', true), ""); - CHECK_EQ(S("///0///" ).gpop_left('/' ), "///0//"); - CHECK_EQ(S("///0///" ).gpop_left('/', true), ""); - - CHECK_EQ(S("/" ).gpop_left('/' ), ""); - CHECK_EQ(S("/" ).gpop_left('/', true), ""); - CHECK_EQ(S("//" ).gpop_left('/' ), "/"); - CHECK_EQ(S("//" ).gpop_left('/', true), ""); - CHECK_EQ(S("///" ).gpop_left('/' ), "//"); - CHECK_EQ(S("///" ).gpop_left('/', true), ""); - - CHECK_EQ(S("" ).gpop_left('/' ), ""); - CHECK_EQ(S("" ).gpop_left('/', true), ""); -} - -TEST_CASE("substr.gpop_right") -{ - using S = csubstr; - - CHECK_EQ(S("0/1/2" ).gpop_right('/' ), "1/2"); - CHECK_EQ(S("0/1/2" ).gpop_right('/', true), "1/2"); - CHECK_EQ(S("0/1/2/" ).gpop_right('/' ), "1/2/"); - CHECK_EQ(S("0/1/2/" ).gpop_right('/', true), "1/2/"); - CHECK_EQ(S("0/1/2//" ).gpop_right('/' ), "1/2//"); - CHECK_EQ(S("0/1/2//" ).gpop_right('/', true), "1/2//"); - CHECK_EQ(S("0/1/2///" ).gpop_right('/' ), "1/2///"); - CHECK_EQ(S("0/1/2///" ).gpop_right('/', true), "1/2///"); - - CHECK_EQ(S("0//1/2" ).gpop_right('/' ), "/1/2"); - CHECK_EQ(S("0//1/2" ).gpop_right('/', true), "1/2"); - CHECK_EQ(S("0//1/2/" ).gpop_right('/' ), "/1/2/"); - CHECK_EQ(S("0//1/2/" ).gpop_right('/', true), "1/2/"); - CHECK_EQ(S("0//1/2//" ).gpop_right('/' ), "/1/2//"); - CHECK_EQ(S("0//1/2//" ).gpop_right('/', true), "1/2//"); - CHECK_EQ(S("0//1/2///" ).gpop_right('/' ), "/1/2///"); - CHECK_EQ(S("0//1/2///" ).gpop_right('/', true), "1/2///"); - - CHECK_EQ(S("0///1/2" ).gpop_right('/' ), "//1/2"); - CHECK_EQ(S("0///1/2" ).gpop_right('/', true), "1/2"); - CHECK_EQ(S("0///1/2/" ).gpop_right('/' ), "//1/2/"); - CHECK_EQ(S("0///1/2/" ).gpop_right('/', true), "1/2/"); - CHECK_EQ(S("0///1/2//" ).gpop_right('/' ), "//1/2//"); - CHECK_EQ(S("0///1/2//" ).gpop_right('/', true), "1/2//"); - CHECK_EQ(S("0///1/2///" ).gpop_right('/' ), "//1/2///"); - CHECK_EQ(S("0///1/2///" ).gpop_right('/', true), "1/2///"); - - - CHECK_EQ(S("/0/1/2" ).gpop_right('/' ), "0/1/2"); - CHECK_EQ(S("/0/1/2" ).gpop_right('/', true), "1/2"); - CHECK_EQ(S("/0/1/2/" ).gpop_right('/' ), "0/1/2/"); - CHECK_EQ(S("/0/1/2/" ).gpop_right('/', true), "1/2/"); - CHECK_EQ(S("/0/1/2//" ).gpop_right('/' ), "0/1/2//"); - CHECK_EQ(S("/0/1/2//" ).gpop_right('/', true), "1/2//"); - CHECK_EQ(S("/0/1/2///" ).gpop_right('/' ), "0/1/2///"); - CHECK_EQ(S("/0/1/2///" ).gpop_right('/', true), "1/2///"); - - CHECK_EQ(S("/0//1/2" ).gpop_right('/' ), "0//1/2"); - CHECK_EQ(S("/0//1/2" ).gpop_right('/', true), "1/2"); - CHECK_EQ(S("/0//1/2/" ).gpop_right('/' ), "0//1/2/"); - CHECK_EQ(S("/0//1/2/" ).gpop_right('/', true), "1/2/"); - CHECK_EQ(S("/0//1/2//" ).gpop_right('/' ), "0//1/2//"); - CHECK_EQ(S("/0//1/2//" ).gpop_right('/', true), "1/2//"); - CHECK_EQ(S("/0//1/2///" ).gpop_right('/' ), "0//1/2///"); - CHECK_EQ(S("/0//1/2///" ).gpop_right('/', true), "1/2///"); - - CHECK_EQ(S("/0///1/2" ).gpop_right('/' ), "0///1/2"); - CHECK_EQ(S("/0///1/2" ).gpop_right('/', true), "1/2"); - CHECK_EQ(S("/0///1/2/" ).gpop_right('/' ), "0///1/2/"); - CHECK_EQ(S("/0///1/2/" ).gpop_right('/', true), "1/2/"); - CHECK_EQ(S("/0///1/2//" ).gpop_right('/' ), "0///1/2//"); - CHECK_EQ(S("/0///1/2//" ).gpop_right('/', true), "1/2//"); - CHECK_EQ(S("/0///1/2///" ).gpop_right('/' ), "0///1/2///"); - CHECK_EQ(S("/0///1/2///" ).gpop_right('/', true), "1/2///"); - - - CHECK_EQ(S("//0/1/2" ).gpop_right('/' ), "/0/1/2"); - CHECK_EQ(S("//0/1/2" ).gpop_right('/', true), "1/2"); - CHECK_EQ(S("//0/1/2/" ).gpop_right('/' ), "/0/1/2/"); - CHECK_EQ(S("//0/1/2/" ).gpop_right('/', true), "1/2/"); - CHECK_EQ(S("//0/1/2//" ).gpop_right('/' ), "/0/1/2//"); - CHECK_EQ(S("//0/1/2//" ).gpop_right('/', true), "1/2//"); - CHECK_EQ(S("//0/1/2///" ).gpop_right('/' ), "/0/1/2///"); - CHECK_EQ(S("//0/1/2///" ).gpop_right('/', true), "1/2///"); - - CHECK_EQ(S("//0//1/2" ).gpop_right('/' ), "/0//1/2"); - CHECK_EQ(S("//0//1/2" ).gpop_right('/', true), "1/2"); - CHECK_EQ(S("//0//1/2/" ).gpop_right('/' ), "/0//1/2/"); - CHECK_EQ(S("//0//1/2/" ).gpop_right('/', true), "1/2/"); - CHECK_EQ(S("//0//1/2//" ).gpop_right('/' ), "/0//1/2//"); - CHECK_EQ(S("//0//1/2//" ).gpop_right('/', true), "1/2//"); - CHECK_EQ(S("//0//1/2///" ).gpop_right('/' ), "/0//1/2///"); - CHECK_EQ(S("//0//1/2///" ).gpop_right('/', true), "1/2///"); - - CHECK_EQ(S("//0///1/2" ).gpop_right('/' ), "/0///1/2"); - CHECK_EQ(S("//0///1/2" ).gpop_right('/', true), "1/2"); - CHECK_EQ(S("//0///1/2/" ).gpop_right('/' ), "/0///1/2/"); - CHECK_EQ(S("//0///1/2/" ).gpop_right('/', true), "1/2/"); - CHECK_EQ(S("//0///1/2//" ).gpop_right('/' ), "/0///1/2//"); - CHECK_EQ(S("//0///1/2//" ).gpop_right('/', true), "1/2//"); - CHECK_EQ(S("//0///1/2///" ).gpop_right('/' ), "/0///1/2///"); - CHECK_EQ(S("//0///1/2///" ).gpop_right('/', true), "1/2///"); - - - CHECK_EQ(S("0/1" ).gpop_right('/' ), "1"); - CHECK_EQ(S("0/1" ).gpop_right('/', true), "1"); - CHECK_EQ(S("0/1/" ).gpop_right('/' ), "1/"); - CHECK_EQ(S("0/1/" ).gpop_right('/', true), "1/"); - CHECK_EQ(S("0/1//" ).gpop_right('/' ), "1//"); - CHECK_EQ(S("0/1//" ).gpop_right('/', true), "1//"); - CHECK_EQ(S("0/1///" ).gpop_right('/' ), "1///"); - CHECK_EQ(S("0/1///" ).gpop_right('/', true), "1///"); - - CHECK_EQ(S("0//1" ).gpop_right('/' ), "/1"); - CHECK_EQ(S("0//1" ).gpop_right('/', true), "1"); - CHECK_EQ(S("0//1/" ).gpop_right('/' ), "/1/"); - CHECK_EQ(S("0//1/" ).gpop_right('/', true), "1/"); - CHECK_EQ(S("0//1//" ).gpop_right('/' ), "/1//"); - CHECK_EQ(S("0//1//" ).gpop_right('/', true), "1//"); - CHECK_EQ(S("0//1///" ).gpop_right('/' ), "/1///"); - CHECK_EQ(S("0//1///" ).gpop_right('/', true), "1///"); - - CHECK_EQ(S("0///1" ).gpop_right('/' ), "//1"); - CHECK_EQ(S("0///1" ).gpop_right('/', true), "1"); - CHECK_EQ(S("0///1/" ).gpop_right('/' ), "//1/"); - CHECK_EQ(S("0///1/" ).gpop_right('/', true), "1/"); - CHECK_EQ(S("0///1//" ).gpop_right('/' ), "//1//"); - CHECK_EQ(S("0///1//" ).gpop_right('/', true), "1//"); - CHECK_EQ(S("0///1///" ).gpop_right('/' ), "//1///"); - CHECK_EQ(S("0///1///" ).gpop_right('/', true), "1///"); - - - CHECK_EQ(S("/0/1" ).gpop_right('/' ), "0/1"); - CHECK_EQ(S("/0/1" ).gpop_right('/', true), "1"); - CHECK_EQ(S("/0/1/" ).gpop_right('/' ), "0/1/"); - CHECK_EQ(S("/0/1/" ).gpop_right('/', true), "1/"); - CHECK_EQ(S("/0/1//" ).gpop_right('/' ), "0/1//"); - CHECK_EQ(S("/0/1//" ).gpop_right('/', true), "1//"); - CHECK_EQ(S("/0/1///" ).gpop_right('/' ), "0/1///"); - CHECK_EQ(S("/0/1///" ).gpop_right('/', true), "1///"); - - CHECK_EQ(S("/0//1" ).gpop_right('/' ), "0//1"); - CHECK_EQ(S("/0//1" ).gpop_right('/', true), "1"); - CHECK_EQ(S("/0//1/" ).gpop_right('/' ), "0//1/"); - CHECK_EQ(S("/0//1/" ).gpop_right('/', true), "1/"); - CHECK_EQ(S("/0//1//" ).gpop_right('/' ), "0//1//"); - CHECK_EQ(S("/0//1//" ).gpop_right('/', true), "1//"); - CHECK_EQ(S("/0//1///" ).gpop_right('/' ), "0//1///"); - CHECK_EQ(S("/0//1///" ).gpop_right('/', true), "1///"); - - CHECK_EQ(S("/0///1" ).gpop_right('/' ), "0///1"); - CHECK_EQ(S("/0///1" ).gpop_right('/', true), "1"); - CHECK_EQ(S("/0///1/" ).gpop_right('/' ), "0///1/"); - CHECK_EQ(S("/0///1/" ).gpop_right('/', true), "1/"); - CHECK_EQ(S("/0///1//" ).gpop_right('/' ), "0///1//"); - CHECK_EQ(S("/0///1//" ).gpop_right('/', true), "1//"); - CHECK_EQ(S("/0///1///" ).gpop_right('/' ), "0///1///"); - CHECK_EQ(S("/0///1///" ).gpop_right('/', true), "1///"); - - - CHECK_EQ(S("//0/1" ).gpop_right('/' ), "/0/1"); - CHECK_EQ(S("//0/1" ).gpop_right('/', true), "1"); - CHECK_EQ(S("//0/1/" ).gpop_right('/' ), "/0/1/"); - CHECK_EQ(S("//0/1/" ).gpop_right('/', true), "1/"); - CHECK_EQ(S("//0/1//" ).gpop_right('/' ), "/0/1//"); - CHECK_EQ(S("//0/1//" ).gpop_right('/', true), "1//"); - CHECK_EQ(S("//0/1///" ).gpop_right('/' ), "/0/1///"); - CHECK_EQ(S("//0/1///" ).gpop_right('/', true), "1///"); - - CHECK_EQ(S("//0//1" ).gpop_right('/' ), "/0//1"); - CHECK_EQ(S("//0//1" ).gpop_right('/', true), "1"); - CHECK_EQ(S("//0//1/" ).gpop_right('/' ), "/0//1/"); - CHECK_EQ(S("//0//1/" ).gpop_right('/', true), "1/"); - CHECK_EQ(S("//0//1//" ).gpop_right('/' ), "/0//1//"); - CHECK_EQ(S("//0//1//" ).gpop_right('/', true), "1//"); - CHECK_EQ(S("//0//1///" ).gpop_right('/' ), "/0//1///"); - CHECK_EQ(S("//0//1///" ).gpop_right('/', true), "1///"); - - CHECK_EQ(S("//0///1" ).gpop_right('/' ), "/0///1"); - CHECK_EQ(S("//0///1" ).gpop_right('/', true), "1"); - CHECK_EQ(S("//0///1/" ).gpop_right('/' ), "/0///1/"); - CHECK_EQ(S("//0///1/" ).gpop_right('/', true), "1/"); - CHECK_EQ(S("//0///1//" ).gpop_right('/' ), "/0///1//"); - CHECK_EQ(S("//0///1//" ).gpop_right('/', true), "1//"); - CHECK_EQ(S("//0///1///" ).gpop_right('/' ), "/0///1///"); - CHECK_EQ(S("//0///1///" ).gpop_right('/', true), "1///"); - - - CHECK_EQ(S("0" ).gpop_right('/' ), ""); - CHECK_EQ(S("0" ).gpop_right('/', true), ""); - CHECK_EQ(S("0/" ).gpop_right('/' ), ""); - CHECK_EQ(S("0/" ).gpop_right('/', true), ""); - CHECK_EQ(S("0//" ).gpop_right('/' ), "/"); - CHECK_EQ(S("0//" ).gpop_right('/', true), ""); - CHECK_EQ(S("0///" ).gpop_right('/' ), "//"); - CHECK_EQ(S("0///" ).gpop_right('/', true), ""); - - CHECK_EQ(S("/0" ).gpop_right('/' ), "0"); - CHECK_EQ(S("/0" ).gpop_right('/', true), ""); - CHECK_EQ(S("/0/" ).gpop_right('/' ), "0/"); - CHECK_EQ(S("/0/" ).gpop_right('/', true), ""); - CHECK_EQ(S("/0//" ).gpop_right('/' ), "0//"); - CHECK_EQ(S("/0//" ).gpop_right('/', true), ""); - CHECK_EQ(S("/0///" ).gpop_right('/' ), "0///"); - CHECK_EQ(S("/0///" ).gpop_right('/', true), ""); - - CHECK_EQ(S("//0" ).gpop_right('/' ), "/0"); - CHECK_EQ(S("//0" ).gpop_right('/', true), ""); - CHECK_EQ(S("//0/" ).gpop_right('/' ), "/0/"); - CHECK_EQ(S("//0/" ).gpop_right('/', true), ""); - CHECK_EQ(S("//0//" ).gpop_right('/' ), "/0//"); - CHECK_EQ(S("//0//" ).gpop_right('/', true), ""); - CHECK_EQ(S("//0///" ).gpop_right('/' ), "/0///"); - CHECK_EQ(S("//0///" ).gpop_right('/', true), ""); - - CHECK_EQ(S("///0" ).gpop_right('/' ), "//0"); - CHECK_EQ(S("///0" ).gpop_right('/', true), ""); - CHECK_EQ(S("///0/" ).gpop_right('/' ), "//0/"); - CHECK_EQ(S("///0/" ).gpop_right('/', true), ""); - CHECK_EQ(S("///0//" ).gpop_right('/' ), "//0//"); - CHECK_EQ(S("///0//" ).gpop_right('/', true), ""); - CHECK_EQ(S("///0///" ).gpop_right('/' ), "//0///"); - CHECK_EQ(S("///0///" ).gpop_right('/', true), ""); - - CHECK_EQ(S("/" ).gpop_right('/' ), ""); - CHECK_EQ(S("/" ).gpop_right('/', true), ""); - CHECK_EQ(S("//" ).gpop_right('/' ), "/"); - CHECK_EQ(S("//" ).gpop_right('/', true), ""); - CHECK_EQ(S("///" ).gpop_right('/' ), "//"); - CHECK_EQ(S("///" ).gpop_right('/', true), ""); - - CHECK_EQ(S("" ).gpop_right('/' ), ""); - CHECK_EQ(S("" ).gpop_right('/', true), ""); -} - -TEST_CASE("substr.basename") -{ - using S = csubstr; - CHECK_EQ(S("0/1/2").basename(), "2"); - CHECK_EQ(S("0/1/2/").basename(), "2"); - CHECK_EQ(S("0/1/2///").basename(), "2"); - CHECK_EQ(S("/0/1/2").basename(), "2"); - CHECK_EQ(S("/0/1/2/").basename(), "2"); - CHECK_EQ(S("/0/1/2///").basename(), "2"); - CHECK_EQ(S("///0/1/2").basename(), "2"); - CHECK_EQ(S("///0/1/2/").basename(), "2"); - CHECK_EQ(S("///0/1/2///").basename(), "2"); - CHECK_EQ(S("/").basename(), ""); - CHECK_EQ(S("//").basename(), ""); - CHECK_EQ(S("///").basename(), ""); - CHECK_EQ(S("////").basename(), ""); - CHECK_EQ(S("").basename(), ""); -} - -TEST_CASE("substr.dirname") -{ - using S = csubstr; - CHECK_EQ(S("0/1/2").dirname(), "0/1/"); - CHECK_EQ(S("0/1/2/").dirname(), "0/1/"); - CHECK_EQ(S("/0/1/2").dirname(), "/0/1/"); - CHECK_EQ(S("/0/1/2/").dirname(), "/0/1/"); - CHECK_EQ(S("///0/1/2").dirname(), "///0/1/"); - CHECK_EQ(S("///0/1/2/").dirname(), "///0/1/"); - CHECK_EQ(S("/0").dirname(), "/"); - CHECK_EQ(S("/").dirname(), "/"); - CHECK_EQ(S("//").dirname(), "//"); - CHECK_EQ(S("///").dirname(), "///"); - CHECK_EQ(S("////").dirname(), "////"); - CHECK_EQ(S("").dirname(), ""); -} - -TEST_CASE("substr.extshort") -{ - using S = csubstr; - CHECK_EQ(S("filename.with.ext").extshort(), "ext"); - CHECK_EQ(S("filename.with.ext.").extshort(), ""); - CHECK_EQ(S(".a.b").extshort(), "b"); - CHECK_EQ(S(".a.b.").extshort(), ""); - CHECK_EQ(S(".b..").extshort(), ""); - CHECK_EQ(S("..b.").extshort(), ""); -} - -TEST_CASE("substr.extlong") -{ - using S = csubstr; - CHECK_EQ(S("filename.with.ext").extlong(), "with.ext"); - CHECK_EQ(S("filename.with.ext.").extlong(), "with.ext."); - CHECK_EQ(S(".a.b").extlong(), "a.b"); - CHECK_EQ(S(".a.b.").extlong(), "a.b."); - CHECK_EQ(S(".b..").extlong(), "b.."); - CHECK_EQ(S("..b.").extlong(), ".b."); -} - -TEST_CASE("substr.next_split") -{ - using S = csubstr; - - { - S const n; - typename S::size_type pos = 0; - S ss; - CHECK_EQ(n.next_split(':', &pos, &ss), false); - CHECK_EQ(ss.empty(), true); - CHECK_EQ(n.next_split(':', &pos, &ss), false); - CHECK_EQ(ss.empty(), true); - pos = 0; - CHECK_EQ(n.next_split(',', &pos, &ss), false); - CHECK_EQ(ss.empty(), true); - CHECK_EQ(n.next_split(',', &pos, &ss), false); - CHECK_EQ(ss.empty(), true); - } - - { - S const n("0"); - typename S::size_type pos = 0; - S ss; - CHECK_EQ(n.next_split(':', &pos, &ss), true); - CHECK_EQ(ss.empty(), false); - CHECK_EQ(n.next_split(':', &pos, &ss), false); - CHECK_EQ(ss.empty(), true); - CHECK_EQ(n.next_split(':', &pos, &ss), false); - CHECK_EQ(ss.empty(), true); - pos = 0; - CHECK_EQ(n.next_split(',', &pos, &ss), true); - CHECK_EQ(ss.empty(), false); - CHECK_EQ(n.next_split(',', &pos, &ss), false); - CHECK_EQ(ss.empty(), true); - CHECK_EQ(n.next_split(',', &pos, &ss), false); - CHECK_EQ(ss.empty(), true); - } - - { - S const n; - typename S::size_type pos = 0; - typename S::size_type count = 0; - S ss; - while(n.next_split(':', &pos, &ss)) - { - ++count; - } - CHECK_EQ(count, 0); - } - - { - S const n("0123456"); - typename S::size_type pos = 0; - typename S::size_type count = 0; - S ss; - while(n.next_split(':', &pos, &ss)) - { - switch(count) - { - case 0: - CHECK_EQ(ss.size(), n.size()); - CHECK_EQ(ss.empty(), false); - break; - default: - CHECK_UNARY(false);//GTEST_FAIL(); - break; - } - ++count; - } - CHECK_EQ(count, 1); - } - - { - S const n("0123456:"); - typename S::size_type pos = 0; - typename S::size_type count = 0; - S ss; - while(n.next_split(':', &pos, &ss)) - { - switch(count) - { - case 0: - CHECK_EQ(ss.size(), n.size()-1); - CHECK_EQ(ss.empty(), false); - break; - case 1: - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.empty(), true); - break; - default: - CHECK_UNARY(false);//GTEST_FAIL(); - break; - } - ++count; - } - CHECK_EQ(count, 2); - } - - { - S const n(":0123456:"); - typename S::size_type pos = 0; - typename S::size_type count = 0; - S ss; - while(n.next_split(':', &pos, &ss)) - { - switch(count) - { - case 0: - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.empty(), true); - break; - case 1: - CHECK_EQ(ss.size(), n.size()-2); - CHECK_EQ(ss.empty(), false); - break; - case 2: - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.empty(), true); - break; - default: - CHECK_UNARY(false);//GTEST_FAIL(); - break; - } - ++count; - } - CHECK_EQ(count, 3); - } - - { - S const n(":"); - typename S::size_type pos = 0; - typename S::size_type count = 0; - S ss; - while(n.next_split(':', &pos, &ss)) - { - switch(count) - { - case 0: - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.empty(), true); - break; - case 1: - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.empty(), true); - break; - default: - CHECK_UNARY(false);//GTEST_FAIL(); - break; - } - ++count; - } - CHECK_EQ(count, 2); - } - - { - S const n("01:23:45:67"); - typename S::size_type pos = 0; - typename S::size_type count = 0; - S ss; - while(n.next_split(':', &pos, &ss)) - { - switch(count) - { - case 0: - CHECK_EQ(ss.size(), 2); - CHECK_EQ(ss, "01"); - CHECK_NE(ss, "01:"); - CHECK_NE(ss, ":01:"); - CHECK_NE(ss, ":01"); - break; - case 1: - CHECK_EQ(ss.size(), 2); - CHECK_EQ(ss, "23"); - CHECK_NE(ss, "23:"); - CHECK_NE(ss, ":23:"); - CHECK_NE(ss, ":23"); - break; - case 2: - CHECK_EQ(ss.size(), 2); - CHECK_EQ(ss, "45"); - CHECK_NE(ss, "45:"); - CHECK_NE(ss, ":45:"); - CHECK_NE(ss, ":45"); - break; - case 3: - CHECK_EQ(ss.size(), 2); - CHECK_EQ(ss, "67"); - CHECK_NE(ss, "67:"); - CHECK_NE(ss, ":67:"); - CHECK_NE(ss, ":67"); - break; - default: - CHECK_UNARY(false);//GTEST_FAIL(); - break; - } - count++; - } - CHECK_EQ(count, 4); - } - - { - const S n(":01:23:45:67:"); - typename S::size_type pos = 0; - typename S::size_type count = 0; - S ss; - while(n.next_split(':', &pos, &ss)) - { - switch(count) - { - case 0: - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.empty(), true); - break; - case 1: - CHECK_EQ(ss.size(), 2); - CHECK_EQ(ss, "01"); - CHECK_NE(ss, "01:"); - CHECK_NE(ss, ":01:"); - CHECK_NE(ss, ":01"); - break; - case 2: - CHECK_EQ(ss.size(), 2); - CHECK_EQ(ss, "23"); - CHECK_NE(ss, "23:"); - CHECK_NE(ss, ":23:"); - CHECK_NE(ss, ":23"); - break; - case 3: - CHECK_EQ(ss.size(), 2); - CHECK_EQ(ss, "45"); - CHECK_NE(ss, "45:"); - CHECK_NE(ss, ":45:"); - CHECK_NE(ss, ":45"); - break; - case 4: - CHECK_EQ(ss.size(), 2); - CHECK_EQ(ss, "67"); - CHECK_NE(ss, "67:"); - CHECK_NE(ss, ":67:"); - CHECK_NE(ss, ":67"); - break; - case 5: - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.empty(), true); - break; - default: - CHECK_UNARY(false);//GTEST_FAIL(); - break; - } - count++; - } - CHECK_EQ(count, 6); - } - - { - const S n("::::01:23:45:67::::"); - typename S::size_type pos = 0; - typename S::size_type count = 0; - S ss; - while(n.next_split(':', &pos, &ss)) - { - switch(count) - { - case 0: - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.empty(), true); - CHECK_NE(ss, "::"); - break; - case 1: - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.empty(), true); - CHECK_NE(ss, "::"); - break; - case 2: - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.empty(), true); - CHECK_NE(ss, "::"); - break; - case 3: - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.empty(), true); - CHECK_NE(ss, "::"); - break; - case 4: - CHECK_EQ(ss.size(), 2); - CHECK_EQ(ss, "01"); - CHECK_NE(ss, "01:"); - CHECK_NE(ss, ":01:"); - CHECK_NE(ss, ":01"); - break; - case 5: - CHECK_EQ(ss.size(), 2); - CHECK_EQ(ss, "23"); - CHECK_NE(ss, "23:"); - CHECK_NE(ss, ":23:"); - CHECK_NE(ss, ":23"); - break; - case 6: - CHECK_EQ(ss.size(), 2); - CHECK_EQ(ss, "45"); - CHECK_NE(ss, "45:"); - CHECK_NE(ss, ":45:"); - CHECK_NE(ss, ":45"); - break; - case 7: - CHECK_EQ(ss.size(), 2); - CHECK_EQ(ss, "67"); - CHECK_NE(ss, "67:"); - CHECK_NE(ss, ":67:"); - CHECK_NE(ss, ":67"); - break; - case 8: - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.empty(), true); - CHECK_NE(ss, "::"); - break; - case 9: - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.empty(), true); - CHECK_NE(ss, "::"); - break; - case 10: - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.empty(), true); - CHECK_NE(ss, "::"); - break; - case 11: - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.empty(), true); - CHECK_NE(ss, "::"); - break; - default: - CHECK_UNARY(false);//GTEST_FAIL(); - break; - } - count++; - } - CHECK_EQ(count, 12); - } -} - -TEST_CASE("substr.split") -{ - using S = csubstr; - - { - S const n; - { - auto spl = n.split(':'); - auto beg = spl.begin(); - auto end = spl.end(); - CHECK_UNARY(beg == end); - } - } - - { - S const n("foo:bar:baz"); - auto spl = n.split(':'); - auto beg = spl.begin(); - auto end = spl.end(); - CHECK_EQ(beg->size(), 3); - CHECK_EQ(end->size(), 0); - CHECK_EQ(*beg, "foo"); - CHECK_UNARY(beg != end); - auto it = beg; - CHECK_EQ(it->size(), 3); - CHECK_EQ(*it, "foo"); - CHECK_UNARY(it != end); - CHECK_UNARY(it == beg); - CHECK_EQ(beg->size(), 3); - CHECK_EQ(*beg, "foo"); - CHECK_UNARY(beg != end); - ++it; - CHECK_EQ(it->size(), 3); - CHECK_EQ(*it, "bar"); - CHECK_UNARY(it != end); - CHECK_UNARY(it != beg); - CHECK_EQ(beg->size(), 3); - CHECK_EQ(*beg, "foo"); - CHECK_UNARY(beg != end); - ++it; - CHECK_EQ(it->size(), 3); - CHECK_EQ(*it, "baz"); - CHECK_UNARY(it != end); - CHECK_UNARY(it != beg); - CHECK_EQ(beg->size(), 3); - CHECK_EQ(*beg, "foo"); - CHECK_UNARY(beg != end); - ++it; - CHECK_EQ(it->size(), 0); - CHECK_UNARY(it == end); - CHECK_UNARY(it != beg); - CHECK_EQ(beg->size(), 3); - CHECK_EQ(*beg, "foo"); - CHECK_UNARY(beg != end); - it = beg; - CHECK_EQ(it->size(), 3); - CHECK_EQ(*it, "foo"); - CHECK_UNARY(it != end); - CHECK_UNARY(it == beg); - CHECK_EQ(beg->size(), 3); - CHECK_EQ(*beg, "foo"); - CHECK_UNARY(beg != end); - it++; - CHECK_EQ(it->size(), 3); - CHECK_EQ(*it, "bar"); - CHECK_UNARY(it != end); - CHECK_UNARY(it != beg); - CHECK_EQ(beg->size(), 3); - CHECK_EQ(*beg, "foo"); - CHECK_UNARY(beg != end); - it++; - CHECK_EQ(it->size(), 3); - CHECK_EQ(*it, "baz"); - CHECK_UNARY(it != end); - CHECK_UNARY(it != beg); - CHECK_EQ(beg->size(), 3); - CHECK_EQ(*beg, "foo"); - CHECK_UNARY(beg != end); - it++; - CHECK_EQ(it->size(), 0); - CHECK_UNARY(it == end); - CHECK_UNARY(it != beg); - CHECK_EQ(beg->size(), 3); - CHECK_EQ(*beg, "foo"); - CHECK_UNARY(beg != end); - } - - { - S const n("foo:bar:baz:"); - auto spl = n.split(':'); - auto beg = spl.begin(); - auto end = spl.end(); - CHECK_EQ(beg->size(), 3); - CHECK_EQ(end->size(), 0); - CHECK_EQ(*beg, "foo"); - CHECK_UNARY(beg != end); - auto it = beg; - CHECK_EQ(it->size(), 3); - CHECK_EQ(*it, "foo"); - CHECK_UNARY(it != end); - CHECK_UNARY(it == beg); - CHECK_EQ(beg->size(), 3); - CHECK_EQ(*beg, "foo"); - CHECK_UNARY(beg != end); - ++it; - CHECK_EQ(it->size(), 3); - CHECK_EQ(*it, "bar"); - CHECK_UNARY(it != end); - CHECK_UNARY(it != beg); - CHECK_EQ(beg->size(), 3); - CHECK_EQ(*beg, "foo"); - CHECK_UNARY(beg != end); - ++it; - CHECK_EQ(it->size(), 3); - CHECK_EQ(*it, "baz"); - CHECK_UNARY(it != end); - CHECK_UNARY(it != beg); - CHECK_EQ(beg->size(), 3); - CHECK_EQ(*beg, "foo"); - CHECK_UNARY(beg != end); - ++it; - CHECK_EQ(it->size(), 0); - CHECK_EQ(*it, ""); - CHECK_UNARY(it != end); - CHECK_UNARY(it != beg); - CHECK_EQ(beg->size(), 3); - CHECK_EQ(*beg, "foo"); - CHECK_UNARY(beg != end); - ++it; - CHECK_EQ(it->size(), 0); - CHECK_UNARY(it == end); - CHECK_UNARY(it != beg); - CHECK_EQ(beg->size(), 3); - CHECK_EQ(*beg, "foo"); - CHECK_UNARY(beg != end); - //-------------------------- - it = beg; - CHECK_EQ(it->size(), 3); - CHECK_EQ(*it, "foo"); - CHECK_UNARY(it != end); - CHECK_UNARY(it == beg); - CHECK_EQ(beg->size(), 3); - CHECK_EQ(*beg, "foo"); - CHECK_UNARY(beg != end); - it++; - CHECK_EQ(it->size(), 3); - CHECK_EQ(*it, "bar"); - CHECK_UNARY(it != end); - CHECK_UNARY(it != beg); - CHECK_EQ(beg->size(), 3); - CHECK_EQ(*beg, "foo"); - CHECK_UNARY(beg != end); - it++; - CHECK_EQ(it->size(), 3); - CHECK_EQ(*it, "baz"); - CHECK_UNARY(it != end); - CHECK_UNARY(it != beg); - CHECK_EQ(beg->size(), 3); - CHECK_EQ(*beg, "foo"); - CHECK_UNARY(beg != end); - it++; - CHECK_EQ(it->size(), 0); - CHECK_EQ(*it, ""); - CHECK_UNARY(it != end); - CHECK_UNARY(it != beg); - CHECK_EQ(beg->size(), 3); - CHECK_EQ(*beg, "foo"); - CHECK_UNARY(beg != end); - it++; - CHECK_EQ(it->size(), 0); - CHECK_UNARY(it == end); - CHECK_UNARY(it != beg); - CHECK_EQ(beg->size(), 3); - CHECK_EQ(*beg, "foo"); - CHECK_UNARY(beg != end); - } - - { - S const n; - auto s = n.split(':'); - // check that multiple calls to begin() always yield the same result - CHECK_EQ(*s.begin(), ""); - CHECK_EQ(*s.begin(), ""); - CHECK_EQ(*s.begin(), ""); - // check that multiple calls to end() always yield the same result - auto e = s.end(); - CHECK_UNARY(s.end() == e); - CHECK_UNARY(s.end() == e); - // - auto it = s.begin(); - CHECK_EQ(*it, ""); - CHECK_EQ(it->empty(), true); - CHECK_EQ(it->size(), 0); - ++it; - CHECK_UNARY(it == e); - } - - { - S const n("01:23:45:67"); - auto s = n.split(':'); - // check that multiple calls to begin() always yield the same result - CHECK_EQ(*s.begin(), "01"); - CHECK_EQ(*s.begin(), "01"); - CHECK_EQ(*s.begin(), "01"); - // check that multiple calls to end() always yield the same result - auto e = s.end(); - CHECK_UNARY(s.end() == e); - CHECK_UNARY(s.end() == e); - CHECK_UNARY(s.end() == e); - // - auto it = s.begin(); - CHECK_EQ(*it, "01"); - CHECK_EQ(it->size(), 2); - ++it; - CHECK_EQ(*it, "23"); - CHECK_EQ(it->size(), 2); - ++it; - CHECK_EQ(*it, "45"); - CHECK_EQ(it->size(), 2); - ++it; - CHECK_EQ(*it, "67"); - CHECK_EQ(it->size(), 2); - ++it; - CHECK_UNARY(it == s.end()); - } - - { - S const n; - typename S::size_type count = 0; - for(auto &ss : n.split(':')) - { - ++count; - } - CHECK_EQ(count, 0); - } - - { - S const n("0123456"); - { - auto spl = n.split(':'); - auto beg = spl.begin(); - auto end = spl.end(); - CHECK_EQ(beg->size(), n.size()); - CHECK_EQ(end->size(), 0); - } - typename S::size_type count = 0; - for(auto &ss : n.split(':')) - { - switch(count) - { - case 0: - CHECK_EQ(ss.size(), n.size()); - CHECK_EQ(ss.empty(), false); - break; - } - ++count; - } - CHECK_EQ(count, 1); - } - - { - S const n("foo:bar"); - typename S::size_type count = 0; - for(auto &ss : n.split(':')) - { - switch(count) - { - case 0: - CHECK_EQ(ss.size(), 3); - CHECK_EQ(ss.empty(), false); - CHECK_EQ(ss, "foo"); - break; - case 1: - CHECK_EQ(ss.size(), 3); - CHECK_EQ(ss.empty(), false); - CHECK_EQ(ss, "bar"); - break; - } - ++count; - } - CHECK_EQ(count, 2); - } - - { - S const n("0123456:"); - typename S::size_type count = 0; - for(auto &ss : n.split(':')) - { - switch(count) - { - case 0: - CHECK_EQ(ss.size(), n.size()-1); - CHECK_EQ(ss.empty(), false); - break; - case 1: - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.empty(), true); - break; - } - ++count; - } - CHECK_EQ(count, 2); - } - - { - S const n(":0123456:"); - typename S::size_type count = 0; - for(auto &ss : n.split(':')) - { - switch(count) - { - case 0: - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.empty(), true); - break; - case 1: - CHECK_EQ(ss.size(), n.size()-2); - CHECK_EQ(ss.empty(), false); - break; - case 2: - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.empty(), true); - break; - } - ++count; - } - CHECK_EQ(count, 3); - } - - { - S const n(":"); - typename S::size_type count = 0; - for(auto &ss : n.split(':')) - { - switch(count) - { - case 0: - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.empty(), true); - break; - case 1: - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.empty(), true); - break; - } - ++count; - } - CHECK_EQ(count, 2); - } - - { - S const n("01:23:45:67"); - typename S::size_type count = 0; - for(auto &ss : n.split(':')) - { - switch(count) - { - case 0: - CHECK_EQ(ss, "01"); - CHECK_NE(ss, "01:"); - CHECK_NE(ss, ":01:"); - CHECK_NE(ss, ":01"); - break; - case 1: - CHECK_EQ(ss, "23"); - CHECK_NE(ss, "23:"); - CHECK_NE(ss, ":23:"); - CHECK_NE(ss, ":23"); - break; - case 2: - CHECK_EQ(ss, "45"); - CHECK_NE(ss, "45:"); - CHECK_NE(ss, ":45:"); - CHECK_NE(ss, ":45"); - break; - case 3: - CHECK_EQ(ss, "67"); - CHECK_NE(ss, "67:"); - CHECK_NE(ss, ":67:"); - CHECK_NE(ss, ":67"); - break; - } - count++; - } - CHECK_EQ(count, 4); - } - - { - const S n(":01:23:45:67:"); - typename S::size_type count = 0; - for(auto &ss : n.split(':')) - { - switch(count) - { - case 0: - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.empty(), true); - break; - case 1: - CHECK_EQ(ss, "01"); - CHECK_NE(ss, "01:"); - CHECK_NE(ss, ":01:"); - CHECK_NE(ss, ":01"); - break; - case 2: - CHECK_EQ(ss, "23"); - CHECK_NE(ss, "23:"); - CHECK_NE(ss, ":23:"); - CHECK_NE(ss, ":23"); - break; - case 3: - CHECK_EQ(ss, "45"); - CHECK_NE(ss, "45:"); - CHECK_NE(ss, ":45:"); - CHECK_NE(ss, ":45"); - break; - case 4: - CHECK_EQ(ss, "67"); - CHECK_NE(ss, "67:"); - CHECK_NE(ss, ":67:"); - CHECK_NE(ss, ":67"); - break; - case 5: - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.empty(), true); - break; - } - count++; - } - CHECK_EQ(count, 6); - } - - { - const S n("::::01:23:45:67::::"); - typename S::size_type count = 0; - for(auto &ss : n.split(':')) - { - switch(count) - { - case 0: - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.empty(), true); - CHECK_NE(ss, "::"); - break; - case 1: - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.empty(), true); - CHECK_NE(ss, "::"); - break; - case 2: - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.empty(), true); - CHECK_NE(ss, "::"); - break; - case 3: - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.empty(), true); - CHECK_NE(ss, "::"); - break; - case 4: - CHECK_EQ(ss, "01"); - CHECK_NE(ss, "01:"); - CHECK_NE(ss, ":01:"); - CHECK_NE(ss, ":01"); - break; - case 5: - CHECK_EQ(ss, "23"); - CHECK_NE(ss, "23:"); - CHECK_NE(ss, ":23:"); - CHECK_NE(ss, ":23"); - break; - case 6: - CHECK_EQ(ss, "45"); - CHECK_NE(ss, "45:"); - CHECK_NE(ss, ":45:"); - CHECK_NE(ss, ":45"); - break; - case 7: - CHECK_EQ(ss, "67"); - CHECK_NE(ss, "67:"); - CHECK_NE(ss, ":67:"); - CHECK_NE(ss, ":67"); - break; - case 8: - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.empty(), true); - CHECK_NE(ss, "::"); - break; - case 9: - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.empty(), true); - CHECK_NE(ss, "::"); - break; - case 10: - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.empty(), true); - CHECK_NE(ss, "::"); - break; - case 11: - CHECK_EQ(ss.size(), 0); - CHECK_EQ(ss.empty(), true); - CHECK_NE(ss, "::"); - break; - } - count++; - } - CHECK_EQ(count, 12); - } -} - - -//----------------------------------------------------------------------------- -TEST_CASE("substr.copy_from") -{ - char buf[128] = {0}; - substr s = buf; - CHECK_EQ(s.size(), sizeof(buf)-1); - CHECK_NE(s.first(3), "123"); - s.copy_from("123"); - CHECK_EQ(s.first(3), "123"); - CHECK_EQ(s.first(6), "123\0\0\0"); - s.copy_from("+++", 3); - CHECK_EQ(s.first(6), "123+++"); - CHECK_EQ(s.first(9), "123+++\0\0\0"); - s.copy_from("456", 6); - CHECK_EQ(s.first(9), "123+++456"); - CHECK_EQ(s.first(12), "123+++456\0\0\0"); - s.copy_from("***", 3); - CHECK_EQ(s.first(9), "123***456"); - CHECK_EQ(s.first(12), "123***456\0\0\0"); - - // make sure that it's safe to pass source strings that don't fit - // in the remaining destination space - substr ss = s.first(9); - ss.copy_from("987654321", 9); // should be a no-op - CHECK_EQ(s.first(12), "123***456\0\0\0"); - ss.copy_from("987654321", 6); - CHECK_EQ(s.first(12), "123***987\0\0\0"); - ss.copy_from("987654321", 3); - CHECK_EQ(s.first(12), "123987654\0\0\0"); - ss.first(3).copy_from("987654321"); - CHECK_EQ(s.first(12), "987987654\0\0\0"); -} - - -//----------------------------------------------------------------------------- -void do_test_reverse(substr s, csubstr orig, csubstr expected) -{ - CHECK_EQ(s, orig); - s.reverse(); - CHECK_EQ(s, expected); - s.reverse(); - CHECK_EQ(s, orig); - // - CHECK_EQ(s, orig); - s.reverse_sub(0, s.len); - CHECK_EQ(s, expected); - s.reverse_sub(0, s.len); - CHECK_EQ(s, orig); - // - CHECK_EQ(s, orig); - s.reverse_range(0, s.len); - CHECK_EQ(s, expected); - s.reverse_range(0, s.len); - CHECK_EQ(s, orig); -} - -TEST_CASE("substr.reverse") -{ - char buf[] = "0123456789"; - do_test_reverse(buf, "0123456789", "9876543210"); - do_test_reverse(buf, "0123456789", "9876543210"); - - // in the middle - substr s = buf; - s.sub(2, 2).reverse(); - CHECK_EQ(s, "0132456789"); - s.sub(2, 2).reverse(); - CHECK_EQ(s, "0123456789"); - - s.sub(4, 2).reverse(); - CHECK_EQ(s, "0123546789"); - s.sub(4, 2).reverse(); - CHECK_EQ(s, "0123456789"); - - // at the beginning - s.first(3).reverse(); - CHECK_EQ(s, "2103456789"); - s.first(3).reverse(); - CHECK_EQ(s, "0123456789"); - - // at the end - s.last(3).reverse(); - CHECK_EQ(s, "0123456987"); - s.last(3).reverse(); - CHECK_EQ(s, "0123456789"); -} - - -TEST_CASE("substr.reverse_sub") -{ - char buf[] = "0123456789"; - substr s = buf; - - s.reverse_sub(0, s.len); - CHECK_EQ(s, "9876543210"); - s.reverse_sub(0, s.len); - CHECK_EQ(s, "0123456789"); - - s.reverse_sub(0, 0); - CHECK_EQ(s, "0123456789"); - s.reverse_sub(s.len, 0); - CHECK_EQ(s, "0123456789"); - - s.reverse_sub(1, 3); - CHECK_EQ(s, "0321456789"); - s.reverse_sub(1, 3); - CHECK_EQ(s, "0123456789"); -} - -TEST_CASE("substr.reverse_range") -{ - char buf[] = "0123456789"; - substr s = buf; - - s.reverse_range(0, s.len); - CHECK_EQ(s, "9876543210"); - s.reverse_range(0, s.len); - CHECK_EQ(s, "0123456789"); - - s.reverse_range(0, 0); - CHECK_EQ(s, "0123456789"); - s.reverse_range(s.len, s.len); - CHECK_EQ(s, "0123456789"); - - s.reverse_range(1, 3); - CHECK_EQ(s, "0213456789"); - s.reverse_range(1, 3); - CHECK_EQ(s, "0123456789"); -} - - -//----------------------------------------------------------------------------- -TEST_CASE("substr.erase") -{ - char buf[] = "0123456789"; - - substr s = buf; - CHECK_EQ(s.len, s.size()); - CHECK_EQ(s.len, 10); - CHECK_EQ(s, "0123456789"); - - substr ss = s.first(6); - CHECK_EQ(ss.len, 6); - for(size_t i = 0; i <= ss.len; ++i) - { - ss.erase(i, 0); // must be a no-op - CHECK_EQ(s, "0123456789"); - ss.erase_range(i, i); // must be a no-op - CHECK_EQ(s, "0123456789"); - ss.erase(ss.len-i, i); // must be a no-op - CHECK_EQ(s, "0123456789"); - } - - substr r; - ss = ss.erase(0, 1); - CHECK_EQ(ss.len, 5); - CHECK_EQ(ss, "12345"); - CHECK_EQ(s, "1234556789"); - ss = ss.erase(0, 2); - CHECK_EQ(ss.len, 3); - CHECK_EQ(ss, "345"); - CHECK_EQ(s, "3454556789"); - - csubstr s55 = s.sub(4, 2); - ss = s.erase(s55); - CHECK_EQ(s, "3454678989"); -} - - -//----------------------------------------------------------------------------- -TEST_CASE("substr.replace") -{ - char buf[] = "0.1.2.3.4.5.6.7.8.9"; - - substr s = buf; - - auto ret = s.replace('+', '.'); - CHECK_EQ(ret, 0); - - ret = s.replace('.', '.', s.len); - CHECK_EQ(s, "0.1.2.3.4.5.6.7.8.9"); - CHECK_EQ(ret, 0); - ret = s.replace('.', '.'); - CHECK_EQ(ret, 9); - CHECK_EQ(s, "0.1.2.3.4.5.6.7.8.9"); - - ret = s.replace('.', '+', s.len); - CHECK_EQ(s, "0.1.2.3.4.5.6.7.8.9"); - CHECK_EQ(ret, 0); - ret = s.replace('.', '+'); - CHECK_EQ(ret, 9); - CHECK_EQ(s, "0+1+2+3+4+5+6+7+8+9"); - - ret = s.replace("16", '.', s.len); - CHECK_EQ(s, "0+1+2+3+4+5+6+7+8+9"); - CHECK_EQ(ret, 0); - ret = s.replace("16", '.'); - CHECK_EQ(ret, 2); - CHECK_EQ(s, "0+.+2+3+4+5+.+7+8+9"); - ret = s.replace("3+2", '_'); - CHECK_EQ(ret, 11); - CHECK_EQ(s, "0_._____4_5_._7_8_9"); - - // must accept empty string - ret = s.sub(0, 0).replace('0', '1'); - CHECK_EQ(ret, 0); - CHECK_EQ(s, "0_._____4_5_._7_8_9"); - ret = s.sub(0, 0).replace("0", '1'); - CHECK_EQ(ret, 0); - CHECK_EQ(s, "0_._____4_5_._7_8_9"); -} - -TEST_CASE("substr.replace_all") -{ - char buf[] = "0.1.2.3.4.5.6.7.8.9"; - std::string tmp, out("0+1+2+3+4+5+6+7+8+9"); - - // must accept empty string - substr(buf).sub(0, 0).replace_all(to_substr(tmp), "0", "X"); - CHECK_EQ(csubstr(buf), "0.1.2.3.4.5.6.7.8.9"); - - substr r; - auto replall = [&](csubstr pattern, csubstr repl) -> substr { - tmp = out; - csubstr rtmp = to_csubstr(tmp); - out.resize(128); - substr dst = to_substr(out); - size_t sz = rtmp.replace_all(dst, pattern, repl); - CHECK_LE(sz, out.size()); - out.resize(sz); - return dst.first(sz); - }; - r = replall("0+1", "0+++++1"); - // the result must be a view of out - CHECK_FALSE(r.empty()); - CHECK_FALSE(out.empty()); - CHECK_EQ(r.size(), out.size()); - CHECK_EQ(r.front(), out.front()); - CHECK_EQ(r.back(), out.back()); - CHECK_EQ(r, "0+++++1+2+3+4+5+6+7+8+9"); - - r = replall("+", ""); - CHECK_EQ(r, "0123456789"); - - r = replall("+", ""); - CHECK_EQ(r, "0123456789"); // must not change - - r = replall("0123456789", "9876543210"); - CHECK_EQ(r, "9876543210"); - - r = replall("987", "."); - CHECK_EQ(r, ".6543210"); - - r = replall("210", "."); - CHECK_EQ(r, ".6543."); - - r = replall("6543", ":"); - CHECK_EQ(r, ".:."); - - r = replall(".:.", ""); - CHECK_EQ(r, ""); -} - -TEST_CASE("substr.short_integer") -{ - char buf[] = "-"; - CHECK_FALSE(substr(buf).is_integer()); - CHECK_FALSE(csubstr("-").is_integer()); - CHECK_FALSE(csubstr("+").is_integer()); -} - -} // namespace c4 - -#include "c4/libtest/supprwarn_pop.hpp" diff --git a/thirdparty/ryml/ext/c4core/test/test_szconv.cpp b/thirdparty/ryml/ext/c4core/test/test_szconv.cpp deleted file mode 100644 index d54bf48a0..000000000 --- a/thirdparty/ryml/ext/c4core/test/test_szconv.cpp +++ /dev/null @@ -1,166 +0,0 @@ -#ifndef C4CORE_SINGLE_HEADER -#include "c4/szconv.hpp" -#endif - -#include "c4/libtest/supprwarn_push.hpp" -#include "c4/test.hpp" - -#define C4_EXPECT_NARROWER(yes_or_no, ty_out, ty_in) \ - CHECK_UNARY(( yes_or_no (is_narrower_size::value))); - -namespace c4 { - -TEST_CASE("is_narrower_size.signed_types") -{ - C4_EXPECT_NARROWER( ! , int8_t , int8_t ); - C4_EXPECT_NARROWER( , int8_t , int16_t); - C4_EXPECT_NARROWER( , int8_t , int32_t); - C4_EXPECT_NARROWER( , int8_t , int64_t); - C4_EXPECT_NARROWER( , int8_t , uint8_t ); - C4_EXPECT_NARROWER( , int8_t , uint16_t); - C4_EXPECT_NARROWER( , int8_t , uint32_t); - C4_EXPECT_NARROWER( , int8_t , uint64_t); - C4_EXPECT_NARROWER( ! , int16_t , int8_t ); - C4_EXPECT_NARROWER( ! , int16_t , int16_t); - C4_EXPECT_NARROWER( , int16_t , int32_t); - C4_EXPECT_NARROWER( , int16_t , int64_t); - C4_EXPECT_NARROWER( ! , int16_t , uint8_t ); - C4_EXPECT_NARROWER( , int16_t , uint16_t); - C4_EXPECT_NARROWER( , int16_t , uint32_t); - C4_EXPECT_NARROWER( , int16_t , uint64_t); - C4_EXPECT_NARROWER( ! , int32_t , int8_t ); - C4_EXPECT_NARROWER( ! , int32_t , int16_t); - C4_EXPECT_NARROWER( ! , int32_t , int32_t); - C4_EXPECT_NARROWER( , int32_t , int64_t); - C4_EXPECT_NARROWER( ! , int32_t , uint8_t ); - C4_EXPECT_NARROWER( ! , int32_t , uint16_t); - C4_EXPECT_NARROWER( , int32_t , uint32_t); - C4_EXPECT_NARROWER( , int32_t , uint64_t); - C4_EXPECT_NARROWER( ! , int64_t , int8_t ); - C4_EXPECT_NARROWER( ! , int64_t , int16_t); - C4_EXPECT_NARROWER( ! , int64_t , int32_t); - C4_EXPECT_NARROWER( ! , int64_t , int64_t); - C4_EXPECT_NARROWER( ! , int64_t , uint8_t ); - C4_EXPECT_NARROWER( ! , int64_t , uint16_t); - C4_EXPECT_NARROWER( ! , int64_t , uint32_t); - C4_EXPECT_NARROWER( , int64_t , uint64_t); -} - -TEST_CASE("is_narrower_size.unsigned_types") -{ - C4_EXPECT_NARROWER( ! , uint8_t , int8_t ); - C4_EXPECT_NARROWER( , uint8_t , int16_t); - C4_EXPECT_NARROWER( , uint8_t , int32_t); - C4_EXPECT_NARROWER( , uint8_t , int64_t); - C4_EXPECT_NARROWER( ! , uint8_t , uint8_t ); - C4_EXPECT_NARROWER( , uint8_t , uint16_t); - C4_EXPECT_NARROWER( , uint8_t , uint32_t); - C4_EXPECT_NARROWER( , uint8_t , uint64_t); - C4_EXPECT_NARROWER( ! , uint16_t , int8_t ); - C4_EXPECT_NARROWER( ! , uint16_t , int16_t); - C4_EXPECT_NARROWER( , uint16_t , int32_t); - C4_EXPECT_NARROWER( , uint16_t , int64_t); - C4_EXPECT_NARROWER( ! , uint16_t , uint8_t ); - C4_EXPECT_NARROWER( ! , uint16_t , uint16_t); - C4_EXPECT_NARROWER( , uint16_t , uint32_t); - C4_EXPECT_NARROWER( , uint16_t , uint64_t); - C4_EXPECT_NARROWER( ! , uint32_t , int8_t ); - C4_EXPECT_NARROWER( ! , uint32_t , int16_t); - C4_EXPECT_NARROWER( ! , uint32_t , int32_t); - C4_EXPECT_NARROWER( , uint32_t , int64_t); - C4_EXPECT_NARROWER( ! , uint32_t , uint8_t ); - C4_EXPECT_NARROWER( ! , uint32_t , uint16_t); - C4_EXPECT_NARROWER( ! , uint32_t , uint32_t); - C4_EXPECT_NARROWER( , uint32_t , uint64_t); - C4_EXPECT_NARROWER( ! , uint64_t , int8_t ); - C4_EXPECT_NARROWER( ! , uint64_t , int16_t); - C4_EXPECT_NARROWER( ! , uint64_t , int32_t); - C4_EXPECT_NARROWER( ! , uint64_t , int64_t); - C4_EXPECT_NARROWER( ! , uint64_t , uint8_t ); - C4_EXPECT_NARROWER( ! , uint64_t , uint16_t); - C4_EXPECT_NARROWER( ! , uint64_t , uint32_t); - C4_EXPECT_NARROWER( ! , uint64_t , uint64_t); -} - -template -typename std::enable_if::value, void>::type -test_szconv() -{ - // nothing to do here -} - -template -typename std::enable_if< ! std::is_same::value, void>::type -test_szconv() -{ - C4_STATIC_ASSERT(std::is_integral::value); - C4_STATIC_ASSERT(std::is_integral::value); - - const I imax = std::numeric_limits::max(); - const I imin = std::numeric_limits::min(); - const O omax = std::numeric_limits::max(); - const O omin = std::numeric_limits::min(); - - CHECK_EQ(szconv(I(0)), O(0)); - CHECK_EQ(szconv(I(0)), I(0)); - -#if C4_USE_XASSERT - if((uint64_t)omax < (uint64_t)imax) - { - C4_EXPECT_ERROR_OCCURS(); - O out = szconv(imax); - } - else if((uint64_t)omax > (uint64_t)imax) - { - C4_EXPECT_ERROR_OCCURS(); - I out = szconv(omax); - } -#endif -} - -#define DO_TEST_SZCONV(ty) \ - TEST_CASE("szconv." #ty "_to_int8") \ - { \ - test_szconv(); \ - } \ - TEST_CASE("zconv." #ty "_to_uint8") \ - { \ - test_szconv(); \ - } \ - TEST_CASE("zconv." #ty "_to_int16") \ - { \ - test_szconv(); \ - } \ - TEST_CASE("zconv." #ty "_to_uint16") \ - { \ - test_szconv(); \ - } \ - TEST_CASE("zconv." #ty "_to_int32") \ - { \ - test_szconv(); \ - } \ - TEST_CASE("zconv." #ty "_to_uint32") \ - { \ - test_szconv(); \ - } \ - TEST_CASE("zconv." #ty "_to_int64") \ - { \ - test_szconv(); \ - } \ - TEST_CASE("szconv." #ty "_to_uint64") \ - { \ - test_szconv(); \ - } - -DO_TEST_SZCONV(int8) -DO_TEST_SZCONV(uint8) -DO_TEST_SZCONV(int16) -DO_TEST_SZCONV(uint16) -DO_TEST_SZCONV(int32) -DO_TEST_SZCONV(uint32) -DO_TEST_SZCONV(int64) -DO_TEST_SZCONV(uint64) - -} // namespace c4 - -#include "c4/libtest/supprwarn_pop.hpp" diff --git a/thirdparty/ryml/ext/c4core/test/test_type_name.cpp b/thirdparty/ryml/ext/c4core/test/test_type_name.cpp deleted file mode 100644 index 422676bcf..000000000 --- a/thirdparty/ryml/ext/c4core/test/test_type_name.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#include "c4/test.hpp" - -#ifndef C4CORE_SINGLE_HEADER -#include "c4/type_name.hpp" -#endif - -class SomeTypeName {}; -struct SomeStructName {}; - -namespace c4 { - -class SomeTypeNameInsideANamespace {}; -struct SomeStructNameInsideANamespace {}; - -template -cspan cstr(const char (&s)[N]) -{ - cspan o(s, N-1); - return o; -} - -TEST_CASE("type_name.intrinsic_types") -{ - CHECK_EQ(type_name(), cstr("int")); - CHECK_EQ(type_name(), cstr("float")); - CHECK_EQ(type_name(), cstr("double")); -} -TEST_CASE("type_name.classes") -{ - CHECK_EQ(type_name(), cstr("SomeTypeName")); - CHECK_EQ(type_name<::SomeTypeName>(), cstr("SomeTypeName")); -} -TEST_CASE("type_name.structs") -{ - CHECK_EQ(type_name(), cstr("SomeStructName")); - CHECK_EQ(type_name<::SomeStructName>(), cstr("SomeStructName")); -} -TEST_CASE("type_name.inside_namespace") -{ - CHECK_EQ(type_name(), cstr("c4::SomeTypeNameInsideANamespace")); - CHECK_EQ(type_name(), cstr("c4::SomeTypeNameInsideANamespace")); - CHECK_EQ(type_name<::c4::SomeTypeNameInsideANamespace>(), cstr("c4::SomeTypeNameInsideANamespace")); - - CHECK_EQ(type_name(), cstr("c4::SomeStructNameInsideANamespace")); - CHECK_EQ(type_name(), cstr("c4::SomeStructNameInsideANamespace")); - CHECK_EQ(type_name<::c4::SomeStructNameInsideANamespace>(), cstr("c4::SomeStructNameInsideANamespace")); -} - -} // namespace c4 diff --git a/thirdparty/ryml/ext/c4core/test/test_types.cpp b/thirdparty/ryml/ext/c4core/test/test_types.cpp deleted file mode 100644 index 697ce289d..000000000 --- a/thirdparty/ryml/ext/c4core/test/test_types.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef C4CORE_SINGLE_HEADER -#include "c4/config.hpp" -#endif -#include - -#include "c4/libtest/supprwarn_push.hpp" -#include "c4/test.hpp" - -namespace c4 { - -C4_STATIC_ASSERT((std::is_same< fastcref< char >, char >::value)); -C4_STATIC_ASSERT((std::is_same< fastcref< i8 >, i8 >::value)); -C4_STATIC_ASSERT((std::is_same< fastcref< u8 >, u8 >::value)); -C4_STATIC_ASSERT((std::is_same< fastcref< i16 >, i16 >::value)); -C4_STATIC_ASSERT((std::is_same< fastcref< u16 >, u16 >::value)); -C4_STATIC_ASSERT((std::is_same< fastcref< i32 >, i32 >::value)); -C4_STATIC_ASSERT((std::is_same< fastcref< u32 >, u32 >::value)); -C4_STATIC_ASSERT((std::is_same< fastcref< i64 >, i64 >::value)); -C4_STATIC_ASSERT((std::is_same< fastcref< u64 >, u64 >::value)); - -using carr64 = char[64]; -C4_STATIC_ASSERT((std::is_same< fastcref< carr64 >, carr64 const& >::value)); -C4_STATIC_ASSERT((std::is_same< fastcref< std::string >, std::string const& >::value)); - -//----------------------------------------------------------------------------- - -C4_BEGIN_HIDDEN_NAMESPACE -template< class T > struct ufonix { T a; }; -using F = ufonix< uint32_t >; -C4_END_HIDDEN_NAMESPACE - -TEST_CASE("TestSizeStructs.min_remainder") -{ - CHECK_EQ(min_remainder(4, 6), 2); - CHECK_EQ(min_remainder(6, 6), 0); - CHECK_EQ(min_remainder(8, 6), 0); -} - -TEST_CASE("TestSizeStructs.mult_remainder") -{ - CHECK_EQ(mult_remainder(6, 1), 0); - CHECK_EQ(mult_remainder(6, 2), 0); - CHECK_EQ(mult_remainder(6, 3), 0); - CHECK_EQ(mult_remainder(6, 4), 2); - CHECK_EQ(mult_remainder(6, 5), 4); - CHECK_EQ(mult_remainder(6, 6), 0); - CHECK_EQ(mult_remainder(6, 7), 1); -} -TEST_CASE("TestSizeStructs.Padded") -{ - CHECK_EQ(sizeof(F), sizeof(uint32_t)); - CHECK_EQ((sizeof(Padded< F, 0 >)), sizeof(F)); - CHECK_EQ((sizeof(Padded< F, 1 >)), sizeof(F)+1); - CHECK_EQ((sizeof(Padded< F, 2 >)), sizeof(F)+2); - CHECK_EQ((sizeof(Padded< F, 3 >)), sizeof(F)+3); -} -TEST_CASE("TestSizeStructs.MinSized") -{ - CHECK_EQ((sizeof(MinSized< F, 14 >)), 14); - CHECK_EQ((sizeof(MinSized< F, 15 >)), 15); - CHECK_EQ((sizeof(MinSized< F, 16 >)), 16); - CHECK_EQ((sizeof(MinSized< F, 17 >)), 17); -} -TEST_CASE("TestSizeStructs.MultSized") -{ - using G = ufonix< char[8] >; - CHECK_EQ((sizeof(MultSized< G, 7 >)), 14); - CHECK_EQ((sizeof(MultSized< G, 6 >)), 12); - CHECK_EQ((sizeof(MultSized< G, 5 >)), 10); - CHECK_EQ((sizeof(MultSized< G, 4 >)), 8); -} -TEST_CASE("TestSizeStructs.UbufSized") -{ - CHECK_EQ((sizeof(UbufSized>)), 64); - CHECK_EQ((sizeof(UbufSized>)), 64); - CHECK_EQ((sizeof(UbufSized>)), 80); -} - -} // namespace c4 - -#include "c4/libtest/supprwarn_pop.hpp" diff --git a/thirdparty/ryml/ext/c4core/test/test_utf.cpp b/thirdparty/ryml/ext/c4core/test/test_utf.cpp deleted file mode 100644 index ffa4fb338..000000000 --- a/thirdparty/ryml/ext/c4core/test/test_utf.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "c4/test.hpp" -#ifndef C4CORE_SINGLE_HEADER -#include "c4/std/string.hpp" -#include "c4/std/vector.hpp" -#include "c4/format.hpp" -#include "c4/utf.hpp" -#endif - -#include "c4/libtest/supprwarn_push.hpp" - -#include - -namespace c4 { - -struct utft -{ - csubstr code_point; - csubstr character; - uint32_t character_val; - csubstr character_val_hex; -}; -constexpr const utft utf_chars[] = { -#include "./utfchars.inc" -}; - -TEST_CASE("utf.decode_code_point") -{ - size_t i = 0; - char decoded_buf[64]; - for(auto uc : utf_chars) - { - INFO("utfchars[", i, "]: codepoint=", uc.code_point, ' ', - "character=", uc.character.empty() ? csubstr{} : uc.character, ' ', - "val=", uc.character_val_hex, '(', uc.character_val, ')'); - i++; - csubstr cpstr = uc.code_point.sub(2).triml('0'); - if(cpstr.empty()) - continue; - csubstr decoded = decode_code_point(decoded_buf, cpstr); - CHECK_UNARY(uc.code_point.begins_with("U+")); - if(uc.character.empty()) - continue; - CHECK_EQ(decoded.len, uc.character.len); - CHECK_EQ(decoded, uc.character); - } -} - -} // namespace c4 diff --git a/thirdparty/ryml/ext/c4core/test/utfchars.inc b/thirdparty/ryml/ext/c4core/test/utfchars.inc deleted file mode 100644 index b0b23d4c0..000000000 --- a/thirdparty/ryml/ext/c4core/test/utfchars.inc +++ /dev/null @@ -1,6274 +0,0 @@ -// https://www.utf8-chartable.de/unicode-utf8-table.pl -#define _c(cp, wysiwyg, hex) utft{csubstr{#cp}, csubstr{wysiwyg}, UINT32_C(0x##hex), csubstr{"0x" #hex}} -_c(U+0000, "\0", 00), -_c(U+0001, "", 01), -_c(U+0002, "", 02), -_c(U+0003, "", 03), -_c(U+0004, "", 04), -_c(U+0005, "", 05), -_c(U+0006, "", 06), -_c(U+0007, "", 07), -_c(U+0008, "\b", 08), -_c(U+0009, "\t", 09), -_c(U+000A, "\n", 0a), -_c(U+000B, "", 0b), -_c(U+000C, "", 0c), -_c(U+000D, "\r", 0d), -_c(U+000E, "", 0e), -_c(U+000F, "", 0f), -_c(U+0010, "", 10), -_c(U+0011, "", 11), -_c(U+0012, "", 12), -_c(U+0013, "", 13), -_c(U+0014, "", 14), -_c(U+0015, "", 15), -_c(U+0016, "", 16), -_c(U+0017, "", 17), -_c(U+0018, "", 18), -_c(U+0019, "", 19), -_c(U+001A, "", 1a), -_c(U+001B, "", 1b), -_c(U+001C, "", 1c), -_c(U+001D, "", 1d), -_c(U+001E, "", 1e), -_c(U+001F, "", 1f), -_c(U+0020, " ", 20), -_c(U+0021, "!", 21), -_c(U+0022, "\"", 22), -_c(U+0023, "#", 23), -_c(U+0024, "$", 24), -_c(U+0025, "%", 25), -_c(U+0026, "&", 26), -_c(U+0027, "'", 27), -_c(U+0028, "(", 28), -_c(U+0029, ")", 29), -_c(U+002A, "*", 2a), -_c(U+002B, "+", 2b), -_c(U+002C, ",", 2c), -_c(U+002D, "-", 2d), -_c(U+002E, ".", 2e), -_c(U+002F, "/", 2f), -_c(U+0030, "0", 30), -_c(U+0031, "1", 31), -_c(U+0032, "2", 32), -_c(U+0033, "3", 33), -_c(U+0034, "4", 34), -_c(U+0035, "5", 35), -_c(U+0036, "6", 36), -_c(U+0037, "7", 37), -_c(U+0038, "8", 38), -_c(U+0039, "9", 39), -_c(U+003A, ":", 3a), -_c(U+003B, ";", 3b), -_c(U+003C, "<", 3c), -_c(U+003D, "=", 3d), -_c(U+003E, ">", 3e), -_c(U+003F, "?", 3f), -_c(U+0040, "@", 40), -_c(U+0041, "A", 41), -_c(U+0042, "B", 42), -_c(U+0043, "C", 43), -_c(U+0044, "D", 44), -_c(U+0045, "E", 45), -_c(U+0046, "F", 46), -_c(U+0047, "G", 47), -_c(U+0048, "H", 48), -_c(U+0049, "I", 49), -_c(U+004A, "J", 4a), -_c(U+004B, "K", 4b), -_c(U+004C, "L", 4c), -_c(U+004D, "M", 4d), -_c(U+004E, "N", 4e), -_c(U+004F, "O", 4f), -_c(U+0050, "P", 50), -_c(U+0051, "Q", 51), -_c(U+0052, "R", 52), -_c(U+0053, "S", 53), -_c(U+0054, "T", 54), -_c(U+0055, "U", 55), -_c(U+0056, "V", 56), -_c(U+0057, "W", 57), -_c(U+0058, "X", 58), -_c(U+0059, "Y", 59), -_c(U+005A, "Z", 5a), -_c(U+005B, "[", 5b), -_c(U+005C, "\\", 5c), -_c(U+005D, "]", 5d), -_c(U+005E, "^", 5e), -_c(U+005F, "_", 5f), -_c(U+0060, "`", 60), -_c(U+0061, "a", 61), -_c(U+0062, "b", 62), -_c(U+0063, "c", 63), -_c(U+0064, "d", 64), -_c(U+0065, "e", 65), -_c(U+0066, "f", 66), -_c(U+0067, "g", 67), -_c(U+0068, "h", 68), -_c(U+0069, "i", 69), -_c(U+006A, "j", 6a), -_c(U+006B, "k", 6b), -_c(U+006C, "l", 6c), -_c(U+006D, "m", 6d), -_c(U+006E, "n", 6e), -_c(U+006F, "o", 6f), -_c(U+0070, "p", 70), -_c(U+0071, "q", 71), -_c(U+0072, "r", 72), -_c(U+0073, "s", 73), -_c(U+0074, "t", 74), -_c(U+0075, "u", 75), -_c(U+0076, "v", 76), -_c(U+0077, "w", 77), -_c(U+0078, "x", 78), -_c(U+0079, "y", 79), -_c(U+007A, "z", 7a), -_c(U+007B, "", 7b), -_c(U+007C, "|", 7c), -_c(U+007D, "}", 7d), -_c(U+007E, "~", 7e), -_c(U+007F, "", 7f), // del -_c(U+0080, "", c280), -_c(U+0081, "", c281), -_c(U+0082, "", c282), -_c(U+0083, "", c283), -_c(U+0084, "", c284), -_c(U+0085, "", c285), -_c(U+0086, "", c286), -_c(U+0087, "", c287), -_c(U+0088, "", c288), -_c(U+0089, "", c289), -_c(U+008A, "", c28a), -_c(U+008B, "", c28b), -_c(U+008C, "", c28c), -_c(U+008D, "", c28d), -_c(U+008E, "", c28e), -_c(U+008F, "", c28f), -_c(U+0090, "", c290), -_c(U+0091, "", c291), -_c(U+0092, "", c292), -_c(U+0093, "", c293), -_c(U+0094, "", c294), -_c(U+0095, "", c295), -_c(U+0096, "", c296), -_c(U+0097, "", c297), -_c(U+0098, "", c298), -_c(U+0099, "", c299), -_c(U+009A, "", c29a), -_c(U+009B, "", c29b), -_c(U+009C, "", c29c), -_c(U+009D, "", c29d), -_c(U+009E, "", c29e), -_c(U+009F, "", c29f), -_c(U+00A0, "", c2a0), -_c(U+00A1, "¡", c2a1), -_c(U+00A2, "¢", c2a2), -_c(U+00A3, "£", c2a3), -_c(U+00A4, "¤", c2a4), -_c(U+00A5, "¥", c2a5), -_c(U+00A6, "¦", c2a6), -_c(U+00A7, "§", c2a7), -_c(U+00A8, "¨", c2a8), -_c(U+00A9, "©", c2a9), -_c(U+00AA, "ª", c2aa), -_c(U+00AB, "«", c2ab), -_c(U+00AC, "¬", c2ac), -_c(U+00AD, "­", c2ad), -_c(U+00AE, "®", c2ae), -_c(U+00AF, "¯", c2af), -_c(U+00B0, "°", c2b0), -_c(U+00B1, "±", c2b1), -_c(U+00B2, "²", c2b2), -_c(U+00B3, "³", c2b3), -_c(U+00B4, "´", c2b4), -_c(U+00B5, "µ", c2b5), -_c(U+00B6, "¶", c2b6), -_c(U+00B7, "·", c2b7), -_c(U+00B8, "¸", c2b8), -_c(U+00B9, "¹", c2b9), -_c(U+00BA, "º", c2ba), -_c(U+00BB, "»", c2bb), -_c(U+00BC, "¼", c2bc), -_c(U+00BD, "½", c2bd), -_c(U+00BE, "¾", c2be), -_c(U+00BF, "¿", c2bf), -_c(U+00C0, "À", c380), -_c(U+00C1, "Á", c381), -_c(U+00C2, "Â", c382), -_c(U+00C3, "Ã", c383), -_c(U+00C4, "Ä", c384), -_c(U+00C5, "Å", c385), -_c(U+00C6, "Æ", c386), -_c(U+00C7, "Ç", c387), -_c(U+00C8, "È", c388), -_c(U+00C9, "É", c389), -_c(U+00CA, "Ê", c38a), -_c(U+00CB, "Ë", c38b), -_c(U+00CC, "Ì", c38c), -_c(U+00CD, "Í", c38d), -_c(U+00CE, "Î", c38e), -_c(U+00CF, "Ï", c38f), -_c(U+00D0, "Ð", c390), -_c(U+00D1, "Ñ", c391), -_c(U+00D2, "Ò", c392), -_c(U+00D3, "Ó", c393), -_c(U+00D4, "Ô", c394), -_c(U+00D5, "Õ", c395), -_c(U+00D6, "Ö", c396), -_c(U+00D7, "×", c397), -_c(U+00D8, "Ø", c398), -_c(U+00D9, "Ù", c399), -_c(U+00DA, "Ú", c39a), -_c(U+00DB, "Û", c39b), -_c(U+00DC, "Ü", c39c), -_c(U+00DD, "Ý", c39d), -_c(U+00DE, "Þ", c39e), -_c(U+00DF, "ß", c39f), -_c(U+00E0, "à", c3a0), -_c(U+00E1, "á", c3a1), -_c(U+00E2, "â", c3a2), -_c(U+00E3, "ã", c3a3), -_c(U+00E4, "ä", c3a4), -_c(U+00E5, "å", c3a5), -_c(U+00E6, "æ", c3a6), -_c(U+00E7, "ç", c3a7), -_c(U+00E8, "è", c3a8), -_c(U+00E9, "é", c3a9), -_c(U+00EA, "ê", c3aa), -_c(U+00EB, "ë", c3ab), -_c(U+00EC, "ì", c3ac), -_c(U+00ED, "í", c3ad), -_c(U+00EE, "î", c3ae), -_c(U+00EF, "ï", c3af), -_c(U+00F0, "ð", c3b0), -_c(U+00F1, "ñ", c3b1), -_c(U+00F2, "ò", c3b2), -_c(U+00F3, "ó", c3b3), -_c(U+00F4, "ô", c3b4), -_c(U+00F5, "õ", c3b5), -_c(U+00F6, "ö", c3b6), -_c(U+00F7, "÷", c3b7), -_c(U+00F8, "ø", c3b8), -_c(U+00F9, "ù", c3b9), -_c(U+00FA, "ú", c3ba), -_c(U+00FB, "û", c3bb), -_c(U+00FC, "ü", c3bc), -_c(U+00FD, "ý", c3bd), -_c(U+00FE, "þ", c3be), -_c(U+00FF, "ÿ", c3bf), -_c(U+0100, "Ā", c480), -_c(U+0101, "ā", c481), -_c(U+0102, "Ă", c482), -_c(U+0103, "ă", c483), -_c(U+0104, "Ą", c484), -_c(U+0105, "ą", c485), -_c(U+0106, "Ć", c486), -_c(U+0107, "ć", c487), -_c(U+0108, "Ĉ", c488), -_c(U+0109, "ĉ", c489), -_c(U+010A, "Ċ", c48a), -_c(U+010B, "ċ", c48b), -_c(U+010C, "Č", c48c), -_c(U+010D, "č", c48d), -_c(U+010E, "Ď", c48e), -_c(U+010F, "ď", c48f), -_c(U+0110, "Đ", c490), -_c(U+0111, "đ", c491), -_c(U+0112, "Ē", c492), -_c(U+0113, "ē", c493), -_c(U+0114, "Ĕ", c494), -_c(U+0115, "ĕ", c495), -_c(U+0116, "Ė", c496), -_c(U+0117, "ė", c497), -_c(U+0118, "Ę", c498), -_c(U+0119, "ę", c499), -_c(U+011A, "Ě", c49a), -_c(U+011B, "ě", c49b), -_c(U+011C, "Ĝ", c49c), -_c(U+011D, "ĝ", c49d), -_c(U+011E, "Ğ", c49e), -_c(U+011F, "ğ", c49f), -_c(U+0120, "Ġ", c4a0), -_c(U+0121, "ġ", c4a1), -_c(U+0122, "Ģ", c4a2), -_c(U+0123, "ģ", c4a3), -_c(U+0124, "Ĥ", c4a4), -_c(U+0125, "ĥ", c4a5), -_c(U+0126, "Ħ", c4a6), -_c(U+0127, "ħ", c4a7), -_c(U+0128, "Ĩ", c4a8), -_c(U+0129, "ĩ", c4a9), -_c(U+012A, "Ī", c4aa), -_c(U+012B, "ī", c4ab), -_c(U+012C, "Ĭ", c4ac), -_c(U+012D, "ĭ", c4ad), -_c(U+012E, "Į", c4ae), -_c(U+012F, "į", c4af), -_c(U+0130, "İ", c4b0), -_c(U+0131, "ı", c4b1), -_c(U+0132, "IJ", c4b2), -_c(U+0133, "ij", c4b3), -_c(U+0134, "Ĵ", c4b4), -_c(U+0135, "ĵ", c4b5), -_c(U+0136, "Ķ", c4b6), -_c(U+0137, "ķ", c4b7), -_c(U+0138, "ĸ", c4b8), -_c(U+0139, "Ĺ", c4b9), -_c(U+013A, "ĺ", c4ba), -_c(U+013B, "Ļ", c4bb), -_c(U+013C, "ļ", c4bc), -_c(U+013D, "Ľ", c4bd), -_c(U+013E, "ľ", c4be), -_c(U+013F, "Ŀ", c4bf), -_c(U+0140, "ŀ", c580), -_c(U+0141, "Ł", c581), -_c(U+0142, "ł", c582), -_c(U+0143, "Ń", c583), -_c(U+0144, "ń", c584), -_c(U+0145, "Ņ", c585), -_c(U+0146, "ņ", c586), -_c(U+0147, "Ň", c587), -_c(U+0148, "ň", c588), -_c(U+0149, "ʼn", c589), -_c(U+014A, "Ŋ", c58a), -_c(U+014B, "ŋ", c58b), -_c(U+014C, "Ō", c58c), -_c(U+014D, "ō", c58d), -_c(U+014E, "Ŏ", c58e), -_c(U+014F, "ŏ", c58f), -_c(U+0150, "Ő", c590), -_c(U+0151, "ő", c591), -_c(U+0152, "Œ", c592), -_c(U+0153, "œ", c593), -_c(U+0154, "Ŕ", c594), -_c(U+0155, "ŕ", c595), -_c(U+0156, "Ŗ", c596), -_c(U+0157, "ŗ", c597), -_c(U+0158, "Ř", c598), -_c(U+0159, "ř", c599), -_c(U+015A, "Ś", c59a), -_c(U+015B, "ś", c59b), -_c(U+015C, "Ŝ", c59c), -_c(U+015D, "ŝ", c59d), -_c(U+015E, "Ş", c59e), -_c(U+015F, "ş", c59f), -_c(U+0160, "Š", c5a0), -_c(U+0161, "š", c5a1), -_c(U+0162, "Ţ", c5a2), -_c(U+0163, "ţ", c5a3), -_c(U+0164, "Ť", c5a4), -_c(U+0165, "ť", c5a5), -_c(U+0166, "Ŧ", c5a6), -_c(U+0167, "ŧ", c5a7), -_c(U+0168, "Ũ", c5a8), -_c(U+0169, "ũ", c5a9), -_c(U+016A, "Ū", c5aa), -_c(U+016B, "ū", c5ab), -_c(U+016C, "Ŭ", c5ac), -_c(U+016D, "ŭ", c5ad), -_c(U+016E, "Ů", c5ae), -_c(U+016F, "ů", c5af), -_c(U+0170, "Ű", c5b0), -_c(U+0171, "ű", c5b1), -_c(U+0172, "Ų", c5b2), -_c(U+0173, "ų", c5b3), -_c(U+0174, "Ŵ", c5b4), -_c(U+0175, "ŵ", c5b5), -_c(U+0176, "Ŷ", c5b6), -_c(U+0177, "ŷ", c5b7), -_c(U+0178, "Ÿ", c5b8), -_c(U+0179, "Ź", c5b9), -_c(U+017A, "ź", c5ba), -_c(U+017B, "Ż", c5bb), -_c(U+017C, "ż", c5bc), -_c(U+017D, "Ž", c5bd), -_c(U+017E, "ž", c5be), -_c(U+017F, "ſ", c5bf), -_c(U+0180, "ƀ", c680), -_c(U+0181, "Ɓ", c681), -_c(U+0182, "Ƃ", c682), -_c(U+0183, "ƃ", c683), -_c(U+0184, "Ƅ", c684), -_c(U+0185, "ƅ", c685), -_c(U+0186, "Ɔ", c686), -_c(U+0187, "Ƈ", c687), -_c(U+0188, "ƈ", c688), -_c(U+0189, "Ɖ", c689), -_c(U+018A, "Ɗ", c68a), -_c(U+018B, "Ƌ", c68b), -_c(U+018C, "ƌ", c68c), -_c(U+018D, "ƍ", c68d), -_c(U+018E, "Ǝ", c68e), -_c(U+018F, "Ə", c68f), -_c(U+0190, "Ɛ", c690), -_c(U+0191, "Ƒ", c691), -_c(U+0192, "ƒ", c692), -_c(U+0193, "Ɠ", c693), -_c(U+0194, "Ɣ", c694), -_c(U+0195, "ƕ", c695), -_c(U+0196, "Ɩ", c696), -_c(U+0197, "Ɨ", c697), -_c(U+0198, "Ƙ", c698), -_c(U+0199, "ƙ", c699), -_c(U+019A, "ƚ", c69a), -_c(U+019B, "ƛ", c69b), -_c(U+019C, "Ɯ", c69c), -_c(U+019D, "Ɲ", c69d), -_c(U+019E, "ƞ", c69e), -_c(U+019F, "Ɵ", c69f), -_c(U+01A0, "Ơ", c6a0), -_c(U+01A1, "ơ", c6a1), -_c(U+01A2, "Ƣ", c6a2), -_c(U+01A3, "ƣ", c6a3), -_c(U+01A4, "Ƥ", c6a4), -_c(U+01A5, "ƥ", c6a5), -_c(U+01A6, "Ʀ", c6a6), -_c(U+01A7, "Ƨ", c6a7), -_c(U+01A8, "ƨ", c6a8), -_c(U+01A9, "Ʃ", c6a9), -_c(U+01AA, "ƪ", c6aa), -_c(U+01AB, "ƫ", c6ab), -_c(U+01AC, "Ƭ", c6ac), -_c(U+01AD, "ƭ", c6ad), -_c(U+01AE, "Ʈ", c6ae), -_c(U+01AF, "Ư", c6af), -_c(U+01B0, "ư", c6b0), -_c(U+01B1, "Ʊ", c6b1), -_c(U+01B2, "Ʋ", c6b2), -_c(U+01B3, "Ƴ", c6b3), -_c(U+01B4, "ƴ", c6b4), -_c(U+01B5, "Ƶ", c6b5), -_c(U+01B6, "ƶ", c6b6), -_c(U+01B7, "Ʒ", c6b7), -_c(U+01B8, "Ƹ", c6b8), -_c(U+01B9, "ƹ", c6b9), -_c(U+01BA, "ƺ", c6ba), -_c(U+01BB, "ƻ", c6bb), -_c(U+01BC, "Ƽ", c6bc), -_c(U+01BD, "ƽ", c6bd), -_c(U+01BE, "ƾ", c6be), -_c(U+01BF, "ƿ", c6bf), -_c(U+01C0, "ǀ", c780), -_c(U+01C1, "ǁ", c781), -_c(U+01C2, "ǂ", c782), -_c(U+01C3, "ǃ", c783), -_c(U+01C4, "DŽ", c784), -_c(U+01C5, "Dž", c785), -_c(U+01C6, "dž", c786), -_c(U+01C7, "LJ", c787), -_c(U+01C8, "Lj", c788), -_c(U+01C9, "lj", c789), -_c(U+01CA, "NJ", c78a), -_c(U+01CB, "Nj", c78b), -_c(U+01CC, "nj", c78c), -_c(U+01CD, "Ǎ", c78d), -_c(U+01CE, "ǎ", c78e), -_c(U+01CF, "Ǐ", c78f), -_c(U+01D0, "ǐ", c790), -_c(U+01D1, "Ǒ", c791), -_c(U+01D2, "ǒ", c792), -_c(U+01D3, "Ǔ", c793), -_c(U+01D4, "ǔ", c794), -_c(U+01D5, "Ǖ", c795), -_c(U+01D6, "ǖ", c796), -_c(U+01D7, "Ǘ", c797), -_c(U+01D8, "ǘ", c798), -_c(U+01D9, "Ǚ", c799), -_c(U+01DA, "ǚ", c79a), -_c(U+01DB, "Ǜ", c79b), -_c(U+01DC, "ǜ", c79c), -_c(U+01DD, "ǝ", c79d), -_c(U+01DE, "Ǟ", c79e), -_c(U+01DF, "ǟ", c79f), -_c(U+01E0, "Ǡ", c7a0), -_c(U+01E1, "ǡ", c7a1), -_c(U+01E2, "Ǣ", c7a2), -_c(U+01E3, "ǣ", c7a3), -_c(U+01E4, "Ǥ", c7a4), -_c(U+01E5, "ǥ", c7a5), -_c(U+01E6, "Ǧ", c7a6), -_c(U+01E7, "ǧ", c7a7), -_c(U+01E8, "Ǩ", c7a8), -_c(U+01E9, "ǩ", c7a9), -_c(U+01EA, "Ǫ", c7aa), -_c(U+01EB, "ǫ", c7ab), -_c(U+01EC, "Ǭ", c7ac), -_c(U+01ED, "ǭ", c7ad), -_c(U+01EE, "Ǯ", c7ae), -_c(U+01EF, "ǯ", c7af), -_c(U+01F0, "ǰ", c7b0), -_c(U+01F1, "DZ", c7b1), -_c(U+01F2, "Dz", c7b2), -_c(U+01F3, "dz", c7b3), -_c(U+01F4, "Ǵ", c7b4), -_c(U+01F5, "ǵ", c7b5), -_c(U+01F6, "Ƕ", c7b6), -_c(U+01F7, "Ƿ", c7b7), -_c(U+01F8, "Ǹ", c7b8), -_c(U+01F9, "ǹ", c7b9), -_c(U+01FA, "Ǻ", c7ba), -_c(U+01FB, "ǻ", c7bb), -_c(U+01FC, "Ǽ", c7bc), -_c(U+01FD, "ǽ", c7bd), -_c(U+01FE, "Ǿ", c7be), -_c(U+01FF, "ǿ", c7bf), -_c(U+0200, "Ȁ", c880), -_c(U+0201, "ȁ", c881), -_c(U+0202, "Ȃ", c882), -_c(U+0203, "ȃ", c883), -_c(U+0204, "Ȅ", c884), -_c(U+0205, "ȅ", c885), -_c(U+0206, "Ȇ", c886), -_c(U+0207, "ȇ", c887), -_c(U+0208, "Ȉ", c888), -_c(U+0209, "ȉ", c889), -_c(U+020A, "Ȋ", c88a), -_c(U+020B, "ȋ", c88b), -_c(U+020C, "Ȍ", c88c), -_c(U+020D, "ȍ", c88d), -_c(U+020E, "Ȏ", c88e), -_c(U+020F, "ȏ", c88f), -_c(U+0210, "Ȑ", c890), -_c(U+0211, "ȑ", c891), -_c(U+0212, "Ȓ", c892), -_c(U+0213, "ȓ", c893), -_c(U+0214, "Ȕ", c894), -_c(U+0215, "ȕ", c895), -_c(U+0216, "Ȗ", c896), -_c(U+0217, "ȗ", c897), -_c(U+0218, "Ș", c898), -_c(U+0219, "ș", c899), -_c(U+021A, "Ț", c89a), -_c(U+021B, "ț", c89b), -_c(U+021C, "Ȝ", c89c), -_c(U+021D, "ȝ", c89d), -_c(U+021E, "Ȟ", c89e), -_c(U+021F, "ȟ", c89f), -_c(U+0220, "Ƞ", c8a0), -_c(U+0221, "ȡ", c8a1), -_c(U+0222, "Ȣ", c8a2), -_c(U+0223, "ȣ", c8a3), -_c(U+0224, "Ȥ", c8a4), -_c(U+0225, "ȥ", c8a5), -_c(U+0226, "Ȧ", c8a6), -_c(U+0227, "ȧ", c8a7), -_c(U+0228, "Ȩ", c8a8), -_c(U+0229, "ȩ", c8a9), -_c(U+022A, "Ȫ", c8aa), -_c(U+022B, "ȫ", c8ab), -_c(U+022C, "Ȭ", c8ac), -_c(U+022D, "ȭ", c8ad), -_c(U+022E, "Ȯ", c8ae), -_c(U+022F, "ȯ", c8af), -_c(U+0230, "Ȱ", c8b0), -_c(U+0231, "ȱ", c8b1), -_c(U+0232, "Ȳ", c8b2), -_c(U+0233, "ȳ", c8b3), -_c(U+0234, "ȴ", c8b4), -_c(U+0235, "ȵ", c8b5), -_c(U+0236, "ȶ", c8b6), -_c(U+0237, "ȷ", c8b7), -_c(U+0238, "ȸ", c8b8), -_c(U+0239, "ȹ", c8b9), -_c(U+023A, "Ⱥ", c8ba), -_c(U+023B, "Ȼ", c8bb), -_c(U+023C, "ȼ", c8bc), -_c(U+023D, "Ƚ", c8bd), -_c(U+023E, "Ⱦ", c8be), -_c(U+023F, "ȿ", c8bf), -_c(U+0240, "ɀ", c980), -_c(U+0241, "Ɂ", c981), -_c(U+0242, "ɂ", c982), -_c(U+0243, "Ƀ", c983), -_c(U+0244, "Ʉ", c984), -_c(U+0245, "Ʌ", c985), -_c(U+0246, "Ɇ", c986), -_c(U+0247, "ɇ", c987), -_c(U+0248, "Ɉ", c988), -_c(U+0249, "ɉ", c989), -_c(U+024A, "Ɋ", c98a), -_c(U+024B, "ɋ", c98b), -_c(U+024C, "Ɍ", c98c), -_c(U+024D, "ɍ", c98d), -_c(U+024E, "Ɏ", c98e), -_c(U+024F, "ɏ", c98f), -_c(U+0250, "ɐ", c990), -_c(U+0251, "ɑ", c991), -_c(U+0252, "ɒ", c992), -_c(U+0253, "ɓ", c993), -_c(U+0254, "ɔ", c994), -_c(U+0255, "ɕ", c995), -_c(U+0256, "ɖ", c996), -_c(U+0257, "ɗ", c997), -_c(U+0258, "ɘ", c998), -_c(U+0259, "ə", c999), -_c(U+025A, "ɚ", c99a), -_c(U+025B, "ɛ", c99b), -_c(U+025C, "ɜ", c99c), -_c(U+025D, "ɝ", c99d), -_c(U+025E, "ɞ", c99e), -_c(U+025F, "ɟ", c99f), -_c(U+0260, "ɠ", c9a0), -_c(U+0261, "ɡ", c9a1), -_c(U+0262, "ɢ", c9a2), -_c(U+0263, "ɣ", c9a3), -_c(U+0264, "ɤ", c9a4), -_c(U+0265, "ɥ", c9a5), -_c(U+0266, "ɦ", c9a6), -_c(U+0267, "ɧ", c9a7), -_c(U+0268, "ɨ", c9a8), -_c(U+0269, "ɩ", c9a9), -_c(U+026A, "ɪ", c9aa), -_c(U+026B, "ɫ", c9ab), -_c(U+026C, "ɬ", c9ac), -_c(U+026D, "ɭ", c9ad), -_c(U+026E, "ɮ", c9ae), -_c(U+026F, "ɯ", c9af), -_c(U+0270, "ɰ", c9b0), -_c(U+0271, "ɱ", c9b1), -_c(U+0272, "ɲ", c9b2), -_c(U+0273, "ɳ", c9b3), -_c(U+0274, "ɴ", c9b4), -_c(U+0275, "ɵ", c9b5), -_c(U+0276, "ɶ", c9b6), -_c(U+0277, "ɷ", c9b7), -_c(U+0278, "ɸ", c9b8), -_c(U+0279, "ɹ", c9b9), -_c(U+027A, "ɺ", c9ba), -_c(U+027B, "ɻ", c9bb), -_c(U+027C, "ɼ", c9bc), -_c(U+027D, "ɽ", c9bd), -_c(U+027E, "ɾ", c9be), -_c(U+027F, "ɿ", c9bf), -_c(U+0280, "ʀ", ca80), -_c(U+0281, "ʁ", ca81), -_c(U+0282, "ʂ", ca82), -_c(U+0283, "ʃ", ca83), -_c(U+0284, "ʄ", ca84), -_c(U+0285, "ʅ", ca85), -_c(U+0286, "ʆ", ca86), -_c(U+0287, "ʇ", ca87), -_c(U+0288, "ʈ", ca88), -_c(U+0289, "ʉ", ca89), -_c(U+028A, "ʊ", ca8a), -_c(U+028B, "ʋ", ca8b), -_c(U+028C, "ʌ", ca8c), -_c(U+028D, "ʍ", ca8d), -_c(U+028E, "ʎ", ca8e), -_c(U+028F, "ʏ", ca8f), -_c(U+0290, "ʐ", ca90), -_c(U+0291, "ʑ", ca91), -_c(U+0292, "ʒ", ca92), -_c(U+0293, "ʓ", ca93), -_c(U+0294, "ʔ", ca94), -_c(U+0295, "ʕ", ca95), -_c(U+0296, "ʖ", ca96), -_c(U+0297, "ʗ", ca97), -_c(U+0298, "ʘ", ca98), -_c(U+0299, "ʙ", ca99), -_c(U+029A, "ʚ", ca9a), -_c(U+029B, "ʛ", ca9b), -_c(U+029C, "ʜ", ca9c), -_c(U+029D, "ʝ", ca9d), -_c(U+029E, "ʞ", ca9e), -_c(U+029F, "ʟ", ca9f), -_c(U+02A0, "ʠ", caa0), -_c(U+02A1, "ʡ", caa1), -_c(U+02A2, "ʢ", caa2), -_c(U+02A3, "ʣ", caa3), -_c(U+02A4, "ʤ", caa4), -_c(U+02A5, "ʥ", caa5), -_c(U+02A6, "ʦ", caa6), -_c(U+02A7, "ʧ", caa7), -_c(U+02A8, "ʨ", caa8), -_c(U+02A9, "ʩ", caa9), -_c(U+02AA, "ʪ", caaa), -_c(U+02AB, "ʫ", caab), -_c(U+02AC, "ʬ", caac), -_c(U+02AD, "ʭ", caad), -_c(U+02AE, "ʮ", caae), -_c(U+02AF, "ʯ", caaf), -_c(U+02B0, "ʰ", cab0), -_c(U+02B1, "ʱ", cab1), -_c(U+02B2, "ʲ", cab2), -_c(U+02B3, "ʳ", cab3), -_c(U+02B4, "ʴ", cab4), -_c(U+02B5, "ʵ", cab5), -_c(U+02B6, "ʶ", cab6), -_c(U+02B7, "ʷ", cab7), -_c(U+02B8, "ʸ", cab8), -_c(U+02B9, "ʹ", cab9), -_c(U+02BA, "ʺ", caba), -_c(U+02BB, "ʻ", cabb), -_c(U+02BC, "ʼ", cabc), -_c(U+02BD, "ʽ", cabd), -_c(U+02BE, "ʾ", cabe), -_c(U+02BF, "ʿ", cabf), -_c(U+02C0, "ˀ", cb80), -_c(U+02C1, "ˁ", cb81), -_c(U+02C2, "˂", cb82), -_c(U+02C3, "˃", cb83), -_c(U+02C4, "˄", cb84), -_c(U+02C5, "˅", cb85), -_c(U+02C6, "ˆ", cb86), -_c(U+02C7, "ˇ", cb87), -_c(U+02C8, "ˈ", cb88), -_c(U+02C9, "ˉ", cb89), -_c(U+02CA, "ˊ", cb8a), -_c(U+02CB, "ˋ", cb8b), -_c(U+02CC, "ˌ", cb8c), -_c(U+02CD, "ˍ", cb8d), -_c(U+02CE, "ˎ", cb8e), -_c(U+02CF, "ˏ", cb8f), -_c(U+02D0, "ː", cb90), -_c(U+02D1, "ˑ", cb91), -_c(U+02D2, "˒", cb92), -_c(U+02D3, "˓", cb93), -_c(U+02D4, "˔", cb94), -_c(U+02D5, "˕", cb95), -_c(U+02D6, "˖", cb96), -_c(U+02D7, "˗", cb97), -_c(U+02D8, "˘", cb98), -_c(U+02D9, "˙", cb99), -_c(U+02DA, "˚", cb9a), -_c(U+02DB, "˛", cb9b), -_c(U+02DC, "˜", cb9c), -_c(U+02DD, "˝", cb9d), -_c(U+02DE, "˞", cb9e), -_c(U+02DF, "˟", cb9f), -_c(U+02E0, "ˠ", cba0), -_c(U+02E1, "ˡ", cba1), -_c(U+02E2, "ˢ", cba2), -_c(U+02E3, "ˣ", cba3), -_c(U+02E4, "ˤ", cba4), -_c(U+02E5, "˥", cba5), -_c(U+02E6, "˦", cba6), -_c(U+02E7, "˧", cba7), -_c(U+02E8, "˨", cba8), -_c(U+02E9, "˩", cba9), -_c(U+02EA, "˪", cbaa), -_c(U+02EB, "˫", cbab), -_c(U+02EC, "ˬ", cbac), -_c(U+02ED, "˭", cbad), -_c(U+02EE, "ˮ", cbae), -_c(U+02EF, "˯", cbaf), -_c(U+02F0, "˰", cbb0), -_c(U+02F1, "˱", cbb1), -_c(U+02F2, "˲", cbb2), -_c(U+02F3, "˳", cbb3), -_c(U+02F4, "˴", cbb4), -_c(U+02F5, "˵", cbb5), -_c(U+02F6, "˶", cbb6), -_c(U+02F7, "˷", cbb7), -_c(U+02F8, "˸", cbb8), -_c(U+02F9, "˹", cbb9), -_c(U+02FA, "˺", cbba), -_c(U+02FB, "˻", cbbb), -_c(U+02FC, "˼", cbbc), -_c(U+02FD, "˽", cbbd), -_c(U+02FE, "˾", cbbe), -//_c(U+02FF, "˿", cbbf), -//_c(U+0300, ̀"̀ ", cc80), -//_c(U+0301, ́" ", cc81), -//_c(U+0302, ̂" ", cc82), -//_c(U+0303, ̃" ", cc83), -//_c(U+0304, ̄" ", cc84), -//_c(U+0305, "̅" , cc85), -//_c(U+0306, ̆" ", cc86), -//_c(U+0307, ̇" ", cc87), -//_c(U+0308, ̈" ", cc88), -//_c(U+0309, ̉" ", cc89), -//_c(U+030A, ̊" ", cc8a), -//_c(U+030B, ̋" ", cc8b), -//_c(U+030C, ̌" ", cc8c), -//_c(U+030D, "̍" , cc8d), -//_c(U+030E, "̎" , cc8e), -//_c(U+030F, ̏" ", cc8f), -//_c(U+0310, "̐" , cc90), -//_c(U+0311, ̑" ", cc91), -//_c(U+0312, ̒" ", cc92), -//_c(U+0313, "̓" , cc93), -//_c(U+0314, "̔" , cc94), -//_c(U+0315, "̕" , cc95), -//_c(U+0316, "̖" , cc96), -//_c(U+0317, "̗" , cc97), -//_c(U+0318, "̘" , cc98), -//_c(U+0319, "̙" , cc99), -//_c(U+031A, "̚" , cc9a), -//_c(U+031B, ̛" ", cc9b), -//_c(U+031C, "̜" , cc9c), -//_c(U+031D, "̝" , cc9d), -//_c(U+031E, "̞" , cc9e), -_c(U+031F, "̟" , cc9f), -_c(U+0320, "̠" , cca0), -_c(U+0321, "̡" , cca1), -_c(U+0322, "̢" , cca2), -//_c(U+0323, ̣" ", cca3), -//_c(U+0324, ̤" ", cca4), -_c(U+0325, "̥" , cca5), -//_c(U+0326, ̦" ", cca6), -//_c(U+0327, ̧" ", cca7), -//_c(U+0328, ̨" ", cca8), -//_c(U+0329, "̩" , cca9), -_c(U+032A, "̪" , ccaa), -_c(U+032B, "̫" , ccab), -_c(U+032C, "̬" , ccac), -_c(U+032D, "̭" , ccad), -//_c(U+032E, ̮" ", ccae), -_c(U+032F, "̯" , ccaf), -_c(U+0330, "̰" , ccb0), -//_c(U+0331, ̱" ", ccb1), -_c(U+0332, "̲" , ccb2), -_c(U+0333, "̳" , ccb3), -_c(U+0334, "̴" , ccb4), -//_c(U+0335, ̵" ", ccb5), -//_c(U+0336, ̶" ", ccb6), -_c(U+0337, "̷" , ccb7), -_c(U+0338, "̸" , ccb8), -_c(U+0339, "̹" , ccb9), -_c(U+033A, "̺" , ccba), -_c(U+033B, "̻" , ccbb), -_c(U+033C, "̼" , ccbc), -_c(U+033D, "̽" , ccbd), -_c(U+033E, "̾" , ccbe), -_c(U+033F, "̿" , ccbf), -_c(U+0340, "̀" , cd80), -_c(U+0341, "́" , cd81), -_c(U+0342, "͂" , cd82), -_c(U+0343, "̓" , cd83), -_c(U+0344, "̈́" , cd84), -_c(U+0345, "ͅ" , cd85), -_c(U+0346, "͆" , cd86), -_c(U+0347, "͇" , cd87), -_c(U+0348, "͈" , cd88), -_c(U+0349, "͉" , cd89), -_c(U+034A, "͊" , cd8a), -_c(U+034B, "͋" , cd8b), -_c(U+034C, "͌" , cd8c), -_c(U+034D, "͍" , cd8d), -_c(U+034E, "͎" , cd8e), -_c(U+034F, "͏" , cd8f), -_c(U+0350, "͐" , cd90), -_c(U+0351, "͑" , cd91), -_c(U+0352, "͒" , cd92), -_c(U+0353, "͓" , cd93), -_c(U+0354, "͔" , cd94), -_c(U+0355, "͕" , cd95), -_c(U+0356, "͖" , cd96), -_c(U+0357, "͗" , cd97), -_c(U+0358, "͘" , cd98), -_c(U+0359, "͙" , cd99), -_c(U+035A, "͚" , cd9a), -_c(U+035B, "͛" , cd9b), -_c(U+035C, "͜" , cd9c), -_c(U+035D, "͝" , cd9d), -_c(U+035E, "͞" , cd9e), -_c(U+035F, "͟" , cd9f), -_c(U+0360, "͠" , cda0), -_c(U+0361, "͡" , cda1), -_c(U+0362, "͢" , cda2), -_c(U+0363, "ͣ" , cda3), -_c(U+0364, "ͤ" , cda4), -_c(U+0365, "ͥ" , cda5), -_c(U+0366, "ͦ" , cda6), -_c(U+0367, "ͧ" , cda7), -_c(U+0368, "ͨ" , cda8), -_c(U+0369, "ͩ" , cda9), -_c(U+036A, "ͪ" , cdaa), -_c(U+036B, "ͫ" , cdab), -_c(U+036C, "ͬ" , cdac), -_c(U+036D, "ͭ" , cdad), -_c(U+036E, "ͮ" , cdae), -_c(U+036F, "ͯ" , cdaf), -_c(U+0370, "Ͱ", cdb0), -_c(U+0371, "ͱ", cdb1), -_c(U+0372, "Ͳ", cdb2), -_c(U+0373, "ͳ", cdb3), -_c(U+0374, "ʹ", cdb4), -_c(U+0375, "͵", cdb5), -_c(U+0376, "Ͷ", cdb6), -_c(U+0377, "ͷ", cdb7), -_c(U+0378, "͸", cdb8), -_c(U+0379, "͹", cdb9), -_c(U+037A, "ͺ", cdba), -_c(U+037B, "ͻ", cdbb), -_c(U+037C, "ͼ", cdbc), -_c(U+037D, "ͽ", cdbd), -_c(U+037E, ";", cdbe), -_c(U+037F, "Ϳ", cdbf), -_c(U+0380, "΀", ce80), -_c(U+0381, "΁", ce81), -_c(U+0382, "΂", ce82), -_c(U+0383, "΃", ce83), -_c(U+0384, "΄", ce84), -_c(U+0385, "΅", ce85), -_c(U+0386, "Ά", ce86), -_c(U+0387, "·", ce87), -_c(U+0388, "Έ", ce88), -_c(U+0389, "Ή", ce89), -_c(U+038A, "Ί", ce8a), -_c(U+038B, "΋", ce8b), -_c(U+038C, "Ό", ce8c), -_c(U+038D, "΍", ce8d), -_c(U+038E, "Ύ", ce8e), -_c(U+038F, "Ώ", ce8f), -_c(U+0390, "ΐ", ce90), -_c(U+0391, "Α", ce91), -_c(U+0392, "Β", ce92), -_c(U+0393, "Γ", ce93), -_c(U+0394, "Δ", ce94), -_c(U+0395, "Ε", ce95), -_c(U+0396, "Ζ", ce96), -_c(U+0397, "Η", ce97), -_c(U+0398, "Θ", ce98), -_c(U+0399, "Ι", ce99), -_c(U+039A, "Κ", ce9a), -_c(U+039B, "Λ", ce9b), -_c(U+039C, "Μ", ce9c), -_c(U+039D, "Ν", ce9d), -_c(U+039E, "Ξ", ce9e), -_c(U+039F, "Ο", ce9f), -_c(U+03A0, "Π", cea0), -_c(U+03A1, "Ρ", cea1), -_c(U+03A2, "΢", cea2), -_c(U+03A3, "Σ", cea3), -_c(U+03A4, "Τ", cea4), -_c(U+03A5, "Υ", cea5), -_c(U+03A6, "Φ", cea6), -_c(U+03A7, "Χ", cea7), -_c(U+03A8, "Ψ", cea8), -_c(U+03A9, "Ω", cea9), -_c(U+03AA, "Ϊ", ceaa), -_c(U+03AB, "Ϋ", ceab), -_c(U+03AC, "ά", ceac), -_c(U+03AD, "έ", cead), -_c(U+03AE, "ή", ceae), -_c(U+03AF, "ί", ceaf), -_c(U+03B0, "ΰ", ceb0), -_c(U+03B1, "α", ceb1), -_c(U+03B2, "β", ceb2), -_c(U+03B3, "γ", ceb3), -_c(U+03B4, "δ", ceb4), -_c(U+03B5, "ε", ceb5), -_c(U+03B6, "ζ", ceb6), -_c(U+03B7, "η", ceb7), -_c(U+03B8, "θ", ceb8), -_c(U+03B9, "ι", ceb9), -_c(U+03BA, "κ", ceba), -_c(U+03BB, "λ", cebb), -_c(U+03BC, "μ", cebc), -_c(U+03BD, "ν", cebd), -_c(U+03BE, "ξ", cebe), -_c(U+03BF, "ο", cebf), -_c(U+03C0, "π", cf80), -_c(U+03C1, "ρ", cf81), -_c(U+03C2, "ς", cf82), -_c(U+03C3, "σ", cf83), -_c(U+03C4, "τ", cf84), -_c(U+03C5, "υ", cf85), -_c(U+03C6, "φ", cf86), -_c(U+03C7, "χ", cf87), -_c(U+03C8, "ψ", cf88), -_c(U+03C9, "ω", cf89), -_c(U+03CA, "ϊ", cf8a), -_c(U+03CB, "ϋ", cf8b), -_c(U+03CC, "ό", cf8c), -_c(U+03CD, "ύ", cf8d), -_c(U+03CE, "ώ", cf8e), -_c(U+03CF, "Ϗ", cf8f), -_c(U+03D0, "ϐ", cf90), -_c(U+03D1, "ϑ", cf91), -_c(U+03D2, "ϒ", cf92), -_c(U+03D3, "ϓ", cf93), -_c(U+03D4, "ϔ", cf94), -_c(U+03D5, "ϕ", cf95), -_c(U+03D6, "ϖ", cf96), -_c(U+03D7, "ϗ", cf97), -_c(U+03D8, "Ϙ", cf98), -_c(U+03D9, "ϙ", cf99), -_c(U+03DA, "Ϛ", cf9a), -_c(U+03DB, "ϛ", cf9b), -_c(U+03DC, "Ϝ", cf9c), -_c(U+03DD, "ϝ", cf9d), -_c(U+03DE, "Ϟ", cf9e), -_c(U+03DF, "ϟ", cf9f), -_c(U+03E0, "Ϡ", cfa0), -_c(U+03E1, "ϡ", cfa1), -_c(U+03E2, "Ϣ", cfa2), -_c(U+03E3, "ϣ", cfa3), -_c(U+03E4, "Ϥ", cfa4), -_c(U+03E5, "ϥ", cfa5), -_c(U+03E6, "Ϧ", cfa6), -_c(U+03E7, "ϧ", cfa7), -_c(U+03E8, "Ϩ", cfa8), -_c(U+03E9, "ϩ", cfa9), -_c(U+03EA, "Ϫ", cfaa), -_c(U+03EB, "ϫ", cfab), -_c(U+03EC, "Ϭ", cfac), -_c(U+03ED, "ϭ", cfad), -_c(U+03EE, "Ϯ", cfae), -_c(U+03EF, "ϯ", cfaf), -_c(U+03F0, "ϰ", cfb0), -_c(U+03F1, "ϱ", cfb1), -_c(U+03F2, "ϲ", cfb2), -_c(U+03F3, "ϳ", cfb3), -_c(U+03F4, "ϴ", cfb4), -_c(U+03F5, "ϵ", cfb5), -_c(U+03F6, "϶", cfb6), -_c(U+03F7, "Ϸ", cfb7), -_c(U+03F8, "ϸ", cfb8), -_c(U+03F9, "Ϲ", cfb9), -_c(U+03FA, "Ϻ", cfba), -_c(U+03FB, "ϻ", cfbb), -_c(U+03FC, "ϼ", cfbc), -_c(U+03FD, "Ͻ", cfbd), -_c(U+03FE, "Ͼ", cfbe), -_c(U+03FF, "Ͽ", cfbf), -_c(U+0400, "Ѐ", d080), -_c(U+0401, "Ё", d081), -_c(U+0402, "Ђ", d082), -_c(U+0403, "Ѓ", d083), -_c(U+0404, "Є", d084), -_c(U+0405, "Ѕ", d085), -_c(U+0406, "І", d086), -_c(U+0407, "Ї", d087), -_c(U+0408, "Ј", d088), -_c(U+0409, "Љ", d089), -_c(U+040A, "Њ", d08a), -_c(U+040B, "Ћ", d08b), -_c(U+040C, "Ќ", d08c), -_c(U+040D, "Ѝ", d08d), -_c(U+040E, "Ў", d08e), -_c(U+040F, "Џ", d08f), -_c(U+0410, "А", d090), -_c(U+0411, "Б", d091), -_c(U+0412, "В", d092), -_c(U+0413, "Г", d093), -_c(U+0414, "Д", d094), -_c(U+0415, "Е", d095), -_c(U+0416, "Ж", d096), -_c(U+0417, "З", d097), -_c(U+0418, "И", d098), -_c(U+0419, "Й", d099), -_c(U+041A, "К", d09a), -_c(U+041B, "Л", d09b), -_c(U+041C, "М", d09c), -_c(U+041D, "Н", d09d), -_c(U+041E, "О", d09e), -_c(U+041F, "П", d09f), -_c(U+0420, "Р", d0a0), -_c(U+0421, "С", d0a1), -_c(U+0422, "Т", d0a2), -_c(U+0423, "У", d0a3), -_c(U+0424, "Ф", d0a4), -_c(U+0425, "Х", d0a5), -_c(U+0426, "Ц", d0a6), -_c(U+0427, "Ч", d0a7), -_c(U+0428, "Ш", d0a8), -_c(U+0429, "Щ", d0a9), -_c(U+042A, "Ъ", d0aa), -_c(U+042B, "Ы", d0ab), -_c(U+042C, "Ь", d0ac), -_c(U+042D, "Э", d0ad), -_c(U+042E, "Ю", d0ae), -_c(U+042F, "Я", d0af), -_c(U+0430, "а", d0b0), -_c(U+0431, "б", d0b1), -_c(U+0432, "в", d0b2), -_c(U+0433, "г", d0b3), -_c(U+0434, "д", d0b4), -_c(U+0435, "е", d0b5), -_c(U+0436, "ж", d0b6), -_c(U+0437, "з", d0b7), -_c(U+0438, "и", d0b8), -_c(U+0439, "й", d0b9), -_c(U+043A, "к", d0ba), -_c(U+043B, "л", d0bb), -_c(U+043C, "м", d0bc), -_c(U+043D, "н", d0bd), -_c(U+043E, "о", d0be), -_c(U+043F, "п", d0bf), -_c(U+0440, "р", d180), -_c(U+0441, "с", d181), -_c(U+0442, "т", d182), -_c(U+0443, "у", d183), -_c(U+0444, "ф", d184), -_c(U+0445, "х", d185), -_c(U+0446, "ц", d186), -_c(U+0447, "ч", d187), -_c(U+0448, "ш", d188), -_c(U+0449, "щ", d189), -_c(U+044A, "ъ", d18a), -_c(U+044B, "ы", d18b), -_c(U+044C, "ь", d18c), -_c(U+044D, "э", d18d), -_c(U+044E, "ю", d18e), -_c(U+044F, "я", d18f), -_c(U+0450, "ѐ", d190), -_c(U+0451, "ё", d191), -_c(U+0452, "ђ", d192), -_c(U+0453, "ѓ", d193), -_c(U+0454, "є", d194), -_c(U+0455, "ѕ", d195), -_c(U+0456, "і", d196), -_c(U+0457, "ї", d197), -_c(U+0458, "ј", d198), -_c(U+0459, "љ", d199), -_c(U+045A, "њ", d19a), -_c(U+045B, "ћ", d19b), -_c(U+045C, "ќ", d19c), -_c(U+045D, "ѝ", d19d), -_c(U+045E, "ў", d19e), -_c(U+045F, "џ", d19f), -_c(U+0460, "Ѡ", d1a0), -_c(U+0461, "ѡ", d1a1), -_c(U+0462, "Ѣ", d1a2), -_c(U+0463, "ѣ", d1a3), -_c(U+0464, "Ѥ", d1a4), -_c(U+0465, "ѥ", d1a5), -_c(U+0466, "Ѧ", d1a6), -_c(U+0467, "ѧ", d1a7), -_c(U+0468, "Ѩ", d1a8), -_c(U+0469, "ѩ", d1a9), -_c(U+046A, "Ѫ", d1aa), -_c(U+046B, "ѫ", d1ab), -_c(U+046C, "Ѭ", d1ac), -_c(U+046D, "ѭ", d1ad), -_c(U+046E, "Ѯ", d1ae), -_c(U+046F, "ѯ", d1af), -_c(U+0470, "Ѱ", d1b0), -_c(U+0471, "ѱ", d1b1), -_c(U+0472, "Ѳ", d1b2), -_c(U+0473, "ѳ", d1b3), -_c(U+0474, "Ѵ", d1b4), -_c(U+0475, "ѵ", d1b5), -_c(U+0476, "Ѷ", d1b6), -_c(U+0477, "ѷ", d1b7), -_c(U+0478, "Ѹ", d1b8), -_c(U+0479, "ѹ", d1b9), -_c(U+047A, "Ѻ", d1ba), -_c(U+047B, "ѻ", d1bb), -_c(U+047C, "Ѽ", d1bc), -_c(U+047D, "ѽ", d1bd), -_c(U+047E, "Ѿ", d1be), -_c(U+047F, "ѿ", d1bf), -_c(U+20A0, "₠", e282a0), -_c(U+20A1, "₡", e282a1), -_c(U+20A2, "₢", e282a2), -_c(U+20A3, "₣", e282a3), -_c(U+20A4, "₤", e282a4), -_c(U+20A5, "₥", e282a5), -_c(U+20A6, "₦", e282a6), -_c(U+20A7, "₧", e282a7), -_c(U+20A8, "₨", e282a8), -_c(U+20A9, "₩", e282a9), -_c(U+20AA, "₪", e282aa), -_c(U+20AB, "₫", e282ab), -_c(U+20AC, "€", e282ac), -_c(U+20AD, "₭", e282ad), -_c(U+20AE, "₮", e282ae), -_c(U+20AF, "₯", e282af), -_c(U+20B0, "₰", e282b0), -_c(U+20B1, "₱", e282b1), -_c(U+20B2, "₲", e282b2), -_c(U+20B3, "₳", e282b3), -_c(U+20B4, "₴", e282b4), -_c(U+20B5, "₵", e282b5), -_c(U+20B6, "₶", e282b6), -_c(U+20B7, "₷", e282b7), -_c(U+20B8, "₸", e282b8), -_c(U+20B9, "₹", e282b9), -_c(U+20BA, "₺", e282ba), -_c(U+20BB, "₻", e282bb), -_c(U+20BC, "₼", e282bc), -_c(U+20BD, "₽", e282bd), -_c(U+20BE, "₾", e282be), -_c(U+20BF, "₿", e282bf), -_c(U+20C0, "⃀", e28380), -_c(U+20C1, "⃁", e28381), -_c(U+20C2, "⃂", e28382), -_c(U+20C3, "⃃", e28383), -_c(U+20C4, "⃄", e28384), -_c(U+20C5, "⃅", e28385), -_c(U+20C6, "⃆", e28386), -_c(U+20C7, "⃇", e28387), -_c(U+20C8, "⃈", e28388), -_c(U+20C9, "⃉", e28389), -_c(U+20CA, "⃊", e2838a), -_c(U+20CB, "⃋", e2838b), -_c(U+20CC, "⃌", e2838c), -_c(U+20CD, "⃍", e2838d), -_c(U+20CE, "⃎", e2838e), -_c(U+20CF, "⃏", e2838f), -_c(U+20D0, "⃐", e28390), -_c(U+20D1, "⃑", e28391), -_c(U+20D2, "⃒", e28392), -_c(U+20D3, "⃓", e28393), -_c(U+20D4, "⃔", e28394), -_c(U+20D5, "⃕", e28395), -_c(U+20D6, "⃖", e28396), -_c(U+20D7, "⃗", e28397), -_c(U+20D8, "⃘", e28398), -_c(U+20D9, "⃙", e28399), -_c(U+20DA, "⃚", e2839a), -_c(U+20DB, "⃛", e2839b), -_c(U+20DC, "⃜", e2839c), -_c(U+20DD, "⃝", e2839d), -_c(U+20DE, "⃞", e2839e), -_c(U+20DF, "⃟", e2839f), -_c(U+20E0, "⃠", e283a0), -_c(U+20E1, "⃡", e283a1), -_c(U+20E2, "⃢", e283a2), -_c(U+20E3, "⃣", e283a3), -_c(U+20E4, "⃤", e283a4), -_c(U+20E5, "⃥", e283a5), -_c(U+20E6, "⃦", e283a6), -_c(U+20E7, "⃧", e283a7), -_c(U+20E8, "⃨", e283a8), -_c(U+20E9, "⃩", e283a9), -_c(U+20EA, "⃪", e283aa), -_c(U+20EB, "⃫", e283ab), -_c(U+20EC, "⃬", e283ac), -_c(U+20ED, "⃭", e283ad), -_c(U+20EE, "⃮", e283ae), -_c(U+20EF, "⃯", e283af), -_c(U+20F0, "⃰", e283b0), -_c(U+20F1, "⃱", e283b1), -_c(U+20F2, "⃲", e283b2), -_c(U+20F3, "⃳", e283b3), -_c(U+20F4, "⃴", e283b4), -_c(U+20F5, "⃵", e283b5), -_c(U+20F6, "⃶", e283b6), -_c(U+20F7, "⃷", e283b7), -_c(U+20F8, "⃸", e283b8), -_c(U+20F9, "⃹", e283b9), -_c(U+20FA, "⃺", e283ba), -_c(U+20FB, "⃻", e283bb), -_c(U+20FC, "⃼", e283bc), -_c(U+20FD, "⃽", e283bd), -_c(U+20FE, "⃾", e283be), -_c(U+20FF, "⃿", e283bf), -_c(U+2100, "℀", e28480), -_c(U+2101, "℁", e28481), -_c(U+2102, "ℂ", e28482), -_c(U+2103, "℃", e28483), -_c(U+2104, "℄", e28484), -_c(U+2105, "℅", e28485), -_c(U+2106, "℆", e28486), -_c(U+2107, "ℇ", e28487), -_c(U+2108, "℈", e28488), -_c(U+2109, "℉", e28489), -_c(U+210A, "ℊ", e2848a), -_c(U+210B, "ℋ", e2848b), -_c(U+210C, "ℌ", e2848c), -_c(U+210D, "ℍ", e2848d), -_c(U+210E, "ℎ", e2848e), -_c(U+210F, "ℏ", e2848f), -_c(U+2110, "ℐ", e28490), -_c(U+2111, "ℑ", e28491), -_c(U+2112, "ℒ", e28492), -_c(U+2113, "ℓ", e28493), -_c(U+2114, "℔", e28494), -_c(U+2115, "ℕ", e28495), -_c(U+2116, "№", e28496), -_c(U+2117, "℗", e28497), -_c(U+2118, "℘", e28498), -_c(U+2119, "ℙ", e28499), -_c(U+211A, "ℚ", e2849a), -_c(U+211B, "ℛ", e2849b), -_c(U+211C, "ℜ", e2849c), -_c(U+211D, "ℝ", e2849d), -_c(U+211E, "℞", e2849e), -_c(U+211F, "℟", e2849f), -_c(U+2120, "℠", e284a0), -_c(U+2121, "℡", e284a1), -_c(U+2122, "™", e284a2), -_c(U+2123, "℣", e284a3), -_c(U+2124, "ℤ", e284a4), -_c(U+2125, "℥", e284a5), -_c(U+2126, "Ω", e284a6), -_c(U+2127, "℧", e284a7), -_c(U+2128, "ℨ", e284a8), -_c(U+2129, "℩", e284a9), -_c(U+212A, "K", e284aa), -_c(U+212B, "Å", e284ab), -_c(U+212C, "ℬ", e284ac), -_c(U+212D, "ℭ", e284ad), -_c(U+212E, "℮", e284ae), -_c(U+212F, "ℯ", e284af), -_c(U+2130, "ℰ", e284b0), -_c(U+2131, "ℱ", e284b1), -_c(U+2132, "Ⅎ", e284b2), -_c(U+2133, "ℳ", e284b3), -_c(U+2134, "ℴ", e284b4), -_c(U+2135, "ℵ", e284b5), -_c(U+2136, "ℶ", e284b6), -_c(U+2137, "ℷ", e284b7), -_c(U+2138, "ℸ", e284b8), -_c(U+2139, "ℹ", e284b9), -_c(U+213A, "℺", e284ba), -_c(U+213B, "℻", e284bb), -_c(U+213C, "ℼ", e284bc), -_c(U+213D, "ℽ", e284bd), -_c(U+213E, "ℾ", e284be), -_c(U+213F, "ℿ", e284bf), -_c(U+2140, "⅀", e28580), -_c(U+2141, "⅁", e28581), -_c(U+2142, "⅂", e28582), -_c(U+2143, "⅃", e28583), -_c(U+2144, "⅄", e28584), -_c(U+2145, "ⅅ", e28585), -_c(U+2146, "ⅆ", e28586), -_c(U+2147, "ⅇ", e28587), -_c(U+2148, "ⅈ", e28588), -_c(U+2149, "ⅉ", e28589), -_c(U+214A, "⅊", e2858a), -_c(U+214B, "⅋", e2858b), -_c(U+214C, "⅌", e2858c), -_c(U+214D, "⅍", e2858d), -_c(U+214E, "ⅎ", e2858e), -_c(U+214F, "⅏", e2858f), -_c(U+2150, "⅐", e28590), -_c(U+2151, "⅑", e28591), -_c(U+2152, "⅒", e28592), -_c(U+2153, "⅓", e28593), -_c(U+2154, "⅔", e28594), -_c(U+2155, "⅕", e28595), -_c(U+2156, "⅖", e28596), -_c(U+2157, "⅗", e28597), -_c(U+2158, "⅘", e28598), -_c(U+2159, "⅙", e28599), -_c(U+215A, "⅚", e2859a), -_c(U+215B, "⅛", e2859b), -_c(U+215C, "⅜", e2859c), -_c(U+215D, "⅝", e2859d), -_c(U+215E, "⅞", e2859e), -_c(U+215F, "⅟", e2859f), -_c(U+2160, "Ⅰ", e285a0), -_c(U+2161, "Ⅱ", e285a1), -_c(U+2162, "Ⅲ", e285a2), -_c(U+2163, "Ⅳ", e285a3), -_c(U+2164, "Ⅴ", e285a4), -_c(U+2165, "Ⅵ", e285a5), -_c(U+2166, "Ⅶ", e285a6), -_c(U+2167, "Ⅷ", e285a7), -_c(U+2168, "Ⅸ", e285a8), -_c(U+2169, "Ⅹ", e285a9), -_c(U+216A, "Ⅺ", e285aa), -_c(U+216B, "Ⅻ", e285ab), -_c(U+216C, "Ⅼ", e285ac), -_c(U+216D, "Ⅽ", e285ad), -_c(U+216E, "Ⅾ", e285ae), -_c(U+216F, "Ⅿ", e285af), -_c(U+2170, "ⅰ", e285b0), -_c(U+2171, "ⅱ", e285b1), -_c(U+2172, "ⅲ", e285b2), -_c(U+2173, "ⅳ", e285b3), -_c(U+2174, "ⅴ", e285b4), -_c(U+2175, "ⅵ", e285b5), -_c(U+2176, "ⅶ", e285b6), -_c(U+2177, "ⅷ", e285b7), -_c(U+2178, "ⅸ", e285b8), -_c(U+2179, "ⅹ", e285b9), -_c(U+217A, "ⅺ", e285ba), -_c(U+217B, "ⅻ", e285bb), -_c(U+217C, "ⅼ", e285bc), -_c(U+217D, "ⅽ", e285bd), -_c(U+217E, "ⅾ", e285be), -_c(U+217F, "ⅿ", e285bf), -_c(U+2180, "ↀ", e28680), -_c(U+2181, "ↁ", e28681), -_c(U+2182, "ↂ", e28682), -_c(U+2183, "Ↄ", e28683), -_c(U+2184, "ↄ", e28684), -_c(U+2185, "ↅ", e28685), -_c(U+2186, "ↆ", e28686), -_c(U+2187, "ↇ", e28687), -_c(U+2188, "ↈ", e28688), -_c(U+2189, "↉", e28689), -_c(U+218A, "↊", e2868a), -_c(U+218B, "↋", e2868b), -_c(U+218C, "↌", e2868c), -_c(U+218D, "↍", e2868d), -_c(U+218E, "↎", e2868e), -_c(U+218F, "↏", e2868f), -_c(U+2190, "←", e28690), -_c(U+2191, "↑", e28691), -_c(U+2192, "→", e28692), -_c(U+2193, "↓", e28693), -_c(U+2194, "↔", e28694), -_c(U+2195, "↕", e28695), -_c(U+2196, "↖", e28696), -_c(U+2197, "↗", e28697), -_c(U+2198, "↘", e28698), -_c(U+2199, "↙", e28699), -_c(U+219A, "↚", e2869a), -_c(U+219B, "↛", e2869b), -_c(U+219C, "↜", e2869c), -_c(U+219D, "↝", e2869d), -_c(U+219E, "↞", e2869e), -_c(U+219F, "↟", e2869f), -_c(U+21A0, "↠", e286a0), -_c(U+21A1, "↡", e286a1), -_c(U+21A2, "↢", e286a2), -_c(U+21A3, "↣", e286a3), -_c(U+21A4, "↤", e286a4), -_c(U+21A5, "↥", e286a5), -_c(U+21A6, "↦", e286a6), -_c(U+21A7, "↧", e286a7), -_c(U+21A8, "↨", e286a8), -_c(U+21A9, "↩", e286a9), -_c(U+21AA, "↪", e286aa), -_c(U+21AB, "↫", e286ab), -_c(U+21AC, "↬", e286ac), -_c(U+21AD, "↭", e286ad), -_c(U+21AE, "↮", e286ae), -_c(U+21AF, "↯", e286af), -_c(U+21B0, "↰", e286b0), -_c(U+21B1, "↱", e286b1), -_c(U+21B2, "↲", e286b2), -_c(U+21B3, "↳", e286b3), -_c(U+21B4, "↴", e286b4), -_c(U+21B5, "↵", e286b5), -_c(U+21B6, "↶", e286b6), -_c(U+21B7, "↷", e286b7), -_c(U+21B8, "↸", e286b8), -_c(U+21B9, "↹", e286b9), -_c(U+21BA, "↺", e286ba), -_c(U+21BB, "↻", e286bb), -_c(U+21BC, "↼", e286bc), -_c(U+21BD, "↽", e286bd), -_c(U+21BE, "↾", e286be), -_c(U+21BF, "↿", e286bf), -_c(U+21C0, "⇀", e28780), -_c(U+21C1, "⇁", e28781), -_c(U+21C2, "⇂", e28782), -_c(U+21C3, "⇃", e28783), -_c(U+21C4, "⇄", e28784), -_c(U+21C5, "⇅", e28785), -_c(U+21C6, "⇆", e28786), -_c(U+21C7, "⇇", e28787), -_c(U+21C8, "⇈", e28788), -_c(U+21C9, "⇉", e28789), -_c(U+21CA, "⇊", e2878a), -_c(U+21CB, "⇋", e2878b), -_c(U+21CC, "⇌", e2878c), -_c(U+21CD, "⇍", e2878d), -_c(U+21CE, "⇎", e2878e), -_c(U+21CF, "⇏", e2878f), -_c(U+21D0, "⇐", e28790), -_c(U+21D1, "⇑", e28791), -_c(U+21D2, "⇒", e28792), -_c(U+21D3, "⇓", e28793), -_c(U+21D4, "⇔", e28794), -_c(U+21D5, "⇕", e28795), -_c(U+21D6, "⇖", e28796), -_c(U+21D7, "⇗", e28797), -_c(U+21D8, "⇘", e28798), -_c(U+21D9, "⇙", e28799), -_c(U+21DA, "⇚", e2879a), -_c(U+21DB, "⇛", e2879b), -_c(U+21DC, "⇜", e2879c), -_c(U+21DD, "⇝", e2879d), -_c(U+21DE, "⇞", e2879e), -_c(U+21DF, "⇟", e2879f), -_c(U+21E0, "⇠", e287a0), -_c(U+21E1, "⇡", e287a1), -_c(U+21E2, "⇢", e287a2), -_c(U+21E3, "⇣", e287a3), -_c(U+21E4, "⇤", e287a4), -_c(U+21E5, "⇥", e287a5), -_c(U+21E6, "⇦", e287a6), -_c(U+21E7, "⇧", e287a7), -_c(U+21E8, "⇨", e287a8), -_c(U+21E9, "⇩", e287a9), -_c(U+21EA, "⇪", e287aa), -_c(U+21EB, "⇫", e287ab), -_c(U+21EC, "⇬", e287ac), -_c(U+21ED, "⇭", e287ad), -_c(U+21EE, "⇮", e287ae), -_c(U+21EF, "⇯", e287af), -_c(U+21F0, "⇰", e287b0), -_c(U+21F1, "⇱", e287b1), -_c(U+21F2, "⇲", e287b2), -_c(U+21F3, "⇳", e287b3), -_c(U+21F4, "⇴", e287b4), -_c(U+21F5, "⇵", e287b5), -_c(U+21F6, "⇶", e287b6), -_c(U+21F7, "⇷", e287b7), -_c(U+21F8, "⇸", e287b8), -_c(U+21F9, "⇹", e287b9), -_c(U+21FA, "⇺", e287ba), -_c(U+21FB, "⇻", e287bb), -_c(U+21FC, "⇼", e287bc), -_c(U+21FD, "⇽", e287bd), -_c(U+21FE, "⇾", e287be), -_c(U+21FF, "⇿", e287bf), -_c(U+2200, "∀", e28880), -_c(U+2201, "∁", e28881), -_c(U+2202, "∂", e28882), -_c(U+2203, "∃", e28883), -_c(U+2204, "∄", e28884), -_c(U+2205, "∅", e28885), -_c(U+2206, "∆", e28886), -_c(U+2207, "∇", e28887), -_c(U+2208, "∈", e28888), -_c(U+2209, "∉", e28889), -_c(U+220A, "∊", e2888a), -_c(U+220B, "∋", e2888b), -_c(U+220C, "∌", e2888c), -_c(U+220D, "∍", e2888d), -_c(U+220E, "∎", e2888e), -_c(U+220F, "∏", e2888f), -_c(U+2210, "∐", e28890), -_c(U+2211, "∑", e28891), -_c(U+2212, "−", e28892), -_c(U+2213, "∓", e28893), -_c(U+2214, "∔", e28894), -_c(U+2215, "∕", e28895), -_c(U+2216, "∖", e28896), -_c(U+2217, "∗", e28897), -_c(U+2218, "∘", e28898), -_c(U+2219, "∙", e28899), -_c(U+221A, "√", e2889a), -_c(U+221B, "∛", e2889b), -_c(U+221C, "∜", e2889c), -_c(U+221D, "∝", e2889d), -_c(U+221E, "∞", e2889e), -_c(U+221F, "∟", e2889f), -_c(U+2220, "∠", e288a0), -_c(U+2221, "∡", e288a1), -_c(U+2222, "∢", e288a2), -_c(U+2223, "∣", e288a3), -_c(U+2224, "∤", e288a4), -_c(U+2225, "∥", e288a5), -_c(U+2226, "∦", e288a6), -_c(U+2227, "∧", e288a7), -_c(U+2228, "∨", e288a8), -_c(U+2229, "∩", e288a9), -_c(U+222A, "∪", e288aa), -_c(U+222B, "∫", e288ab), -_c(U+222C, "∬", e288ac), -_c(U+222D, "∭", e288ad), -_c(U+222E, "∮", e288ae), -_c(U+222F, "∯", e288af), -_c(U+2230, "∰", e288b0), -_c(U+2231, "∱", e288b1), -_c(U+2232, "∲", e288b2), -_c(U+2233, "∳", e288b3), -_c(U+2234, "∴", e288b4), -_c(U+2235, "∵", e288b5), -_c(U+2236, "∶", e288b6), -_c(U+2237, "∷", e288b7), -_c(U+2238, "∸", e288b8), -_c(U+2239, "∹", e288b9), -_c(U+223A, "∺", e288ba), -_c(U+223B, "∻", e288bb), -_c(U+223C, "∼", e288bc), -_c(U+223D, "∽", e288bd), -_c(U+223E, "∾", e288be), -_c(U+223F, "∿", e288bf), -_c(U+2240, "≀", e28980), -_c(U+2241, "≁", e28981), -_c(U+2242, "≂", e28982), -_c(U+2243, "≃", e28983), -_c(U+2244, "≄", e28984), -_c(U+2245, "≅", e28985), -_c(U+2246, "≆", e28986), -_c(U+2247, "≇", e28987), -_c(U+2248, "≈", e28988), -_c(U+2249, "≉", e28989), -_c(U+224A, "≊", e2898a), -_c(U+224B, "≋", e2898b), -_c(U+224C, "≌", e2898c), -_c(U+224D, "≍", e2898d), -_c(U+224E, "≎", e2898e), -_c(U+224F, "≏", e2898f), -_c(U+2250, "≐", e28990), -_c(U+2251, "≑", e28991), -_c(U+2252, "≒", e28992), -_c(U+2253, "≓", e28993), -_c(U+2254, "≔", e28994), -_c(U+2255, "≕", e28995), -_c(U+2256, "≖", e28996), -_c(U+2257, "≗", e28997), -_c(U+2258, "≘", e28998), -_c(U+2259, "≙", e28999), -_c(U+225A, "≚", e2899a), -_c(U+225B, "≛", e2899b), -_c(U+225C, "≜", e2899c), -_c(U+225D, "≝", e2899d), -_c(U+225E, "≞", e2899e), -_c(U+225F, "≟", e2899f), -_c(U+2260, "≠", e289a0), -_c(U+2261, "≡", e289a1), -_c(U+2262, "≢", e289a2), -_c(U+2263, "≣", e289a3), -_c(U+2264, "≤", e289a4), -_c(U+2265, "≥", e289a5), -_c(U+2266, "≦", e289a6), -_c(U+2267, "≧", e289a7), -_c(U+2268, "≨", e289a8), -_c(U+2269, "≩", e289a9), -_c(U+226A, "≪", e289aa), -_c(U+226B, "≫", e289ab), -_c(U+226C, "≬", e289ac), -_c(U+226D, "≭", e289ad), -_c(U+226E, "≮", e289ae), -_c(U+226F, "≯", e289af), -_c(U+2270, "≰", e289b0), -_c(U+2271, "≱", e289b1), -_c(U+2272, "≲", e289b2), -_c(U+2273, "≳", e289b3), -_c(U+2274, "≴", e289b4), -_c(U+2275, "≵", e289b5), -_c(U+2276, "≶", e289b6), -_c(U+2277, "≷", e289b7), -_c(U+2278, "≸", e289b8), -_c(U+2279, "≹", e289b9), -_c(U+227A, "≺", e289ba), -_c(U+227B, "≻", e289bb), -_c(U+227C, "≼", e289bc), -_c(U+227D, "≽", e289bd), -_c(U+227E, "≾", e289be), -_c(U+227F, "≿", e289bf), -_c(U+2280, "⊀", e28a80), -_c(U+2281, "⊁", e28a81), -_c(U+2282, "⊂", e28a82), -_c(U+2283, "⊃", e28a83), -_c(U+2284, "⊄", e28a84), -_c(U+2285, "⊅", e28a85), -_c(U+2286, "⊆", e28a86), -_c(U+2287, "⊇", e28a87), -_c(U+2288, "⊈", e28a88), -_c(U+2289, "⊉", e28a89), -_c(U+228A, "⊊", e28a8a), -_c(U+228B, "⊋", e28a8b), -_c(U+228C, "⊌", e28a8c), -_c(U+228D, "⊍", e28a8d), -_c(U+228E, "⊎", e28a8e), -_c(U+228F, "⊏", e28a8f), -_c(U+2290, "⊐", e28a90), -_c(U+2291, "⊑", e28a91), -_c(U+2292, "⊒", e28a92), -_c(U+2293, "⊓", e28a93), -_c(U+2294, "⊔", e28a94), -_c(U+2295, "⊕", e28a95), -_c(U+2296, "⊖", e28a96), -_c(U+2297, "⊗", e28a97), -_c(U+2298, "⊘", e28a98), -_c(U+2299, "⊙", e28a99), -_c(U+229A, "⊚", e28a9a), -_c(U+229B, "⊛", e28a9b), -_c(U+229C, "⊜", e28a9c), -_c(U+229D, "⊝", e28a9d), -_c(U+229E, "⊞", e28a9e), -_c(U+229F, "⊟", e28a9f), -_c(U+22A0, "⊠", e28aa0), -_c(U+22A1, "⊡", e28aa1), -_c(U+22A2, "⊢", e28aa2), -_c(U+22A3, "⊣", e28aa3), -_c(U+22A4, "⊤", e28aa4), -_c(U+22A5, "⊥", e28aa5), -_c(U+22A6, "⊦", e28aa6), -_c(U+22A7, "⊧", e28aa7), -_c(U+22A8, "⊨", e28aa8), -_c(U+22A9, "⊩", e28aa9), -_c(U+22AA, "⊪", e28aaa), -_c(U+22AB, "⊫", e28aab), -_c(U+22AC, "⊬", e28aac), -_c(U+22AD, "⊭", e28aad), -_c(U+22AE, "⊮", e28aae), -_c(U+22AF, "⊯", e28aaf), -_c(U+22B0, "⊰", e28ab0), -_c(U+22B1, "⊱", e28ab1), -_c(U+22B2, "⊲", e28ab2), -_c(U+22B3, "⊳", e28ab3), -_c(U+22B4, "⊴", e28ab4), -_c(U+22B5, "⊵", e28ab5), -_c(U+22B6, "⊶", e28ab6), -_c(U+22B7, "⊷", e28ab7), -_c(U+22B8, "⊸", e28ab8), -_c(U+22B9, "⊹", e28ab9), -_c(U+22BA, "⊺", e28aba), -_c(U+22BB, "⊻", e28abb), -_c(U+22BC, "⊼", e28abc), -_c(U+22BD, "⊽", e28abd), -_c(U+22BE, "⊾", e28abe), -_c(U+22BF, "⊿", e28abf), -_c(U+22C0, "⋀", e28b80), -_c(U+22C1, "⋁", e28b81), -_c(U+22C2, "⋂", e28b82), -_c(U+22C3, "⋃", e28b83), -_c(U+22C4, "⋄", e28b84), -_c(U+22C5, "⋅", e28b85), -_c(U+22C6, "⋆", e28b86), -_c(U+22C7, "⋇", e28b87), -_c(U+22C8, "⋈", e28b88), -_c(U+22C9, "⋉", e28b89), -_c(U+22CA, "⋊", e28b8a), -_c(U+22CB, "⋋", e28b8b), -_c(U+22CC, "⋌", e28b8c), -_c(U+22CD, "⋍", e28b8d), -_c(U+22CE, "⋎", e28b8e), -_c(U+22CF, "⋏", e28b8f), -_c(U+22D0, "⋐", e28b90), -_c(U+22D1, "⋑", e28b91), -_c(U+22D2, "⋒", e28b92), -_c(U+22D3, "⋓", e28b93), -_c(U+22D4, "⋔", e28b94), -_c(U+22D5, "⋕", e28b95), -_c(U+22D6, "⋖", e28b96), -_c(U+22D7, "⋗", e28b97), -_c(U+22D8, "⋘", e28b98), -_c(U+22D9, "⋙", e28b99), -_c(U+22DA, "⋚", e28b9a), -_c(U+22DB, "⋛", e28b9b), -_c(U+22DC, "⋜", e28b9c), -_c(U+22DD, "⋝", e28b9d), -_c(U+22DE, "⋞", e28b9e), -_c(U+22DF, "⋟", e28b9f), -_c(U+22E0, "⋠", e28ba0), -_c(U+22E1, "⋡", e28ba1), -_c(U+22E2, "⋢", e28ba2), -_c(U+22E3, "⋣", e28ba3), -_c(U+22E4, "⋤", e28ba4), -_c(U+22E5, "⋥", e28ba5), -_c(U+22E6, "⋦", e28ba6), -_c(U+22E7, "⋧", e28ba7), -_c(U+22E8, "⋨", e28ba8), -_c(U+22E9, "⋩", e28ba9), -_c(U+22EA, "⋪", e28baa), -_c(U+22EB, "⋫", e28bab), -_c(U+22EC, "⋬", e28bac), -_c(U+22ED, "⋭", e28bad), -_c(U+22EE, "⋮", e28bae), -_c(U+22EF, "⋯", e28baf), -_c(U+22F0, "⋰", e28bb0), -_c(U+22F1, "⋱", e28bb1), -_c(U+22F2, "⋲", e28bb2), -_c(U+22F3, "⋳", e28bb3), -_c(U+22F4, "⋴", e28bb4), -_c(U+22F5, "⋵", e28bb5), -_c(U+22F6, "⋶", e28bb6), -_c(U+22F7, "⋷", e28bb7), -_c(U+22F8, "⋸", e28bb8), -_c(U+22F9, "⋹", e28bb9), -_c(U+22FA, "⋺", e28bba), -_c(U+22FB, "⋻", e28bbb), -_c(U+22FC, "⋼", e28bbc), -_c(U+22FD, "⋽", e28bbd), -_c(U+22FE, "⋾", e28bbe), -_c(U+22FF, "⋿", e28bbf), -_c(U+2300, "⌀", e28c80), -_c(U+2301, "⌁", e28c81), -_c(U+2302, "⌂", e28c82), -_c(U+2303, "⌃", e28c83), -_c(U+2304, "⌄", e28c84), -_c(U+2305, "⌅", e28c85), -_c(U+2306, "⌆", e28c86), -_c(U+2307, "⌇", e28c87), -_c(U+2308, "⌈", e28c88), -_c(U+2309, "⌉", e28c89), -_c(U+230A, "⌊", e28c8a), -_c(U+230B, "⌋", e28c8b), -_c(U+230C, "⌌", e28c8c), -_c(U+230D, "⌍", e28c8d), -_c(U+230E, "⌎", e28c8e), -_c(U+230F, "⌏", e28c8f), -_c(U+2310, "⌐", e28c90), -_c(U+2311, "⌑", e28c91), -_c(U+2312, "⌒", e28c92), -_c(U+2313, "⌓", e28c93), -_c(U+2314, "⌔", e28c94), -_c(U+2315, "⌕", e28c95), -_c(U+2316, "⌖", e28c96), -_c(U+2317, "⌗", e28c97), -_c(U+2318, "⌘", e28c98), -_c(U+2319, "⌙", e28c99), -_c(U+231A, "⌚", e28c9a), -_c(U+231B, "⌛", e28c9b), -_c(U+231C, "⌜", e28c9c), -_c(U+231D, "⌝", e28c9d), -_c(U+231E, "⌞", e28c9e), -_c(U+231F, "⌟", e28c9f), -_c(U+2320, "⌠", e28ca0), -_c(U+2321, "⌡", e28ca1), -_c(U+2322, "⌢", e28ca2), -_c(U+2323, "⌣", e28ca3), -_c(U+2324, "⌤", e28ca4), -_c(U+2325, "⌥", e28ca5), -_c(U+2326, "⌦", e28ca6), -_c(U+2327, "⌧", e28ca7), -_c(U+2328, "⌨", e28ca8), -_c(U+2329, "〈", e28ca9), -_c(U+232A, "〉", e28caa), -_c(U+232B, "⌫", e28cab), -_c(U+232C, "⌬", e28cac), -_c(U+232D, "⌭", e28cad), -_c(U+232E, "⌮", e28cae), -_c(U+232F, "⌯", e28caf), -_c(U+2330, "⌰", e28cb0), -_c(U+2331, "⌱", e28cb1), -_c(U+2332, "⌲", e28cb2), -_c(U+2333, "⌳", e28cb3), -_c(U+2334, "⌴", e28cb4), -_c(U+2335, "⌵", e28cb5), -_c(U+2336, "⌶", e28cb6), -_c(U+2337, "⌷", e28cb7), -_c(U+2338, "⌸", e28cb8), -_c(U+2339, "⌹", e28cb9), -_c(U+233A, "⌺", e28cba), -_c(U+233B, "⌻", e28cbb), -_c(U+233C, "⌼", e28cbc), -_c(U+233D, "⌽", e28cbd), -_c(U+233E, "⌾", e28cbe), -_c(U+233F, "⌿", e28cbf), -_c(U+2340, "⍀", e28d80), -_c(U+2341, "⍁", e28d81), -_c(U+2342, "⍂", e28d82), -_c(U+2343, "⍃", e28d83), -_c(U+2344, "⍄", e28d84), -_c(U+2345, "⍅", e28d85), -_c(U+2346, "⍆", e28d86), -_c(U+2347, "⍇", e28d87), -_c(U+2348, "⍈", e28d88), -_c(U+2349, "⍉", e28d89), -_c(U+234A, "⍊", e28d8a), -_c(U+234B, "⍋", e28d8b), -_c(U+234C, "⍌", e28d8c), -_c(U+234D, "⍍", e28d8d), -_c(U+234E, "⍎", e28d8e), -_c(U+234F, "⍏", e28d8f), -_c(U+2350, "⍐", e28d90), -_c(U+2351, "⍑", e28d91), -_c(U+2352, "⍒", e28d92), -_c(U+2353, "⍓", e28d93), -_c(U+2354, "⍔", e28d94), -_c(U+2355, "⍕", e28d95), -_c(U+2356, "⍖", e28d96), -_c(U+2357, "⍗", e28d97), -_c(U+2358, "⍘", e28d98), -_c(U+2359, "⍙", e28d99), -_c(U+235A, "⍚", e28d9a), -_c(U+235B, "⍛", e28d9b), -_c(U+235C, "⍜", e28d9c), -_c(U+235D, "⍝", e28d9d), -_c(U+235E, "⍞", e28d9e), -_c(U+235F, "⍟", e28d9f), -_c(U+2360, "⍠", e28da0), -_c(U+2361, "⍡", e28da1), -_c(U+2362, "⍢", e28da2), -_c(U+2363, "⍣", e28da3), -_c(U+2364, "⍤", e28da4), -_c(U+2365, "⍥", e28da5), -_c(U+2366, "⍦", e28da6), -_c(U+2367, "⍧", e28da7), -_c(U+2368, "⍨", e28da8), -_c(U+2369, "⍩", e28da9), -_c(U+236A, "⍪", e28daa), -_c(U+236B, "⍫", e28dab), -_c(U+236C, "⍬", e28dac), -_c(U+236D, "⍭", e28dad), -_c(U+236E, "⍮", e28dae), -_c(U+236F, "⍯", e28daf), -_c(U+2370, "⍰", e28db0), -_c(U+2371, "⍱", e28db1), -_c(U+2372, "⍲", e28db2), -_c(U+2373, "⍳", e28db3), -_c(U+2374, "⍴", e28db4), -_c(U+2375, "⍵", e28db5), -_c(U+2376, "⍶", e28db6), -_c(U+2377, "⍷", e28db7), -_c(U+2378, "⍸", e28db8), -_c(U+2379, "⍹", e28db9), -_c(U+237A, "⍺", e28dba), -_c(U+237B, "⍻", e28dbb), -_c(U+237C, "⍼", e28dbc), -_c(U+237D, "⍽", e28dbd), -_c(U+237E, "⍾", e28dbe), -_c(U+237F, "⍿", e28dbf), -_c(U+2380, "⎀", e28e80), -_c(U+2381, "⎁", e28e81), -_c(U+2382, "⎂", e28e82), -_c(U+2383, "⎃", e28e83), -_c(U+2384, "⎄", e28e84), -_c(U+2385, "⎅", e28e85), -_c(U+2386, "⎆", e28e86), -_c(U+2387, "⎇", e28e87), -_c(U+2388, "⎈", e28e88), -_c(U+2389, "⎉", e28e89), -_c(U+238A, "⎊", e28e8a), -_c(U+238B, "⎋", e28e8b), -_c(U+238C, "⎌", e28e8c), -_c(U+238D, "⎍", e28e8d), -_c(U+238E, "⎎", e28e8e), -_c(U+238F, "⎏", e28e8f), -_c(U+2390, "⎐", e28e90), -_c(U+2391, "⎑", e28e91), -_c(U+2392, "⎒", e28e92), -_c(U+2393, "⎓", e28e93), -_c(U+2394, "⎔", e28e94), -_c(U+2395, "⎕", e28e95), -_c(U+2396, "⎖", e28e96), -_c(U+2397, "⎗", e28e97), -_c(U+2398, "⎘", e28e98), -_c(U+2399, "⎙", e28e99), -_c(U+239A, "⎚", e28e9a), -_c(U+239B, "⎛", e28e9b), -_c(U+239C, "⎜", e28e9c), -_c(U+239D, "⎝", e28e9d), -_c(U+239E, "⎞", e28e9e), -_c(U+239F, "⎟", e28e9f), -_c(U+23A0, "⎠", e28ea0), -_c(U+23A1, "⎡", e28ea1), -_c(U+23A2, "⎢", e28ea2), -_c(U+23A3, "⎣", e28ea3), -_c(U+23A4, "⎤", e28ea4), -_c(U+23A5, "⎥", e28ea5), -_c(U+23A6, "⎦", e28ea6), -_c(U+23A7, "⎧", e28ea7), -_c(U+23A8, "⎨", e28ea8), -_c(U+23A9, "⎩", e28ea9), -_c(U+23AA, "⎪", e28eaa), -_c(U+23AB, "⎫", e28eab), -_c(U+23AC, "⎬", e28eac), -_c(U+23AD, "⎭", e28ead), -_c(U+23AE, "⎮", e28eae), -_c(U+23AF, "⎯", e28eaf), -_c(U+23B0, "⎰", e28eb0), -_c(U+23B1, "⎱", e28eb1), -_c(U+23B2, "⎲", e28eb2), -_c(U+23B3, "⎳", e28eb3), -_c(U+23B4, "⎴", e28eb4), -_c(U+23B5, "⎵", e28eb5), -_c(U+23B6, "⎶", e28eb6), -_c(U+23B7, "⎷", e28eb7), -_c(U+23B8, "⎸", e28eb8), -_c(U+23B9, "⎹", e28eb9), -_c(U+23BA, "⎺", e28eba), -_c(U+23BB, "⎻", e28ebb), -_c(U+23BC, "⎼", e28ebc), -_c(U+23BD, "⎽", e28ebd), -_c(U+23BE, "⎾", e28ebe), -_c(U+23BF, "⎿", e28ebf), -_c(U+23C0, "⏀", e28f80), -_c(U+23C1, "⏁", e28f81), -_c(U+23C2, "⏂", e28f82), -_c(U+23C3, "⏃", e28f83), -_c(U+23C4, "⏄", e28f84), -_c(U+23C5, "⏅", e28f85), -_c(U+23C6, "⏆", e28f86), -_c(U+23C7, "⏇", e28f87), -_c(U+23C8, "⏈", e28f88), -_c(U+23C9, "⏉", e28f89), -_c(U+23CA, "⏊", e28f8a), -_c(U+23CB, "⏋", e28f8b), -_c(U+23CC, "⏌", e28f8c), -_c(U+23CD, "⏍", e28f8d), -_c(U+23CE, "⏎", e28f8e), -_c(U+23CF, "⏏", e28f8f), -_c(U+23D0, "⏐", e28f90), -_c(U+23D1, "⏑", e28f91), -_c(U+23D2, "⏒", e28f92), -_c(U+23D3, "⏓", e28f93), -_c(U+23D4, "⏔", e28f94), -_c(U+23D5, "⏕", e28f95), -_c(U+23D6, "⏖", e28f96), -_c(U+23D7, "⏗", e28f97), -_c(U+23D8, "⏘", e28f98), -_c(U+23D9, "⏙", e28f99), -_c(U+23DA, "⏚", e28f9a), -_c(U+23DB, "⏛", e28f9b), -_c(U+23DC, "⏜", e28f9c), -_c(U+23DD, "⏝", e28f9d), -_c(U+23DE, "⏞", e28f9e), -_c(U+23DF, "⏟", e28f9f), -_c(U+23E0, "⏠", e28fa0), -_c(U+23E1, "⏡", e28fa1), -_c(U+23E2, "⏢", e28fa2), -_c(U+23E3, "⏣", e28fa3), -_c(U+23E4, "⏤", e28fa4), -_c(U+23E5, "⏥", e28fa5), -_c(U+23E6, "⏦", e28fa6), -_c(U+23E7, "⏧", e28fa7), -_c(U+23E8, "⏨", e28fa8), -_c(U+23E9, "⏩", e28fa9), -_c(U+23EA, "⏪", e28faa), -_c(U+23EB, "⏫", e28fab), -_c(U+23EC, "⏬", e28fac), -_c(U+23ED, "⏭", e28fad), -_c(U+23EE, "⏮", e28fae), -_c(U+23EF, "⏯", e28faf), -_c(U+23F0, "⏰", e28fb0), -_c(U+23F1, "⏱", e28fb1), -_c(U+23F2, "⏲", e28fb2), -_c(U+23F3, "⏳", e28fb3), -_c(U+23F4, "⏴", e28fb4), -_c(U+23F5, "⏵", e28fb5), -_c(U+23F6, "⏶", e28fb6), -_c(U+23F7, "⏷", e28fb7), -_c(U+23F8, "⏸", e28fb8), -_c(U+23F9, "⏹", e28fb9), -_c(U+23FA, "⏺", e28fba), -_c(U+23FB, "⏻", e28fbb), -_c(U+23FC, "⏼", e28fbc), -_c(U+23FD, "⏽", e28fbd), -_c(U+23FE, "⏾", e28fbe), -_c(U+23FF, "⏿", e28fbf), -_c(U+2400, "␀", e29080), -_c(U+2401, "␁", e29081), -_c(U+2402, "␂", e29082), -_c(U+2403, "␃", e29083), -_c(U+2404, "␄", e29084), -_c(U+2405, "␅", e29085), -_c(U+2406, "␆", e29086), -_c(U+2407, "␇", e29087), -_c(U+2408, "␈", e29088), -_c(U+2409, "␉", e29089), -_c(U+240A, "␊", e2908a), -_c(U+240B, "␋", e2908b), -_c(U+240C, "␌", e2908c), -_c(U+240D, "␍", e2908d), -_c(U+240E, "␎", e2908e), -_c(U+240F, "␏", e2908f), -_c(U+2410, "␐", e29090), -_c(U+2411, "␑", e29091), -_c(U+2412, "␒", e29092), -_c(U+2413, "␓", e29093), -_c(U+2414, "␔", e29094), -_c(U+2415, "␕", e29095), -_c(U+2416, "␖", e29096), -_c(U+2417, "␗", e29097), -_c(U+2418, "␘", e29098), -_c(U+2419, "␙", e29099), -_c(U+241A, "␚", e2909a), -_c(U+241B, "␛", e2909b), -_c(U+241C, "␜", e2909c), -_c(U+241D, "␝", e2909d), -_c(U+241E, "␞", e2909e), -_c(U+241F, "␟", e2909f), -_c(U+2420, "␠", e290a0), -_c(U+2421, "␡", e290a1), -_c(U+2422, "␢", e290a2), -_c(U+2423, "␣", e290a3), -_c(U+2424, "␤", e290a4), -_c(U+2425, "␥", e290a5), -_c(U+2426, "␦", e290a6), -_c(U+2427, "␧", e290a7), -_c(U+2428, "␨", e290a8), -_c(U+2429, "␩", e290a9), -_c(U+242A, "␪", e290aa), -_c(U+242B, "␫", e290ab), -_c(U+242C, "␬", e290ac), -_c(U+242D, "␭", e290ad), -_c(U+242E, "␮", e290ae), -_c(U+242F, "␯", e290af), -_c(U+2430, "␰", e290b0), -_c(U+2431, "␱", e290b1), -_c(U+2432, "␲", e290b2), -_c(U+2433, "␳", e290b3), -_c(U+2434, "␴", e290b4), -_c(U+2435, "␵", e290b5), -_c(U+2436, "␶", e290b6), -_c(U+2437, "␷", e290b7), -_c(U+2438, "␸", e290b8), -_c(U+2439, "␹", e290b9), -_c(U+243A, "␺", e290ba), -_c(U+243B, "␻", e290bb), -_c(U+243C, "␼", e290bc), -_c(U+243D, "␽", e290bd), -_c(U+243E, "␾", e290be), -_c(U+243F, "␿", e290bf), -_c(U+2440, "⑀", e29180), -_c(U+2441, "⑁", e29181), -_c(U+2442, "⑂", e29182), -_c(U+2443, "⑃", e29183), -_c(U+2444, "⑄", e29184), -_c(U+2445, "⑅", e29185), -_c(U+2446, "⑆", e29186), -_c(U+2447, "⑇", e29187), -_c(U+2448, "⑈", e29188), -_c(U+2449, "⑉", e29189), -_c(U+244A, "⑊", e2918a), -_c(U+244B, "⑋", e2918b), -_c(U+244C, "⑌", e2918c), -_c(U+244D, "⑍", e2918d), -_c(U+244E, "⑎", e2918e), -_c(U+244F, "⑏", e2918f), -_c(U+2450, "⑐", e29190), -_c(U+2451, "⑑", e29191), -_c(U+2452, "⑒", e29192), -_c(U+2453, "⑓", e29193), -_c(U+2454, "⑔", e29194), -_c(U+2455, "⑕", e29195), -_c(U+2456, "⑖", e29196), -_c(U+2457, "⑗", e29197), -_c(U+2458, "⑘", e29198), -_c(U+2459, "⑙", e29199), -_c(U+245A, "⑚", e2919a), -_c(U+245B, "⑛", e2919b), -_c(U+245C, "⑜", e2919c), -_c(U+245D, "⑝", e2919d), -_c(U+245E, "⑞", e2919e), -_c(U+245F, "⑟", e2919f), -_c(U+2460, "①", e291a0), -_c(U+2461, "②", e291a1), -_c(U+2462, "③", e291a2), -_c(U+2463, "④", e291a3), -_c(U+2464, "⑤", e291a4), -_c(U+2465, "⑥", e291a5), -_c(U+2466, "⑦", e291a6), -_c(U+2467, "⑧", e291a7), -_c(U+2468, "⑨", e291a8), -_c(U+2469, "⑩", e291a9), -_c(U+246A, "⑪", e291aa), -_c(U+246B, "⑫", e291ab), -_c(U+246C, "⑬", e291ac), -_c(U+246D, "⑭", e291ad), -_c(U+246E, "⑮", e291ae), -_c(U+246F, "⑯", e291af), -_c(U+2470, "⑰", e291b0), -_c(U+2471, "⑱", e291b1), -_c(U+2472, "⑲", e291b2), -_c(U+2473, "⑳", e291b3), -_c(U+2474, "⑴", e291b4), -_c(U+2475, "⑵", e291b5), -_c(U+2476, "⑶", e291b6), -_c(U+2477, "⑷", e291b7), -_c(U+2478, "⑸", e291b8), -_c(U+2479, "⑹", e291b9), -_c(U+247A, "⑺", e291ba), -_c(U+247B, "⑻", e291bb), -_c(U+247C, "⑼", e291bc), -_c(U+247D, "⑽", e291bd), -_c(U+247E, "⑾", e291be), -_c(U+247F, "⑿", e291bf), -_c(U+2480, "⒀", e29280), -_c(U+2481, "⒁", e29281), -_c(U+2482, "⒂", e29282), -_c(U+2483, "⒃", e29283), -_c(U+2484, "⒄", e29284), -_c(U+2485, "⒅", e29285), -_c(U+2486, "⒆", e29286), -_c(U+2487, "⒇", e29287), -_c(U+2488, "⒈", e29288), -_c(U+2489, "⒉", e29289), -_c(U+248A, "⒊", e2928a), -_c(U+248B, "⒋", e2928b), -_c(U+248C, "⒌", e2928c), -_c(U+248D, "⒍", e2928d), -_c(U+248E, "⒎", e2928e), -_c(U+248F, "⒏", e2928f), -_c(U+2490, "⒐", e29290), -_c(U+2491, "⒑", e29291), -_c(U+2492, "⒒", e29292), -_c(U+2493, "⒓", e29293), -_c(U+2494, "⒔", e29294), -_c(U+2495, "⒕", e29295), -_c(U+2496, "⒖", e29296), -_c(U+2497, "⒗", e29297), -_c(U+2498, "⒘", e29298), -_c(U+2499, "⒙", e29299), -_c(U+249A, "⒚", e2929a), -_c(U+249B, "⒛", e2929b), -_c(U+249C, "⒜", e2929c), -_c(U+249D, "⒝", e2929d), -_c(U+249E, "⒞", e2929e), -_c(U+249F, "⒟", e2929f), -_c(U+2601, "☁", e29881), -_c(U+2602, "☂", e29882), -_c(U+2603, "☃", e29883), -_c(U+2604, "☄", e29884), -_c(U+2605, "★", e29885), -_c(U+2606, "☆", e29886), -_c(U+2607, "☇", e29887), -_c(U+2608, "☈", e29888), -_c(U+2609, "☉", e29889), -_c(U+260A, "☊", e2988a), -_c(U+260B, "☋", e2988b), -_c(U+260C, "☌", e2988c), -_c(U+260D, "☍", e2988d), -_c(U+260E, "☎", e2988e), -_c(U+260F, "☏", e2988f), -_c(U+2610, "☐", e29890), -_c(U+2611, "☑", e29891), -_c(U+2612, "☒", e29892), -_c(U+2613, "☓", e29893), -_c(U+2614, "☔", e29894), -_c(U+2615, "☕", e29895), -_c(U+2616, "☖", e29896), -_c(U+2617, "☗", e29897), -_c(U+2618, "☘", e29898), -_c(U+2619, "☙", e29899), -_c(U+261A, "☚", e2989a), -_c(U+261B, "☛", e2989b), -_c(U+261C, "☜", e2989c), -_c(U+261D, "☝", e2989d), -_c(U+261E, "☞", e2989e), -_c(U+261F, "☟", e2989f), -_c(U+2620, "☠", e298a0), -_c(U+2621, "☡", e298a1), -_c(U+2622, "☢", e298a2), -_c(U+2623, "☣", e298a3), -_c(U+2624, "☤", e298a4), -_c(U+2625, "☥", e298a5), -_c(U+2626, "☦", e298a6), -_c(U+2627, "☧", e298a7), -_c(U+2628, "☨", e298a8), -_c(U+2629, "☩", e298a9), -_c(U+262A, "☪", e298aa), -_c(U+262B, "☫", e298ab), -_c(U+262C, "☬", e298ac), -_c(U+262D, "☭", e298ad), -_c(U+262E, "☮", e298ae), -_c(U+262F, "☯", e298af), -_c(U+2630, "☰", e298b0), -_c(U+2631, "☱", e298b1), -_c(U+2632, "☲", e298b2), -_c(U+2633, "☳", e298b3), -_c(U+2634, "☴", e298b4), -_c(U+2635, "☵", e298b5), -_c(U+2636, "☶", e298b6), -_c(U+2637, "☷", e298b7), -_c(U+2638, "☸", e298b8), -_c(U+2639, "☹", e298b9), -_c(U+263A, "☺", e298ba), -_c(U+263B, "☻", e298bb), -_c(U+263C, "☼", e298bc), -_c(U+263D, "☽", e298bd), -_c(U+263E, "☾", e298be), -_c(U+263F, "☿", e298bf), -_c(U+2640, "♀", e29980), -_c(U+2641, "♁", e29981), -_c(U+2642, "♂", e29982), -_c(U+2643, "♃", e29983), -_c(U+2644, "♄", e29984), -_c(U+2645, "♅", e29985), -_c(U+2646, "♆", e29986), -_c(U+2647, "♇", e29987), -_c(U+2648, "♈", e29988), -_c(U+2649, "♉", e29989), -_c(U+264A, "♊", e2998a), -_c(U+264B, "♋", e2998b), -_c(U+264C, "♌", e2998c), -_c(U+264D, "♍", e2998d), -_c(U+264E, "♎", e2998e), -_c(U+264F, "♏", e2998f), -_c(U+2650, "♐", e29990), -_c(U+2651, "♑", e29991), -_c(U+2652, "♒", e29992), -_c(U+2653, "♓", e29993), -_c(U+2654, "♔", e29994), -_c(U+2655, "♕", e29995), -_c(U+2656, "♖", e29996), -_c(U+2657, "♗", e29997), -_c(U+2658, "♘", e29998), -_c(U+2659, "♙", e29999), -_c(U+265A, "♚", e2999a), -_c(U+265B, "♛", e2999b), -_c(U+265C, "♜", e2999c), -_c(U+265D, "♝", e2999d), -_c(U+265E, "♞", e2999e), -_c(U+265F, "♟", e2999f), -_c(U+2660, "♠", e299a0), -_c(U+2661, "♡", e299a1), -_c(U+2662, "♢", e299a2), -_c(U+2663, "♣", e299a3), -_c(U+2664, "♤", e299a4), -_c(U+2665, "♥", e299a5), -_c(U+2666, "♦", e299a6), -_c(U+2667, "♧", e299a7), -_c(U+2668, "♨", e299a8), -_c(U+2669, "♩", e299a9), -_c(U+266A, "♪", e299aa), -_c(U+266B, "♫", e299ab), -_c(U+266C, "♬", e299ac), -_c(U+266D, "♭", e299ad), -_c(U+266E, "♮", e299ae), -_c(U+266F, "♯", e299af), -_c(U+2670, "♰", e299b0), -_c(U+2671, "♱", e299b1), -_c(U+2672, "♲", e299b2), -_c(U+2673, "♳", e299b3), -_c(U+2674, "♴", e299b4), -_c(U+2675, "♵", e299b5), -_c(U+2676, "♶", e299b6), -_c(U+2677, "♷", e299b7), -_c(U+2678, "♸", e299b8), -_c(U+2679, "♹", e299b9), -_c(U+267A, "♺", e299ba), -_c(U+267B, "♻", e299bb), -_c(U+267C, "♼", e299bc), -_c(U+267D, "♽", e299bd), -_c(U+267E, "♾", e299be), -_c(U+267F, "♿", e299bf), -_c(U+2680, "⚀", e29a80), -_c(U+2681, "⚁", e29a81), -_c(U+2682, "⚂", e29a82), -_c(U+2683, "⚃", e29a83), -_c(U+2684, "⚄", e29a84), -_c(U+2685, "⚅", e29a85), -_c(U+2686, "⚆", e29a86), -_c(U+2687, "⚇", e29a87), -_c(U+2688, "⚈", e29a88), -_c(U+2689, "⚉", e29a89), -_c(U+268A, "⚊", e29a8a), -_c(U+268B, "⚋", e29a8b), -_c(U+268C, "⚌", e29a8c), -_c(U+268D, "⚍", e29a8d), -_c(U+268E, "⚎", e29a8e), -_c(U+268F, "⚏", e29a8f), -_c(U+2690, "⚐", e29a90), -_c(U+2691, "⚑", e29a91), -_c(U+2692, "⚒", e29a92), -_c(U+2693, "⚓", e29a93), -_c(U+2694, "⚔", e29a94), -_c(U+2695, "⚕", e29a95), -_c(U+2696, "⚖", e29a96), -_c(U+2697, "⚗", e29a97), -_c(U+2698, "⚘", e29a98), -_c(U+2699, "⚙", e29a99), -_c(U+269A, "⚚", e29a9a), -_c(U+269B, "⚛", e29a9b), -_c(U+269C, "⚜", e29a9c), -_c(U+269D, "⚝", e29a9d), -_c(U+269E, "⚞", e29a9e), -_c(U+269F, "⚟", e29a9f), -_c(U+26A0, "⚠", e29aa0), -_c(U+26A1, "⚡", e29aa1), -_c(U+26A2, "⚢", e29aa2), -_c(U+26A3, "⚣", e29aa3), -_c(U+26A4, "⚤", e29aa4), -_c(U+26A5, "⚥", e29aa5), -_c(U+26A6, "⚦", e29aa6), -_c(U+26A7, "⚧", e29aa7), -_c(U+26A8, "⚨", e29aa8), -_c(U+26A9, "⚩", e29aa9), -_c(U+26AA, "⚪", e29aaa), -_c(U+26AB, "⚫", e29aab), -_c(U+26AC, "⚬", e29aac), -_c(U+26AD, "⚭", e29aad), -_c(U+26AE, "⚮", e29aae), -_c(U+26AF, "⚯", e29aaf), -_c(U+26B0, "⚰", e29ab0), -_c(U+26B1, "⚱", e29ab1), -_c(U+26B2, "⚲", e29ab2), -_c(U+26B3, "⚳", e29ab3), -_c(U+26B4, "⚴", e29ab4), -_c(U+26B5, "⚵", e29ab5), -_c(U+26B6, "⚶", e29ab6), -_c(U+26B7, "⚷", e29ab7), -_c(U+26B8, "⚸", e29ab8), -_c(U+26B9, "⚹", e29ab9), -_c(U+26BA, "⚺", e29aba), -_c(U+26BB, "⚻", e29abb), -_c(U+26BC, "⚼", e29abc), -_c(U+26BD, "⚽", e29abd), -_c(U+26BE, "⚾", e29abe), -_c(U+26BF, "⚿", e29abf), -_c(U+26C0, "⛀", e29b80), -_c(U+26C1, "⛁", e29b81), -_c(U+26C2, "⛂", e29b82), -_c(U+26C3, "⛃", e29b83), -_c(U+26C4, "⛄", e29b84), -_c(U+26C5, "⛅", e29b85), -_c(U+26C6, "⛆", e29b86), -_c(U+26C7, "⛇", e29b87), -_c(U+26C8, "⛈", e29b88), -_c(U+26C9, "⛉", e29b89), -_c(U+26CA, "⛊", e29b8a), -_c(U+26CB, "⛋", e29b8b), -_c(U+26CC, "⛌", e29b8c), -_c(U+26CD, "⛍", e29b8d), -_c(U+26CE, "⛎", e29b8e), -_c(U+26CF, "⛏", e29b8f), -_c(U+26D0, "⛐", e29b90), -_c(U+26D1, "⛑", e29b91), -_c(U+26D2, "⛒", e29b92), -_c(U+26D3, "⛓", e29b93), -_c(U+26D4, "⛔", e29b94), -_c(U+26D5, "⛕", e29b95), -_c(U+26D6, "⛖", e29b96), -_c(U+26D7, "⛗", e29b97), -_c(U+26D8, "⛘", e29b98), -_c(U+26D9, "⛙", e29b99), -_c(U+26DA, "⛚", e29b9a), -_c(U+26DB, "⛛", e29b9b), -_c(U+26DC, "⛜", e29b9c), -_c(U+26DD, "⛝", e29b9d), -_c(U+26DE, "⛞", e29b9e), -_c(U+26DF, "⛟", e29b9f), -_c(U+26E0, "⛠", e29ba0), -_c(U+26E1, "⛡", e29ba1), -_c(U+26E2, "⛢", e29ba2), -_c(U+26E3, "⛣", e29ba3), -_c(U+26E4, "⛤", e29ba4), -_c(U+26E5, "⛥", e29ba5), -_c(U+26E6, "⛦", e29ba6), -_c(U+26E7, "⛧", e29ba7), -_c(U+26E8, "⛨", e29ba8), -_c(U+26E9, "⛩", e29ba9), -_c(U+26EA, "⛪", e29baa), -_c(U+26EB, "⛫", e29bab), -_c(U+26EC, "⛬", e29bac), -_c(U+26ED, "⛭", e29bad), -_c(U+26EE, "⛮", e29bae), -_c(U+26EF, "⛯", e29baf), -_c(U+26F0, "⛰", e29bb0), -_c(U+26F1, "⛱", e29bb1), -_c(U+26F2, "⛲", e29bb2), -_c(U+26F3, "⛳", e29bb3), -_c(U+26F4, "⛴", e29bb4), -_c(U+26F5, "⛵", e29bb5), -_c(U+26F6, "⛶", e29bb6), -_c(U+26F7, "⛷", e29bb7), -_c(U+26F8, "⛸", e29bb8), -_c(U+26F9, "⛹", e29bb9), -_c(U+26FA, "⛺", e29bba), -_c(U+26FB, "⛻", e29bbb), -_c(U+26FC, "⛼", e29bbc), -_c(U+26FD, "⛽", e29bbd), -_c(U+26FE, "⛾", e29bbe), -_c(U+26FF, "⛿", e29bbf), -_c(U+2700, "✀", e29c80), -_c(U+2701, "✁", e29c81), -_c(U+2702, "✂", e29c82), -_c(U+2703, "✃", e29c83), -_c(U+2704, "✄", e29c84), -_c(U+2705, "✅", e29c85), -_c(U+2706, "✆", e29c86), -_c(U+2707, "✇", e29c87), -_c(U+2708, "✈", e29c88), -_c(U+2709, "✉", e29c89), -_c(U+270A, "✊", e29c8a), -_c(U+270B, "✋", e29c8b), -_c(U+270C, "✌", e29c8c), -_c(U+270D, "✍", e29c8d), -_c(U+270E, "✎", e29c8e), -_c(U+270F, "✏", e29c8f), -_c(U+2710, "✐", e29c90), -_c(U+2711, "✑", e29c91), -_c(U+2712, "✒", e29c92), -_c(U+2713, "✓", e29c93), -_c(U+2714, "✔", e29c94), -_c(U+2715, "✕", e29c95), -_c(U+2716, "✖", e29c96), -_c(U+2717, "✗", e29c97), -_c(U+2718, "✘", e29c98), -_c(U+2719, "✙", e29c99), -_c(U+271A, "✚", e29c9a), -_c(U+271B, "✛", e29c9b), -_c(U+271C, "✜", e29c9c), -_c(U+271D, "✝", e29c9d), -_c(U+271E, "✞", e29c9e), -_c(U+271F, "✟", e29c9f), -_c(U+2720, "✠", e29ca0), -_c(U+2721, "✡", e29ca1), -_c(U+2722, "✢", e29ca2), -_c(U+2723, "✣", e29ca3), -_c(U+2724, "✤", e29ca4), -_c(U+2725, "✥", e29ca5), -_c(U+2726, "✦", e29ca6), -_c(U+2727, "✧", e29ca7), -_c(U+2728, "✨", e29ca8), -_c(U+2729, "✩", e29ca9), -_c(U+272A, "✪", e29caa), -_c(U+272B, "✫", e29cab), -_c(U+272C, "✬", e29cac), -_c(U+272D, "✭", e29cad), -_c(U+272E, "✮", e29cae), -_c(U+272F, "✯", e29caf), -_c(U+2730, "✰", e29cb0), -_c(U+2731, "✱", e29cb1), -_c(U+2732, "✲", e29cb2), -_c(U+2733, "✳", e29cb3), -_c(U+2734, "✴", e29cb4), -_c(U+2735, "✵", e29cb5), -_c(U+2736, "✶", e29cb6), -_c(U+2737, "✷", e29cb7), -_c(U+2738, "✸", e29cb8), -_c(U+2739, "✹", e29cb9), -_c(U+273A, "✺", e29cba), -_c(U+273B, "✻", e29cbb), -_c(U+273C, "✼", e29cbc), -_c(U+273D, "✽", e29cbd), -_c(U+273E, "✾", e29cbe), -_c(U+273F, "✿", e29cbf), -_c(U+2740, "❀", e29d80), -_c(U+2741, "❁", e29d81), -_c(U+2742, "❂", e29d82), -_c(U+2743, "❃", e29d83), -_c(U+2744, "❄", e29d84), -_c(U+2745, "❅", e29d85), -_c(U+2746, "❆", e29d86), -_c(U+2747, "❇", e29d87), -_c(U+2748, "❈", e29d88), -_c(U+2749, "❉", e29d89), -_c(U+274A, "❊", e29d8a), -_c(U+274B, "❋", e29d8b), -_c(U+274C, "❌", e29d8c), -_c(U+274D, "❍", e29d8d), -_c(U+274E, "❎", e29d8e), -_c(U+274F, "❏", e29d8f), -_c(U+2750, "❐", e29d90), -_c(U+2751, "❑", e29d91), -_c(U+2752, "❒", e29d92), -_c(U+2753, "❓", e29d93), -_c(U+2754, "❔", e29d94), -_c(U+2755, "❕", e29d95), -_c(U+2756, "❖", e29d96), -_c(U+2757, "❗", e29d97), -_c(U+2758, "❘", e29d98), -_c(U+2759, "❙", e29d99), -_c(U+275A, "❚", e29d9a), -_c(U+275B, "❛", e29d9b), -_c(U+275C, "❜", e29d9c), -_c(U+275D, "❝", e29d9d), -_c(U+275E, "❞", e29d9e), -_c(U+275F, "❟", e29d9f), -_c(U+2760, "❠", e29da0), -_c(U+2761, "❡", e29da1), -_c(U+2762, "❢", e29da2), -_c(U+2763, "❣", e29da3), -_c(U+2764, "❤", e29da4), -_c(U+2765, "❥", e29da5), -_c(U+2766, "❦", e29da6), -_c(U+2767, "❧", e29da7), -_c(U+2768, "❨", e29da8), -_c(U+2769, "❩", e29da9), -_c(U+276A, "❪", e29daa), -_c(U+276B, "❫", e29dab), -_c(U+276C, "❬", e29dac), -_c(U+276D, "❭", e29dad), -_c(U+276E, "❮", e29dae), -_c(U+276F, "❯", e29daf), -_c(U+2770, "❰", e29db0), -_c(U+2771, "❱", e29db1), -_c(U+2772, "❲", e29db2), -_c(U+2773, "❳", e29db3), -_c(U+2774, "❴", e29db4), -_c(U+2775, "❵", e29db5), -_c(U+2776, "❶", e29db6), -_c(U+2777, "❷", e29db7), -_c(U+2778, "❸", e29db8), -_c(U+2779, "❹", e29db9), -_c(U+277A, "❺", e29dba), -_c(U+277B, "❻", e29dbb), -_c(U+277C, "❼", e29dbc), -_c(U+277D, "❽", e29dbd), -_c(U+277E, "❾", e29dbe), -_c(U+277F, "❿", e29dbf), -_c(U+2780, "➀", e29e80), -_c(U+2781, "➁", e29e81), -_c(U+2782, "➂", e29e82), -_c(U+2783, "➃", e29e83), -_c(U+2784, "➄", e29e84), -_c(U+2785, "➅", e29e85), -_c(U+2786, "➆", e29e86), -_c(U+2787, "➇", e29e87), -_c(U+2788, "➈", e29e88), -_c(U+2789, "➉", e29e89), -_c(U+278A, "➊", e29e8a), -_c(U+278B, "➋", e29e8b), -_c(U+278C, "➌", e29e8c), -_c(U+278D, "➍", e29e8d), -_c(U+278E, "➎", e29e8e), -_c(U+278F, "➏", e29e8f), -_c(U+2790, "➐", e29e90), -_c(U+2791, "➑", e29e91), -_c(U+2792, "➒", e29e92), -_c(U+2793, "➓", e29e93), -_c(U+2794, "➔", e29e94), -_c(U+2795, "➕", e29e95), -_c(U+2796, "➖", e29e96), -_c(U+2797, "➗", e29e97), -_c(U+2798, "➘", e29e98), -_c(U+2799, "➙", e29e99), -_c(U+279A, "➚", e29e9a), -_c(U+279B, "➛", e29e9b), -_c(U+279C, "➜", e29e9c), -_c(U+279D, "➝", e29e9d), -_c(U+279E, "➞", e29e9e), -_c(U+279F, "➟", e29e9f), -_c(U+27A0, "➠", e29ea0), -_c(U+27A1, "➡", e29ea1), -_c(U+27A2, "➢", e29ea2), -_c(U+27A3, "➣", e29ea3), -_c(U+27A4, "➤", e29ea4), -_c(U+27A5, "➥", e29ea5), -_c(U+27A6, "➦", e29ea6), -_c(U+27A7, "➧", e29ea7), -_c(U+27A8, "➨", e29ea8), -_c(U+27A9, "➩", e29ea9), -_c(U+27AA, "➪", e29eaa), -_c(U+27AB, "➫", e29eab), -_c(U+27AC, "➬", e29eac), -_c(U+27AD, "➭", e29ead), -_c(U+27AE, "➮", e29eae), -_c(U+27AF, "➯", e29eaf), -_c(U+27B0, "➰", e29eb0), -_c(U+27B1, "➱", e29eb1), -_c(U+27B2, "➲", e29eb2), -_c(U+27B3, "➳", e29eb3), -_c(U+27B4, "➴", e29eb4), -_c(U+27B5, "➵", e29eb5), -_c(U+27B6, "➶", e29eb6), -_c(U+27B7, "➷", e29eb7), -_c(U+27B8, "➸", e29eb8), -_c(U+27B9, "➹", e29eb9), -_c(U+27BA, "➺", e29eba), -_c(U+27BB, "➻", e29ebb), -_c(U+27BC, "➼", e29ebc), -_c(U+27BD, "➽", e29ebd), -_c(U+27BE, "➾", e29ebe), -_c(U+27BF, "➿", e29ebf), -_c(U+27C0, "⟀", e29f80), -_c(U+27C1, "⟁", e29f81), -_c(U+27C2, "⟂", e29f82), -_c(U+27C3, "⟃", e29f83), -_c(U+27C4, "⟄", e29f84), -_c(U+27C5, "⟅", e29f85), -_c(U+27C6, "⟆", e29f86), -_c(U+27C7, "⟇", e29f87), -_c(U+27C8, "⟈", e29f88), -_c(U+27C9, "⟉", e29f89), -_c(U+27CA, "⟊", e29f8a), -_c(U+27CB, "⟋", e29f8b), -_c(U+27CC, "⟌", e29f8c), -_c(U+27CD, "⟍", e29f8d), -_c(U+27CE, "⟎", e29f8e), -_c(U+27CF, "⟏", e29f8f), -_c(U+27D0, "⟐", e29f90), -_c(U+27D1, "⟑", e29f91), -_c(U+27D2, "⟒", e29f92), -_c(U+27D3, "⟓", e29f93), -_c(U+27D4, "⟔", e29f94), -_c(U+27D5, "⟕", e29f95), -_c(U+27D6, "⟖", e29f96), -_c(U+27D7, "⟗", e29f97), -_c(U+27D8, "⟘", e29f98), -_c(U+27D9, "⟙", e29f99), -_c(U+27DA, "⟚", e29f9a), -_c(U+27DB, "⟛", e29f9b), -_c(U+27DC, "⟜", e29f9c), -_c(U+27DD, "⟝", e29f9d), -_c(U+27DE, "⟞", e29f9e), -_c(U+27DF, "⟟", e29f9f), -_c(U+27E0, "⟠", e29fa0), -_c(U+27E1, "⟡", e29fa1), -_c(U+27E2, "⟢", e29fa2), -_c(U+27E3, "⟣", e29fa3), -_c(U+27E4, "⟤", e29fa4), -_c(U+27E5, "⟥", e29fa5), -_c(U+27E6, "⟦", e29fa6), -_c(U+27E7, "⟧", e29fa7), -_c(U+27E8, "⟨", e29fa8), -_c(U+27E9, "⟩", e29fa9), -_c(U+27EA, "⟪", e29faa), -_c(U+27EB, "⟫", e29fab), -_c(U+27EC, "⟬", e29fac), -_c(U+27ED, "⟭", e29fad), -_c(U+27EE, "⟮", e29fae), -_c(U+27EF, "⟯", e29faf), -_c(U+27F0, "⟰", e29fb0), -_c(U+27F1, "⟱", e29fb1), -_c(U+27F2, "⟲", e29fb2), -_c(U+27F3, "⟳", e29fb3), -_c(U+27F4, "⟴", e29fb4), -_c(U+27F5, "⟵", e29fb5), -_c(U+27F6, "⟶", e29fb6), -_c(U+27F7, "⟷", e29fb7), -_c(U+27F8, "⟸", e29fb8), -_c(U+27F9, "⟹", e29fb9), -_c(U+27FA, "⟺", e29fba), -_c(U+27FB, "⟻", e29fbb), -_c(U+27FC, "⟼", e29fbc), -_c(U+27FD, "⟽", e29fbd), -_c(U+27FE, "⟾", e29fbe), -_c(U+27FF, "⟿", e29fbf), -_c(U+2800, "⠀", e2a080), -_c(U+2801, "⠁", e2a081), -_c(U+2802, "⠂", e2a082), -_c(U+2803, "⠃", e2a083), -_c(U+2804, "⠄", e2a084), -_c(U+2805, "⠅", e2a085), -_c(U+2806, "⠆", e2a086), -_c(U+2807, "⠇", e2a087), -_c(U+2808, "⠈", e2a088), -_c(U+2809, "⠉", e2a089), -_c(U+280A, "⠊", e2a08a), -_c(U+280B, "⠋", e2a08b), -_c(U+280C, "⠌", e2a08c), -_c(U+280D, "⠍", e2a08d), -_c(U+280E, "⠎", e2a08e), -_c(U+280F, "⠏", e2a08f), -_c(U+2810, "⠐", e2a090), -_c(U+2811, "⠑", e2a091), -_c(U+2812, "⠒", e2a092), -_c(U+2813, "⠓", e2a093), -_c(U+2814, "⠔", e2a094), -_c(U+2815, "⠕", e2a095), -_c(U+2816, "⠖", e2a096), -_c(U+2817, "⠗", e2a097), -_c(U+2818, "⠘", e2a098), -_c(U+2819, "⠙", e2a099), -_c(U+281A, "⠚", e2a09a), -_c(U+281B, "⠛", e2a09b), -_c(U+281C, "⠜", e2a09c), -_c(U+281D, "⠝", e2a09d), -_c(U+281E, "⠞", e2a09e), -_c(U+281F, "⠟", e2a09f), -_c(U+2820, "⠠", e2a0a0), -_c(U+2821, "⠡", e2a0a1), -_c(U+2822, "⠢", e2a0a2), -_c(U+2823, "⠣", e2a0a3), -_c(U+2824, "⠤", e2a0a4), -_c(U+2825, "⠥", e2a0a5), -_c(U+2826, "⠦", e2a0a6), -_c(U+2827, "⠧", e2a0a7), -_c(U+2828, "⠨", e2a0a8), -_c(U+2829, "⠩", e2a0a9), -_c(U+282A, "⠪", e2a0aa), -_c(U+282B, "⠫", e2a0ab), -_c(U+282C, "⠬", e2a0ac), -_c(U+282D, "⠭", e2a0ad), -_c(U+282E, "⠮", e2a0ae), -_c(U+282F, "⠯", e2a0af), -_c(U+2830, "⠰", e2a0b0), -_c(U+2831, "⠱", e2a0b1), -_c(U+2832, "⠲", e2a0b2), -_c(U+2833, "⠳", e2a0b3), -_c(U+2834, "⠴", e2a0b4), -_c(U+2835, "⠵", e2a0b5), -_c(U+2836, "⠶", e2a0b6), -_c(U+2837, "⠷", e2a0b7), -_c(U+2838, "⠸", e2a0b8), -_c(U+2839, "⠹", e2a0b9), -_c(U+283A, "⠺", e2a0ba), -_c(U+283B, "⠻", e2a0bb), -_c(U+283C, "⠼", e2a0bc), -_c(U+283D, "⠽", e2a0bd), -_c(U+283E, "⠾", e2a0be), -_c(U+283F, "⠿", e2a0bf), -_c(U+2840, "⡀", e2a180), -_c(U+2841, "⡁", e2a181), -_c(U+2842, "⡂", e2a182), -_c(U+2843, "⡃", e2a183), -_c(U+2844, "⡄", e2a184), -_c(U+2845, "⡅", e2a185), -_c(U+2846, "⡆", e2a186), -_c(U+2847, "⡇", e2a187), -_c(U+2848, "⡈", e2a188), -_c(U+2849, "⡉", e2a189), -_c(U+284A, "⡊", e2a18a), -_c(U+284B, "⡋", e2a18b), -_c(U+284C, "⡌", e2a18c), -_c(U+284D, "⡍", e2a18d), -_c(U+284E, "⡎", e2a18e), -_c(U+284F, "⡏", e2a18f), -_c(U+2850, "⡐", e2a190), -_c(U+2851, "⡑", e2a191), -_c(U+2852, "⡒", e2a192), -_c(U+2853, "⡓", e2a193), -_c(U+2854, "⡔", e2a194), -_c(U+2855, "⡕", e2a195), -_c(U+2856, "⡖", e2a196), -_c(U+2857, "⡗", e2a197), -_c(U+2858, "⡘", e2a198), -_c(U+2859, "⡙", e2a199), -_c(U+285A, "⡚", e2a19a), -_c(U+285B, "⡛", e2a19b), -_c(U+285C, "⡜", e2a19c), -_c(U+285D, "⡝", e2a19d), -_c(U+285E, "⡞", e2a19e), -_c(U+285F, "⡟", e2a19f), -_c(U+2860, "⡠", e2a1a0), -_c(U+2861, "⡡", e2a1a1), -_c(U+2862, "⡢", e2a1a2), -_c(U+2863, "⡣", e2a1a3), -_c(U+2864, "⡤", e2a1a4), -_c(U+2865, "⡥", e2a1a5), -_c(U+2866, "⡦", e2a1a6), -_c(U+2867, "⡧", e2a1a7), -_c(U+2868, "⡨", e2a1a8), -_c(U+2869, "⡩", e2a1a9), -_c(U+286A, "⡪", e2a1aa), -_c(U+286B, "⡫", e2a1ab), -_c(U+286C, "⡬", e2a1ac), -_c(U+286D, "⡭", e2a1ad), -_c(U+286E, "⡮", e2a1ae), -_c(U+286F, "⡯", e2a1af), -_c(U+2870, "⡰", e2a1b0), -_c(U+2871, "⡱", e2a1b1), -_c(U+2872, "⡲", e2a1b2), -_c(U+2873, "⡳", e2a1b3), -_c(U+2874, "⡴", e2a1b4), -_c(U+2875, "⡵", e2a1b5), -_c(U+2876, "⡶", e2a1b6), -_c(U+2877, "⡷", e2a1b7), -_c(U+2878, "⡸", e2a1b8), -_c(U+2879, "⡹", e2a1b9), -_c(U+287A, "⡺", e2a1ba), -_c(U+287B, "⡻", e2a1bb), -_c(U+287C, "⡼", e2a1bc), -_c(U+287D, "⡽", e2a1bd), -_c(U+287E, "⡾", e2a1be), -_c(U+287F, "⡿", e2a1bf), -_c(U+2880, "⢀", e2a280), -_c(U+2881, "⢁", e2a281), -_c(U+2882, "⢂", e2a282), -_c(U+2883, "⢃", e2a283), -_c(U+2884, "⢄", e2a284), -_c(U+2885, "⢅", e2a285), -_c(U+2886, "⢆", e2a286), -_c(U+2887, "⢇", e2a287), -_c(U+2888, "⢈", e2a288), -_c(U+2889, "⢉", e2a289), -_c(U+288A, "⢊", e2a28a), -_c(U+288B, "⢋", e2a28b), -_c(U+288C, "⢌", e2a28c), -_c(U+288D, "⢍", e2a28d), -_c(U+288E, "⢎", e2a28e), -_c(U+288F, "⢏", e2a28f), -_c(U+2890, "⢐", e2a290), -_c(U+2891, "⢑", e2a291), -_c(U+2892, "⢒", e2a292), -_c(U+2893, "⢓", e2a293), -_c(U+2894, "⢔", e2a294), -_c(U+2895, "⢕", e2a295), -_c(U+2896, "⢖", e2a296), -_c(U+2897, "⢗", e2a297), -_c(U+2898, "⢘", e2a298), -_c(U+2899, "⢙", e2a299), -_c(U+289A, "⢚", e2a29a), -_c(U+289B, "⢛", e2a29b), -_c(U+289C, "⢜", e2a29c), -_c(U+289D, "⢝", e2a29d), -_c(U+289E, "⢞", e2a29e), -_c(U+289F, "⢟", e2a29f), -_c(U+28A0, "⢠", e2a2a0), -_c(U+28A1, "⢡", e2a2a1), -_c(U+28A2, "⢢", e2a2a2), -_c(U+28A3, "⢣", e2a2a3), -_c(U+28A4, "⢤", e2a2a4), -_c(U+28A5, "⢥", e2a2a5), -_c(U+28A6, "⢦", e2a2a6), -_c(U+28A7, "⢧", e2a2a7), -_c(U+28A8, "⢨", e2a2a8), -_c(U+28A9, "⢩", e2a2a9), -_c(U+28AA, "⢪", e2a2aa), -_c(U+28AB, "⢫", e2a2ab), -_c(U+28AC, "⢬", e2a2ac), -_c(U+28AD, "⢭", e2a2ad), -_c(U+28AE, "⢮", e2a2ae), -_c(U+28AF, "⢯", e2a2af), -_c(U+28B0, "⢰", e2a2b0), -_c(U+28B1, "⢱", e2a2b1), -_c(U+28B2, "⢲", e2a2b2), -_c(U+28B3, "⢳", e2a2b3), -_c(U+28B4, "⢴", e2a2b4), -_c(U+28B5, "⢵", e2a2b5), -_c(U+28B6, "⢶", e2a2b6), -_c(U+28B7, "⢷", e2a2b7), -_c(U+28B8, "⢸", e2a2b8), -_c(U+28B9, "⢹", e2a2b9), -_c(U+28BA, "⢺", e2a2ba), -_c(U+28BB, "⢻", e2a2bb), -_c(U+28BC, "⢼", e2a2bc), -_c(U+28BD, "⢽", e2a2bd), -_c(U+28BE, "⢾", e2a2be), -_c(U+28BF, "⢿", e2a2bf), -_c(U+28C0, "⣀", e2a380), -_c(U+28C1, "⣁", e2a381), -_c(U+28C2, "⣂", e2a382), -_c(U+28C3, "⣃", e2a383), -_c(U+28C4, "⣄", e2a384), -_c(U+28C5, "⣅", e2a385), -_c(U+28C6, "⣆", e2a386), -_c(U+28C7, "⣇", e2a387), -_c(U+28C8, "⣈", e2a388), -_c(U+28C9, "⣉", e2a389), -_c(U+28CA, "⣊", e2a38a), -_c(U+28CB, "⣋", e2a38b), -_c(U+28CC, "⣌", e2a38c), -_c(U+28CD, "⣍", e2a38d), -_c(U+28CE, "⣎", e2a38e), -_c(U+28CF, "⣏", e2a38f), -_c(U+28D0, "⣐", e2a390), -_c(U+28D1, "⣑", e2a391), -_c(U+28D2, "⣒", e2a392), -_c(U+28D3, "⣓", e2a393), -_c(U+28D4, "⣔", e2a394), -_c(U+28D5, "⣕", e2a395), -_c(U+28D6, "⣖", e2a396), -_c(U+28D7, "⣗", e2a397), -_c(U+28D8, "⣘", e2a398), -_c(U+28D9, "⣙", e2a399), -_c(U+28DA, "⣚", e2a39a), -_c(U+28DB, "⣛", e2a39b), -_c(U+28DC, "⣜", e2a39c), -_c(U+28DD, "⣝", e2a39d), -_c(U+28DE, "⣞", e2a39e), -_c(U+28DF, "⣟", e2a39f), -_c(U+28E0, "⣠", e2a3a0), -_c(U+28E1, "⣡", e2a3a1), -_c(U+28E2, "⣢", e2a3a2), -_c(U+28E3, "⣣", e2a3a3), -_c(U+28E4, "⣤", e2a3a4), -_c(U+28E5, "⣥", e2a3a5), -_c(U+28E6, "⣦", e2a3a6), -_c(U+28E7, "⣧", e2a3a7), -_c(U+28E8, "⣨", e2a3a8), -_c(U+28E9, "⣩", e2a3a9), -_c(U+28EA, "⣪", e2a3aa), -_c(U+28EB, "⣫", e2a3ab), -_c(U+28EC, "⣬", e2a3ac), -_c(U+28ED, "⣭", e2a3ad), -_c(U+28EE, "⣮", e2a3ae), -_c(U+28EF, "⣯", e2a3af), -_c(U+28F0, "⣰", e2a3b0), -_c(U+28F1, "⣱", e2a3b1), -_c(U+28F2, "⣲", e2a3b2), -_c(U+28F3, "⣳", e2a3b3), -_c(U+28F4, "⣴", e2a3b4), -_c(U+28F5, "⣵", e2a3b5), -_c(U+28F6, "⣶", e2a3b6), -_c(U+28F7, "⣷", e2a3b7), -_c(U+28F8, "⣸", e2a3b8), -_c(U+28F9, "⣹", e2a3b9), -_c(U+28FA, "⣺", e2a3ba), -_c(U+28FB, "⣻", e2a3bb), -_c(U+28FC, "⣼", e2a3bc), -_c(U+28FD, "⣽", e2a3bd), -_c(U+28FE, "⣾", e2a3be), -_c(U+28FF, "⣿", e2a3bf), -_c(U+2900, "⤀", e2a480), -_c(U+2901, "⤁", e2a481), -_c(U+2902, "⤂", e2a482), -_c(U+2903, "⤃", e2a483), -_c(U+2904, "⤄", e2a484), -_c(U+2905, "⤅", e2a485), -_c(U+2906, "⤆", e2a486), -_c(U+2907, "⤇", e2a487), -_c(U+2908, "⤈", e2a488), -_c(U+2909, "⤉", e2a489), -_c(U+290A, "⤊", e2a48a), -_c(U+290B, "⤋", e2a48b), -_c(U+290C, "⤌", e2a48c), -_c(U+290D, "⤍", e2a48d), -_c(U+290E, "⤎", e2a48e), -_c(U+290F, "⤏", e2a48f), -_c(U+2910, "⤐", e2a490), -_c(U+2911, "⤑", e2a491), -_c(U+2912, "⤒", e2a492), -_c(U+2913, "⤓", e2a493), -_c(U+2914, "⤔", e2a494), -_c(U+2915, "⤕", e2a495), -_c(U+2916, "⤖", e2a496), -_c(U+2917, "⤗", e2a497), -_c(U+2918, "⤘", e2a498), -_c(U+2919, "⤙", e2a499), -_c(U+291A, "⤚", e2a49a), -_c(U+291B, "⤛", e2a49b), -_c(U+291C, "⤜", e2a49c), -_c(U+291D, "⤝", e2a49d), -_c(U+291E, "⤞", e2a49e), -_c(U+291F, "⤟", e2a49f), -_c(U+2920, "⤠", e2a4a0), -_c(U+2921, "⤡", e2a4a1), -_c(U+2922, "⤢", e2a4a2), -_c(U+2923, "⤣", e2a4a3), -_c(U+2924, "⤤", e2a4a4), -_c(U+2925, "⤥", e2a4a5), -_c(U+2926, "⤦", e2a4a6), -_c(U+2927, "⤧", e2a4a7), -_c(U+2928, "⤨", e2a4a8), -_c(U+2929, "⤩", e2a4a9), -_c(U+292A, "⤪", e2a4aa), -_c(U+292B, "⤫", e2a4ab), -_c(U+292C, "⤬", e2a4ac), -_c(U+292D, "⤭", e2a4ad), -_c(U+292E, "⤮", e2a4ae), -_c(U+292F, "⤯", e2a4af), -_c(U+2930, "⤰", e2a4b0), -_c(U+2931, "⤱", e2a4b1), -_c(U+2932, "⤲", e2a4b2), -_c(U+2933, "⤳", e2a4b3), -_c(U+2934, "⤴", e2a4b4), -_c(U+2935, "⤵", e2a4b5), -_c(U+2936, "⤶", e2a4b6), -_c(U+2937, "⤷", e2a4b7), -_c(U+2938, "⤸", e2a4b8), -_c(U+2939, "⤹", e2a4b9), -_c(U+293A, "⤺", e2a4ba), -_c(U+293B, "⤻", e2a4bb), -_c(U+293C, "⤼", e2a4bc), -_c(U+293D, "⤽", e2a4bd), -_c(U+293E, "⤾", e2a4be), -_c(U+293F, "⤿", e2a4bf), -_c(U+2940, "⥀", e2a580), -_c(U+2941, "⥁", e2a581), -_c(U+2942, "⥂", e2a582), -_c(U+2943, "⥃", e2a583), -_c(U+2944, "⥄", e2a584), -_c(U+2945, "⥅", e2a585), -_c(U+2946, "⥆", e2a586), -_c(U+2947, "⥇", e2a587), -_c(U+2948, "⥈", e2a588), -_c(U+2949, "⥉", e2a589), -_c(U+294A, "⥊", e2a58a), -_c(U+294B, "⥋", e2a58b), -_c(U+294C, "⥌", e2a58c), -_c(U+294D, "⥍", e2a58d), -_c(U+294E, "⥎", e2a58e), -_c(U+294F, "⥏", e2a58f), -_c(U+2950, "⥐", e2a590), -_c(U+2951, "⥑", e2a591), -_c(U+2952, "⥒", e2a592), -_c(U+2953, "⥓", e2a593), -_c(U+2954, "⥔", e2a594), -_c(U+2955, "⥕", e2a595), -_c(U+2956, "⥖", e2a596), -_c(U+2957, "⥗", e2a597), -_c(U+2958, "⥘", e2a598), -_c(U+2959, "⥙", e2a599), -_c(U+295A, "⥚", e2a59a), -_c(U+295B, "⥛", e2a59b), -_c(U+295C, "⥜", e2a59c), -_c(U+295D, "⥝", e2a59d), -_c(U+295E, "⥞", e2a59e), -_c(U+295F, "⥟", e2a59f), -_c(U+2960, "⥠", e2a5a0), -_c(U+2961, "⥡", e2a5a1), -_c(U+2962, "⥢", e2a5a2), -_c(U+2963, "⥣", e2a5a3), -_c(U+2964, "⥤", e2a5a4), -_c(U+2965, "⥥", e2a5a5), -_c(U+2966, "⥦", e2a5a6), -_c(U+2967, "⥧", e2a5a7), -_c(U+2968, "⥨", e2a5a8), -_c(U+2969, "⥩", e2a5a9), -_c(U+296A, "⥪", e2a5aa), -_c(U+296B, "⥫", e2a5ab), -_c(U+296C, "⥬", e2a5ac), -_c(U+296D, "⥭", e2a5ad), -_c(U+296E, "⥮", e2a5ae), -_c(U+296F, "⥯", e2a5af), -_c(U+2970, "⥰", e2a5b0), -_c(U+2971, "⥱", e2a5b1), -_c(U+2972, "⥲", e2a5b2), -_c(U+2973, "⥳", e2a5b3), -_c(U+2974, "⥴", e2a5b4), -_c(U+2975, "⥵", e2a5b5), -_c(U+2976, "⥶", e2a5b6), -_c(U+2977, "⥷", e2a5b7), -_c(U+2978, "⥸", e2a5b8), -_c(U+2979, "⥹", e2a5b9), -_c(U+297A, "⥺", e2a5ba), -_c(U+297B, "⥻", e2a5bb), -_c(U+297C, "⥼", e2a5bc), -_c(U+297D, "⥽", e2a5bd), -_c(U+297E, "⥾", e2a5be), -_c(U+297F, "⥿", e2a5bf), -_c(U+2980, "⦀", e2a680), -_c(U+2981, "⦁", e2a681), -_c(U+2982, "⦂", e2a682), -_c(U+2983, "⦃", e2a683), -_c(U+2984, "⦄", e2a684), -_c(U+2985, "⦅", e2a685), -_c(U+2986, "⦆", e2a686), -_c(U+2987, "⦇", e2a687), -_c(U+2988, "⦈", e2a688), -_c(U+2989, "⦉", e2a689), -_c(U+298A, "⦊", e2a68a), -_c(U+298B, "⦋", e2a68b), -_c(U+298C, "⦌", e2a68c), -_c(U+298D, "⦍", e2a68d), -_c(U+298E, "⦎", e2a68e), -_c(U+298F, "⦏", e2a68f), -_c(U+2990, "⦐", e2a690), -_c(U+2991, "⦑", e2a691), -_c(U+2992, "⦒", e2a692), -_c(U+2993, "⦓", e2a693), -_c(U+2994, "⦔", e2a694), -_c(U+2995, "⦕", e2a695), -_c(U+2996, "⦖", e2a696), -_c(U+2997, "⦗", e2a697), -_c(U+2998, "⦘", e2a698), -_c(U+2999, "⦙", e2a699), -_c(U+299A, "⦚", e2a69a), -_c(U+299B, "⦛", e2a69b), -_c(U+299C, "⦜", e2a69c), -_c(U+299D, "⦝", e2a69d), -_c(U+299E, "⦞", e2a69e), -_c(U+299F, "⦟", e2a69f), -_c(U+29A0, "⦠", e2a6a0), -_c(U+29A1, "⦡", e2a6a1), -_c(U+29A2, "⦢", e2a6a2), -_c(U+29A3, "⦣", e2a6a3), -_c(U+29A4, "⦤", e2a6a4), -_c(U+29A5, "⦥", e2a6a5), -_c(U+29A6, "⦦", e2a6a6), -_c(U+29A7, "⦧", e2a6a7), -_c(U+29A8, "⦨", e2a6a8), -_c(U+29A9, "⦩", e2a6a9), -_c(U+29AA, "⦪", e2a6aa), -_c(U+29AB, "⦫", e2a6ab), -_c(U+29AC, "⦬", e2a6ac), -_c(U+29AD, "⦭", e2a6ad), -_c(U+29AE, "⦮", e2a6ae), -_c(U+29AF, "⦯", e2a6af), -_c(U+29B0, "⦰", e2a6b0), -_c(U+29B1, "⦱", e2a6b1), -_c(U+29B2, "⦲", e2a6b2), -_c(U+29B3, "⦳", e2a6b3), -_c(U+29B4, "⦴", e2a6b4), -_c(U+29B5, "⦵", e2a6b5), -_c(U+29B6, "⦶", e2a6b6), -_c(U+29B7, "⦷", e2a6b7), -_c(U+29B8, "⦸", e2a6b8), -_c(U+29B9, "⦹", e2a6b9), -_c(U+29BA, "⦺", e2a6ba), -_c(U+29BB, "⦻", e2a6bb), -_c(U+29BC, "⦼", e2a6bc), -_c(U+29BD, "⦽", e2a6bd), -_c(U+29BE, "⦾", e2a6be), -_c(U+29BF, "⦿", e2a6bf), -_c(U+29C0, "⧀", e2a780), -_c(U+29C1, "⧁", e2a781), -_c(U+29C2, "⧂", e2a782), -_c(U+29C3, "⧃", e2a783), -_c(U+29C4, "⧄", e2a784), -_c(U+29C5, "⧅", e2a785), -_c(U+29C6, "⧆", e2a786), -_c(U+29C7, "⧇", e2a787), -_c(U+29C8, "⧈", e2a788), -_c(U+29C9, "⧉", e2a789), -_c(U+29CA, "⧊", e2a78a), -_c(U+29CB, "⧋", e2a78b), -_c(U+29CC, "⧌", e2a78c), -_c(U+29CD, "⧍", e2a78d), -_c(U+29CE, "⧎", e2a78e), -_c(U+29CF, "⧏", e2a78f), -_c(U+29D0, "⧐", e2a790), -_c(U+29D1, "⧑", e2a791), -_c(U+29D2, "⧒", e2a792), -_c(U+29D3, "⧓", e2a793), -_c(U+29D4, "⧔", e2a794), -_c(U+29D5, "⧕", e2a795), -_c(U+29D6, "⧖", e2a796), -_c(U+29D7, "⧗", e2a797), -_c(U+29D8, "⧘", e2a798), -_c(U+29D9, "⧙", e2a799), -_c(U+29DA, "⧚", e2a79a), -_c(U+29DB, "⧛", e2a79b), -_c(U+29DC, "⧜", e2a79c), -_c(U+29DD, "⧝", e2a79d), -_c(U+29DE, "⧞", e2a79e), -_c(U+29DF, "⧟", e2a79f), -_c(U+29E0, "⧠", e2a7a0), -_c(U+29E1, "⧡", e2a7a1), -_c(U+29E2, "⧢", e2a7a2), -_c(U+29E3, "⧣", e2a7a3), -_c(U+29E4, "⧤", e2a7a4), -_c(U+29E5, "⧥", e2a7a5), -_c(U+29E6, "⧦", e2a7a6), -_c(U+29E7, "⧧", e2a7a7), -_c(U+29E8, "⧨", e2a7a8), -_c(U+29E9, "⧩", e2a7a9), -_c(U+29EA, "⧪", e2a7aa), -_c(U+29EB, "⧫", e2a7ab), -_c(U+29EC, "⧬", e2a7ac), -_c(U+29ED, "⧭", e2a7ad), -_c(U+29EE, "⧮", e2a7ae), -_c(U+29EF, "⧯", e2a7af), -_c(U+29F0, "⧰", e2a7b0), -_c(U+29F1, "⧱", e2a7b1), -_c(U+29F2, "⧲", e2a7b2), -_c(U+29F3, "⧳", e2a7b3), -_c(U+29F4, "⧴", e2a7b4), -_c(U+29F5, "⧵", e2a7b5), -_c(U+29F6, "⧶", e2a7b6), -_c(U+29F7, "⧷", e2a7b7), -_c(U+29F8, "⧸", e2a7b8), -_c(U+29F9, "⧹", e2a7b9), -_c(U+29FA, "⧺", e2a7ba), -_c(U+29FB, "⧻", e2a7bb), -_c(U+29FC, "⧼", e2a7bc), -_c(U+29FD, "⧽", e2a7bd), -_c(U+29FE, "⧾", e2a7be), -_c(U+29FF, "⧿", e2a7bf), -_c(U+1D100, "𝄀", f09d8480), -_c(U+1D101, "𝄁", f09d8481), -_c(U+1D102, "𝄂", f09d8482), -_c(U+1D103, "𝄃", f09d8483), -_c(U+1D104, "𝄄", f09d8484), -_c(U+1D105, "𝄅", f09d8485), -_c(U+1D106, "𝄆", f09d8486), -_c(U+1D107, "𝄇", f09d8487), -_c(U+1D108, "𝄈", f09d8488), -_c(U+1D109, "𝄉", f09d8489), -_c(U+1D10A, "𝄊", f09d848a), -_c(U+1D10B, "𝄋", f09d848b), -_c(U+1D10C, "𝄌", f09d848c), -_c(U+1D10D, "𝄍", f09d848d), -_c(U+1D10E, "𝄎", f09d848e), -_c(U+1D10F, "𝄏", f09d848f), -_c(U+1D110, "𝄐", f09d8490), -_c(U+1D111, "𝄑", f09d8491), -_c(U+1D112, "𝄒", f09d8492), -_c(U+1D113, "𝄓", f09d8493), -_c(U+1D114, "𝄔", f09d8494), -_c(U+1D115, "𝄕", f09d8495), -_c(U+1D116, "𝄖", f09d8496), -_c(U+1D117, "𝄗", f09d8497), -_c(U+1D118, "𝄘", f09d8498), -_c(U+1D119, "𝄙", f09d8499), -_c(U+1D11A, "𝄚", f09d849a), -_c(U+1D11B, "𝄛", f09d849b), -_c(U+1D11C, "𝄜", f09d849c), -_c(U+1D11D, "𝄝", f09d849d), -_c(U+1D11E, "𝄞", f09d849e), -_c(U+1D11F, "𝄟", f09d849f), -_c(U+1D120, "𝄠", f09d84a0), -_c(U+1D121, "𝄡", f09d84a1), -_c(U+1D122, "𝄢", f09d84a2), -_c(U+1D123, "𝄣", f09d84a3), -_c(U+1D124, "𝄤", f09d84a4), -_c(U+1D125, "𝄥", f09d84a5), -_c(U+1D126, "𝄦", f09d84a6), -_c(U+1D127, "𝄧", f09d84a7), -_c(U+1D128, "𝄨", f09d84a8), -_c(U+1D129, "𝄩", f09d84a9), -_c(U+1D12A, "𝄪", f09d84aa), -_c(U+1D12B, "𝄫", f09d84ab), -_c(U+1D12C, "𝄬", f09d84ac), -_c(U+1D12D, "𝄭", f09d84ad), -_c(U+1D12E, "𝄮", f09d84ae), -_c(U+1D12F, "𝄯", f09d84af), -_c(U+1D130, "𝄰", f09d84b0), -_c(U+1D131, "𝄱", f09d84b1), -_c(U+1D132, "𝄲", f09d84b2), -_c(U+1D133, "𝄳", f09d84b3), -_c(U+1D134, "𝄴", f09d84b4), -_c(U+1D135, "𝄵", f09d84b5), -_c(U+1D136, "𝄶", f09d84b6), -_c(U+1D137, "𝄷", f09d84b7), -_c(U+1D138, "𝄸", f09d84b8), -_c(U+1D139, "𝄹", f09d84b9), -_c(U+1D13A, "𝄺", f09d84ba), -_c(U+1D13B, "𝄻", f09d84bb), -_c(U+1D13C, "𝄼", f09d84bc), -_c(U+1D13D, "𝄽", f09d84bd), -_c(U+1D13E, "𝄾", f09d84be), -_c(U+1D13F, "𝄿", f09d84bf), -_c(U+1D140, "𝅀", f09d8580), -_c(U+1D141, "𝅁", f09d8581), -_c(U+1D142, "𝅂", f09d8582), -_c(U+1D143, "𝅃", f09d8583), -_c(U+1D144, "𝅄", f09d8584), -_c(U+1D145, "𝅅", f09d8585), -_c(U+1D146, "𝅆", f09d8586), -_c(U+1D147, "𝅇", f09d8587), -_c(U+1D148, "𝅈", f09d8588), -_c(U+1D149, "𝅉", f09d8589), -_c(U+1D14A, "𝅊", f09d858a), -_c(U+1D14B, "𝅋", f09d858b), -_c(U+1D14C, "𝅌", f09d858c), -_c(U+1D14D, "𝅍", f09d858d), -_c(U+1D14E, "𝅎", f09d858e), -_c(U+1D14F, "𝅏", f09d858f), -_c(U+1D150, "𝅐", f09d8590), -_c(U+1D151, "𝅑", f09d8591), -_c(U+1D152, "𝅒", f09d8592), -_c(U+1D153, "𝅓", f09d8593), -_c(U+1D154, "𝅔", f09d8594), -_c(U+1D155, "𝅕", f09d8595), -_c(U+1D156, "𝅖", f09d8596), -_c(U+1D157, "𝅗", f09d8597), -_c(U+1D158, "𝅘", f09d8598), -_c(U+1D159, "𝅙", f09d8599), -_c(U+1D15A, "𝅚", f09d859a), -_c(U+1D15B, "𝅛", f09d859b), -_c(U+1D15C, "𝅜", f09d859c), -_c(U+1D15D, "𝅝", f09d859d), -_c(U+1D15E, "𝅗𝅥", f09d859e), -_c(U+1D15F, "𝅘𝅥", f09d859f), -_c(U+1D160, "𝅘𝅥𝅮", f09d85a0), -_c(U+1D161, "𝅘𝅥𝅯", f09d85a1), -_c(U+1D162, "𝅘𝅥𝅰", f09d85a2), -_c(U+1D163, "𝅘𝅥𝅱", f09d85a3), -_c(U+1D164, "𝅘𝅥𝅲", f09d85a4), -_c(U+1D165, "𝅥", f09d85a5), -_c(U+1D166, "𝅦", f09d85a6), -_c(U+1D167, "𝅧", f09d85a7), -_c(U+1D168, "𝅨", f09d85a8), -_c(U+1D169, "𝅩", f09d85a9), -_c(U+1D16A, "𝅪", f09d85aa), -_c(U+1D16B, "𝅫", f09d85ab), -_c(U+1D16C, "𝅬", f09d85ac), -_c(U+1D16D, "𝅭", f09d85ad), -_c(U+1D16E, "𝅮", f09d85ae), -_c(U+1D16F, "𝅯", f09d85af), -_c(U+1D170, "𝅰", f09d85b0), -_c(U+1D171, "𝅱", f09d85b1), -_c(U+1D172, "𝅲", f09d85b2), -_c(U+1D173, "𝅳", f09d85b3), -_c(U+1D174, "𝅴", f09d85b4), -_c(U+1D175, "𝅵", f09d85b5), -_c(U+1D176, "𝅶", f09d85b6), -_c(U+1D177, "𝅷", f09d85b7), -_c(U+1D178, "𝅸", f09d85b8), -_c(U+1D179, "𝅹", f09d85b9), -_c(U+1D17A, "𝅺", f09d85ba), -_c(U+1D17B, "𝅻", f09d85bb), -_c(U+1D17C, "𝅼", f09d85bc), -_c(U+1D17D, "𝅽", f09d85bd), -_c(U+1D17E, "𝅾", f09d85be), -_c(U+1D17F, "𝅿", f09d85bf), -_c(U+1D180, "𝆀", f09d8680), -_c(U+1D181, "𝆁", f09d8681), -_c(U+1D182, "𝆂", f09d8682), -_c(U+1D183, "𝆃", f09d8683), -_c(U+1D184, "𝆄", f09d8684), -_c(U+1D185, "𝆅", f09d8685), -_c(U+1D186, "𝆆", f09d8686), -_c(U+1D187, "𝆇", f09d8687), -_c(U+1D188, "𝆈", f09d8688), -_c(U+1D189, "𝆉", f09d8689), -_c(U+1D18A, "𝆊", f09d868a), -_c(U+1D18B, "𝆋", f09d868b), -_c(U+1D18C, "𝆌", f09d868c), -_c(U+1D18D, "𝆍", f09d868d), -_c(U+1D18E, "𝆎", f09d868e), -_c(U+1D18F, "𝆏", f09d868f), -_c(U+1D190, "𝆐", f09d8690), -_c(U+1D191, "𝆑", f09d8691), -_c(U+1D192, "𝆒", f09d8692), -_c(U+1D193, "𝆓", f09d8693), -_c(U+1D194, "𝆔", f09d8694), -_c(U+1D195, "𝆕", f09d8695), -_c(U+1D196, "𝆖", f09d8696), -_c(U+1D197, "𝆗", f09d8697), -_c(U+1D198, "𝆘", f09d8698), -_c(U+1D199, "𝆙", f09d8699), -_c(U+1D19A, "𝆚", f09d869a), -_c(U+1D19B, "𝆛", f09d869b), -_c(U+1D19C, "𝆜", f09d869c), -_c(U+1D19D, "𝆝", f09d869d), -_c(U+1D19E, "𝆞", f09d869e), -_c(U+1D19F, "𝆟", f09d869f), -_c(U+1D1A0, "𝆠", f09d86a0), -_c(U+1D1A1, "𝆡", f09d86a1), -_c(U+1D1A2, "𝆢", f09d86a2), -_c(U+1D1A3, "𝆣", f09d86a3), -_c(U+1D1A4, "𝆤", f09d86a4), -_c(U+1D1A5, "𝆥", f09d86a5), -_c(U+1D1A6, "𝆦", f09d86a6), -_c(U+1D1A7, "𝆧", f09d86a7), -_c(U+1D1A8, "𝆨", f09d86a8), -_c(U+1D1A9, "𝆩", f09d86a9), -_c(U+1D1AA, "𝆪", f09d86aa), -_c(U+1D1AB, "𝆫", f09d86ab), -_c(U+1D1AC, "𝆬", f09d86ac), -_c(U+1D1AD, "𝆭", f09d86ad), -_c(U+1D1AE, "𝆮", f09d86ae), -_c(U+1D1AF, "𝆯", f09d86af), -_c(U+1D1B0, "𝆰", f09d86b0), -_c(U+1D1B1, "𝆱", f09d86b1), -_c(U+1D1B2, "𝆲", f09d86b2), -_c(U+1D1B3, "𝆳", f09d86b3), -_c(U+1D1B4, "𝆴", f09d86b4), -_c(U+1D1B5, "𝆵", f09d86b5), -_c(U+1D1B6, "𝆶", f09d86b6), -_c(U+1D1B7, "𝆷", f09d86b7), -_c(U+1D1B8, "𝆸", f09d86b8), -_c(U+1D1B9, "𝆹", f09d86b9), -_c(U+1D1BA, "𝆺", f09d86ba), -_c(U+1D1BB, "𝆹𝅥", f09d86bb), -_c(U+1D1BC, "𝆺𝅥", f09d86bc), -_c(U+1D1BD, "𝆹𝅥𝅮", f09d86bd), -_c(U+1D1BE, "𝆺𝅥𝅮", f09d86be), -_c(U+1D1BF, "𝆹𝅥𝅯", f09d86bf), -_c(U+1D1C0, "𝆺𝅥𝅯", f09d8780), -_c(U+1D1C1, "𝇁", f09d8781), -_c(U+1D1C2, "𝇂", f09d8782), -_c(U+1D1C3, "𝇃", f09d8783), -_c(U+1D1C4, "𝇄", f09d8784), -_c(U+1D1C5, "𝇅", f09d8785), -_c(U+1D1C6, "𝇆", f09d8786), -_c(U+1D1C7, "𝇇", f09d8787), -_c(U+1D1C8, "𝇈", f09d8788), -_c(U+1D1C9, "𝇉", f09d8789), -_c(U+1D1CA, "𝇊", f09d878a), -_c(U+1D1CB, "𝇋", f09d878b), -_c(U+1D1CC, "𝇌", f09d878c), -_c(U+1D1CD, "𝇍", f09d878d), -_c(U+1D1CE, "𝇎", f09d878e), -_c(U+1D1CF, "𝇏", f09d878f), -_c(U+1D1D0, "𝇐", f09d8790), -_c(U+1D1D1, "𝇑", f09d8791), -_c(U+1D1D2, "𝇒", f09d8792), -_c(U+1D1D3, "𝇓", f09d8793), -_c(U+1D1D4, "𝇔", f09d8794), -_c(U+1D1D5, "𝇕", f09d8795), -_c(U+1D1D6, "𝇖", f09d8796), -_c(U+1D1D7, "𝇗", f09d8797), -_c(U+1D1D8, "𝇘", f09d8798), -_c(U+1D1D9, "𝇙", f09d8799), -_c(U+1D1DA, "𝇚", f09d879a), -_c(U+1D1DB, "𝇛", f09d879b), -_c(U+1D1DC, "𝇜", f09d879c), -_c(U+1D1DD, "𝇝", f09d879d), -_c(U+1D1DE, "𝇞", f09d879e), -_c(U+1D1DF, "𝇟", f09d879f), -_c(U+1D1E0, "𝇠", f09d87a0), -_c(U+1D1E1, "𝇡", f09d87a1), -_c(U+1D1E2, "𝇢", f09d87a2), -_c(U+1D1E3, "𝇣", f09d87a3), -_c(U+1D1E4, "𝇤", f09d87a4), -_c(U+1D1E5, "𝇥", f09d87a5), -_c(U+1D1E6, "𝇦", f09d87a6), -_c(U+1D1E7, "𝇧", f09d87a7), -_c(U+1D1E8, "𝇨", f09d87a8), -_c(U+1D1E9, "𝇩", f09d87a9), -_c(U+1D1EA, "𝇪", f09d87aa), -_c(U+1D1EB, "𝇫", f09d87ab), -_c(U+1D1EC, "𝇬", f09d87ac), -_c(U+1D1ED, "𝇭", f09d87ad), -_c(U+1D1EE, "𝇮", f09d87ae), -_c(U+1D1EF, "𝇯", f09d87af), -_c(U+1D1F0, "𝇰", f09d87b0), -_c(U+1D1F1, "𝇱", f09d87b1), -_c(U+1D1F2, "𝇲", f09d87b2), -_c(U+1D1F3, "𝇳", f09d87b3), -_c(U+1D1F4, "𝇴", f09d87b4), -_c(U+1D1F5, "𝇵", f09d87b5), -_c(U+1D1F6, "𝇶", f09d87b6), -_c(U+1D1F7, "𝇷", f09d87b7), -_c(U+1D1F8, "𝇸", f09d87b8), -_c(U+1D1F9, "𝇹", f09d87b9), -_c(U+1D1FA, "𝇺", f09d87ba), -_c(U+1D1FB, "𝇻", f09d87bb), -_c(U+1D1FC, "𝇼", f09d87bc), -_c(U+1D1FD, "𝇽", f09d87bd), -_c(U+1D1FE, "𝇾", f09d87be), -_c(U+1D1FF, "𝇿", f09d87bf), -_c(U+1D200, "𝈀", f09d8880), -_c(U+1D201, "𝈁", f09d8881), -_c(U+1D202, "𝈂", f09d8882), -_c(U+1D203, "𝈃", f09d8883), -_c(U+1D204, "𝈄", f09d8884), -_c(U+1D205, "𝈅", f09d8885), -_c(U+1D206, "𝈆", f09d8886), -_c(U+1D207, "𝈇", f09d8887), -_c(U+1D208, "𝈈", f09d8888), -_c(U+1D209, "𝈉", f09d8889), -_c(U+1D20A, "𝈊", f09d888a), -_c(U+1D20B, "𝈋", f09d888b), -_c(U+1D20C, "𝈌", f09d888c), -_c(U+1D20D, "𝈍", f09d888d), -_c(U+1D20E, "𝈎", f09d888e), -_c(U+1D20F, "𝈏", f09d888f), -_c(U+1D210, "𝈐", f09d8890), -_c(U+1D211, "𝈑", f09d8891), -_c(U+1D212, "𝈒", f09d8892), -_c(U+1D213, "𝈓", f09d8893), -_c(U+1D214, "𝈔", f09d8894), -_c(U+1D215, "𝈕", f09d8895), -_c(U+1D216, "𝈖", f09d8896), -_c(U+1D217, "𝈗", f09d8897), -_c(U+1D218, "𝈘", f09d8898), -_c(U+1D219, "𝈙", f09d8899), -_c(U+1D21A, "𝈚", f09d889a), -_c(U+1D21B, "𝈛", f09d889b), -_c(U+1D21C, "𝈜", f09d889c), -_c(U+1D21D, "𝈝", f09d889d), -_c(U+1D21E, "𝈞", f09d889e), -_c(U+1D21F, "𝈟", f09d889f), -_c(U+1D220, "𝈠", f09d88a0), -_c(U+1D221, "𝈡", f09d88a1), -_c(U+1D222, "𝈢", f09d88a2), -_c(U+1D223, "𝈣", f09d88a3), -_c(U+1D224, "𝈤", f09d88a4), -_c(U+1D225, "𝈥", f09d88a5), -_c(U+1D226, "𝈦", f09d88a6), -_c(U+1D227, "𝈧", f09d88a7), -_c(U+1D228, "𝈨", f09d88a8), -_c(U+1D229, "𝈩", f09d88a9), -_c(U+1D22A, "𝈪", f09d88aa), -_c(U+1D22B, "𝈫", f09d88ab), -_c(U+1D22C, "𝈬", f09d88ac), -_c(U+1D22D, "𝈭", f09d88ad), -_c(U+1D22E, "𝈮", f09d88ae), -_c(U+1D22F, "𝈯", f09d88af), -_c(U+1D230, "𝈰", f09d88b0), -_c(U+1D231, "𝈱", f09d88b1), -_c(U+1D232, "𝈲", f09d88b2), -_c(U+1D233, "𝈳", f09d88b3), -_c(U+1D234, "𝈴", f09d88b4), -_c(U+1D235, "𝈵", f09d88b5), -_c(U+1D236, "𝈶", f09d88b6), -_c(U+1D237, "𝈷", f09d88b7), -_c(U+1D238, "𝈸", f09d88b8), -_c(U+1D239, "𝈹", f09d88b9), -_c(U+1D23A, "𝈺", f09d88ba), -_c(U+1D23B, "𝈻", f09d88bb), -_c(U+1D23C, "𝈼", f09d88bc), -_c(U+1D23D, "𝈽", f09d88bd), -_c(U+1D23E, "𝈾", f09d88be), -_c(U+1D23F, "𝈿", f09d88bf), -_c(U+1D240, "𝉀", f09d8980), -_c(U+1D241, "𝉁", f09d8981), -_c(U+1D242, "𝉂", f09d8982), -_c(U+1D243, "𝉃", f09d8983), -_c(U+1D244, "𝉄", f09d8984), -_c(U+1D245, "𝉅", f09d8985), -_c(U+1D246, "𝉆", f09d8986), -_c(U+1D247, "𝉇", f09d8987), -_c(U+1D248, "𝉈", f09d8988), -_c(U+1D249, "𝉉", f09d8989), -_c(U+1D24A, "𝉊", f09d898a), -_c(U+1D24B, "𝉋", f09d898b), -_c(U+1D24C, "𝉌", f09d898c), -_c(U+1D24D, "𝉍", f09d898d), -_c(U+1D24E, "𝉎", f09d898e), -_c(U+1D24F, "𝉏", f09d898f), -_c(U+1D250, "𝉐", f09d8990), -_c(U+1D251, "𝉑", f09d8991), -_c(U+1D252, "𝉒", f09d8992), -_c(U+1D253, "𝉓", f09d8993), -_c(U+1D254, "𝉔", f09d8994), -_c(U+1D255, "𝉕", f09d8995), -_c(U+1D256, "𝉖", f09d8996), -_c(U+1D257, "𝉗", f09d8997), -_c(U+1D258, "𝉘", f09d8998), -_c(U+1D259, "𝉙", f09d8999), -_c(U+1D25A, "𝉚", f09d899a), -_c(U+1D25B, "𝉛", f09d899b), -_c(U+1D25C, "𝉜", f09d899c), -_c(U+1D25D, "𝉝", f09d899d), -_c(U+1D25E, "𝉞", f09d899e), -_c(U+1D25F, "𝉟", f09d899f), -_c(U+1D260, "𝉠", f09d89a0), -_c(U+1D261, "𝉡", f09d89a1), -_c(U+1D262, "𝉢", f09d89a2), -_c(U+1D263, "𝉣", f09d89a3), -_c(U+1D264, "𝉤", f09d89a4), -_c(U+1D265, "𝉥", f09d89a5), -_c(U+1D266, "𝉦", f09d89a6), -_c(U+1D267, "𝉧", f09d89a7), -_c(U+1D268, "𝉨", f09d89a8), -_c(U+1D269, "𝉩", f09d89a9), -_c(U+1D26A, "𝉪", f09d89aa), -_c(U+1D26B, "𝉫", f09d89ab), -_c(U+1D26C, "𝉬", f09d89ac), -_c(U+1D26D, "𝉭", f09d89ad), -_c(U+1D26E, "𝉮", f09d89ae), -_c(U+1D26F, "𝉯", f09d89af), -_c(U+1D270, "𝉰", f09d89b0), -_c(U+1D271, "𝉱", f09d89b1), -_c(U+1D272, "𝉲", f09d89b2), -_c(U+1D273, "𝉳", f09d89b3), -_c(U+1D274, "𝉴", f09d89b4), -_c(U+1D275, "𝉵", f09d89b5), -_c(U+1D276, "𝉶", f09d89b6), -_c(U+1D277, "𝉷", f09d89b7), -_c(U+1D278, "𝉸", f09d89b8), -_c(U+1D279, "𝉹", f09d89b9), -_c(U+1D27A, "𝉺", f09d89ba), -_c(U+1D27B, "𝉻", f09d89bb), -_c(U+1D27C, "𝉼", f09d89bc), -_c(U+1D27D, "𝉽", f09d89bd), -_c(U+1D27E, "𝉾", f09d89be), -_c(U+1D27F, "𝉿", f09d89bf), -_c(U+1D280, "𝊀", f09d8a80), -_c(U+1D281, "𝊁", f09d8a81), -_c(U+1D282, "𝊂", f09d8a82), -_c(U+1D283, "𝊃", f09d8a83), -_c(U+1D284, "𝊄", f09d8a84), -_c(U+1D285, "𝊅", f09d8a85), -_c(U+1D286, "𝊆", f09d8a86), -_c(U+1D287, "𝊇", f09d8a87), -_c(U+1D288, "𝊈", f09d8a88), -_c(U+1D289, "𝊉", f09d8a89), -_c(U+1D28A, "𝊊", f09d8a8a), -_c(U+1D28B, "𝊋", f09d8a8b), -_c(U+1D28C, "𝊌", f09d8a8c), -_c(U+1D28D, "𝊍", f09d8a8d), -_c(U+1D28E, "𝊎", f09d8a8e), -_c(U+1D28F, "𝊏", f09d8a8f), -_c(U+1D290, "𝊐", f09d8a90), -_c(U+1D291, "𝊑", f09d8a91), -_c(U+1D292, "𝊒", f09d8a92), -_c(U+1D293, "𝊓", f09d8a93), -_c(U+1D294, "𝊔", f09d8a94), -_c(U+1D295, "𝊕", f09d8a95), -_c(U+1D296, "𝊖", f09d8a96), -_c(U+1D297, "𝊗", f09d8a97), -_c(U+1D298, "𝊘", f09d8a98), -_c(U+1D299, "𝊙", f09d8a99), -_c(U+1D29A, "𝊚", f09d8a9a), -_c(U+1D29B, "𝊛", f09d8a9b), -_c(U+1D29C, "𝊜", f09d8a9c), -_c(U+1D29D, "𝊝", f09d8a9d), -_c(U+1D29E, "𝊞", f09d8a9e), -_c(U+1D29F, "𝊟", f09d8a9f), -_c(U+1D2A0, "𝊠", f09d8aa0), -_c(U+1D2A1, "𝊡", f09d8aa1), -_c(U+1D2A2, "𝊢", f09d8aa2), -_c(U+1D2A3, "𝊣", f09d8aa3), -_c(U+1D2A4, "𝊤", f09d8aa4), -_c(U+1D2A5, "𝊥", f09d8aa5), -_c(U+1D2A6, "𝊦", f09d8aa6), -_c(U+1D2A7, "𝊧", f09d8aa7), -_c(U+1D2A8, "𝊨", f09d8aa8), -_c(U+1D2A9, "𝊩", f09d8aa9), -_c(U+1D2AA, "𝊪", f09d8aaa), -_c(U+1D2AB, "𝊫", f09d8aab), -_c(U+1D2AC, "𝊬", f09d8aac), -_c(U+1D2AD, "𝊭", f09d8aad), -_c(U+1D2AE, "𝊮", f09d8aae), -_c(U+1D2AF, "𝊯", f09d8aaf), -_c(U+1D2B0, "𝊰", f09d8ab0), -_c(U+1D2B1, "𝊱", f09d8ab1), -_c(U+1D2B2, "𝊲", f09d8ab2), -_c(U+1D2B3, "𝊳", f09d8ab3), -_c(U+1D2B4, "𝊴", f09d8ab4), -_c(U+1D2B5, "𝊵", f09d8ab5), -_c(U+1D2B6, "𝊶", f09d8ab6), -_c(U+1D2B7, "𝊷", f09d8ab7), -_c(U+1D2B8, "𝊸", f09d8ab8), -_c(U+1D2B9, "𝊹", f09d8ab9), -_c(U+1D2BA, "𝊺", f09d8aba), -_c(U+1D2BB, "𝊻", f09d8abb), -_c(U+1D2BC, "𝊼", f09d8abc), -_c(U+1D2BD, "𝊽", f09d8abd), -_c(U+1D2BE, "𝊾", f09d8abe), -_c(U+1D2BF, "𝊿", f09d8abf), -_c(U+1D2C0, "𝋀", f09d8b80), -_c(U+1D2C1, "𝋁", f09d8b81), -_c(U+1D2C2, "𝋂", f09d8b82), -_c(U+1D2C3, "𝋃", f09d8b83), -_c(U+1D2C4, "𝋄", f09d8b84), -_c(U+1D2C5, "𝋅", f09d8b85), -_c(U+1D2C6, "𝋆", f09d8b86), -_c(U+1D2C7, "𝋇", f09d8b87), -_c(U+1D2C8, "𝋈", f09d8b88), -_c(U+1D2C9, "𝋉", f09d8b89), -_c(U+1D2CA, "𝋊", f09d8b8a), -_c(U+1D2CB, "𝋋", f09d8b8b), -_c(U+1D2CC, "𝋌", f09d8b8c), -_c(U+1D2CD, "𝋍", f09d8b8d), -_c(U+1D2CE, "𝋎", f09d8b8e), -_c(U+1D2CF, "𝋏", f09d8b8f), -_c(U+1D2D0, "𝋐", f09d8b90), -_c(U+1D2D1, "𝋑", f09d8b91), -_c(U+1D2D2, "𝋒", f09d8b92), -_c(U+1D2D3, "𝋓", f09d8b93), -_c(U+1D2D4, "𝋔", f09d8b94), -_c(U+1D2D5, "𝋕", f09d8b95), -_c(U+1D2D6, "𝋖", f09d8b96), -_c(U+1D2D7, "𝋗", f09d8b97), -_c(U+1D2D8, "𝋘", f09d8b98), -_c(U+1D2D9, "𝋙", f09d8b99), -_c(U+1D2DA, "𝋚", f09d8b9a), -_c(U+1D2DB, "𝋛", f09d8b9b), -_c(U+1D2DC, "𝋜", f09d8b9c), -_c(U+1D2DD, "𝋝", f09d8b9d), -_c(U+1D2DE, "𝋞", f09d8b9e), -_c(U+1D2DF, "𝋟", f09d8b9f), -_c(U+1D2E0, "𝋠", f09d8ba0), -_c(U+1D2E1, "𝋡", f09d8ba1), -_c(U+1D2E2, "𝋢", f09d8ba2), -_c(U+1D2E3, "𝋣", f09d8ba3), -_c(U+1D2E4, "𝋤", f09d8ba4), -_c(U+1D2E5, "𝋥", f09d8ba5), -_c(U+1D2E6, "𝋦", f09d8ba6), -_c(U+1D2E7, "𝋧", f09d8ba7), -_c(U+1D2E8, "𝋨", f09d8ba8), -_c(U+1D2E9, "𝋩", f09d8ba9), -_c(U+1D2EA, "𝋪", f09d8baa), -_c(U+1D2EB, "𝋫", f09d8bab), -_c(U+1D2EC, "𝋬", f09d8bac), -_c(U+1D2ED, "𝋭", f09d8bad), -_c(U+1D2EE, "𝋮", f09d8bae), -_c(U+1D2EF, "𝋯", f09d8baf), -_c(U+1D2F0, "𝋰", f09d8bb0), -_c(U+1D2F1, "𝋱", f09d8bb1), -_c(U+1D2F2, "𝋲", f09d8bb2), -_c(U+1D2F3, "𝋳", f09d8bb3), -_c(U+1D2F4, "𝋴", f09d8bb4), -_c(U+1D2F5, "𝋵", f09d8bb5), -_c(U+1D2F6, "𝋶", f09d8bb6), -_c(U+1D2F7, "𝋷", f09d8bb7), -_c(U+1D2F8, "𝋸", f09d8bb8), -_c(U+1D2F9, "𝋹", f09d8bb9), -_c(U+1D2FA, "𝋺", f09d8bba), -_c(U+1D2FB, "𝋻", f09d8bbb), -_c(U+1D2FC, "𝋼", f09d8bbc), -_c(U+1D2FD, "𝋽", f09d8bbd), -_c(U+1D2FE, "𝋾", f09d8bbe), -_c(U+1D2FF, "𝋿", f09d8bbf), -_c(U+1D300, "𝌀", f09d8c80), -_c(U+1D301, "𝌁", f09d8c81), -_c(U+1D302, "𝌂", f09d8c82), -_c(U+1D303, "𝌃", f09d8c83), -_c(U+1D304, "𝌄", f09d8c84), -_c(U+1D305, "𝌅", f09d8c85), -_c(U+1D306, "𝌆", f09d8c86), -_c(U+1D307, "𝌇", f09d8c87), -_c(U+1D308, "𝌈", f09d8c88), -_c(U+1D309, "𝌉", f09d8c89), -_c(U+1D30A, "𝌊", f09d8c8a), -_c(U+1D30B, "𝌋", f09d8c8b), -_c(U+1D30C, "𝌌", f09d8c8c), -_c(U+1D30D, "𝌍", f09d8c8d), -_c(U+1D30E, "𝌎", f09d8c8e), -_c(U+1D30F, "𝌏", f09d8c8f), -_c(U+1D310, "𝌐", f09d8c90), -_c(U+1D311, "𝌑", f09d8c91), -_c(U+1D312, "𝌒", f09d8c92), -_c(U+1D313, "𝌓", f09d8c93), -_c(U+1D314, "𝌔", f09d8c94), -_c(U+1D315, "𝌕", f09d8c95), -_c(U+1D316, "𝌖", f09d8c96), -_c(U+1D317, "𝌗", f09d8c97), -_c(U+1D318, "𝌘", f09d8c98), -_c(U+1D319, "𝌙", f09d8c99), -_c(U+1D31A, "𝌚", f09d8c9a), -_c(U+1D31B, "𝌛", f09d8c9b), -_c(U+1D31C, "𝌜", f09d8c9c), -_c(U+1D31D, "𝌝", f09d8c9d), -_c(U+1D31E, "𝌞", f09d8c9e), -_c(U+1D31F, "𝌟", f09d8c9f), -_c(U+1D320, "𝌠", f09d8ca0), -_c(U+1D321, "𝌡", f09d8ca1), -_c(U+1D322, "𝌢", f09d8ca2), -_c(U+1D323, "𝌣", f09d8ca3), -_c(U+1D324, "𝌤", f09d8ca4), -_c(U+1D325, "𝌥", f09d8ca5), -_c(U+1D326, "𝌦", f09d8ca6), -_c(U+1D327, "𝌧", f09d8ca7), -_c(U+1D328, "𝌨", f09d8ca8), -_c(U+1D329, "𝌩", f09d8ca9), -_c(U+1D32A, "𝌪", f09d8caa), -_c(U+1D32B, "𝌫", f09d8cab), -_c(U+1D32C, "𝌬", f09d8cac), -_c(U+1D32D, "𝌭", f09d8cad), -_c(U+1D32E, "𝌮", f09d8cae), -_c(U+1D32F, "𝌯", f09d8caf), -_c(U+1D330, "𝌰", f09d8cb0), -_c(U+1D331, "𝌱", f09d8cb1), -_c(U+1D332, "𝌲", f09d8cb2), -_c(U+1D333, "𝌳", f09d8cb3), -_c(U+1D334, "𝌴", f09d8cb4), -_c(U+1D335, "𝌵", f09d8cb5), -_c(U+1D336, "𝌶", f09d8cb6), -_c(U+1D337, "𝌷", f09d8cb7), -_c(U+1D338, "𝌸", f09d8cb8), -_c(U+1D339, "𝌹", f09d8cb9), -_c(U+1D33A, "𝌺", f09d8cba), -_c(U+1D33B, "𝌻", f09d8cbb), -_c(U+1D33C, "𝌼", f09d8cbc), -_c(U+1D33D, "𝌽", f09d8cbd), -_c(U+1D33E, "𝌾", f09d8cbe), -_c(U+1D33F, "𝌿", f09d8cbf), -_c(U+1D340, "𝍀", f09d8d80), -_c(U+1D341, "𝍁", f09d8d81), -_c(U+1D342, "𝍂", f09d8d82), -_c(U+1D343, "𝍃", f09d8d83), -_c(U+1D344, "𝍄", f09d8d84), -_c(U+1D345, "𝍅", f09d8d85), -_c(U+1D346, "𝍆", f09d8d86), -_c(U+1D347, "𝍇", f09d8d87), -_c(U+1D348, "𝍈", f09d8d88), -_c(U+1D349, "𝍉", f09d8d89), -_c(U+1D34A, "𝍊", f09d8d8a), -_c(U+1D34B, "𝍋", f09d8d8b), -_c(U+1D34C, "𝍌", f09d8d8c), -_c(U+1D34D, "𝍍", f09d8d8d), -_c(U+1D34E, "𝍎", f09d8d8e), -_c(U+1D34F, "𝍏", f09d8d8f), -_c(U+1D350, "𝍐", f09d8d90), -_c(U+1D351, "𝍑", f09d8d91), -_c(U+1D352, "𝍒", f09d8d92), -_c(U+1D353, "𝍓", f09d8d93), -_c(U+1D354, "𝍔", f09d8d94), -_c(U+1D355, "𝍕", f09d8d95), -_c(U+1D356, "𝍖", f09d8d96), -_c(U+1D357, "𝍗", f09d8d97), -_c(U+1D358, "𝍘", f09d8d98), -_c(U+1D359, "𝍙", f09d8d99), -_c(U+1D35A, "𝍚", f09d8d9a), -_c(U+1D35B, "𝍛", f09d8d9b), -_c(U+1D35C, "𝍜", f09d8d9c), -_c(U+1D35D, "𝍝", f09d8d9d), -_c(U+1D35E, "𝍞", f09d8d9e), -_c(U+1D35F, "𝍟", f09d8d9f), -_c(U+1D360, "𝍠", f09d8da0), -_c(U+1D361, "𝍡", f09d8da1), -_c(U+1D362, "𝍢", f09d8da2), -_c(U+1D363, "𝍣", f09d8da3), -_c(U+1D364, "𝍤", f09d8da4), -_c(U+1D365, "𝍥", f09d8da5), -_c(U+1D366, "𝍦", f09d8da6), -_c(U+1D367, "𝍧", f09d8da7), -_c(U+1D368, "𝍨", f09d8da8), -_c(U+1D369, "𝍩", f09d8da9), -_c(U+1D36A, "𝍪", f09d8daa), -_c(U+1D36B, "𝍫", f09d8dab), -_c(U+1D36C, "𝍬", f09d8dac), -_c(U+1D36D, "𝍭", f09d8dad), -_c(U+1D36E, "𝍮", f09d8dae), -_c(U+1D36F, "𝍯", f09d8daf), -_c(U+1D370, "𝍰", f09d8db0), -_c(U+1D371, "𝍱", f09d8db1), -_c(U+1D372, "𝍲", f09d8db2), -_c(U+1D373, "𝍳", f09d8db3), -_c(U+1D374, "𝍴", f09d8db4), -_c(U+1D375, "𝍵", f09d8db5), -_c(U+1D376, "𝍶", f09d8db6), -_c(U+1D377, "𝍷", f09d8db7), -_c(U+1D378, "𝍸", f09d8db8), -_c(U+1D379, "𝍹", f09d8db9), -_c(U+1D37A, "𝍺", f09d8dba), -_c(U+1D37B, "𝍻", f09d8dbb), -_c(U+1D37C, "𝍼", f09d8dbc), -_c(U+1D37D, "𝍽", f09d8dbd), -_c(U+1D37E, "𝍾", f09d8dbe), -_c(U+1D37F, "𝍿", f09d8dbf), -_c(U+1D380, "𝎀", f09d8e80), -_c(U+1D381, "𝎁", f09d8e81), -_c(U+1D382, "𝎂", f09d8e82), -_c(U+1D383, "𝎃", f09d8e83), -_c(U+1D384, "𝎄", f09d8e84), -_c(U+1D385, "𝎅", f09d8e85), -_c(U+1D386, "𝎆", f09d8e86), -_c(U+1D387, "𝎇", f09d8e87), -_c(U+1D388, "𝎈", f09d8e88), -_c(U+1D389, "𝎉", f09d8e89), -_c(U+1D38A, "𝎊", f09d8e8a), -_c(U+1D38B, "𝎋", f09d8e8b), -_c(U+1D38C, "𝎌", f09d8e8c), -_c(U+1D38D, "𝎍", f09d8e8d), -_c(U+1D38E, "𝎎", f09d8e8e), -_c(U+1D38F, "𝎏", f09d8e8f), -_c(U+1D390, "𝎐", f09d8e90), -_c(U+1D391, "𝎑", f09d8e91), -_c(U+1D392, "𝎒", f09d8e92), -_c(U+1D393, "𝎓", f09d8e93), -_c(U+1D394, "𝎔", f09d8e94), -_c(U+1D395, "𝎕", f09d8e95), -_c(U+1D396, "𝎖", f09d8e96), -_c(U+1D397, "𝎗", f09d8e97), -_c(U+1D398, "𝎘", f09d8e98), -_c(U+1D399, "𝎙", f09d8e99), -_c(U+1D39A, "𝎚", f09d8e9a), -_c(U+1D39B, "𝎛", f09d8e9b), -_c(U+1D39C, "𝎜", f09d8e9c), -_c(U+1D39D, "𝎝", f09d8e9d), -_c(U+1D39E, "𝎞", f09d8e9e), -_c(U+1D39F, "𝎟", f09d8e9f), -_c(U+1D3A0, "𝎠", f09d8ea0), -_c(U+1D3A1, "𝎡", f09d8ea1), -_c(U+1D3A2, "𝎢", f09d8ea2), -_c(U+1D3A3, "𝎣", f09d8ea3), -_c(U+1D3A4, "𝎤", f09d8ea4), -_c(U+1D3A5, "𝎥", f09d8ea5), -_c(U+1D3A6, "𝎦", f09d8ea6), -_c(U+1D3A7, "𝎧", f09d8ea7), -_c(U+1D3A8, "𝎨", f09d8ea8), -_c(U+1D3A9, "𝎩", f09d8ea9), -_c(U+1D3AA, "𝎪", f09d8eaa), -_c(U+1D3AB, "𝎫", f09d8eab), -_c(U+1D3AC, "𝎬", f09d8eac), -_c(U+1D3AD, "𝎭", f09d8ead), -_c(U+1D3AE, "𝎮", f09d8eae), -_c(U+1D3AF, "𝎯", f09d8eaf), -_c(U+1D3B0, "𝎰", f09d8eb0), -_c(U+1D3B1, "𝎱", f09d8eb1), -_c(U+1D3B2, "𝎲", f09d8eb2), -_c(U+1D3B3, "𝎳", f09d8eb3), -_c(U+1D3B4, "𝎴", f09d8eb4), -_c(U+1D3B5, "𝎵", f09d8eb5), -_c(U+1D3B6, "𝎶", f09d8eb6), -_c(U+1D3B7, "𝎷", f09d8eb7), -_c(U+1D3B8, "𝎸", f09d8eb8), -_c(U+1D3B9, "𝎹", f09d8eb9), -_c(U+1D3BA, "𝎺", f09d8eba), -_c(U+1D3BB, "𝎻", f09d8ebb), -_c(U+1D3BC, "𝎼", f09d8ebc), -_c(U+1D3BD, "𝎽", f09d8ebd), -_c(U+1D3BE, "𝎾", f09d8ebe), -_c(U+1D3BF, "𝎿", f09d8ebf), -_c(U+1D3C0, "𝏀", f09d8f80), -_c(U+1D3C1, "𝏁", f09d8f81), -_c(U+1D3C2, "𝏂", f09d8f82), -_c(U+1D3C3, "𝏃", f09d8f83), -_c(U+1D3C4, "𝏄", f09d8f84), -_c(U+1D3C5, "𝏅", f09d8f85), -_c(U+1D3C6, "𝏆", f09d8f86), -_c(U+1D3C7, "𝏇", f09d8f87), -_c(U+1D3C8, "𝏈", f09d8f88), -_c(U+1D3C9, "𝏉", f09d8f89), -_c(U+1D3CA, "𝏊", f09d8f8a), -_c(U+1D3CB, "𝏋", f09d8f8b), -_c(U+1D3CC, "𝏌", f09d8f8c), -_c(U+1D3CD, "𝏍", f09d8f8d), -_c(U+1D3CE, "𝏎", f09d8f8e), -_c(U+1D3CF, "𝏏", f09d8f8f), -_c(U+1D3D0, "𝏐", f09d8f90), -_c(U+1D3D1, "𝏑", f09d8f91), -_c(U+1D3D2, "𝏒", f09d8f92), -_c(U+1D3D3, "𝏓", f09d8f93), -_c(U+1D3D4, "𝏔", f09d8f94), -_c(U+1D3D5, "𝏕", f09d8f95), -_c(U+1D3D6, "𝏖", f09d8f96), -_c(U+1D3D7, "𝏗", f09d8f97), -_c(U+1D3D8, "𝏘", f09d8f98), -_c(U+1D3D9, "𝏙", f09d8f99), -_c(U+1D3DA, "𝏚", f09d8f9a), -_c(U+1D3DB, "𝏛", f09d8f9b), -_c(U+1D3DC, "𝏜", f09d8f9c), -_c(U+1D3DD, "𝏝", f09d8f9d), -_c(U+1D3DE, "𝏞", f09d8f9e), -_c(U+1D3DF, "𝏟", f09d8f9f), -_c(U+1D3E0, "𝏠", f09d8fa0), -_c(U+1D3E1, "𝏡", f09d8fa1), -_c(U+1D3E2, "𝏢", f09d8fa2), -_c(U+1D3E3, "𝏣", f09d8fa3), -_c(U+1D3E4, "𝏤", f09d8fa4), -_c(U+1D3E5, "𝏥", f09d8fa5), -_c(U+1D3E6, "𝏦", f09d8fa6), -_c(U+1D3E7, "𝏧", f09d8fa7), -_c(U+1D3E8, "𝏨", f09d8fa8), -_c(U+1D3E9, "𝏩", f09d8fa9), -_c(U+1D3EA, "𝏪", f09d8faa), -_c(U+1D3EB, "𝏫", f09d8fab), -_c(U+1D3EC, "𝏬", f09d8fac), -_c(U+1D3ED, "𝏭", f09d8fad), -_c(U+1D3EE, "𝏮", f09d8fae), -_c(U+1D3EF, "𝏯", f09d8faf), -_c(U+1D3F0, "𝏰", f09d8fb0), -_c(U+1D3F1, "𝏱", f09d8fb1), -_c(U+1D3F2, "𝏲", f09d8fb2), -_c(U+1D3F3, "𝏳", f09d8fb3), -_c(U+1D3F4, "𝏴", f09d8fb4), -_c(U+1D3F5, "𝏵", f09d8fb5), -_c(U+1D3F6, "𝏶", f09d8fb6), -_c(U+1D3F7, "𝏷", f09d8fb7), -_c(U+1D3F8, "𝏸", f09d8fb8), -_c(U+1D3F9, "𝏹", f09d8fb9), -_c(U+1D3FA, "𝏺", f09d8fba), -_c(U+1D3FB, "𝏻", f09d8fbb), -_c(U+1D3FC, "𝏼", f09d8fbc), -_c(U+1D3FD, "𝏽", f09d8fbd), -_c(U+1D3FE, "𝏾", f09d8fbe), -_c(U+1D3FF, "𝏿", f09d8fbf), -_c(U+1D400, "𝐀", f09d9080), -_c(U+1D401, "𝐁", f09d9081), -_c(U+1D402, "𝐂", f09d9082), -_c(U+1D403, "𝐃", f09d9083), -_c(U+1D404, "𝐄", f09d9084), -_c(U+1D405, "𝐅", f09d9085), -_c(U+1D406, "𝐆", f09d9086), -_c(U+1D407, "𝐇", f09d9087), -_c(U+1D408, "𝐈", f09d9088), -_c(U+1D409, "𝐉", f09d9089), -_c(U+1D40A, "𝐊", f09d908a), -_c(U+1D40B, "𝐋", f09d908b), -_c(U+1D40C, "𝐌", f09d908c), -_c(U+1D40D, "𝐍", f09d908d), -_c(U+1D40E, "𝐎", f09d908e), -_c(U+1D40F, "𝐏", f09d908f), -_c(U+1D410, "𝐐", f09d9090), -_c(U+1D411, "𝐑", f09d9091), -_c(U+1D412, "𝐒", f09d9092), -_c(U+1D413, "𝐓", f09d9093), -_c(U+1D414, "𝐔", f09d9094), -_c(U+1D415, "𝐕", f09d9095), -_c(U+1D416, "𝐖", f09d9096), -_c(U+1D417, "𝐗", f09d9097), -_c(U+1D418, "𝐘", f09d9098), -_c(U+1D419, "𝐙", f09d9099), -_c(U+1D41A, "𝐚", f09d909a), -_c(U+1D41B, "𝐛", f09d909b), -_c(U+1D41C, "𝐜", f09d909c), -_c(U+1D41D, "𝐝", f09d909d), -_c(U+1D41E, "𝐞", f09d909e), -_c(U+1D41F, "𝐟", f09d909f), -_c(U+1D420, "𝐠", f09d90a0), -_c(U+1D421, "𝐡", f09d90a1), -_c(U+1D422, "𝐢", f09d90a2), -_c(U+1D423, "𝐣", f09d90a3), -_c(U+1D424, "𝐤", f09d90a4), -_c(U+1D425, "𝐥", f09d90a5), -_c(U+1D426, "𝐦", f09d90a6), -_c(U+1D427, "𝐧", f09d90a7), -_c(U+1D428, "𝐨", f09d90a8), -_c(U+1D429, "𝐩", f09d90a9), -_c(U+1D42A, "𝐪", f09d90aa), -_c(U+1D42B, "𝐫", f09d90ab), -_c(U+1D42C, "𝐬", f09d90ac), -_c(U+1D42D, "𝐭", f09d90ad), -_c(U+1D42E, "𝐮", f09d90ae), -_c(U+1D42F, "𝐯", f09d90af), -_c(U+1D430, "𝐰", f09d90b0), -_c(U+1D431, "𝐱", f09d90b1), -_c(U+1D432, "𝐲", f09d90b2), -_c(U+1D433, "𝐳", f09d90b3), -_c(U+1D434, "𝐴", f09d90b4), -_c(U+1D435, "𝐵", f09d90b5), -_c(U+1D436, "𝐶", f09d90b6), -_c(U+1D437, "𝐷", f09d90b7), -_c(U+1D438, "𝐸", f09d90b8), -_c(U+1D439, "𝐹", f09d90b9), -_c(U+1D43A, "𝐺", f09d90ba), -_c(U+1D43B, "𝐻", f09d90bb), -_c(U+1D43C, "𝐼", f09d90bc), -_c(U+1D43D, "𝐽", f09d90bd), -_c(U+1D43E, "𝐾", f09d90be), -_c(U+1D43F, "𝐿", f09d90bf), -_c(U+1D440, "𝑀", f09d9180), -_c(U+1D441, "𝑁", f09d9181), -_c(U+1D442, "𝑂", f09d9182), -_c(U+1D443, "𝑃", f09d9183), -_c(U+1D444, "𝑄", f09d9184), -_c(U+1D445, "𝑅", f09d9185), -_c(U+1D446, "𝑆", f09d9186), -_c(U+1D447, "𝑇", f09d9187), -_c(U+1D448, "𝑈", f09d9188), -_c(U+1D449, "𝑉", f09d9189), -_c(U+1D44A, "𝑊", f09d918a), -_c(U+1D44B, "𝑋", f09d918b), -_c(U+1D44C, "𝑌", f09d918c), -_c(U+1D44D, "𝑍", f09d918d), -_c(U+1D44E, "𝑎", f09d918e), -_c(U+1D44F, "𝑏", f09d918f), -_c(U+1D450, "𝑐", f09d9190), -_c(U+1D451, "𝑑", f09d9191), -_c(U+1D452, "𝑒", f09d9192), -_c(U+1D453, "𝑓", f09d9193), -_c(U+1D454, "𝑔", f09d9194), -_c(U+1D455, "𝑕", f09d9195), -_c(U+1D456, "𝑖", f09d9196), -_c(U+1D457, "𝑗", f09d9197), -_c(U+1D458, "𝑘", f09d9198), -_c(U+1D459, "𝑙", f09d9199), -_c(U+1D45A, "𝑚", f09d919a), -_c(U+1D45B, "𝑛", f09d919b), -_c(U+1D45C, "𝑜", f09d919c), -_c(U+1D45D, "𝑝", f09d919d), -_c(U+1D45E, "𝑞", f09d919e), -_c(U+1D45F, "𝑟", f09d919f), -_c(U+1D460, "𝑠", f09d91a0), -_c(U+1D461, "𝑡", f09d91a1), -_c(U+1D462, "𝑢", f09d91a2), -_c(U+1D463, "𝑣", f09d91a3), -_c(U+1D464, "𝑤", f09d91a4), -_c(U+1D465, "𝑥", f09d91a5), -_c(U+1D466, "𝑦", f09d91a6), -_c(U+1D467, "𝑧", f09d91a7), -_c(U+1D468, "𝑨", f09d91a8), -_c(U+1D469, "𝑩", f09d91a9), -_c(U+1D46A, "𝑪", f09d91aa), -_c(U+1D46B, "𝑫", f09d91ab), -_c(U+1D46C, "𝑬", f09d91ac), -_c(U+1D46D, "𝑭", f09d91ad), -_c(U+1D46E, "𝑮", f09d91ae), -_c(U+1D46F, "𝑯", f09d91af), -_c(U+1D470, "𝑰", f09d91b0), -_c(U+1D471, "𝑱", f09d91b1), -_c(U+1D472, "𝑲", f09d91b2), -_c(U+1D473, "𝑳", f09d91b3), -_c(U+1D474, "𝑴", f09d91b4), -_c(U+1D475, "𝑵", f09d91b5), -_c(U+1D476, "𝑶", f09d91b6), -_c(U+1D477, "𝑷", f09d91b7), -_c(U+1D478, "𝑸", f09d91b8), -_c(U+1D479, "𝑹", f09d91b9), -_c(U+1D47A, "𝑺", f09d91ba), -_c(U+1D47B, "𝑻", f09d91bb), -_c(U+1D47C, "𝑼", f09d91bc), -_c(U+1D47D, "𝑽", f09d91bd), -_c(U+1D47E, "𝑾", f09d91be), -_c(U+1D47F, "𝑿", f09d91bf), -_c(U+1D480, "𝒀", f09d9280), -_c(U+1D481, "𝒁", f09d9281), -_c(U+1D482, "𝒂", f09d9282), -_c(U+1D483, "𝒃", f09d9283), -_c(U+1D484, "𝒄", f09d9284), -_c(U+1D485, "𝒅", f09d9285), -_c(U+1D486, "𝒆", f09d9286), -_c(U+1D487, "𝒇", f09d9287), -_c(U+1D488, "𝒈", f09d9288), -_c(U+1D489, "𝒉", f09d9289), -_c(U+1D48A, "𝒊", f09d928a), -_c(U+1D48B, "𝒋", f09d928b), -_c(U+1D48C, "𝒌", f09d928c), -_c(U+1D48D, "𝒍", f09d928d), -_c(U+1D48E, "𝒎", f09d928e), -_c(U+1D48F, "𝒏", f09d928f), -_c(U+1D490, "𝒐", f09d9290), -_c(U+1D491, "𝒑", f09d9291), -_c(U+1D492, "𝒒", f09d9292), -_c(U+1D493, "𝒓", f09d9293), -_c(U+1D494, "𝒔", f09d9294), -_c(U+1D495, "𝒕", f09d9295), -_c(U+1D496, "𝒖", f09d9296), -_c(U+1D497, "𝒗", f09d9297), -_c(U+1D498, "𝒘", f09d9298), -_c(U+1D499, "𝒙", f09d9299), -_c(U+1D49A, "𝒚", f09d929a), -_c(U+1D49B, "𝒛", f09d929b), -_c(U+1D49C, "𝒜", f09d929c), -_c(U+1D49D, "𝒝", f09d929d), -_c(U+1D49E, "𝒞", f09d929e), -_c(U+1D49F, "𝒟", f09d929f), -_c(U+1D4A0, "𝒠", f09d92a0), -_c(U+1D4A1, "𝒡", f09d92a1), -_c(U+1D4A2, "𝒢", f09d92a2), -_c(U+1D4A3, "𝒣", f09d92a3), -_c(U+1D4A4, "𝒤", f09d92a4), -_c(U+1D4A5, "𝒥", f09d92a5), -_c(U+1D4A6, "𝒦", f09d92a6), -_c(U+1D4A7, "𝒧", f09d92a7), -_c(U+1D4A8, "𝒨", f09d92a8), -_c(U+1D4A9, "𝒩", f09d92a9), -_c(U+1D4AA, "𝒪", f09d92aa), -_c(U+1D4AB, "𝒫", f09d92ab), -_c(U+1D4AC, "𝒬", f09d92ac), -_c(U+1D4AD, "𝒭", f09d92ad), -_c(U+1D4AE, "𝒮", f09d92ae), -_c(U+1D4AF, "𝒯", f09d92af), -_c(U+1D4B0, "𝒰", f09d92b0), -_c(U+1D4B1, "𝒱", f09d92b1), -_c(U+1D4B2, "𝒲", f09d92b2), -_c(U+1D4B3, "𝒳", f09d92b3), -_c(U+1D4B4, "𝒴", f09d92b4), -_c(U+1D4B5, "𝒵", f09d92b5), -_c(U+1D4B6, "𝒶", f09d92b6), -_c(U+1D4B7, "𝒷", f09d92b7), -_c(U+1D4B8, "𝒸", f09d92b8), -_c(U+1D4B9, "𝒹", f09d92b9), -_c(U+1D4BA, "𝒺", f09d92ba), -_c(U+1D4BB, "𝒻", f09d92bb), -_c(U+1D4BC, "𝒼", f09d92bc), -_c(U+1D4BD, "𝒽", f09d92bd), -_c(U+1D4BE, "𝒾", f09d92be), -_c(U+1D4BF, "𝒿", f09d92bf), -_c(U+1D4C0, "𝓀", f09d9380), -_c(U+1D4C1, "𝓁", f09d9381), -_c(U+1D4C2, "𝓂", f09d9382), -_c(U+1D4C3, "𝓃", f09d9383), -_c(U+1D4C4, "𝓄", f09d9384), -_c(U+1D4C5, "𝓅", f09d9385), -_c(U+1D4C6, "𝓆", f09d9386), -_c(U+1D4C7, "𝓇", f09d9387), -_c(U+1D4C8, "𝓈", f09d9388), -_c(U+1D4C9, "𝓉", f09d9389), -_c(U+1D4CA, "𝓊", f09d938a), -_c(U+1D4CB, "𝓋", f09d938b), -_c(U+1D4CC, "𝓌", f09d938c), -_c(U+1D4CD, "𝓍", f09d938d), -_c(U+1D4CE, "𝓎", f09d938e), -_c(U+1D4CF, "𝓏", f09d938f), -_c(U+1D4D0, "𝓐", f09d9390), -_c(U+1D4D1, "𝓑", f09d9391), -_c(U+1D4D2, "𝓒", f09d9392), -_c(U+1D4D3, "𝓓", f09d9393), -_c(U+1D4D4, "𝓔", f09d9394), -_c(U+1D4D5, "𝓕", f09d9395), -_c(U+1D4D6, "𝓖", f09d9396), -_c(U+1D4D7, "𝓗", f09d9397), -_c(U+1D4D8, "𝓘", f09d9398), -_c(U+1D4D9, "𝓙", f09d9399), -_c(U+1D4DA, "𝓚", f09d939a), -_c(U+1D4DB, "𝓛", f09d939b), -_c(U+1D4DC, "𝓜", f09d939c), -_c(U+1D4DD, "𝓝", f09d939d), -_c(U+1D4DE, "𝓞", f09d939e), -_c(U+1D4DF, "𝓟", f09d939f), -_c(U+1D4E0, "𝓠", f09d93a0), -_c(U+1D4E1, "𝓡", f09d93a1), -_c(U+1D4E2, "𝓢", f09d93a2), -_c(U+1D4E3, "𝓣", f09d93a3), -_c(U+1D4E4, "𝓤", f09d93a4), -_c(U+1D4E5, "𝓥", f09d93a5), -_c(U+1D4E6, "𝓦", f09d93a6), -_c(U+1D4E7, "𝓧", f09d93a7), -_c(U+1D4E8, "𝓨", f09d93a8), -_c(U+1D4E9, "𝓩", f09d93a9), -_c(U+1D4EA, "𝓪", f09d93aa), -_c(U+1D4EB, "𝓫", f09d93ab), -_c(U+1D4EC, "𝓬", f09d93ac), -_c(U+1D4ED, "𝓭", f09d93ad), -_c(U+1D4EE, "𝓮", f09d93ae), -_c(U+1D4EF, "𝓯", f09d93af), -_c(U+1D4F0, "𝓰", f09d93b0), -_c(U+1D4F1, "𝓱", f09d93b1), -_c(U+1D4F2, "𝓲", f09d93b2), -_c(U+1D4F3, "𝓳", f09d93b3), -_c(U+1D4F4, "𝓴", f09d93b4), -_c(U+1D4F5, "𝓵", f09d93b5), -_c(U+1D4F6, "𝓶", f09d93b6), -_c(U+1D4F7, "𝓷", f09d93b7), -_c(U+1D4F8, "𝓸", f09d93b8), -_c(U+1D4F9, "𝓹", f09d93b9), -_c(U+1D4FA, "𝓺", f09d93ba), -_c(U+1D4FB, "𝓻", f09d93bb), -_c(U+1D4FC, "𝓼", f09d93bc), -_c(U+1D4FD, "𝓽", f09d93bd), -_c(U+1D4FE, "𝓾", f09d93be), -_c(U+1D4FF, "𝓿", f09d93bf), -_c(U+1F600, "😀", f09f9880), -_c(U+1F601, "😁", f09f9881), -_c(U+1F602, "😂", f09f9882), -_c(U+1F603, "😃", f09f9883), -_c(U+1F604, "😄", f09f9884), -_c(U+1F605, "😅", f09f9885), -_c(U+1F606, "😆", f09f9886), -_c(U+1F607, "😇", f09f9887), -_c(U+1F608, "😈", f09f9888), -_c(U+1F609, "😉", f09f9889), -_c(U+1F60A, "😊", f09f988a), -_c(U+1F60B, "😋", f09f988b), -_c(U+1F60C, "😌", f09f988c), -_c(U+1F60D, "😍", f09f988d), -_c(U+1F60E, "😎", f09f988e), -_c(U+1F60F, "😏", f09f988f), -_c(U+1F610, "😐", f09f9890), -_c(U+1F611, "😑", f09f9891), -_c(U+1F612, "😒", f09f9892), -_c(U+1F613, "😓", f09f9893), -_c(U+1F614, "😔", f09f9894), -_c(U+1F615, "😕", f09f9895), -_c(U+1F616, "😖", f09f9896), -_c(U+1F617, "😗", f09f9897), -_c(U+1F618, "😘", f09f9898), -_c(U+1F619, "😙", f09f9899), -_c(U+1F61A, "😚", f09f989a), -_c(U+1F61B, "😛", f09f989b), -_c(U+1F61C, "😜", f09f989c), -_c(U+1F61D, "😝", f09f989d), -_c(U+1F61E, "😞", f09f989e), -_c(U+1F61F, "😟", f09f989f), -_c(U+1F620, "😠", f09f98a0), -_c(U+1F621, "😡", f09f98a1), -_c(U+1F622, "😢", f09f98a2), -_c(U+1F623, "😣", f09f98a3), -_c(U+1F624, "😤", f09f98a4), -_c(U+1F625, "😥", f09f98a5), -_c(U+1F626, "😦", f09f98a6), -_c(U+1F627, "😧", f09f98a7), -_c(U+1F628, "😨", f09f98a8), -_c(U+1F629, "😩", f09f98a9), -_c(U+1F62A, "😪", f09f98aa), -_c(U+1F62B, "😫", f09f98ab), -_c(U+1F62C, "😬", f09f98ac), -_c(U+1F62D, "😭", f09f98ad), -_c(U+1F62E, "😮", f09f98ae), -_c(U+1F62F, "😯", f09f98af), -_c(U+1F630, "😰", f09f98b0), -_c(U+1F631, "😱", f09f98b1), -_c(U+1F632, "😲", f09f98b2), -_c(U+1F633, "😳", f09f98b3), -_c(U+1F634, "😴", f09f98b4), -_c(U+1F635, "😵", f09f98b5), -_c(U+1F636, "😶", f09f98b6), -_c(U+1F637, "😷", f09f98b7), -_c(U+1F638, "😸", f09f98b8), -_c(U+1F639, "😹", f09f98b9), -_c(U+1F63A, "😺", f09f98ba), -_c(U+1F63B, "😻", f09f98bb), -_c(U+1F63C, "😼", f09f98bc), -_c(U+1F63D, "😽", f09f98bd), -_c(U+1F63E, "😾", f09f98be), -_c(U+1F63F, "😿", f09f98bf), -_c(U+1F640, "🙀", f09f9980), -_c(U+1F641, "🙁", f09f9981), -_c(U+1F642, "🙂", f09f9982), -_c(U+1F643, "🙃", f09f9983), -_c(U+1F644, "🙄", f09f9984), -_c(U+1F645, "🙅", f09f9985), -_c(U+1F646, "🙆", f09f9986), -_c(U+1F647, "🙇", f09f9987), -_c(U+1F648, "🙈", f09f9988), -_c(U+1F649, "🙉", f09f9989), -_c(U+1F64A, "🙊", f09f998a), -_c(U+1F64B, "🙋", f09f998b), -_c(U+1F64C, "🙌", f09f998c), -_c(U+1F64D, "🙍", f09f998d), -_c(U+1F64E, "🙎", f09f998e), -_c(U+1F64F, "🙏", f09f998f), -_c(U+1F650, "🙐", f09f9990), -_c(U+1F651, "🙑", f09f9991), -_c(U+1F652, "🙒", f09f9992), -_c(U+1F653, "🙓", f09f9993), -_c(U+1F654, "🙔", f09f9994), -_c(U+1F655, "🙕", f09f9995), -_c(U+1F656, "🙖", f09f9996), -_c(U+1F657, "🙗", f09f9997), -_c(U+1F658, "🙘", f09f9998), -_c(U+1F659, "🙙", f09f9999), -_c(U+1F65A, "🙚", f09f999a), -_c(U+1F65B, "🙛", f09f999b), -_c(U+1F65C, "🙜", f09f999c), -_c(U+1F65D, "🙝", f09f999d), -_c(U+1F65E, "🙞", f09f999e), -_c(U+1F65F, "🙟", f09f999f), -_c(U+1F660, "🙠", f09f99a0), -_c(U+1F661, "🙡", f09f99a1), -_c(U+1F662, "🙢", f09f99a2), -_c(U+1F663, "🙣", f09f99a3), -_c(U+1F664, "🙤", f09f99a4), -_c(U+1F665, "🙥", f09f99a5), -_c(U+1F666, "🙦", f09f99a6), -_c(U+1F667, "🙧", f09f99a7), -_c(U+1F668, "🙨", f09f99a8), -_c(U+1F669, "🙩", f09f99a9), -_c(U+1F66A, "🙪", f09f99aa), -_c(U+1F66B, "🙫", f09f99ab), -_c(U+1F66C, "🙬", f09f99ac), -_c(U+1F66D, "🙭", f09f99ad), -_c(U+1F66E, "🙮", f09f99ae), -_c(U+1F66F, "🙯", f09f99af), -_c(U+1F670, "🙰", f09f99b0), -_c(U+1F671, "🙱", f09f99b1), -_c(U+1F672, "🙲", f09f99b2), -_c(U+1F673, "🙳", f09f99b3), -_c(U+1F674, "🙴", f09f99b4), -_c(U+1F675, "🙵", f09f99b5), -_c(U+1F676, "🙶", f09f99b6), -_c(U+1F677, "🙷", f09f99b7), -_c(U+1F678, "🙸", f09f99b8), -_c(U+1F679, "🙹", f09f99b9), -_c(U+1F67A, "🙺", f09f99ba), -_c(U+1F67B, "🙻", f09f99bb), -_c(U+1F67C, "🙼", f09f99bc), -_c(U+1F67D, "🙽", f09f99bd), -_c(U+1F67E, "🙾", f09f99be), -_c(U+1F67F, "🙿", f09f99bf), -_c(U+1F680, "🚀", f09f9a80), -_c(U+1F681, "🚁", f09f9a81), -_c(U+1F682, "🚂", f09f9a82), -_c(U+1F683, "🚃", f09f9a83), -_c(U+1F684, "🚄", f09f9a84), -_c(U+1F685, "🚅", f09f9a85), -_c(U+1F686, "🚆", f09f9a86), -_c(U+1F687, "🚇", f09f9a87), -_c(U+1F688, "🚈", f09f9a88), -_c(U+1F689, "🚉", f09f9a89), -_c(U+1F68A, "🚊", f09f9a8a), -_c(U+1F68B, "🚋", f09f9a8b), -_c(U+1F68C, "🚌", f09f9a8c), -_c(U+1F68D, "🚍", f09f9a8d), -_c(U+1F68E, "🚎", f09f9a8e), -_c(U+1F68F, "🚏", f09f9a8f), -_c(U+1F690, "🚐", f09f9a90), -_c(U+1F691, "🚑", f09f9a91), -_c(U+1F692, "🚒", f09f9a92), -_c(U+1F693, "🚓", f09f9a93), -_c(U+1F694, "🚔", f09f9a94), -_c(U+1F695, "🚕", f09f9a95), -_c(U+1F696, "🚖", f09f9a96), -_c(U+1F697, "🚗", f09f9a97), -_c(U+1F698, "🚘", f09f9a98), -_c(U+1F699, "🚙", f09f9a99), -_c(U+1F69A, "🚚", f09f9a9a), -_c(U+1F69B, "🚛", f09f9a9b), -_c(U+1F69C, "🚜", f09f9a9c), -_c(U+1F69D, "🚝", f09f9a9d), -_c(U+1F69E, "🚞", f09f9a9e), -_c(U+1F69F, "🚟", f09f9a9f), -_c(U+1F6A0, "🚠", f09f9aa0), -_c(U+1F6A1, "🚡", f09f9aa1), -_c(U+1F6A2, "🚢", f09f9aa2), -_c(U+1F6A3, "🚣", f09f9aa3), -_c(U+1F6A4, "🚤", f09f9aa4), -_c(U+1F6A5, "🚥", f09f9aa5), -_c(U+1F6A6, "🚦", f09f9aa6), -_c(U+1F6A7, "🚧", f09f9aa7), -_c(U+1F6A8, "🚨", f09f9aa8), -_c(U+1F6A9, "🚩", f09f9aa9), -_c(U+1F6AA, "🚪", f09f9aaa), -_c(U+1F6AB, "🚫", f09f9aab), -_c(U+1F6AC, "🚬", f09f9aac), -_c(U+1F6AD, "🚭", f09f9aad), -_c(U+1F6AE, "🚮", f09f9aae), -_c(U+1F6AF, "🚯", f09f9aaf), -_c(U+1F6B0, "🚰", f09f9ab0), -_c(U+1F6B1, "🚱", f09f9ab1), -_c(U+1F6B2, "🚲", f09f9ab2), -_c(U+1F6B3, "🚳", f09f9ab3), -_c(U+1F6B4, "🚴", f09f9ab4), -_c(U+1F6B5, "🚵", f09f9ab5), -_c(U+1F6B6, "🚶", f09f9ab6), -_c(U+1F6B7, "🚷", f09f9ab7), -_c(U+1F6B8, "🚸", f09f9ab8), -_c(U+1F6B9, "🚹", f09f9ab9), -_c(U+1F6BA, "🚺", f09f9aba), -_c(U+1F6BB, "🚻", f09f9abb), -_c(U+1F6BC, "🚼", f09f9abc), -_c(U+1F6BD, "🚽", f09f9abd), -_c(U+1F6BE, "🚾", f09f9abe), -_c(U+1F6BF, "🚿", f09f9abf), -_c(U+1F6C0, "🛀", f09f9b80), -_c(U+1F6C1, "🛁", f09f9b81), -_c(U+1F6C2, "🛂", f09f9b82), -_c(U+1F6C3, "🛃", f09f9b83), -_c(U+1F6C4, "🛄", f09f9b84), -_c(U+1F6C5, "🛅", f09f9b85), -_c(U+1F6C6, "🛆", f09f9b86), -_c(U+1F6C7, "🛇", f09f9b87), -_c(U+1F6C8, "🛈", f09f9b88), -_c(U+1F6C9, "🛉", f09f9b89), -_c(U+1F6CA, "🛊", f09f9b8a), -_c(U+1F6CB, "🛋", f09f9b8b), -_c(U+1F6CC, "🛌", f09f9b8c), -_c(U+1F6CD, "🛍", f09f9b8d), -_c(U+1F6CE, "🛎", f09f9b8e), -_c(U+1F6CF, "🛏", f09f9b8f), -_c(U+1F6D0, "🛐", f09f9b90), -_c(U+1F6D1, "🛑", f09f9b91), -_c(U+1F6D2, "🛒", f09f9b92), -_c(U+1F6D3, "🛓", f09f9b93), -_c(U+1F6D4, "🛔", f09f9b94), -_c(U+1F6D5, "🛕", f09f9b95), -_c(U+1F6D6, "🛖", f09f9b96), -_c(U+1F6D7, "🛗", f09f9b97), -_c(U+1F6D8, "🛘", f09f9b98), -_c(U+1F6D9, "🛙", f09f9b99), -_c(U+1F6DA, "🛚", f09f9b9a), -_c(U+1F6DB, "🛛", f09f9b9b), -_c(U+1F6DC, "🛜", f09f9b9c), -_c(U+1F6DD, "🛝", f09f9b9d), -_c(U+1F6DE, "🛞", f09f9b9e), -_c(U+1F6DF, "🛟", f09f9b9f), -_c(U+1F6E0, "🛠", f09f9ba0), -_c(U+1F6E1, "🛡", f09f9ba1), -_c(U+1F6E2, "🛢", f09f9ba2), -_c(U+1F6E3, "🛣", f09f9ba3), -_c(U+1F6E4, "🛤", f09f9ba4), -_c(U+1F6E5, "🛥", f09f9ba5), -_c(U+1F6E6, "🛦", f09f9ba6), -_c(U+1F6E7, "🛧", f09f9ba7), -_c(U+1F6E8, "🛨", f09f9ba8), -_c(U+1F6E9, "🛩", f09f9ba9), -_c(U+1F6EA, "🛪", f09f9baa), -_c(U+1F6EB, "🛫", f09f9bab), -_c(U+1F6EC, "🛬", f09f9bac), -_c(U+1F6ED, "🛭", f09f9bad), -_c(U+1F6EE, "🛮", f09f9bae), -_c(U+1F6EF, "🛯", f09f9baf), -_c(U+1F6F0, "🛰", f09f9bb0), -_c(U+1F6F1, "🛱", f09f9bb1), -_c(U+1F6F2, "🛲", f09f9bb2), -_c(U+1F6F3, "🛳", f09f9bb3), -_c(U+1F6F4, "🛴", f09f9bb4), -_c(U+1F6F5, "🛵", f09f9bb5), -_c(U+1F6F6, "🛶", f09f9bb6), -_c(U+1F6F7, "🛷", f09f9bb7), -_c(U+1F6F8, "🛸", f09f9bb8), -_c(U+1F6F9, "🛹", f09f9bb9), -_c(U+1F6FA, "🛺", f09f9bba), -_c(U+1F6FB, "🛻", f09f9bbb), -_c(U+1F6FC, "🛼", f09f9bbc), -_c(U+1F6FD, "🛽", f09f9bbd), -_c(U+1F6FE, "🛾", f09f9bbe), -_c(U+1F6FF, "🛿", f09f9bbf), -_c(U+1F700, "🜀", f09f9c80), -_c(U+1F701, "🜁", f09f9c81), -_c(U+1F702, "🜂", f09f9c82), -_c(U+1F703, "🜃", f09f9c83), -_c(U+1F704, "🜄", f09f9c84), -_c(U+1F705, "🜅", f09f9c85), -_c(U+1F706, "🜆", f09f9c86), -_c(U+1F707, "🜇", f09f9c87), -_c(U+1F708, "🜈", f09f9c88), -_c(U+1F709, "🜉", f09f9c89), -_c(U+1F70A, "🜊", f09f9c8a), -_c(U+1F70B, "🜋", f09f9c8b), -_c(U+1F70C, "🜌", f09f9c8c), -_c(U+1F70D, "🜍", f09f9c8d), -_c(U+1F70E, "🜎", f09f9c8e), -_c(U+1F70F, "🜏", f09f9c8f), -_c(U+1F710, "🜐", f09f9c90), -_c(U+1F711, "🜑", f09f9c91), -_c(U+1F712, "🜒", f09f9c92), -_c(U+1F713, "🜓", f09f9c93), -_c(U+1F714, "🜔", f09f9c94), -_c(U+1F715, "🜕", f09f9c95), -_c(U+1F716, "🜖", f09f9c96), -_c(U+1F717, "🜗", f09f9c97), -_c(U+1F718, "🜘", f09f9c98), -_c(U+1F719, "🜙", f09f9c99), -_c(U+1F71A, "🜚", f09f9c9a), -_c(U+1F71B, "🜛", f09f9c9b), -_c(U+1F71C, "🜜", f09f9c9c), -_c(U+1F71D, "🜝", f09f9c9d), -_c(U+1F71E, "🜞", f09f9c9e), -_c(U+1F71F, "🜟", f09f9c9f), -_c(U+1F720, "🜠", f09f9ca0), -_c(U+1F721, "🜡", f09f9ca1), -_c(U+1F722, "🜢", f09f9ca2), -_c(U+1F723, "🜣", f09f9ca3), -_c(U+1F724, "🜤", f09f9ca4), -_c(U+1F725, "🜥", f09f9ca5), -_c(U+1F726, "🜦", f09f9ca6), -_c(U+1F727, "🜧", f09f9ca7), -_c(U+1F728, "🜨", f09f9ca8), -_c(U+1F729, "🜩", f09f9ca9), -_c(U+1F72A, "🜪", f09f9caa), -_c(U+1F72B, "🜫", f09f9cab), -_c(U+1F72C, "🜬", f09f9cac), -_c(U+1F72D, "🜭", f09f9cad), -_c(U+1F72E, "🜮", f09f9cae), -_c(U+1F72F, "🜯", f09f9caf), -_c(U+1F730, "🜰", f09f9cb0), -_c(U+1F731, "🜱", f09f9cb1), -_c(U+1F732, "🜲", f09f9cb2), -_c(U+1F733, "🜳", f09f9cb3), -_c(U+1F734, "🜴", f09f9cb4), -_c(U+1F735, "🜵", f09f9cb5), -_c(U+1F736, "🜶", f09f9cb6), -_c(U+1F737, "🜷", f09f9cb7), -_c(U+1F738, "🜸", f09f9cb8), -_c(U+1F739, "🜹", f09f9cb9), -_c(U+1F73A, "🜺", f09f9cba), -_c(U+1F73B, "🜻", f09f9cbb), -_c(U+1F73C, "🜼", f09f9cbc), -_c(U+1F73D, "🜽", f09f9cbd), -_c(U+1F73E, "🜾", f09f9cbe), -_c(U+1F73F, "🜿", f09f9cbf), -_c(U+1F740, "🝀", f09f9d80), -_c(U+1F741, "🝁", f09f9d81), -_c(U+1F742, "🝂", f09f9d82), -_c(U+1F743, "🝃", f09f9d83), -_c(U+1F744, "🝄", f09f9d84), -_c(U+1F745, "🝅", f09f9d85), -_c(U+1F746, "🝆", f09f9d86), -_c(U+1F747, "🝇", f09f9d87), -_c(U+1F748, "🝈", f09f9d88), -_c(U+1F749, "🝉", f09f9d89), -_c(U+1F74A, "🝊", f09f9d8a), -_c(U+1F74B, "🝋", f09f9d8b), -_c(U+1F74C, "🝌", f09f9d8c), -_c(U+1F74D, "🝍", f09f9d8d), -_c(U+1F74E, "🝎", f09f9d8e), -_c(U+1F74F, "🝏", f09f9d8f), -_c(U+1F750, "🝐", f09f9d90), -_c(U+1F751, "🝑", f09f9d91), -_c(U+1F752, "🝒", f09f9d92), -_c(U+1F753, "🝓", f09f9d93), -_c(U+1F754, "🝔", f09f9d94), -_c(U+1F755, "🝕", f09f9d95), -_c(U+1F756, "🝖", f09f9d96), -_c(U+1F757, "🝗", f09f9d97), -_c(U+1F758, "🝘", f09f9d98), -_c(U+1F759, "🝙", f09f9d99), -_c(U+1F75A, "🝚", f09f9d9a), -_c(U+1F75B, "🝛", f09f9d9b), -_c(U+1F75C, "🝜", f09f9d9c), -_c(U+1F75D, "🝝", f09f9d9d), -_c(U+1F75E, "🝞", f09f9d9e), -_c(U+1F75F, "🝟", f09f9d9f), -_c(U+1F760, "🝠", f09f9da0), -_c(U+1F761, "🝡", f09f9da1), -_c(U+1F762, "🝢", f09f9da2), -_c(U+1F763, "🝣", f09f9da3), -_c(U+1F764, "🝤", f09f9da4), -_c(U+1F765, "🝥", f09f9da5), -_c(U+1F766, "🝦", f09f9da6), -_c(U+1F767, "🝧", f09f9da7), -_c(U+1F768, "🝨", f09f9da8), -_c(U+1F769, "🝩", f09f9da9), -_c(U+1F76A, "🝪", f09f9daa), -_c(U+1F76B, "🝫", f09f9dab), -_c(U+1F76C, "🝬", f09f9dac), -_c(U+1F76D, "🝭", f09f9dad), -_c(U+1F76E, "🝮", f09f9dae), -_c(U+1F76F, "🝯", f09f9daf), -_c(U+1F770, "🝰", f09f9db0), -_c(U+1F771, "🝱", f09f9db1), -_c(U+1F772, "🝲", f09f9db2), -_c(U+1F773, "🝳", f09f9db3), -_c(U+1F774, "🝴", f09f9db4), -_c(U+1F775, "🝵", f09f9db5), -_c(U+1F776, "🝶", f09f9db6), -_c(U+1F777, "🝷", f09f9db7), -_c(U+1F778, "🝸", f09f9db8), -_c(U+1F779, "🝹", f09f9db9), -_c(U+1F77A, "🝺", f09f9dba), -_c(U+1F77B, "🝻", f09f9dbb), -_c(U+1F77C, "🝼", f09f9dbc), -_c(U+1F77D, "🝽", f09f9dbd), -_c(U+1F77E, "🝾", f09f9dbe), -_c(U+1F77F, "🝿", f09f9dbf), -_c(U+1F780, "🞀", f09f9e80), -_c(U+1F781, "🞁", f09f9e81), -_c(U+1F782, "🞂", f09f9e82), -_c(U+1F783, "🞃", f09f9e83), -_c(U+1F784, "🞄", f09f9e84), -_c(U+1F785, "🞅", f09f9e85), -_c(U+1F786, "🞆", f09f9e86), -_c(U+1F787, "🞇", f09f9e87), -_c(U+1F788, "🞈", f09f9e88), -_c(U+1F789, "🞉", f09f9e89), -_c(U+1F78A, "🞊", f09f9e8a), -_c(U+1F78B, "🞋", f09f9e8b), -_c(U+1F78C, "🞌", f09f9e8c), -_c(U+1F78D, "🞍", f09f9e8d), -_c(U+1F78E, "🞎", f09f9e8e), -_c(U+1F78F, "🞏", f09f9e8f), -_c(U+1F790, "🞐", f09f9e90), -_c(U+1F791, "🞑", f09f9e91), -_c(U+1F792, "🞒", f09f9e92), -_c(U+1F793, "🞓", f09f9e93), -_c(U+1F794, "🞔", f09f9e94), -_c(U+1F795, "🞕", f09f9e95), -_c(U+1F796, "🞖", f09f9e96), -_c(U+1F797, "🞗", f09f9e97), -_c(U+1F798, "🞘", f09f9e98), -_c(U+1F799, "🞙", f09f9e99), -_c(U+1F79A, "🞚", f09f9e9a), -_c(U+1F79B, "🞛", f09f9e9b), -_c(U+1F79C, "🞜", f09f9e9c), -_c(U+1F79D, "🞝", f09f9e9d), -_c(U+1F79E, "🞞", f09f9e9e), -_c(U+1F79F, "🞟", f09f9e9f), -_c(U+1F7A0, "🞠", f09f9ea0), -_c(U+1F7A1, "🞡", f09f9ea1), -_c(U+1F7A2, "🞢", f09f9ea2), -_c(U+1F7A3, "🞣", f09f9ea3), -_c(U+1F7A4, "🞤", f09f9ea4), -_c(U+1F7A5, "🞥", f09f9ea5), -_c(U+1F7A6, "🞦", f09f9ea6), -_c(U+1F7A7, "🞧", f09f9ea7), -_c(U+1F7A8, "🞨", f09f9ea8), -_c(U+1F7A9, "🞩", f09f9ea9), -_c(U+1F7AA, "🞪", f09f9eaa), -_c(U+1F7AB, "🞫", f09f9eab), -_c(U+1F7AC, "🞬", f09f9eac), -_c(U+1F7AD, "🞭", f09f9ead), -_c(U+1F7AE, "🞮", f09f9eae), -_c(U+1F7AF, "🞯", f09f9eaf), -_c(U+1F7B0, "🞰", f09f9eb0), -_c(U+1F7B1, "🞱", f09f9eb1), -_c(U+1F7B2, "🞲", f09f9eb2), -_c(U+1F7B3, "🞳", f09f9eb3), -_c(U+1F7B4, "🞴", f09f9eb4), -_c(U+1F7B5, "🞵", f09f9eb5), -_c(U+1F7B6, "🞶", f09f9eb6), -_c(U+1F7B7, "🞷", f09f9eb7), -_c(U+1F7B8, "🞸", f09f9eb8), -_c(U+1F7B9, "🞹", f09f9eb9), -_c(U+1F7BA, "🞺", f09f9eba), -_c(U+1F7BB, "🞻", f09f9ebb), -_c(U+1F7BC, "🞼", f09f9ebc), -_c(U+1F7BD, "🞽", f09f9ebd), -_c(U+1F7BE, "🞾", f09f9ebe), -_c(U+1F7BF, "🞿", f09f9ebf), -_c(U+1F7C0, "🟀", f09f9f80), -_c(U+1F7C1, "🟁", f09f9f81), -_c(U+1F7C2, "🟂", f09f9f82), -_c(U+1F7C3, "🟃", f09f9f83), -_c(U+1F7C4, "🟄", f09f9f84), -_c(U+1F7C5, "🟅", f09f9f85), -_c(U+1F7C6, "🟆", f09f9f86), -_c(U+1F7C7, "🟇", f09f9f87), -_c(U+1F7C8, "🟈", f09f9f88), -_c(U+1F7C9, "🟉", f09f9f89), -_c(U+1F7CA, "🟊", f09f9f8a), -_c(U+1F7CB, "🟋", f09f9f8b), -_c(U+1F7CC, "🟌", f09f9f8c), -_c(U+1F7CD, "🟍", f09f9f8d), -_c(U+1F7CE, "🟎", f09f9f8e), -_c(U+1F7CF, "🟏", f09f9f8f), -_c(U+1F7D0, "🟐", f09f9f90), -_c(U+1F7D1, "🟑", f09f9f91), -_c(U+1F7D2, "🟒", f09f9f92), -_c(U+1F7D3, "🟓", f09f9f93), -_c(U+1F7D4, "🟔", f09f9f94), -_c(U+1F7D5, "🟕", f09f9f95), -_c(U+1F7D6, "🟖", f09f9f96), -_c(U+1F7D7, "🟗", f09f9f97), -_c(U+1F7D8, "🟘", f09f9f98), -_c(U+1F7D9, "🟙", f09f9f99), -_c(U+1F7DA, "🟚", f09f9f9a), -_c(U+1F7DB, "🟛", f09f9f9b), -_c(U+1F7DC, "🟜", f09f9f9c), -_c(U+1F7DD, "🟝", f09f9f9d), -_c(U+1F7DE, "🟞", f09f9f9e), -_c(U+1F7DF, "🟟", f09f9f9f), -_c(U+1F7E0, "🟠", f09f9fa0), -_c(U+1F7E1, "🟡", f09f9fa1), -_c(U+1F7E2, "🟢", f09f9fa2), -_c(U+1F7E3, "🟣", f09f9fa3), -_c(U+1F7E4, "🟤", f09f9fa4), -_c(U+1F7E5, "🟥", f09f9fa5), -_c(U+1F7E6, "🟦", f09f9fa6), -_c(U+1F7E7, "🟧", f09f9fa7), -_c(U+1F7E8, "🟨", f09f9fa8), -_c(U+1F7E9, "🟩", f09f9fa9), -_c(U+1F7EA, "🟪", f09f9faa), -_c(U+1F7EB, "🟫", f09f9fab), -_c(U+1F7EC, "🟬", f09f9fac), -_c(U+1F7ED, "🟭", f09f9fad), -_c(U+1F7EE, "🟮", f09f9fae), -_c(U+1F7EF, "🟯", f09f9faf), -_c(U+1F7F0, "🟰", f09f9fb0), -_c(U+1F7F1, "🟱", f09f9fb1), -_c(U+1F7F2, "🟲", f09f9fb2), -_c(U+1F7F3, "🟳", f09f9fb3), -_c(U+1F7F4, "🟴", f09f9fb4), -_c(U+1F7F5, "🟵", f09f9fb5), -_c(U+1F7F6, "🟶", f09f9fb6), -_c(U+1F7F7, "🟷", f09f9fb7), -_c(U+1F7F8, "🟸", f09f9fb8), -_c(U+1F7F9, "🟹", f09f9fb9), -_c(U+1F7FA, "🟺", f09f9fba), -_c(U+1F7FB, "🟻", f09f9fbb), -_c(U+1F7FC, "🟼", f09f9fbc), -_c(U+1F7FD, "🟽", f09f9fbd), -_c(U+1F7FE, "🟾", f09f9fbe), -_c(U+1F7FF, "🟿", f09f9fbf), -_c(U+1F800, "🠀", f09fa080), -_c(U+1F801, "🠁", f09fa081), -_c(U+1F802, "🠂", f09fa082), -_c(U+1F803, "🠃", f09fa083), -_c(U+1F804, "🠄", f09fa084), -_c(U+1F805, "🠅", f09fa085), -_c(U+1F806, "🠆", f09fa086), -_c(U+1F807, "🠇", f09fa087), -_c(U+1F808, "🠈", f09fa088), -_c(U+1F809, "🠉", f09fa089), -_c(U+1F80A, "🠊", f09fa08a), -_c(U+1F80B, "🠋", f09fa08b), -_c(U+1F80C, "🠌", f09fa08c), -_c(U+1F80D, "🠍", f09fa08d), -_c(U+1F80E, "🠎", f09fa08e), -_c(U+1F80F, "🠏", f09fa08f), -_c(U+1F810, "🠐", f09fa090), -_c(U+1F811, "🠑", f09fa091), -_c(U+1F812, "🠒", f09fa092), -_c(U+1F813, "🠓", f09fa093), -_c(U+1F814, "🠔", f09fa094), -_c(U+1F815, "🠕", f09fa095), -_c(U+1F816, "🠖", f09fa096), -_c(U+1F817, "🠗", f09fa097), -_c(U+1F818, "🠘", f09fa098), -_c(U+1F819, "🠙", f09fa099), -_c(U+1F81A, "🠚", f09fa09a), -_c(U+1F81B, "🠛", f09fa09b), -_c(U+1F81C, "🠜", f09fa09c), -_c(U+1F81D, "🠝", f09fa09d), -_c(U+1F81E, "🠞", f09fa09e), -_c(U+1F81F, "🠟", f09fa09f), -_c(U+1F820, "🠠", f09fa0a0), -_c(U+1F821, "🠡", f09fa0a1), -_c(U+1F822, "🠢", f09fa0a2), -_c(U+1F823, "🠣", f09fa0a3), -_c(U+1F824, "🠤", f09fa0a4), -_c(U+1F825, "🠥", f09fa0a5), -_c(U+1F826, "🠦", f09fa0a6), -_c(U+1F827, "🠧", f09fa0a7), -_c(U+1F828, "🠨", f09fa0a8), -_c(U+1F829, "🠩", f09fa0a9), -_c(U+1F82A, "🠪", f09fa0aa), -_c(U+1F82B, "🠫", f09fa0ab), -_c(U+1F82C, "🠬", f09fa0ac), -_c(U+1F82D, "🠭", f09fa0ad), -_c(U+1F82E, "🠮", f09fa0ae), -_c(U+1F82F, "🠯", f09fa0af), -_c(U+1F830, "🠰", f09fa0b0), -_c(U+1F831, "🠱", f09fa0b1), -_c(U+1F832, "🠲", f09fa0b2), -_c(U+1F833, "🠳", f09fa0b3), -_c(U+1F834, "🠴", f09fa0b4), -_c(U+1F835, "🠵", f09fa0b5), -_c(U+1F836, "🠶", f09fa0b6), -_c(U+1F837, "🠷", f09fa0b7), -_c(U+1F838, "🠸", f09fa0b8), -_c(U+1F839, "🠹", f09fa0b9), -_c(U+1F83A, "🠺", f09fa0ba), -_c(U+1F83B, "🠻", f09fa0bb), -_c(U+1F83C, "🠼", f09fa0bc), -_c(U+1F83D, "🠽", f09fa0bd), -_c(U+1F83E, "🠾", f09fa0be), -_c(U+1F83F, "🠿", f09fa0bf), -_c(U+1F840, "🡀", f09fa180), -_c(U+1F841, "🡁", f09fa181), -_c(U+1F842, "🡂", f09fa182), -_c(U+1F843, "🡃", f09fa183), -_c(U+1F844, "🡄", f09fa184), -_c(U+1F845, "🡅", f09fa185), -_c(U+1F846, "🡆", f09fa186), -_c(U+1F847, "🡇", f09fa187), -_c(U+1F848, "🡈", f09fa188), -_c(U+1F849, "🡉", f09fa189), -_c(U+1F84A, "🡊", f09fa18a), -_c(U+1F84B, "🡋", f09fa18b), -_c(U+1F84C, "🡌", f09fa18c), -_c(U+1F84D, "🡍", f09fa18d), -_c(U+1F84E, "🡎", f09fa18e), -_c(U+1F84F, "🡏", f09fa18f), -_c(U+1F850, "🡐", f09fa190), -_c(U+1F851, "🡑", f09fa191), -_c(U+1F852, "🡒", f09fa192), -_c(U+1F853, "🡓", f09fa193), -_c(U+1F854, "🡔", f09fa194), -_c(U+1F855, "🡕", f09fa195), -_c(U+1F856, "🡖", f09fa196), -_c(U+1F857, "🡗", f09fa197), -_c(U+1F858, "🡘", f09fa198), -_c(U+1F859, "🡙", f09fa199), -_c(U+1F85A, "🡚", f09fa19a), -_c(U+1F85B, "🡛", f09fa19b), -_c(U+1F85C, "🡜", f09fa19c), -_c(U+1F85D, "🡝", f09fa19d), -_c(U+1F85E, "🡞", f09fa19e), -_c(U+1F85F, "🡟", f09fa19f), -_c(U+1F860, "🡠", f09fa1a0), -_c(U+1F861, "🡡", f09fa1a1), -_c(U+1F862, "🡢", f09fa1a2), -_c(U+1F863, "🡣", f09fa1a3), -_c(U+1F864, "🡤", f09fa1a4), -_c(U+1F865, "🡥", f09fa1a5), -_c(U+1F866, "🡦", f09fa1a6), -_c(U+1F867, "🡧", f09fa1a7), -_c(U+1F868, "🡨", f09fa1a8), -_c(U+1F869, "🡩", f09fa1a9), -_c(U+1F86A, "🡪", f09fa1aa), -_c(U+1F86B, "🡫", f09fa1ab), -_c(U+1F86C, "🡬", f09fa1ac), -_c(U+1F86D, "🡭", f09fa1ad), -_c(U+1F86E, "🡮", f09fa1ae), -_c(U+1F86F, "🡯", f09fa1af), -_c(U+1F870, "🡰", f09fa1b0), -_c(U+1F871, "🡱", f09fa1b1), -_c(U+1F872, "🡲", f09fa1b2), -_c(U+1F873, "🡳", f09fa1b3), -_c(U+1F874, "🡴", f09fa1b4), -_c(U+1F875, "🡵", f09fa1b5), -_c(U+1F876, "🡶", f09fa1b6), -_c(U+1F877, "🡷", f09fa1b7), -_c(U+1F878, "🡸", f09fa1b8), -_c(U+1F879, "🡹", f09fa1b9), -_c(U+1F87A, "🡺", f09fa1ba), -_c(U+1F87B, "🡻", f09fa1bb), -_c(U+1F87C, "🡼", f09fa1bc), -_c(U+1F87D, "🡽", f09fa1bd), -_c(U+1F87E, "🡾", f09fa1be), -_c(U+1F87F, "🡿", f09fa1bf), -_c(U+1F880, "🢀", f09fa280), -_c(U+1F881, "🢁", f09fa281), -_c(U+1F882, "🢂", f09fa282), -_c(U+1F883, "🢃", f09fa283), -_c(U+1F884, "🢄", f09fa284), -_c(U+1F885, "🢅", f09fa285), -_c(U+1F886, "🢆", f09fa286), -_c(U+1F887, "🢇", f09fa287), -_c(U+1F888, "🢈", f09fa288), -_c(U+1F889, "🢉", f09fa289), -_c(U+1F88A, "🢊", f09fa28a), -_c(U+1F88B, "🢋", f09fa28b), -_c(U+1F88C, "🢌", f09fa28c), -_c(U+1F88D, "🢍", f09fa28d), -_c(U+1F88E, "🢎", f09fa28e), -_c(U+1F88F, "🢏", f09fa28f), -_c(U+1F890, "🢐", f09fa290), -_c(U+1F891, "🢑", f09fa291), -_c(U+1F892, "🢒", f09fa292), -_c(U+1F893, "🢓", f09fa293), -_c(U+1F894, "🢔", f09fa294), -_c(U+1F895, "🢕", f09fa295), -_c(U+1F896, "🢖", f09fa296), -_c(U+1F897, "🢗", f09fa297), -_c(U+1F898, "🢘", f09fa298), -_c(U+1F899, "🢙", f09fa299), -_c(U+1F89A, "🢚", f09fa29a), -_c(U+1F89B, "🢛", f09fa29b), -_c(U+1F89C, "🢜", f09fa29c), -_c(U+1F89D, "🢝", f09fa29d), -_c(U+1F89E, "🢞", f09fa29e), -_c(U+1F89F, "🢟", f09fa29f), -_c(U+1F8A0, "🢠", f09fa2a0), -_c(U+1F8A1, "🢡", f09fa2a1), -_c(U+1F8A2, "🢢", f09fa2a2), -_c(U+1F8A3, "🢣", f09fa2a3), -_c(U+1F8A4, "🢤", f09fa2a4), -_c(U+1F8A5, "🢥", f09fa2a5), -_c(U+1F8A6, "🢦", f09fa2a6), -_c(U+1F8A7, "🢧", f09fa2a7), -_c(U+1F8A8, "🢨", f09fa2a8), -_c(U+1F8A9, "🢩", f09fa2a9), -_c(U+1F8AA, "🢪", f09fa2aa), -_c(U+1F8AB, "🢫", f09fa2ab), -_c(U+1F8AC, "🢬", f09fa2ac), -_c(U+1F8AD, "🢭", f09fa2ad), -_c(U+1F8AE, "🢮", f09fa2ae), -_c(U+1F8AF, "🢯", f09fa2af), -_c(U+1F8B0, "🢰", f09fa2b0), -_c(U+1F8B1, "🢱", f09fa2b1), -_c(U+1F8B2, "🢲", f09fa2b2), -_c(U+1F8B3, "🢳", f09fa2b3), -_c(U+1F8B4, "🢴", f09fa2b4), -_c(U+1F8B5, "🢵", f09fa2b5), -_c(U+1F8B6, "🢶", f09fa2b6), -_c(U+1F8B7, "🢷", f09fa2b7), -_c(U+1F8B8, "🢸", f09fa2b8), -_c(U+1F8B9, "🢹", f09fa2b9), -_c(U+1F8BA, "🢺", f09fa2ba), -_c(U+1F8BB, "🢻", f09fa2bb), -_c(U+1F8BC, "🢼", f09fa2bc), -_c(U+1F8BD, "🢽", f09fa2bd), -_c(U+1F8BE, "🢾", f09fa2be), -_c(U+1F8BF, "🢿", f09fa2bf), -_c(U+1F8C0, "🣀", f09fa380), -_c(U+1F8C1, "🣁", f09fa381), -_c(U+1F8C2, "🣂", f09fa382), -_c(U+1F8C3, "🣃", f09fa383), -_c(U+1F8C4, "🣄", f09fa384), -_c(U+1F8C5, "🣅", f09fa385), -_c(U+1F8C6, "🣆", f09fa386), -_c(U+1F8C7, "🣇", f09fa387), -_c(U+1F8C8, "🣈", f09fa388), -_c(U+1F8C9, "🣉", f09fa389), -_c(U+1F8CA, "🣊", f09fa38a), -_c(U+1F8CB, "🣋", f09fa38b), -_c(U+1F8CC, "🣌", f09fa38c), -_c(U+1F8CD, "🣍", f09fa38d), -_c(U+1F8CE, "🣎", f09fa38e), -_c(U+1F8CF, "🣏", f09fa38f), -_c(U+1F8D0, "🣐", f09fa390), -_c(U+1F8D1, "🣑", f09fa391), -_c(U+1F8D2, "🣒", f09fa392), -_c(U+1F8D3, "🣓", f09fa393), -_c(U+1F8D4, "🣔", f09fa394), -_c(U+1F8D5, "🣕", f09fa395), -_c(U+1F8D6, "🣖", f09fa396), -_c(U+1F8D7, "🣗", f09fa397), -_c(U+1F8D8, "🣘", f09fa398), -_c(U+1F8D9, "🣙", f09fa399), -_c(U+1F8DA, "🣚", f09fa39a), -_c(U+1F8DB, "🣛", f09fa39b), -_c(U+1F8DC, "🣜", f09fa39c), -_c(U+1F8DD, "🣝", f09fa39d), -_c(U+1F8DE, "🣞", f09fa39e), -_c(U+1F8DF, "🣟", f09fa39f), -_c(U+1F8E0, "🣠", f09fa3a0), -_c(U+1F8E1, "🣡", f09fa3a1), -_c(U+1F8E2, "🣢", f09fa3a2), -_c(U+1F8E3, "🣣", f09fa3a3), -_c(U+1F8E4, "🣤", f09fa3a4), -_c(U+1F8E5, "🣥", f09fa3a5), -_c(U+1F8E6, "🣦", f09fa3a6), -_c(U+1F8E7, "🣧", f09fa3a7), -_c(U+1F8E8, "🣨", f09fa3a8), -_c(U+1F8E9, "🣩", f09fa3a9), -_c(U+1F8EA, "🣪", f09fa3aa), -_c(U+1F8EB, "🣫", f09fa3ab), -_c(U+1F8EC, "🣬", f09fa3ac), -_c(U+1F8ED, "🣭", f09fa3ad), -_c(U+1F8EE, "🣮", f09fa3ae), -_c(U+1F8EF, "🣯", f09fa3af), -_c(U+1F8F0, "🣰", f09fa3b0), -_c(U+1F8F1, "🣱", f09fa3b1), -_c(U+1F8F2, "🣲", f09fa3b2), -_c(U+1F8F3, "🣳", f09fa3b3), -_c(U+1F8F4, "🣴", f09fa3b4), -_c(U+1F8F5, "🣵", f09fa3b5), -_c(U+1F8F6, "🣶", f09fa3b6), -_c(U+1F8F7, "🣷", f09fa3b7), -_c(U+1F8F8, "🣸", f09fa3b8), -_c(U+1F8F9, "🣹", f09fa3b9), -_c(U+1F8FA, "🣺", f09fa3ba), -_c(U+1F8FB, "🣻", f09fa3bb), -_c(U+1F8FC, "🣼", f09fa3bc), -_c(U+1F8FD, "🣽", f09fa3bd), -_c(U+1F8FE, "🣾", f09fa3be), -_c(U+1F8FF, "🣿", f09fa3bf), -_c(U+1F900, "🤀", f09fa480), -_c(U+1F901, "🤁", f09fa481), -_c(U+1F902, "🤂", f09fa482), -_c(U+1F903, "🤃", f09fa483), -_c(U+1F904, "🤄", f09fa484), -_c(U+1F905, "🤅", f09fa485), -_c(U+1F906, "🤆", f09fa486), -_c(U+1F907, "🤇", f09fa487), -_c(U+1F908, "🤈", f09fa488), -_c(U+1F909, "🤉", f09fa489), -_c(U+1F90A, "🤊", f09fa48a), -_c(U+1F90B, "🤋", f09fa48b), -_c(U+1F90C, "🤌", f09fa48c), -_c(U+1F90D, "🤍", f09fa48d), -_c(U+1F90E, "🤎", f09fa48e), -_c(U+1F90F, "🤏", f09fa48f), -_c(U+1F910, "🤐", f09fa490), -_c(U+1F911, "🤑", f09fa491), -_c(U+1F912, "🤒", f09fa492), -_c(U+1F913, "🤓", f09fa493), -_c(U+1F914, "🤔", f09fa494), -_c(U+1F915, "🤕", f09fa495), -_c(U+1F916, "🤖", f09fa496), -_c(U+1F917, "🤗", f09fa497), -_c(U+1F918, "🤘", f09fa498), -_c(U+1F919, "🤙", f09fa499), -_c(U+1F91A, "🤚", f09fa49a), -_c(U+1F91B, "🤛", f09fa49b), -_c(U+1F91C, "🤜", f09fa49c), -_c(U+1F91D, "🤝", f09fa49d), -_c(U+1F91E, "🤞", f09fa49e), -_c(U+1F91F, "🤟", f09fa49f), -_c(U+1F920, "🤠", f09fa4a0), -_c(U+1F921, "🤡", f09fa4a1), -_c(U+1F922, "🤢", f09fa4a2), -_c(U+1F923, "🤣", f09fa4a3), -_c(U+1F924, "🤤", f09fa4a4), -_c(U+1F925, "🤥", f09fa4a5), -_c(U+1F926, "🤦", f09fa4a6), -_c(U+1F927, "🤧", f09fa4a7), -_c(U+1F928, "🤨", f09fa4a8), -_c(U+1F929, "🤩", f09fa4a9), -_c(U+1F92A, "🤪", f09fa4aa), -_c(U+1F92B, "🤫", f09fa4ab), -_c(U+1F92C, "🤬", f09fa4ac), -_c(U+1F92D, "🤭", f09fa4ad), -_c(U+1F92E, "🤮", f09fa4ae), -_c(U+1F92F, "🤯", f09fa4af), -_c(U+1F930, "🤰", f09fa4b0), -_c(U+1F931, "🤱", f09fa4b1), -_c(U+1F932, "🤲", f09fa4b2), -_c(U+1F933, "🤳", f09fa4b3), -_c(U+1F934, "🤴", f09fa4b4), -_c(U+1F935, "🤵", f09fa4b5), -_c(U+1F936, "🤶", f09fa4b6), -_c(U+1F937, "🤷", f09fa4b7), -_c(U+1F938, "🤸", f09fa4b8), -_c(U+1F939, "🤹", f09fa4b9), -_c(U+1F93A, "🤺", f09fa4ba), -_c(U+1F93B, "🤻", f09fa4bb), -_c(U+1F93C, "🤼", f09fa4bc), -_c(U+1F93D, "🤽", f09fa4bd), -_c(U+1F93E, "🤾", f09fa4be), -_c(U+1F93F, "🤿", f09fa4bf), -_c(U+1F940, "🥀", f09fa580), -_c(U+1F941, "🥁", f09fa581), -_c(U+1F942, "🥂", f09fa582), -_c(U+1F943, "🥃", f09fa583), -_c(U+1F944, "🥄", f09fa584), -_c(U+1F945, "🥅", f09fa585), -_c(U+1F946, "🥆", f09fa586), -_c(U+1F947, "🥇", f09fa587), -_c(U+1F948, "🥈", f09fa588), -_c(U+1F949, "🥉", f09fa589), -_c(U+1F94A, "🥊", f09fa58a), -_c(U+1F94B, "🥋", f09fa58b), -_c(U+1F94C, "🥌", f09fa58c), -_c(U+1F94D, "🥍", f09fa58d), -_c(U+1F94E, "🥎", f09fa58e), -_c(U+1F94F, "🥏", f09fa58f), -_c(U+1F950, "🥐", f09fa590), -_c(U+1F951, "🥑", f09fa591), -_c(U+1F952, "🥒", f09fa592), -_c(U+1F953, "🥓", f09fa593), -_c(U+1F954, "🥔", f09fa594), -_c(U+1F955, "🥕", f09fa595), -_c(U+1F956, "🥖", f09fa596), -_c(U+1F957, "🥗", f09fa597), -_c(U+1F958, "🥘", f09fa598), -_c(U+1F959, "🥙", f09fa599), -_c(U+1F95A, "🥚", f09fa59a), -_c(U+1F95B, "🥛", f09fa59b), -_c(U+1F95C, "🥜", f09fa59c), -_c(U+1F95D, "🥝", f09fa59d), -_c(U+1F95E, "🥞", f09fa59e), -_c(U+1F95F, "🥟", f09fa59f), -_c(U+1F960, "🥠", f09fa5a0), -_c(U+1F961, "🥡", f09fa5a1), -_c(U+1F962, "🥢", f09fa5a2), -_c(U+1F963, "🥣", f09fa5a3), -_c(U+1F964, "🥤", f09fa5a4), -_c(U+1F965, "🥥", f09fa5a5), -_c(U+1F966, "🥦", f09fa5a6), -_c(U+1F967, "🥧", f09fa5a7), -_c(U+1F968, "🥨", f09fa5a8), -_c(U+1F969, "🥩", f09fa5a9), -_c(U+1F96A, "🥪", f09fa5aa), -_c(U+1F96B, "🥫", f09fa5ab), -_c(U+1F96C, "🥬", f09fa5ac), -_c(U+1F96D, "🥭", f09fa5ad), -_c(U+1F96E, "🥮", f09fa5ae), -_c(U+1F96F, "🥯", f09fa5af), -_c(U+1F970, "🥰", f09fa5b0), -_c(U+1F971, "🥱", f09fa5b1), -_c(U+1F972, "🥲", f09fa5b2), -_c(U+1F973, "🥳", f09fa5b3), -_c(U+1F974, "🥴", f09fa5b4), -_c(U+1F975, "🥵", f09fa5b5), -_c(U+1F976, "🥶", f09fa5b6), -_c(U+1F977, "🥷", f09fa5b7), -_c(U+1F978, "🥸", f09fa5b8), -_c(U+1F979, "🥹", f09fa5b9), -_c(U+1F97A, "🥺", f09fa5ba), -_c(U+1F97B, "🥻", f09fa5bb), -_c(U+1F97C, "🥼", f09fa5bc), -_c(U+1F97D, "🥽", f09fa5bd), -_c(U+1F97E, "🥾", f09fa5be), -_c(U+1F97F, "🥿", f09fa5bf), -_c(U+1F980, "🦀", f09fa680), -_c(U+1F981, "🦁", f09fa681), -_c(U+1F982, "🦂", f09fa682), -_c(U+1F983, "🦃", f09fa683), -_c(U+1F984, "🦄", f09fa684), -_c(U+1F985, "🦅", f09fa685), -_c(U+1F986, "🦆", f09fa686), -_c(U+1F987, "🦇", f09fa687), -_c(U+1F988, "🦈", f09fa688), -_c(U+1F989, "🦉", f09fa689), -_c(U+1F98A, "🦊", f09fa68a), -_c(U+1F98B, "🦋", f09fa68b), -_c(U+1F98C, "🦌", f09fa68c), -_c(U+1F98D, "🦍", f09fa68d), -_c(U+1F98E, "🦎", f09fa68e), -_c(U+1F98F, "🦏", f09fa68f), -_c(U+1F990, "🦐", f09fa690), -_c(U+1F991, "🦑", f09fa691), -_c(U+1F992, "🦒", f09fa692), -_c(U+1F993, "🦓", f09fa693), -_c(U+1F994, "🦔", f09fa694), -_c(U+1F995, "🦕", f09fa695), -_c(U+1F996, "🦖", f09fa696), -_c(U+1F997, "🦗", f09fa697), -_c(U+1F998, "🦘", f09fa698), -_c(U+1F999, "🦙", f09fa699), -_c(U+1F99A, "🦚", f09fa69a), -_c(U+1F99B, "🦛", f09fa69b), -_c(U+1F99C, "🦜", f09fa69c), -_c(U+1F99D, "🦝", f09fa69d), -_c(U+1F99E, "🦞", f09fa69e), -_c(U+1F99F, "🦟", f09fa69f), -_c(U+1F9A0, "🦠", f09fa6a0), -_c(U+1F9A1, "🦡", f09fa6a1), -_c(U+1F9A2, "🦢", f09fa6a2), -_c(U+1F9A3, "🦣", f09fa6a3), -_c(U+1F9A4, "🦤", f09fa6a4), -_c(U+1F9A5, "🦥", f09fa6a5), -_c(U+1F9A6, "🦦", f09fa6a6), -_c(U+1F9A7, "🦧", f09fa6a7), -_c(U+1F9A8, "🦨", f09fa6a8), -_c(U+1F9A9, "🦩", f09fa6a9), -_c(U+1F9AA, "🦪", f09fa6aa), -_c(U+1F9AB, "🦫", f09fa6ab), -_c(U+1F9AC, "🦬", f09fa6ac), -_c(U+1F9AD, "🦭", f09fa6ad), -_c(U+1F9AE, "🦮", f09fa6ae), -_c(U+1F9AF, "🦯", f09fa6af), -_c(U+1F9B0, "🦰", f09fa6b0), -_c(U+1F9B1, "🦱", f09fa6b1), -_c(U+1F9B2, "🦲", f09fa6b2), -_c(U+1F9B3, "🦳", f09fa6b3), -_c(U+1F9B4, "🦴", f09fa6b4), -_c(U+1F9B5, "🦵", f09fa6b5), -_c(U+1F9B6, "🦶", f09fa6b6), -_c(U+1F9B7, "🦷", f09fa6b7), -_c(U+1F9B8, "🦸", f09fa6b8), -_c(U+1F9B9, "🦹", f09fa6b9), -_c(U+1F9BA, "🦺", f09fa6ba), -_c(U+1F9BB, "🦻", f09fa6bb), -_c(U+1F9BC, "🦼", f09fa6bc), -_c(U+1F9BD, "🦽", f09fa6bd), -_c(U+1F9BE, "🦾", f09fa6be), -_c(U+1F9BF, "🦿", f09fa6bf), -_c(U+1F9C0, "🧀", f09fa780), -_c(U+1F9C1, "🧁", f09fa781), -_c(U+1F9C2, "🧂", f09fa782), -_c(U+1F9C3, "🧃", f09fa783), -_c(U+1F9C4, "🧄", f09fa784), -_c(U+1F9C5, "🧅", f09fa785), -_c(U+1F9C6, "🧆", f09fa786), -_c(U+1F9C7, "🧇", f09fa787), -_c(U+1F9C8, "🧈", f09fa788), -_c(U+1F9C9, "🧉", f09fa789), -_c(U+1F9CA, "🧊", f09fa78a), -_c(U+1F9CB, "🧋", f09fa78b), -_c(U+1F9CC, "🧌", f09fa78c), -_c(U+1F9CD, "🧍", f09fa78d), -_c(U+1F9CE, "🧎", f09fa78e), -_c(U+1F9CF, "🧏", f09fa78f), -_c(U+1F9D0, "🧐", f09fa790), -_c(U+1F9D1, "🧑", f09fa791), -_c(U+1F9D2, "🧒", f09fa792), -_c(U+1F9D3, "🧓", f09fa793), -_c(U+1F9D4, "🧔", f09fa794), -_c(U+1F9D5, "🧕", f09fa795), -_c(U+1F9D6, "🧖", f09fa796), -_c(U+1F9D7, "🧗", f09fa797), -_c(U+1F9D8, "🧘", f09fa798), -_c(U+1F9D9, "🧙", f09fa799), -_c(U+1F9DA, "🧚", f09fa79a), -_c(U+1F9DB, "🧛", f09fa79b), -_c(U+1F9DC, "🧜", f09fa79c), -_c(U+1F9DD, "🧝", f09fa79d), -_c(U+1F9DE, "🧞", f09fa79e), -_c(U+1F9DF, "🧟", f09fa79f), -_c(U+1F9E0, "🧠", f09fa7a0), -_c(U+1F9E1, "🧡", f09fa7a1), -_c(U+1F9E2, "🧢", f09fa7a2), -_c(U+1F9E3, "🧣", f09fa7a3), -_c(U+1F9E4, "🧤", f09fa7a4), -_c(U+1F9E5, "🧥", f09fa7a5), -_c(U+1F9E6, "🧦", f09fa7a6), -_c(U+1F9E7, "🧧", f09fa7a7), -_c(U+1F9E8, "🧨", f09fa7a8), -_c(U+1F9E9, "🧩", f09fa7a9), -_c(U+1F9EA, "🧪", f09fa7aa), -_c(U+1F9EB, "🧫", f09fa7ab), -_c(U+1F9EC, "🧬", f09fa7ac), -_c(U+1F9ED, "🧭", f09fa7ad), -_c(U+1F9EE, "🧮", f09fa7ae), -_c(U+1F9EF, "🧯", f09fa7af), -_c(U+1F9F0, "🧰", f09fa7b0), -_c(U+1F9F1, "🧱", f09fa7b1), -_c(U+1F9F2, "🧲", f09fa7b2), -_c(U+1F9F3, "🧳", f09fa7b3), -_c(U+1F9F4, "🧴", f09fa7b4), -_c(U+1F9F5, "🧵", f09fa7b5), -_c(U+1F9F6, "🧶", f09fa7b6), -_c(U+1F9F7, "🧷", f09fa7b7), -_c(U+1F9F8, "🧸", f09fa7b8), -_c(U+1F9F9, "🧹", f09fa7b9), -_c(U+1F9FA, "🧺", f09fa7ba), -_c(U+1F9FB, "🧻", f09fa7bb), -_c(U+1F9FC, "🧼", f09fa7bc), -_c(U+1F9FD, "🧽", f09fa7bd), -_c(U+1F9FE, "🧾", f09fa7be), -_c(U+1F9FF, "🧿", f09fa7bf), -_c(U+100000, "􀀀", f4808080), -_c(U+100001, "􀀁", f4808081), -_c(U+100002, "􀀂", f4808082), -_c(U+100003, "􀀃", f4808083), -_c(U+100004, "􀀄", f4808084), -_c(U+100005, "􀀅", f4808085), -_c(U+100006, "􀀆", f4808086), -_c(U+100007, "􀀇", f4808087), -_c(U+100008, "􀀈", f4808088), -_c(U+100009, "􀀉", f4808089), -_c(U+10000A, "􀀊", f480808a), -_c(U+10000B, "􀀋", f480808b), -_c(U+10000C, "􀀌", f480808c), -_c(U+10000D, "􀀍", f480808d), -_c(U+10000E, "􀀎", f480808e), -_c(U+10000F, "􀀏", f480808f), -_c(U+100010, "􀀐", f4808090), -_c(U+100011, "􀀑", f4808091), -_c(U+100012, "􀀒", f4808092), -_c(U+100013, "􀀓", f4808093), -_c(U+100014, "􀀔", f4808094), -_c(U+100015, "􀀕", f4808095), -_c(U+100016, "􀀖", f4808096), -_c(U+100017, "􀀗", f4808097), -_c(U+100018, "􀀘", f4808098), -_c(U+100019, "􀀙", f4808099), -_c(U+10001A, "􀀚", f480809a), -_c(U+10001B, "􀀛", f480809b), -_c(U+10001C, "􀀜", f480809c), -_c(U+10001D, "􀀝", f480809d), -_c(U+10001E, "􀀞", f480809e), -_c(U+10001F, "􀀟", f480809f), -_c(U+100020, "􀀠", f48080a0), -_c(U+100021, "􀀡", f48080a1), -_c(U+100022, "􀀢", f48080a2), -_c(U+100023, "􀀣", f48080a3), -_c(U+100024, "􀀤", f48080a4), -_c(U+100025, "􀀥", f48080a5), -_c(U+100026, "􀀦", f48080a6), -_c(U+100027, "􀀧", f48080a7), -_c(U+100028, "􀀨", f48080a8), -_c(U+100029, "􀀩", f48080a9), -_c(U+10002A, "􀀪", f48080aa), -_c(U+10002B, "􀀫", f48080ab), -_c(U+10002C, "􀀬", f48080ac), -_c(U+10002D, "􀀭", f48080ad), -_c(U+10002E, "􀀮", f48080ae), -_c(U+10002F, "􀀯", f48080af), -_c(U+100030, "􀀰", f48080b0), -_c(U+100031, "􀀱", f48080b1), -_c(U+100032, "􀀲", f48080b2), -_c(U+100033, "􀀳", f48080b3), -_c(U+100034, "􀀴", f48080b4), -_c(U+100035, "􀀵", f48080b5), -_c(U+100036, "􀀶", f48080b6), -_c(U+100037, "􀀷", f48080b7), -_c(U+100038, "􀀸", f48080b8), -_c(U+100039, "􀀹", f48080b9), -_c(U+10003A, "􀀺", f48080ba), -_c(U+10003B, "􀀻", f48080bb), -_c(U+10003C, "􀀼", f48080bc), -_c(U+10003D, "􀀽", f48080bd), -_c(U+10003E, "􀀾", f48080be), -_c(U+10003F, "􀀿", f48080bf), -_c(U+100040, "􀁀", f4808180), -_c(U+100041, "􀁁", f4808181), -_c(U+100042, "􀁂", f4808182), -_c(U+100043, "􀁃", f4808183), -_c(U+100044, "􀁄", f4808184), -_c(U+100045, "􀁅", f4808185), -_c(U+100046, "􀁆", f4808186), -_c(U+100047, "􀁇", f4808187), -_c(U+100048, "􀁈", f4808188), -_c(U+100049, "􀁉", f4808189), -_c(U+10004A, "􀁊", f480818a), -_c(U+10004B, "􀁋", f480818b), -_c(U+10004C, "􀁌", f480818c), -_c(U+10004D, "􀁍", f480818d), -_c(U+10004E, "􀁎", f480818e), -_c(U+10004F, "􀁏", f480818f), -_c(U+100050, "􀁐", f4808190), -_c(U+100051, "􀁑", f4808191), -_c(U+100052, "􀁒", f4808192), -_c(U+100053, "􀁓", f4808193), -_c(U+100054, "􀁔", f4808194), -_c(U+100055, "􀁕", f4808195), -_c(U+100056, "􀁖", f4808196), -_c(U+100057, "􀁗", f4808197), -_c(U+100058, "􀁘", f4808198), -_c(U+100059, "􀁙", f4808199), -_c(U+10005A, "􀁚", f480819a), -_c(U+10005B, "􀁛", f480819b), -_c(U+10005C, "􀁜", f480819c), -_c(U+10005D, "􀁝", f480819d), -_c(U+10005E, "􀁞", f480819e), -_c(U+10005F, "􀁟", f480819f), -_c(U+100060, "􀁠", f48081a0), -_c(U+100061, "􀁡", f48081a1), -_c(U+100062, "􀁢", f48081a2), -_c(U+100063, "􀁣", f48081a3), -_c(U+100064, "􀁤", f48081a4), -_c(U+100065, "􀁥", f48081a5), -_c(U+100066, "􀁦", f48081a6), -_c(U+100067, "􀁧", f48081a7), -_c(U+100068, "􀁨", f48081a8), -_c(U+100069, "􀁩", f48081a9), -_c(U+10006A, "􀁪", f48081aa), -_c(U+10006B, "􀁫", f48081ab), -_c(U+10006C, "􀁬", f48081ac), -_c(U+10006D, "􀁭", f48081ad), -_c(U+10006E, "􀁮", f48081ae), -_c(U+10006F, "􀁯", f48081af), -_c(U+100070, "􀁰", f48081b0), -_c(U+100071, "􀁱", f48081b1), -_c(U+100072, "􀁲", f48081b2), -_c(U+100073, "􀁳", f48081b3), -_c(U+100074, "􀁴", f48081b4), -_c(U+100075, "􀁵", f48081b5), -_c(U+100076, "􀁶", f48081b6), -_c(U+100077, "􀁷", f48081b7), -_c(U+100078, "􀁸", f48081b8), -_c(U+100079, "􀁹", f48081b9), -_c(U+10007A, "􀁺", f48081ba), -_c(U+10007B, "􀁻", f48081bb), -_c(U+10007C, "􀁼", f48081bc), -_c(U+10007D, "􀁽", f48081bd), -_c(U+10007E, "􀁾", f48081be), -_c(U+10007F, "􀁿", f48081bf), -_c(U+100080, "􀂀", f4808280), -_c(U+100081, "􀂁", f4808281), -_c(U+100082, "􀂂", f4808282), -_c(U+100083, "􀂃", f4808283), -_c(U+100084, "􀂄", f4808284), -_c(U+100085, "􀂅", f4808285), -_c(U+100086, "􀂆", f4808286), -_c(U+100087, "􀂇", f4808287), -_c(U+100088, "􀂈", f4808288), -_c(U+100089, "􀂉", f4808289), -_c(U+10008A, "􀂊", f480828a), -_c(U+10008B, "􀂋", f480828b), -_c(U+10008C, "􀂌", f480828c), -_c(U+10008D, "􀂍", f480828d), -_c(U+10008E, "􀂎", f480828e), -_c(U+10008F, "􀂏", f480828f), -_c(U+100090, "􀂐", f4808290), -_c(U+100091, "􀂑", f4808291), -_c(U+100092, "􀂒", f4808292), -_c(U+100093, "􀂓", f4808293), -_c(U+100094, "􀂔", f4808294), -_c(U+100095, "􀂕", f4808295), -_c(U+100096, "􀂖", f4808296), -_c(U+100097, "􀂗", f4808297), -_c(U+100098, "􀂘", f4808298), -_c(U+100099, "􀂙", f4808299), -_c(U+10009A, "􀂚", f480829a), -_c(U+10009B, "􀂛", f480829b), -_c(U+10009C, "􀂜", f480829c), -_c(U+10009D, "􀂝", f480829d), -_c(U+10009E, "􀂞", f480829e), -_c(U+10009F, "􀂟", f480829f), -_c(U+1000A0, "􀂠", f48082a0), -_c(U+1000A1, "􀂡", f48082a1), -_c(U+1000A2, "􀂢", f48082a2), -_c(U+1000A3, "􀂣", f48082a3), -_c(U+1000A4, "􀂤", f48082a4), -_c(U+1000A5, "􀂥", f48082a5), -_c(U+1000A6, "􀂦", f48082a6), -_c(U+1000A7, "􀂧", f48082a7), -_c(U+1000A8, "􀂨", f48082a8), -_c(U+1000A9, "􀂩", f48082a9), -_c(U+1000AA, "􀂪", f48082aa), -_c(U+1000AB, "􀂫", f48082ab), -_c(U+1000AC, "􀂬", f48082ac), -_c(U+1000AD, "􀂭", f48082ad), -_c(U+1000AE, "􀂮", f48082ae), -_c(U+1000AF, "􀂯", f48082af), -_c(U+1000B0, "􀂰", f48082b0), -_c(U+1000B1, "􀂱", f48082b1), -_c(U+1000B2, "􀂲", f48082b2), -_c(U+1000B3, "􀂳", f48082b3), -_c(U+1000B4, "􀂴", f48082b4), -_c(U+1000B5, "􀂵", f48082b5), -_c(U+1000B6, "􀂶", f48082b6), -_c(U+1000B7, "􀂷", f48082b7), -_c(U+1000B8, "􀂸", f48082b8), -_c(U+1000B9, "􀂹", f48082b9), -_c(U+1000BA, "􀂺", f48082ba), -_c(U+1000BB, "􀂻", f48082bb), -_c(U+1000BC, "􀂼", f48082bc), -_c(U+1000BD, "􀂽", f48082bd), -_c(U+1000BE, "􀂾", f48082be), -_c(U+1000BF, "􀂿", f48082bf), -_c(U+1000C0, "􀃀", f4808380), -_c(U+1000C1, "􀃁", f4808381), -_c(U+1000C2, "􀃂", f4808382), -_c(U+1000C3, "􀃃", f4808383), -_c(U+1000C4, "􀃄", f4808384), -_c(U+1000C5, "􀃅", f4808385), -_c(U+1000C6, "􀃆", f4808386), -_c(U+1000C7, "􀃇", f4808387), -_c(U+1000C8, "􀃈", f4808388), -_c(U+1000C9, "􀃉", f4808389), -_c(U+1000CA, "􀃊", f480838a), -_c(U+1000CB, "􀃋", f480838b), -_c(U+1000CC, "􀃌", f480838c), -_c(U+1000CD, "􀃍", f480838d), -_c(U+1000CE, "􀃎", f480838e), -_c(U+1000CF, "􀃏", f480838f), -_c(U+1000D0, "􀃐", f4808390), -_c(U+1000D1, "􀃑", f4808391), -_c(U+1000D2, "􀃒", f4808392), -_c(U+1000D3, "􀃓", f4808393), -_c(U+1000D4, "􀃔", f4808394), -_c(U+1000D5, "􀃕", f4808395), -_c(U+1000D6, "􀃖", f4808396), -_c(U+1000D7, "􀃗", f4808397), -_c(U+1000D8, "􀃘", f4808398), -_c(U+1000D9, "􀃙", f4808399), -_c(U+1000DA, "􀃚", f480839a), -_c(U+1000DB, "􀃛", f480839b), -_c(U+1000DC, "􀃜", f480839c), -_c(U+1000DD, "􀃝", f480839d), -_c(U+1000DE, "􀃞", f480839e), -_c(U+1000DF, "􀃟", f480839f), -_c(U+1000E0, "􀃠", f48083a0), -_c(U+1000E1, "􀃡", f48083a1), -_c(U+1000E2, "􀃢", f48083a2), -_c(U+1000E3, "􀃣", f48083a3), -_c(U+1000E4, "􀃤", f48083a4), -_c(U+1000E5, "􀃥", f48083a5), -_c(U+1000E6, "􀃦", f48083a6), -_c(U+1000E7, "􀃧", f48083a7), -_c(U+1000E8, "􀃨", f48083a8), -_c(U+1000E9, "􀃩", f48083a9), -_c(U+1000EA, "􀃪", f48083aa), -_c(U+1000EB, "􀃫", f48083ab), -_c(U+1000EC, "􀃬", f48083ac), -_c(U+1000ED, "􀃭", f48083ad), -_c(U+1000EE, "􀃮", f48083ae), -_c(U+1000EF, "􀃯", f48083af), -_c(U+1000F0, "􀃰", f48083b0), -_c(U+1000F1, "􀃱", f48083b1), -_c(U+1000F2, "􀃲", f48083b2), -_c(U+1000F3, "􀃳", f48083b3), -_c(U+1000F4, "􀃴", f48083b4), -_c(U+1000F5, "􀃵", f48083b5), -_c(U+1000F6, "􀃶", f48083b6), -_c(U+1000F7, "􀃷", f48083b7), -_c(U+1000F8, "􀃸", f48083b8), -_c(U+1000F9, "􀃹", f48083b9), -_c(U+1000FA, "􀃺", f48083ba), -_c(U+1000FB, "􀃻", f48083bb), -_c(U+1000FC, "􀃼", f48083bc), -_c(U+1000FD, "􀃽", f48083bd), -_c(U+1000FE, "􀃾", f48083be), -_c(U+1000FF, "􀃿", f48083bf), -_c(U+100100, "􀄀", f4808480), -_c(U+100101, "􀄁", f4808481), -_c(U+100102, "􀄂", f4808482), -_c(U+100103, "􀄃", f4808483), -_c(U+100104, "􀄄", f4808484), -_c(U+100105, "􀄅", f4808485), -_c(U+100106, "􀄆", f4808486), -_c(U+100107, "􀄇", f4808487), -_c(U+100108, "􀄈", f4808488), -_c(U+100109, "􀄉", f4808489), -_c(U+10010A, "􀄊", f480848a), -_c(U+10010B, "􀄋", f480848b), -_c(U+10010C, "􀄌", f480848c), -_c(U+10010D, "􀄍", f480848d), -_c(U+10010E, "􀄎", f480848e), -_c(U+10010F, "􀄏", f480848f), -_c(U+100110, "􀄐", f4808490), -_c(U+100111, "􀄑", f4808491), -_c(U+100112, "􀄒", f4808492), -_c(U+100113, "􀄓", f4808493), -_c(U+100114, "􀄔", f4808494), -_c(U+100115, "􀄕", f4808495), -_c(U+100116, "􀄖", f4808496), -_c(U+100117, "􀄗", f4808497), -_c(U+100118, "􀄘", f4808498), -_c(U+100119, "􀄙", f4808499), -_c(U+10011A, "􀄚", f480849a), -_c(U+10011B, "􀄛", f480849b), -_c(U+10011C, "􀄜", f480849c), -_c(U+10011D, "􀄝", f480849d), -_c(U+10011E, "􀄞", f480849e), -_c(U+10011F, "􀄟", f480849f), -_c(U+100120, "􀄠", f48084a0), -_c(U+100121, "􀄡", f48084a1), -_c(U+100122, "􀄢", f48084a2), -_c(U+100123, "􀄣", f48084a3), -_c(U+100124, "􀄤", f48084a4), -_c(U+100125, "􀄥", f48084a5), -_c(U+100126, "􀄦", f48084a6), -_c(U+100127, "􀄧", f48084a7), -_c(U+100128, "􀄨", f48084a8), -_c(U+100129, "􀄩", f48084a9), -_c(U+10012A, "􀄪", f48084aa), -_c(U+10012B, "􀄫", f48084ab), -_c(U+10012C, "􀄬", f48084ac), -_c(U+10012D, "􀄭", f48084ad), -_c(U+10012E, "􀄮", f48084ae), -_c(U+10012F, "􀄯", f48084af), -_c(U+100130, "􀄰", f48084b0), -_c(U+100131, "􀄱", f48084b1), -_c(U+100132, "􀄲", f48084b2), -_c(U+100133, "􀄳", f48084b3), -_c(U+100134, "􀄴", f48084b4), -_c(U+100135, "􀄵", f48084b5), -_c(U+100136, "􀄶", f48084b6), -_c(U+100137, "􀄷", f48084b7), -_c(U+100138, "􀄸", f48084b8), -_c(U+100139, "􀄹", f48084b9), -_c(U+10013A, "􀄺", f48084ba), -_c(U+10013B, "􀄻", f48084bb), -_c(U+10013C, "􀄼", f48084bc), -_c(U+10013D, "􀄽", f48084bd), -_c(U+10013E, "􀄾", f48084be), -_c(U+10013F, "􀄿", f48084bf), -_c(U+100140, "􀅀", f4808580), -_c(U+100141, "􀅁", f4808581), -_c(U+100142, "􀅂", f4808582), -_c(U+100143, "􀅃", f4808583), -_c(U+100144, "􀅄", f4808584), -_c(U+100145, "􀅅", f4808585), -_c(U+100146, "􀅆", f4808586), -_c(U+100147, "􀅇", f4808587), -_c(U+100148, "􀅈", f4808588), -_c(U+100149, "􀅉", f4808589), -_c(U+10014A, "􀅊", f480858a), -_c(U+10014B, "􀅋", f480858b), -_c(U+10014C, "􀅌", f480858c), -_c(U+10014D, "􀅍", f480858d), -_c(U+10014E, "􀅎", f480858e), -_c(U+10014F, "􀅏", f480858f), -_c(U+100150, "􀅐", f4808590), -_c(U+100151, "􀅑", f4808591), -_c(U+100152, "􀅒", f4808592), -_c(U+100153, "􀅓", f4808593), -_c(U+100154, "􀅔", f4808594), -_c(U+100155, "􀅕", f4808595), -_c(U+100156, "􀅖", f4808596), -_c(U+100157, "􀅗", f4808597), -_c(U+100158, "􀅘", f4808598), -_c(U+100159, "􀅙", f4808599), -_c(U+10015A, "􀅚", f480859a), -_c(U+10015B, "􀅛", f480859b), -_c(U+10015C, "􀅜", f480859c), -_c(U+10015D, "􀅝", f480859d), -_c(U+10015E, "􀅞", f480859e), -_c(U+10015F, "􀅟", f480859f), -_c(U+100160, "􀅠", f48085a0), -_c(U+100161, "􀅡", f48085a1), -_c(U+100162, "􀅢", f48085a2), -_c(U+100163, "􀅣", f48085a3), -_c(U+100164, "􀅤", f48085a4), -_c(U+100165, "􀅥", f48085a5), -_c(U+100166, "􀅦", f48085a6), -_c(U+100167, "􀅧", f48085a7), -_c(U+100168, "􀅨", f48085a8), -_c(U+100169, "􀅩", f48085a9), -_c(U+10016A, "􀅪", f48085aa), -_c(U+10016B, "􀅫", f48085ab), -_c(U+10016C, "􀅬", f48085ac), -_c(U+10016D, "􀅭", f48085ad), -_c(U+10016E, "􀅮", f48085ae), -_c(U+10016F, "􀅯", f48085af), -_c(U+100170, "􀅰", f48085b0), -_c(U+100171, "􀅱", f48085b1), -_c(U+100172, "􀅲", f48085b2), -_c(U+100173, "􀅳", f48085b3), -_c(U+100174, "􀅴", f48085b4), -_c(U+100175, "􀅵", f48085b5), -_c(U+100176, "􀅶", f48085b6), -_c(U+100177, "􀅷", f48085b7), -_c(U+100178, "􀅸", f48085b8), -_c(U+100179, "􀅹", f48085b9), -_c(U+10017A, "􀅺", f48085ba), -_c(U+10017B, "􀅻", f48085bb), -_c(U+10017C, "􀅼", f48085bc), -_c(U+10017D, "􀅽", f48085bd), -_c(U+10017E, "􀅾", f48085be), -_c(U+10017F, "􀅿", f48085bf), -_c(U+100180, "􀆀", f4808680), -_c(U+100181, "􀆁", f4808681), -_c(U+100182, "􀆂", f4808682), -_c(U+100183, "􀆃", f4808683), -_c(U+100184, "􀆄", f4808684), -_c(U+100185, "􀆅", f4808685), -_c(U+100186, "􀆆", f4808686), -_c(U+100187, "􀆇", f4808687), -_c(U+100188, "􀆈", f4808688), -_c(U+100189, "􀆉", f4808689), -_c(U+10018A, "􀆊", f480868a), -_c(U+10018B, "􀆋", f480868b), -_c(U+10018C, "􀆌", f480868c), -_c(U+10018D, "􀆍", f480868d), -_c(U+10018E, "􀆎", f480868e), -_c(U+10018F, "􀆏", f480868f), -_c(U+100190, "􀆐", f4808690), -_c(U+100191, "􀆑", f4808691), -_c(U+100192, "􀆒", f4808692), -_c(U+100193, "􀆓", f4808693), -_c(U+100194, "􀆔", f4808694), -_c(U+100195, "􀆕", f4808695), -_c(U+100196, "􀆖", f4808696), -_c(U+100197, "􀆗", f4808697), -_c(U+100198, "􀆘", f4808698), -_c(U+100199, "􀆙", f4808699), -_c(U+10019A, "􀆚", f480869a), -_c(U+10019B, "􀆛", f480869b), -_c(U+10019C, "􀆜", f480869c), -_c(U+10019D, "􀆝", f480869d), -_c(U+10019E, "􀆞", f480869e), -_c(U+10019F, "􀆟", f480869f), -_c(U+1001A0, "􀆠", f48086a0), -_c(U+1001A1, "􀆡", f48086a1), -_c(U+1001A2, "􀆢", f48086a2), -_c(U+1001A3, "􀆣", f48086a3), -_c(U+1001A4, "􀆤", f48086a4), -_c(U+1001A5, "􀆥", f48086a5), -_c(U+1001A6, "􀆦", f48086a6), -_c(U+1001A7, "􀆧", f48086a7), -_c(U+1001A8, "􀆨", f48086a8), -_c(U+1001A9, "􀆩", f48086a9), -_c(U+1001AA, "􀆪", f48086aa), -_c(U+1001AB, "􀆫", f48086ab), -_c(U+1001AC, "􀆬", f48086ac), -_c(U+1001AD, "􀆭", f48086ad), -_c(U+1001AE, "􀆮", f48086ae), -_c(U+1001AF, "􀆯", f48086af), -_c(U+1001B0, "􀆰", f48086b0), -_c(U+1001B1, "􀆱", f48086b1), -_c(U+1001B2, "􀆲", f48086b2), -_c(U+1001B3, "􀆳", f48086b3), -_c(U+1001B4, "􀆴", f48086b4), -_c(U+1001B5, "􀆵", f48086b5), -_c(U+1001B6, "􀆶", f48086b6), -_c(U+1001B7, "􀆷", f48086b7), -_c(U+1001B8, "􀆸", f48086b8), -_c(U+1001B9, "􀆹", f48086b9), -_c(U+1001BA, "􀆺", f48086ba), -_c(U+1001BB, "􀆻", f48086bb), -_c(U+1001BC, "􀆼", f48086bc), -_c(U+1001BD, "􀆽", f48086bd), -_c(U+1001BE, "􀆾", f48086be), -_c(U+1001BF, "􀆿", f48086bf), -_c(U+1001C0, "􀇀", f4808780), -_c(U+1001C1, "􀇁", f4808781), -_c(U+1001C2, "􀇂", f4808782), -_c(U+1001C3, "􀇃", f4808783), -_c(U+1001C4, "􀇄", f4808784), -_c(U+1001C5, "􀇅", f4808785), -_c(U+1001C6, "􀇆", f4808786), -_c(U+1001C7, "􀇇", f4808787), -_c(U+1001C8, "􀇈", f4808788), -_c(U+1001C9, "􀇉", f4808789), -_c(U+1001CA, "􀇊", f480878a), -_c(U+1001CB, "􀇋", f480878b), -_c(U+1001CC, "􀇌", f480878c), -_c(U+1001CD, "􀇍", f480878d), -_c(U+1001CE, "􀇎", f480878e), -_c(U+1001CF, "􀇏", f480878f), -_c(U+1001D0, "􀇐", f4808790), -_c(U+1001D1, "􀇑", f4808791), -_c(U+1001D2, "􀇒", f4808792), -_c(U+1001D3, "􀇓", f4808793), -_c(U+1001D4, "􀇔", f4808794), -_c(U+1001D5, "􀇕", f4808795), -_c(U+1001D6, "􀇖", f4808796), -_c(U+1001D7, "􀇗", f4808797), -_c(U+1001D8, "􀇘", f4808798), -_c(U+1001D9, "􀇙", f4808799), -_c(U+1001DA, "􀇚", f480879a), -_c(U+1001DB, "􀇛", f480879b), -_c(U+1001DC, "􀇜", f480879c), -_c(U+1001DD, "􀇝", f480879d), -_c(U+1001DE, "􀇞", f480879e), -_c(U+1001DF, "􀇟", f480879f), -_c(U+1001E0, "􀇠", f48087a0), -_c(U+1001E1, "􀇡", f48087a1), -_c(U+1001E2, "􀇢", f48087a2), -_c(U+1001E3, "􀇣", f48087a3), -_c(U+1001E4, "􀇤", f48087a4), -_c(U+1001E5, "􀇥", f48087a5), -_c(U+1001E6, "􀇦", f48087a6), -_c(U+1001E7, "􀇧", f48087a7), -_c(U+1001E8, "􀇨", f48087a8), -_c(U+1001E9, "􀇩", f48087a9), -_c(U+1001EA, "􀇪", f48087aa), -_c(U+1001EB, "􀇫", f48087ab), -_c(U+1001EC, "􀇬", f48087ac), -_c(U+1001ED, "􀇭", f48087ad), -_c(U+1001EE, "􀇮", f48087ae), -_c(U+1001EF, "􀇯", f48087af), -_c(U+1001F0, "􀇰", f48087b0), -_c(U+1001F1, "􀇱", f48087b1), -_c(U+1001F2, "􀇲", f48087b2), -_c(U+1001F3, "􀇳", f48087b3), -_c(U+1001F4, "􀇴", f48087b4), -_c(U+1001F5, "􀇵", f48087b5), -_c(U+1001F6, "􀇶", f48087b6), -_c(U+1001F7, "􀇷", f48087b7), -_c(U+1001F8, "􀇸", f48087b8), -_c(U+1001F9, "􀇹", f48087b9), -_c(U+1001FA, "􀇺", f48087ba), -_c(U+1001FB, "􀇻", f48087bb), -_c(U+1001FC, "􀇼", f48087bc), -_c(U+1001FD, "􀇽", f48087bd), -_c(U+1001FE, "􀇾", f48087be), -_c(U+1001FF, "􀇿", f48087bf), -_c(U+100200, "􀈀", f4808880), -_c(U+100201, "􀈁", f4808881), -_c(U+100202, "􀈂", f4808882), -_c(U+100203, "􀈃", f4808883), -_c(U+100204, "􀈄", f4808884), -_c(U+100205, "􀈅", f4808885), -_c(U+100206, "􀈆", f4808886), -_c(U+100207, "􀈇", f4808887), -_c(U+100208, "􀈈", f4808888), -_c(U+100209, "􀈉", f4808889), -_c(U+10020A, "􀈊", f480888a), -_c(U+10020B, "􀈋", f480888b), -_c(U+10020C, "􀈌", f480888c), -_c(U+10020D, "􀈍", f480888d), -_c(U+10020E, "􀈎", f480888e), -_c(U+10020F, "􀈏", f480888f), -_c(U+100210, "􀈐", f4808890), -_c(U+100211, "􀈑", f4808891), -_c(U+100212, "􀈒", f4808892), -_c(U+100213, "􀈓", f4808893), -_c(U+100214, "􀈔", f4808894), -_c(U+100215, "􀈕", f4808895), -_c(U+100216, "􀈖", f4808896), -_c(U+100217, "􀈗", f4808897), -_c(U+100218, "􀈘", f4808898), -_c(U+100219, "􀈙", f4808899), -_c(U+10021A, "􀈚", f480889a), -_c(U+10021B, "􀈛", f480889b), -_c(U+10021C, "􀈜", f480889c), -_c(U+10021D, "􀈝", f480889d), -_c(U+10021E, "􀈞", f480889e), -_c(U+10021F, "􀈟", f480889f), -_c(U+100220, "􀈠", f48088a0), -_c(U+100221, "􀈡", f48088a1), -_c(U+100222, "􀈢", f48088a2), -_c(U+100223, "􀈣", f48088a3), -_c(U+100224, "􀈤", f48088a4), -_c(U+100225, "􀈥", f48088a5), -_c(U+100226, "􀈦", f48088a6), -_c(U+100227, "􀈧", f48088a7), -_c(U+100228, "􀈨", f48088a8), -_c(U+100229, "􀈩", f48088a9), -_c(U+10022A, "􀈪", f48088aa), -_c(U+10022B, "􀈫", f48088ab), -_c(U+10022C, "􀈬", f48088ac), -_c(U+10022D, "􀈭", f48088ad), -_c(U+10022E, "􀈮", f48088ae), -_c(U+10022F, "􀈯", f48088af), -_c(U+100230, "􀈰", f48088b0), -_c(U+100231, "􀈱", f48088b1), -_c(U+100232, "􀈲", f48088b2), -_c(U+100233, "􀈳", f48088b3), -_c(U+100234, "􀈴", f48088b4), -_c(U+100235, "􀈵", f48088b5), -_c(U+100236, "􀈶", f48088b6), -_c(U+100237, "􀈷", f48088b7), -_c(U+100238, "􀈸", f48088b8), -_c(U+100239, "􀈹", f48088b9), -_c(U+10023A, "􀈺", f48088ba), -_c(U+10023B, "􀈻", f48088bb), -_c(U+10023C, "􀈼", f48088bc), -_c(U+10023D, "􀈽", f48088bd), -_c(U+10023E, "􀈾", f48088be), -_c(U+10023F, "􀈿", f48088bf), -_c(U+100240, "􀉀", f4808980), -_c(U+100241, "􀉁", f4808981), -_c(U+100242, "􀉂", f4808982), -_c(U+100243, "􀉃", f4808983), -_c(U+100244, "􀉄", f4808984), -_c(U+100245, "􀉅", f4808985), -_c(U+100246, "􀉆", f4808986), -_c(U+100247, "􀉇", f4808987), -_c(U+100248, "􀉈", f4808988), -_c(U+100249, "􀉉", f4808989), -_c(U+10024A, "􀉊", f480898a), -_c(U+10024B, "􀉋", f480898b), -_c(U+10024C, "􀉌", f480898c), -_c(U+10024D, "􀉍", f480898d), -_c(U+10024E, "􀉎", f480898e), -_c(U+10024F, "􀉏", f480898f), -_c(U+100250, "􀉐", f4808990), -_c(U+100251, "􀉑", f4808991), -_c(U+100252, "􀉒", f4808992), -_c(U+100253, "􀉓", f4808993), -_c(U+100254, "􀉔", f4808994), -_c(U+100255, "􀉕", f4808995), -_c(U+100256, "􀉖", f4808996), -_c(U+100257, "􀉗", f4808997), -_c(U+100258, "􀉘", f4808998), -_c(U+100259, "􀉙", f4808999), -_c(U+10025A, "􀉚", f480899a), -_c(U+10025B, "􀉛", f480899b), -_c(U+10025C, "􀉜", f480899c), -_c(U+10025D, "􀉝", f480899d), -_c(U+10025E, "􀉞", f480899e), -_c(U+10025F, "􀉟", f480899f), -_c(U+100260, "􀉠", f48089a0), -_c(U+100261, "􀉡", f48089a1), -_c(U+100262, "􀉢", f48089a2), -_c(U+100263, "􀉣", f48089a3), -_c(U+100264, "􀉤", f48089a4), -_c(U+100265, "􀉥", f48089a5), -_c(U+100266, "􀉦", f48089a6), -_c(U+100267, "􀉧", f48089a7), -_c(U+100268, "􀉨", f48089a8), -_c(U+100269, "􀉩", f48089a9), -_c(U+10026A, "􀉪", f48089aa), -_c(U+10026B, "􀉫", f48089ab), -_c(U+10026C, "􀉬", f48089ac), -_c(U+10026D, "􀉭", f48089ad), -_c(U+10026E, "􀉮", f48089ae), -_c(U+10026F, "􀉯", f48089af), -_c(U+100270, "􀉰", f48089b0), -_c(U+100271, "􀉱", f48089b1), -_c(U+100272, "􀉲", f48089b2), -_c(U+100273, "􀉳", f48089b3), -_c(U+100274, "􀉴", f48089b4), -_c(U+100275, "􀉵", f48089b5), -_c(U+100276, "􀉶", f48089b6), -_c(U+100277, "􀉷", f48089b7), -_c(U+100278, "􀉸", f48089b8), -_c(U+100279, "􀉹", f48089b9), -_c(U+10027A, "􀉺", f48089ba), -_c(U+10027B, "􀉻", f48089bb), -_c(U+10027C, "􀉼", f48089bc), -_c(U+10027D, "􀉽", f48089bd), -_c(U+10027E, "􀉾", f48089be), -_c(U+10027F, "􀉿", f48089bf), -_c(U+100280, "􀊀", f4808a80), -_c(U+100281, "􀊁", f4808a81), -_c(U+100282, "􀊂", f4808a82), -_c(U+100283, "􀊃", f4808a83), -_c(U+100284, "􀊄", f4808a84), -_c(U+100285, "􀊅", f4808a85), -_c(U+100286, "􀊆", f4808a86), -_c(U+100287, "􀊇", f4808a87), -_c(U+100288, "􀊈", f4808a88), -_c(U+100289, "􀊉", f4808a89), -_c(U+10028A, "􀊊", f4808a8a), -_c(U+10028B, "􀊋", f4808a8b), -_c(U+10028C, "􀊌", f4808a8c), -_c(U+10028D, "􀊍", f4808a8d), -_c(U+10028E, "􀊎", f4808a8e), -_c(U+10028F, "􀊏", f4808a8f), -_c(U+100290, "􀊐", f4808a90), -_c(U+100291, "􀊑", f4808a91), -_c(U+100292, "􀊒", f4808a92), -_c(U+100293, "􀊓", f4808a93), -_c(U+100294, "􀊔", f4808a94), -_c(U+100295, "􀊕", f4808a95), -_c(U+100296, "􀊖", f4808a96), -_c(U+100297, "􀊗", f4808a97), -_c(U+100298, "􀊘", f4808a98), -_c(U+100299, "􀊙", f4808a99), -_c(U+10029A, "􀊚", f4808a9a), -_c(U+10029B, "􀊛", f4808a9b), -_c(U+10029C, "􀊜", f4808a9c), -_c(U+10029D, "􀊝", f4808a9d), -_c(U+10029E, "􀊞", f4808a9e), -_c(U+10029F, "􀊟", f4808a9f), -_c(U+1002A0, "􀊠", f4808aa0), -_c(U+1002A1, "􀊡", f4808aa1), -_c(U+1002A2, "􀊢", f4808aa2), -_c(U+1002A3, "􀊣", f4808aa3), -_c(U+1002A4, "􀊤", f4808aa4), -_c(U+1002A5, "􀊥", f4808aa5), -_c(U+1002A6, "􀊦", f4808aa6), -_c(U+1002A7, "􀊧", f4808aa7), -_c(U+1002A8, "􀊨", f4808aa8), -_c(U+1002A9, "􀊩", f4808aa9), -_c(U+1002AA, "􀊪", f4808aaa), -_c(U+1002AB, "􀊫", f4808aab), -_c(U+1002AC, "􀊬", f4808aac), -_c(U+1002AD, "􀊭", f4808aad), -_c(U+1002AE, "􀊮", f4808aae), -_c(U+1002AF, "􀊯", f4808aaf), -_c(U+1002B0, "􀊰", f4808ab0), -_c(U+1002B1, "􀊱", f4808ab1), -_c(U+1002B2, "􀊲", f4808ab2), -_c(U+1002B3, "􀊳", f4808ab3), -_c(U+1002B4, "􀊴", f4808ab4), -_c(U+1002B5, "􀊵", f4808ab5), -_c(U+1002B6, "􀊶", f4808ab6), -_c(U+1002B7, "􀊷", f4808ab7), -_c(U+1002B8, "􀊸", f4808ab8), -_c(U+1002B9, "􀊹", f4808ab9), -_c(U+1002BA, "􀊺", f4808aba), -_c(U+1002BB, "􀊻", f4808abb), -_c(U+1002BC, "􀊼", f4808abc), -_c(U+1002BD, "􀊽", f4808abd), -_c(U+1002BE, "􀊾", f4808abe), -_c(U+1002BF, "􀊿", f4808abf), -_c(U+1002C0, "􀋀", f4808b80), -_c(U+1002C1, "􀋁", f4808b81), -_c(U+1002C2, "􀋂", f4808b82), -_c(U+1002C3, "􀋃", f4808b83), -_c(U+1002C4, "􀋄", f4808b84), -_c(U+1002C5, "􀋅", f4808b85), -_c(U+1002C6, "􀋆", f4808b86), -_c(U+1002C7, "􀋇", f4808b87), -_c(U+1002C8, "􀋈", f4808b88), -_c(U+1002C9, "􀋉", f4808b89), -_c(U+1002CA, "􀋊", f4808b8a), -_c(U+1002CB, "􀋋", f4808b8b), -_c(U+1002CC, "􀋌", f4808b8c), -_c(U+1002CD, "􀋍", f4808b8d), -_c(U+1002CE, "􀋎", f4808b8e), -_c(U+1002CF, "􀋏", f4808b8f), -_c(U+1002D0, "􀋐", f4808b90), -_c(U+1002D1, "􀋑", f4808b91), -_c(U+1002D2, "􀋒", f4808b92), -_c(U+1002D3, "􀋓", f4808b93), -_c(U+1002D4, "􀋔", f4808b94), -_c(U+1002D5, "􀋕", f4808b95), -_c(U+1002D6, "􀋖", f4808b96), -_c(U+1002D7, "􀋗", f4808b97), -_c(U+1002D8, "􀋘", f4808b98), -_c(U+1002D9, "􀋙", f4808b99), -_c(U+1002DA, "􀋚", f4808b9a), -_c(U+1002DB, "􀋛", f4808b9b), -_c(U+1002DC, "􀋜", f4808b9c), -_c(U+1002DD, "􀋝", f4808b9d), -_c(U+1002DE, "􀋞", f4808b9e), -_c(U+1002DF, "􀋟", f4808b9f), -_c(U+1002E0, "􀋠", f4808ba0), -_c(U+1002E1, "􀋡", f4808ba1), -_c(U+1002E2, "􀋢", f4808ba2), -_c(U+1002E3, "􀋣", f4808ba3), -_c(U+1002E4, "􀋤", f4808ba4), -_c(U+1002E5, "􀋥", f4808ba5), -_c(U+1002E6, "􀋦", f4808ba6), -_c(U+1002E7, "􀋧", f4808ba7), -_c(U+1002E8, "􀋨", f4808ba8), -_c(U+1002E9, "􀋩", f4808ba9), -_c(U+1002EA, "􀋪", f4808baa), -_c(U+1002EB, "􀋫", f4808bab), -_c(U+1002EC, "􀋬", f4808bac), -_c(U+1002ED, "􀋭", f4808bad), -_c(U+1002EE, "􀋮", f4808bae), -_c(U+1002EF, "􀋯", f4808baf), -_c(U+1002F0, "􀋰", f4808bb0), -_c(U+1002F1, "􀋱", f4808bb1), -_c(U+1002F2, "􀋲", f4808bb2), -_c(U+1002F3, "􀋳", f4808bb3), -_c(U+1002F4, "􀋴", f4808bb4), -_c(U+1002F5, "􀋵", f4808bb5), -_c(U+1002F6, "􀋶", f4808bb6), -_c(U+1002F7, "􀋷", f4808bb7), -_c(U+1002F8, "􀋸", f4808bb8), -_c(U+1002F9, "􀋹", f4808bb9), -_c(U+1002FA, "􀋺", f4808bba), -_c(U+1002FB, "􀋻", f4808bbb), -_c(U+1002FC, "􀋼", f4808bbc), -_c(U+1002FD, "􀋽", f4808bbd), -_c(U+1002FE, "􀋾", f4808bbe), -_c(U+1002FF, "􀋿", f4808bbf), -_c(U+100300, "􀌀", f4808c80), -_c(U+100301, "􀌁", f4808c81), -_c(U+100302, "􀌂", f4808c82), -_c(U+100303, "􀌃", f4808c83), -_c(U+100304, "􀌄", f4808c84), -_c(U+100305, "􀌅", f4808c85), -_c(U+100306, "􀌆", f4808c86), -_c(U+100307, "􀌇", f4808c87), -_c(U+100308, "􀌈", f4808c88), -_c(U+100309, "􀌉", f4808c89), -_c(U+10030A, "􀌊", f4808c8a), -_c(U+10030B, "􀌋", f4808c8b), -_c(U+10030C, "􀌌", f4808c8c), -_c(U+10030D, "􀌍", f4808c8d), -_c(U+10030E, "􀌎", f4808c8e), -_c(U+10030F, "􀌏", f4808c8f), -_c(U+100310, "􀌐", f4808c90), -_c(U+100311, "􀌑", f4808c91), -_c(U+100312, "􀌒", f4808c92), -_c(U+100313, "􀌓", f4808c93), -_c(U+100314, "􀌔", f4808c94), -_c(U+100315, "􀌕", f4808c95), -_c(U+100316, "􀌖", f4808c96), -_c(U+100317, "􀌗", f4808c97), -_c(U+100318, "􀌘", f4808c98), -_c(U+100319, "􀌙", f4808c99), -_c(U+10031A, "􀌚", f4808c9a), -_c(U+10031B, "􀌛", f4808c9b), -_c(U+10031C, "􀌜", f4808c9c), -_c(U+10031D, "􀌝", f4808c9d), -_c(U+10031E, "􀌞", f4808c9e), -_c(U+10031F, "􀌟", f4808c9f), -_c(U+100320, "􀌠", f4808ca0), -_c(U+100321, "􀌡", f4808ca1), -_c(U+100322, "􀌢", f4808ca2), -_c(U+100323, "􀌣", f4808ca3), -_c(U+100324, "􀌤", f4808ca4), -_c(U+100325, "􀌥", f4808ca5), -_c(U+100326, "􀌦", f4808ca6), -_c(U+100327, "􀌧", f4808ca7), -_c(U+100328, "􀌨", f4808ca8), -_c(U+100329, "􀌩", f4808ca9), -_c(U+10032A, "􀌪", f4808caa), -_c(U+10032B, "􀌫", f4808cab), -_c(U+10032C, "􀌬", f4808cac), -_c(U+10032D, "􀌭", f4808cad), -_c(U+10032E, "􀌮", f4808cae), -_c(U+10032F, "􀌯", f4808caf), -_c(U+100330, "􀌰", f4808cb0), -_c(U+100331, "􀌱", f4808cb1), -_c(U+100332, "􀌲", f4808cb2), -_c(U+100333, "􀌳", f4808cb3), -_c(U+100334, "􀌴", f4808cb4), -_c(U+100335, "􀌵", f4808cb5), -_c(U+100336, "􀌶", f4808cb6), -_c(U+100337, "􀌷", f4808cb7), -_c(U+100338, "􀌸", f4808cb8), -_c(U+100339, "􀌹", f4808cb9), -_c(U+10033A, "􀌺", f4808cba), -_c(U+10033B, "􀌻", f4808cbb), -_c(U+10033C, "􀌼", f4808cbc), -_c(U+10033D, "􀌽", f4808cbd), -_c(U+10033E, "􀌾", f4808cbe), -_c(U+10033F, "􀌿", f4808cbf), -_c(U+100340, "􀍀", f4808d80), -_c(U+100341, "􀍁", f4808d81), -_c(U+100342, "􀍂", f4808d82), -_c(U+100343, "􀍃", f4808d83), -_c(U+100344, "􀍄", f4808d84), -_c(U+100345, "􀍅", f4808d85), -_c(U+100346, "􀍆", f4808d86), -_c(U+100347, "􀍇", f4808d87), -_c(U+100348, "􀍈", f4808d88), -_c(U+100349, "􀍉", f4808d89), -_c(U+10034A, "􀍊", f4808d8a), -_c(U+10034B, "􀍋", f4808d8b), -_c(U+10034C, "􀍌", f4808d8c), -_c(U+10034D, "􀍍", f4808d8d), -_c(U+10034E, "􀍎", f4808d8e), -_c(U+10034F, "􀍏", f4808d8f), -_c(U+100350, "􀍐", f4808d90), -_c(U+100351, "􀍑", f4808d91), -_c(U+100352, "􀍒", f4808d92), -_c(U+100353, "􀍓", f4808d93), -_c(U+100354, "􀍔", f4808d94), -_c(U+100355, "􀍕", f4808d95), -_c(U+100356, "􀍖", f4808d96), -_c(U+100357, "􀍗", f4808d97), -_c(U+100358, "􀍘", f4808d98), -_c(U+100359, "􀍙", f4808d99), -_c(U+10035A, "􀍚", f4808d9a), -_c(U+10035B, "􀍛", f4808d9b), -_c(U+10035C, "􀍜", f4808d9c), -_c(U+10035D, "􀍝", f4808d9d), -_c(U+10035E, "􀍞", f4808d9e), -_c(U+10035F, "􀍟", f4808d9f), -_c(U+100360, "􀍠", f4808da0), -_c(U+100361, "􀍡", f4808da1), -_c(U+100362, "􀍢", f4808da2), -_c(U+100363, "􀍣", f4808da3), -_c(U+100364, "􀍤", f4808da4), -_c(U+100365, "􀍥", f4808da5), -_c(U+100366, "􀍦", f4808da6), -_c(U+100367, "􀍧", f4808da7), -_c(U+100368, "􀍨", f4808da8), -_c(U+100369, "􀍩", f4808da9), -_c(U+10036A, "􀍪", f4808daa), -_c(U+10036B, "􀍫", f4808dab), -_c(U+10036C, "􀍬", f4808dac), -_c(U+10036D, "􀍭", f4808dad), -_c(U+10036E, "􀍮", f4808dae), -_c(U+10036F, "􀍯", f4808daf), -_c(U+100370, "􀍰", f4808db0), -_c(U+100371, "􀍱", f4808db1), -_c(U+100372, "􀍲", f4808db2), -_c(U+100373, "􀍳", f4808db3), -_c(U+100374, "􀍴", f4808db4), -_c(U+100375, "􀍵", f4808db5), -_c(U+100376, "􀍶", f4808db6), -_c(U+100377, "􀍷", f4808db7), -_c(U+100378, "􀍸", f4808db8), -_c(U+100379, "􀍹", f4808db9), -_c(U+10037A, "􀍺", f4808dba), -_c(U+10037B, "􀍻", f4808dbb), -_c(U+10037C, "􀍼", f4808dbc), -_c(U+10037D, "􀍽", f4808dbd), -_c(U+10037E, "􀍾", f4808dbe), -_c(U+10037F, "􀍿", f4808dbf), -_c(U+100380, "􀎀", f4808e80), -_c(U+100381, "􀎁", f4808e81), -_c(U+100382, "􀎂", f4808e82), -_c(U+100383, "􀎃", f4808e83), -_c(U+100384, "􀎄", f4808e84), -_c(U+100385, "􀎅", f4808e85), -_c(U+100386, "􀎆", f4808e86), -_c(U+100387, "􀎇", f4808e87), -_c(U+100388, "􀎈", f4808e88), -_c(U+100389, "􀎉", f4808e89), -_c(U+10038A, "􀎊", f4808e8a), -_c(U+10038B, "􀎋", f4808e8b), -_c(U+10038C, "􀎌", f4808e8c), -_c(U+10038D, "􀎍", f4808e8d), -_c(U+10038E, "􀎎", f4808e8e), -_c(U+10038F, "􀎏", f4808e8f), -_c(U+100390, "􀎐", f4808e90), -_c(U+100391, "􀎑", f4808e91), -_c(U+100392, "􀎒", f4808e92), -_c(U+100393, "􀎓", f4808e93), -_c(U+100394, "􀎔", f4808e94), -_c(U+100395, "􀎕", f4808e95), -_c(U+100396, "􀎖", f4808e96), -_c(U+100397, "􀎗", f4808e97), -_c(U+100398, "􀎘", f4808e98), -_c(U+100399, "􀎙", f4808e99), -_c(U+10039A, "􀎚", f4808e9a), -_c(U+10039B, "􀎛", f4808e9b), -_c(U+10039C, "􀎜", f4808e9c), -_c(U+10039D, "􀎝", f4808e9d), -_c(U+10039E, "􀎞", f4808e9e), -_c(U+10039F, "􀎟", f4808e9f), -_c(U+1003A0, "􀎠", f4808ea0), -_c(U+1003A1, "􀎡", f4808ea1), -_c(U+1003A2, "􀎢", f4808ea2), -_c(U+1003A3, "􀎣", f4808ea3), -_c(U+1003A4, "􀎤", f4808ea4), -_c(U+1003A5, "􀎥", f4808ea5), -_c(U+1003A6, "􀎦", f4808ea6), -_c(U+1003A7, "􀎧", f4808ea7), -_c(U+1003A8, "􀎨", f4808ea8), -_c(U+1003A9, "􀎩", f4808ea9), -_c(U+1003AA, "􀎪", f4808eaa), -_c(U+1003AB, "􀎫", f4808eab), -_c(U+1003AC, "􀎬", f4808eac), -_c(U+1003AD, "􀎭", f4808ead), -_c(U+1003AE, "􀎮", f4808eae), -_c(U+1003AF, "􀎯", f4808eaf), -_c(U+1003B0, "􀎰", f4808eb0), -_c(U+1003B1, "􀎱", f4808eb1), -_c(U+1003B2, "􀎲", f4808eb2), -_c(U+1003B3, "􀎳", f4808eb3), -_c(U+1003B4, "􀎴", f4808eb4), -_c(U+1003B5, "􀎵", f4808eb5), -_c(U+1003B6, "􀎶", f4808eb6), -_c(U+1003B7, "􀎷", f4808eb7), -_c(U+1003B8, "􀎸", f4808eb8), -_c(U+1003B9, "􀎹", f4808eb9), -_c(U+1003BA, "􀎺", f4808eba), -_c(U+1003BB, "􀎻", f4808ebb), -_c(U+1003BC, "􀎼", f4808ebc), -_c(U+1003BD, "􀎽", f4808ebd), -_c(U+1003BE, "􀎾", f4808ebe), -_c(U+1003BF, "􀎿", f4808ebf), -_c(U+1003C0, "􀏀", f4808f80), -_c(U+1003C1, "􀏁", f4808f81), -_c(U+1003C2, "􀏂", f4808f82), -_c(U+1003C3, "􀏃", f4808f83), -_c(U+1003C4, "􀏄", f4808f84), -_c(U+1003C5, "􀏅", f4808f85), -_c(U+1003C6, "􀏆", f4808f86), -_c(U+1003C7, "􀏇", f4808f87), -_c(U+1003C8, "􀏈", f4808f88), -_c(U+1003C9, "􀏉", f4808f89), -_c(U+1003CA, "􀏊", f4808f8a), -_c(U+1003CB, "􀏋", f4808f8b), -_c(U+1003CC, "􀏌", f4808f8c), -_c(U+1003CD, "􀏍", f4808f8d), -_c(U+1003CE, "􀏎", f4808f8e), -_c(U+1003CF, "􀏏", f4808f8f), -_c(U+1003D0, "􀏐", f4808f90), -_c(U+1003D1, "􀏑", f4808f91), -_c(U+1003D2, "􀏒", f4808f92), -_c(U+1003D3, "􀏓", f4808f93), -_c(U+1003D4, "􀏔", f4808f94), -_c(U+1003D5, "􀏕", f4808f95), -_c(U+1003D6, "􀏖", f4808f96), -_c(U+1003D7, "􀏗", f4808f97), -_c(U+1003D8, "􀏘", f4808f98), -_c(U+1003D9, "􀏙", f4808f99), -_c(U+1003DA, "􀏚", f4808f9a), -_c(U+1003DB, "􀏛", f4808f9b), -_c(U+1003DC, "􀏜", f4808f9c), -_c(U+1003DD, "􀏝", f4808f9d), -_c(U+1003DE, "􀏞", f4808f9e), -_c(U+1003DF, "􀏟", f4808f9f), -_c(U+1003E0, "􀏠", f4808fa0), -_c(U+1003E1, "􀏡", f4808fa1), -_c(U+1003E2, "􀏢", f4808fa2), -_c(U+1003E3, "􀏣", f4808fa3), -_c(U+1003E4, "􀏤", f4808fa4), -_c(U+1003E5, "􀏥", f4808fa5), -_c(U+1003E6, "􀏦", f4808fa6), -_c(U+1003E7, "􀏧", f4808fa7), -_c(U+1003E8, "􀏨", f4808fa8), -_c(U+1003E9, "􀏩", f4808fa9), -_c(U+1003EA, "􀏪", f4808faa), -_c(U+1003EB, "􀏫", f4808fab), -_c(U+1003EC, "􀏬", f4808fac), -_c(U+1003ED, "􀏭", f4808fad), -_c(U+1003EE, "􀏮", f4808fae), -_c(U+1003EF, "􀏯", f4808faf), -_c(U+1003F0, "􀏰", f4808fb0), -_c(U+1003F1, "􀏱", f4808fb1), -_c(U+1003F2, "􀏲", f4808fb2), -_c(U+1003F3, "􀏳", f4808fb3), -_c(U+1003F4, "􀏴", f4808fb4), -_c(U+1003F5, "􀏵", f4808fb5), -_c(U+1003F6, "􀏶", f4808fb6), -_c(U+1003F7, "􀏷", f4808fb7), -_c(U+1003F8, "􀏸", f4808fb8), -_c(U+1003F9, "􀏹", f4808fb9), -_c(U+1003FA, "􀏺", f4808fba), -_c(U+1003FB, "􀏻", f4808fbb), -_c(U+1003FC, "􀏼", f4808fbc), -_c(U+1003FD, "􀏽", f4808fbd), -_c(U+1003FE, "􀏾", f4808fbe), -_c(U+1003FF, "􀏿", f4808fbf), -#undef _c diff --git a/thirdparty/ryml/ext/c4core/tools/amalgamate.py b/thirdparty/ryml/ext/c4core/tools/amalgamate.py deleted file mode 100644 index eabcb4891..000000000 --- a/thirdparty/ryml/ext/c4core/tools/amalgamate.py +++ /dev/null @@ -1,143 +0,0 @@ -import re -from os.path import abspath, dirname -import sys -import subprocess - -projdir = abspath(dirname(dirname(__file__))) -sys.path.insert(0, f"{projdir}/cmake") -import amalgamate_utils as am - - -def amalgamate_fastfloat(): - fastfloatdir = f"{projdir}/src/c4/ext/fast_float" - subprocess.run([ - sys.executable, - f"{fastfloatdir}/script/amalgamate.py", - "--license", "MIT", - "--output", f"{fastfloatdir}/../fast_float_all.h" - ], cwd=fastfloatdir).check_returncode() - - -def amalgamate_c4core(filename: str, - with_stl: bool=True, - with_fastfloat: bool=True): - if with_fastfloat: - amalgamate_fastfloat() - repo = "https://github.com/biojppm/c4core" - defmacro = "C4CORE_SINGLE_HDR_DEFINE_NOW" - exports_def_code = f"""// shared library: export when defining -#if defined(C4CORE_SHARED) && defined({defmacro}) && !defined(C4CORE_EXPORTS) -#define C4CORE_EXPORTS -#endif -""" - required_gcc4_8_include = """// these includes are needed to work around conditional -// includes in the gcc4.8 shim -#include -#include -#include -""" - srcblocks = [ - am.cmttext(f""" -c4core - C++ utilities - -{repo} - -DO NOT EDIT. This file is generated automatically. -This is an amalgamated single-header version of the library. - -INSTRUCTIONS: - - Include at will in any header of your project - - In one (and only one) of your project source files, - #define {defmacro} and then include this header. - This will enable the function and class definitions in - the header file. - - To compile into a shared library, just define the - preprocessor symbol C4CORE_SHARED . This will take - care of symbol export/import. -"""), - am.cmtfile("LICENSE.txt"), - am.injcode(exports_def_code), - "src/c4/export.hpp", - "src/c4/preprocessor.hpp", - "src/c4/platform.hpp", - "src/c4/cpu.hpp", - "src/c4/compiler.hpp", - am.injcode(required_gcc4_8_include), - "cmake/compat/c4/gcc-4.8.hpp", - "src/c4/language.hpp", - "src/c4/types.hpp", - "src/c4/config.hpp", - am.hdrfile("src/c4/ext/debugbreak/debugbreak.h", "c4/ext/debugbreak/debugbreak.h", "DEBUG_BREAK_H"), - "src/c4/error.hpp", - "src/c4/memory_util.hpp", - "src/c4/memory_resource.hpp", - "src/c4/ctor_dtor.hpp", - "src/c4/allocator.hpp", - "src/c4/char_traits.hpp", - "src/c4/hash.hpp", - "src/c4/szconv.hpp", - "src/c4/blob.hpp", - "src/c4/substr_fwd.hpp", - "src/c4/substr.hpp", - am.onlyif(with_fastfloat, am.injfile("src/c4/ext/fast_float_all.h", "c4/ext/fast_float_all.h")), - am.onlyif(with_fastfloat, "src/c4/ext/fast_float.hpp"), - "src/c4/std/vector_fwd.hpp", - "src/c4/std/string_fwd.hpp", - "src/c4/std/std_fwd.hpp", - "src/c4/charconv.hpp", - "src/c4/utf.hpp", - "src/c4/format.hpp", - "src/c4/dump.hpp", - "src/c4/enum.hpp", - "src/c4/bitmask.hpp", - "src/c4/span.hpp", - "src/c4/type_name.hpp", - "src/c4/base64.hpp", - am.onlyif(with_stl, am.ignfile("src/c4/std/std.hpp")), # this is an umbrella include - am.onlyif(with_stl, "src/c4/std/string.hpp"), - am.onlyif(with_stl, "src/c4/std/vector.hpp"), - am.onlyif(with_stl, "src/c4/std/tuple.hpp"), - "src/c4/ext/rng/rng.hpp", - "src/c4/ext/sg14/inplace_function.h", - am.ignfile("src/c4/common.hpp"), - am.ignfile("src/c4/c4_push.hpp"), - am.ignfile("src/c4/c4_pop.hpp"), - am.ignfile("src/c4/restrict.hpp"), - am.ignfile("src/c4/unrestrict.hpp"), - "src/c4/language.cpp", - "src/c4/format.cpp", - "src/c4/memory_util.cpp", - "src/c4/char_traits.cpp", - "src/c4/memory_resource.cpp", - "src/c4/utf.cpp", - "src/c4/base64.cpp", - am.injcode("#define C4_WINDOWS_POP_HPP_"), - "src/c4/windows_push.hpp", - "src/c4/windows.hpp", - "src/c4/windows_pop.hpp", # do NOT include this before windows.hpp - "src/c4/error.cpp", - ] - result = am.catfiles(srcblocks, - projdir, - # comment out lines with these patterns: - include_regexes=[ - re.compile(r'^\s*#\s*include "(c4/.*)".*$'), - re.compile(r'^\s*#\s*include <(c4/.*)>.*$'), - ], - definition_macro=defmacro, - repo=repo, - result_incguard="_C4CORE_SINGLE_HEADER_AMALGAMATED_HPP_") - result_with_only_first_includes = am.include_only_first(result) - am.file_put_contents(filename, result_with_only_first_includes) - - -def mkparser(): - return am.mkparser(fastfloat=(True, "enable fastfloat library"), - stl=(True, "enable stl interop")) - - -if __name__ == "__main__": - args = mkparser().parse_args() - amalgamate_c4core(filename=args.output, - with_fastfloat=args.fastfloat, - with_stl=args.stl) diff --git a/thirdparty/ryml/ext/testbm.cmake b/thirdparty/ryml/ext/testbm.cmake deleted file mode 100644 index 7a1a4366e..000000000 --- a/thirdparty/ryml/ext/testbm.cmake +++ /dev/null @@ -1,4 +0,0 @@ -# these are used both for testing and benchmarking -c4_require_subproject(c4fs REMOTE - GIT_REPOSITORY https://github.com/biojppm/c4fs - GIT_TAG master) diff --git a/thirdparty/ryml/img/first_comparison_yaml_cpp.png b/thirdparty/ryml/img/first_comparison_yaml_cpp.png deleted file mode 100644 index d8f749def..000000000 Binary files a/thirdparty/ryml/img/first_comparison_yaml_cpp.png and /dev/null differ diff --git a/thirdparty/ryml/pyproject.toml b/thirdparty/ryml/pyproject.toml deleted file mode 100644 index 2a5bc9029..000000000 --- a/thirdparty/ryml/pyproject.toml +++ /dev/null @@ -1,8 +0,0 @@ -[build-system] -requires = [ - "setuptools>=42", - "setuptools_scm[toml]>=3.4", - "setuptools-git", - "wheel", - "ninja", - "cmake_build_extension"] diff --git a/thirdparty/ryml/requirements.txt b/thirdparty/ryml/requirements.txt deleted file mode 100644 index 815f8c397..000000000 --- a/thirdparty/ryml/requirements.txt +++ /dev/null @@ -1,8 +0,0 @@ -tbump -wheel -cmake-build-extension -build -twine -setuptools_scm -setuptools-git -deprecation diff --git a/thirdparty/ryml/samples/add_subdirectory/run.sh b/thirdparty/ryml/samples/add_subdirectory/run.sh deleted file mode 100755 index fc2f7d858..000000000 --- a/thirdparty/ryml/samples/add_subdirectory/run.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -x - -# take the build type from the command line, or default to release -cfg=${1:-Release} -# make sure to run from where this file is -cd $(dirname $0) -# configure the sample -cmake -S . -B ./build/$cfg -DCMAKE_BUILD_TYPE=$cfg -# build and run the sample -cmake --build ./build/$cfg --config $cfg --target run diff --git a/thirdparty/ryml/samples/custom_c4core/run.sh b/thirdparty/ryml/samples/custom_c4core/run.sh deleted file mode 100755 index fc2f7d858..000000000 --- a/thirdparty/ryml/samples/custom_c4core/run.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -x - -# take the build type from the command line, or default to release -cfg=${1:-Release} -# make sure to run from where this file is -cd $(dirname $0) -# configure the sample -cmake -S . -B ./build/$cfg -DCMAKE_BUILD_TYPE=$cfg -# build and run the sample -cmake --build ./build/$cfg --config $cfg --target run diff --git a/thirdparty/ryml/samples/fetch_content/run.sh b/thirdparty/ryml/samples/fetch_content/run.sh deleted file mode 100755 index cb1d7a008..000000000 --- a/thirdparty/ryml/samples/fetch_content/run.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -x - -# take the build type from the command line, or default to release -cfg=${1:-Release} -# force cmake's FetchContent to choose a specific branch, or default to nothing -branch=${2:-} -# make sure to run from where this file is -cd $(dirname $0) -# configure the sample -cmake -S . -B ./build/$cfg -DCMAKE_BUILD_TYPE=$cfg -DRYML_BRANCH_NAME="$branch" -# build and run the sample -cmake --build ./build/$cfg --config $cfg --target run diff --git a/thirdparty/ryml/samples/find_package/run.sh b/thirdparty/ryml/samples/find_package/run.sh deleted file mode 100755 index 930783b9c..000000000 --- a/thirdparty/ryml/samples/find_package/run.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash -x - -# take the build type from the command line, or default to release -cfg=${1:-Release} -# make sure to run from where this file is -cd $(dirname $0) - -#------------------------------ -# first, build and install ryml -#------------------------------ -RYML_SRC=$(cd ../.. ; pwd) -RYML_DIR=./build/$cfg/ryml-install # install ryml to this directory -# configure ryml -cmake -S "$RYML_SRC" -B ./build/$cfg/ryml-build "-DCMAKE_INSTALL_PREFIX=$RYML_DIR" -DCMAKE_BUILD_TYPE=$cfg -# build ryml -cmake --build ./build/$cfg/ryml-build --parallel --config $cfg -# install ryml -cmake --build ./build/$cfg/ryml-build --config $cfg --target install - -#----------------------------- -# now build and run the sample -#----------------------------- -# configure the sample -cmake -S . -B ./build/$cfg "-DCMAKE_PREFIX_PATH=$RYML_DIR" -DCMAKE_BUILD_TYPE=$cfg -# build and run the sample -cmake --build ./build/$cfg --config $cfg --target run diff --git a/thirdparty/ryml/samples/quickstart.cpp b/thirdparty/ryml/samples/quickstart.cpp deleted file mode 100644 index 0652f9fd5..000000000 --- a/thirdparty/ryml/samples/quickstart.cpp +++ /dev/null @@ -1,4161 +0,0 @@ -// ryml: quickstart -// -// This file does a quick tour of ryml. It has multiple self-contained -// and commented samples that illustrate how to use ryml, and how it -// works. Although this is not a unit test, the samples are written as -// a sequence of actions and predicate checks to better convey what is -// the expected result at any stage. And to ensure the code here is -// correct and up to date, it's also run as part of the CI tests. -// -// The directories that exist side-by-side with this file contain -// several examples on how to build this with cmake, such that you can -// hit the ground running. I suggest starting first with the -// add_subdirectory example, treating it just like any other -// self-contained cmake project. -// -// If something is unclear, please open an issue or send a pull -// request at https://github.com/biojppm/rapidyaml . If you have an -// issue while using ryml, it is also encouraged to try to reproduce -// the issue here, or look first through the relevant section. -// -// Happy ryml'ing! - - -//----------------------------------------------------------------------------- - -// ryml can be used as a single header, or as a simple library: -#if defined(RYML_SINGLE_HEADER) // using the single header directly in the executable - #define RYML_SINGLE_HDR_DEFINE_NOW - #include -#elif defined(RYML_SINGLE_HEADER_LIB) // using the single header from a library - #include -#else - #include - // is needed if interop with std containers is - // desired; ryml itself does not use any STL container. - // For this sample, we will be using std interop, so... - #include // optional header, provided for std:: interop - #include // needed for the examples below -#endif - -// these are needed for the examples below -#include -#include -#include -#include -#include - - -//----------------------------------------------------------------------------- - -// CONTENTS: -// -// (Each function addresses a topic and is fully self-contained. Jump -// to the function to find out about its topic.) -namespace sample { -void sample_quick_overview(); ///< briefly skim over most of the features -void sample_substr(); ///< about ryml's string views (from c4core) -void sample_parse_file(); ///< ready-to-go example of parsing a file from disk -void sample_parse_in_place(); ///< parse a mutable YAML source buffer -void sample_parse_in_arena(); ///< parse a read-only YAML source buffer -void sample_parse_reuse_tree(); ///< parse into an existing tree, maybe into a node -void sample_parse_reuse_parser(); ///< reuse an existing parser -void sample_parse_reuse_tree_and_parser(); ///< how to reuse existing trees and parsers -void sample_iterate_trees(); ///< visit individual nodes and iterate through trees -void sample_create_trees(); ///< programatically create trees -void sample_tree_arena(); ///< interact with the tree's serialization arena -void sample_fundamental_types(); ///< serialize/deserialize fundamental types -void sample_formatting(); ///< control formatting when serializing/deserializing -void sample_base64(); ///< encode/decode base64 -void sample_user_scalar_types(); ///< serialize/deserialize scalar (leaf/string) types -void sample_user_container_types(); ///< serialize/deserialize container (map or seq) types -void sample_std_types(); ///< serialize/deserialize STL containers -void sample_emit_to_container(); ///< emit to memory, eg a string or vector-like container -void sample_emit_to_stream(); ///< emit to a stream, eg std::ostream -void sample_emit_to_file(); ///< emit to a FILE* -void sample_emit_nested_node(); ///< pick a nested node as the root when emitting -void sample_json(); ///< JSON parsing and emitting -void sample_anchors_and_aliases(); ///< deal with YAML anchors and aliases -void sample_tags(); ///< deal with YAML type tags -void sample_docs(); ///< deal with YAML docs -void sample_error_handler(); ///< set a custom error handler -void sample_global_allocator(); ///< set a global allocator for ryml -void sample_per_tree_allocator(); ///< set per-tree allocators -void sample_static_trees(); ///< how to use static trees in ryml -void sample_location_tracking(); ///< track node locations in the parsed source tree -int report_checks(); -} /* namespace sample */ - -int main() -{ - sample::sample_quick_overview(); - sample::sample_substr(); - sample::sample_parse_file(); - sample::sample_parse_in_place(); - sample::sample_parse_in_arena(); - sample::sample_parse_reuse_tree(); - sample::sample_parse_reuse_parser(); - sample::sample_parse_reuse_tree_and_parser(); - sample::sample_iterate_trees(); - sample::sample_create_trees(); - sample::sample_tree_arena(); - sample::sample_fundamental_types(); - sample::sample_formatting(); - sample::sample_base64(); - sample::sample_user_scalar_types(); - sample::sample_user_container_types(); - sample::sample_std_types(); - sample::sample_emit_to_container(); - sample::sample_emit_to_stream(); - sample::sample_emit_to_file(); - sample::sample_emit_nested_node(); - sample::sample_json(); - sample::sample_anchors_and_aliases(); - sample::sample_tags(); - sample::sample_docs(); - sample::sample_error_handler(); - sample::sample_global_allocator(); - sample::sample_per_tree_allocator(); - sample::sample_static_trees(); - sample::sample_location_tracking(); - return sample::report_checks(); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -namespace sample { - -bool report_check(int line, const char *predicate, bool result); -#ifdef __GNUC__ -#if __GNUC__ == 4 && __GNUC_MINOR__ >= 8 -struct CheckPredicate { - const char *file; - const int line; - - void operator() (bool predicate) const - { - if (!report_check(line, nullptr, predicate)) - { - RYML_DEBUG_BREAK(); - } - } -}; -#define CHECK CheckPredicate{__FILE__, __LINE__} -#endif -#endif - -#if !defined(CHECK) -/// a quick'n'dirty assertion to verify a predicate -#define CHECK(predicate) do { if(!report_check(__LINE__, #predicate, (predicate))) { RYML_DEBUG_BREAK(); } } while(0) -#endif - -//----------------------------------------------------------------------------- - -/** a brief tour over most features */ -void sample_quick_overview() -{ - // Parse YAML code in place, potentially mutating the buffer. - // It is also possible to: - // - parse a read-only buffer using parse_in_arena() - // - reuse an existing tree (advised) - // - reuse an existing parser (advised) - char yml_buf[] = "{foo: 1, bar: [2, 3], john: doe}"; - ryml::Tree tree = ryml::parse_in_place(yml_buf); - - // Note: it will always be significantly faster to use mutable - // buffers and reuse tree+parser. - // - // Below you will find samples that show how to achieve reuse; but - // please note that for brevity and clarity, many of the examples - // here are parsing immutable buffers, and not reusing tree or - // parser. - - - //------------------------------------------------------------------ - // API overview - - // ryml has a two-level API: - // - // The lower level index API is based on the indices of nodes, - // where the node's id is the node's position in the tree's data - // array. This API is very efficient, but somewhat difficult to use: - size_t root_id = tree.root_id(); - size_t bar_id = tree.find_child(root_id, "bar"); // need to get the index right - CHECK(tree.is_map(root_id)); // all of the index methods are in the tree - CHECK(tree.is_seq(bar_id)); // ... and receive the subject index - - // The node API is a lightweight abstraction sitting on top of the - // index API, but offering a much more convenient interaction: - ryml::ConstNodeRef root = tree.rootref(); - ryml::ConstNodeRef bar = tree["bar"]; - CHECK(root.is_map()); - CHECK(bar.is_seq()); - // A node ref is a lightweight handle to the tree and associated id: - CHECK(root.tree() == &tree); // a node ref points at its tree, WITHOUT refcount - CHECK(root.id() == root_id); // a node ref's id is the index of the node - CHECK(bar.id() == bar_id); // a node ref's id is the index of the node - - // The node API translates very cleanly to the index API, so most - // of the code examples below are using the node API. - - // One significant point of the node API is that it holds a raw - // pointer to the tree. Care must be taken to ensure the lifetimes - // match, so that a node will never access the tree after the tree - // went out of scope. - - - //------------------------------------------------------------------ - // To read the parsed tree - - // ConstNodeRef::operator[] does a lookup, is O(num_children[node]). - CHECK(tree["foo"].is_keyval()); - CHECK(tree["foo"].key() == "foo"); - CHECK(tree["foo"].val() == "1"); - CHECK(tree["bar"].is_seq()); - CHECK(tree["bar"].has_key()); - CHECK(tree["bar"].key() == "bar"); - // maps use string keys, seqs use integral keys: - CHECK(tree["bar"][0].val() == "2"); - CHECK(tree["bar"][1].val() == "3"); - CHECK(tree["john"].val() == "doe"); - // An integral key is the position of the child within its parent, - // so even maps can also use int keys, if the key position is - // known. - CHECK(tree[0].id() == tree["foo"].id()); - CHECK(tree[1].id() == tree["bar"].id()); - CHECK(tree[2].id() == tree["john"].id()); - // Tree::operator[](int) searches a ***root*** child by its position. - CHECK(tree[0].id() == tree["foo"].id()); // 0: first child of root - CHECK(tree[1].id() == tree["bar"].id()); // 1: first child of root - CHECK(tree[2].id() == tree["john"].id()); // 2: first child of root - // NodeRef::operator[](int) searches a ***node*** child by its position: - CHECK(bar[0].val() == "2"); // 0 means first child of bar - CHECK(bar[1].val() == "3"); // 1 means second child of bar - // NodeRef::operator[](string): - // A string key is the key of the node: lookup is by name. So it - // is only available for maps, and it is NOT available for seqs, - // since seq members do not have keys. - CHECK(tree["foo"].key() == "foo"); - CHECK(tree["bar"].key() == "bar"); - CHECK(tree["john"].key() == "john"); - CHECK(bar.is_seq()); - // CHECK(bar["BOOM!"].is_seed()); // error, seqs do not have key lookup - - // Note that maps can also use index keys as well as string keys: - CHECK(root["foo"].id() == root[0].id()); - CHECK(root["bar"].id() == root[1].id()); - CHECK(root["john"].id() == root[2].id()); - - // IMPORTANT. The ryml tree uses indexed linked lists for storing - // children, so the complexity of `Tree::operator[csubstr]` and - // `Tree::operator[size_t]` is linear on the number of root - // children. If you use `Tree::operator[]` with a large tree where - // the root has many children, you will see a performance hit. - // - // To avoid this hit, you can create your own accelerator - // structure. For example, before doing a lookup, do a single - // traverse at the root level to fill an `map` - // mapping key names to node indices; with a node index, a lookup - // (via `Tree::get()`) is O(1), so this way you can get O(log n) - // lookup from a key. (But please do not use `std::map` if you - // care about performance; use something else like a flat map or - // sorted vector). - // - // As for node refs, the difference from `NodeRef::operator[]` and - // `ConstNodeRef::operator[]` to `Tree::operator[]` is that the - // latter refers to the root node, whereas the former are invoked - // on their target node. But the lookup process works the same for - // both and their algorithmic complexity is the same: they are - // both linear in the number of direct children. But of course, - // depending on the data, that number may be very different from - // one to another. - - //------------------------------------------------------------------ - // Hierarchy: - - { - ryml::ConstNodeRef foo = root.first_child(); - ryml::ConstNodeRef john = root.last_child(); - CHECK(tree.size() == 6); // O(1) number of nodes in the tree - CHECK(root.num_children() == 3); // O(num_children[root]) - CHECK(foo.num_siblings() == 3); // O(num_children[parent(foo)]) - CHECK(foo.parent().id() == root.id()); // parent() is O(1) - CHECK(root.first_child().id() == root["foo"].id()); // first_child() is O(1) - CHECK(root.last_child().id() == root["john"].id()); // last_child() is O(1) - CHECK(john.first_sibling().id() == foo.id()); - CHECK(foo.last_sibling().id() == john.id()); - // prev_sibling(), next_sibling(): (both are O(1)) - CHECK(foo.num_siblings() == root.num_children()); - CHECK(foo.prev_sibling().id() == ryml::NONE); // foo is the first_child() - CHECK(foo.next_sibling().key() == "bar"); - CHECK(foo.next_sibling().next_sibling().key() == "john"); - CHECK(foo.next_sibling().next_sibling().next_sibling().id() == ryml::NONE); // john is the last_child() - } - - - //------------------------------------------------------------------ - // Iterating: - { - ryml::csubstr expected_keys[] = {"foo", "bar", "john"}; - // iterate children using the high-level node API: - { - size_t count = 0; - for(ryml::ConstNodeRef const& child : root.children()) - CHECK(child.key() == expected_keys[count++]); - } - // iterate siblings using the high-level node API: - { - size_t count = 0; - for(ryml::ConstNodeRef const& child : root["foo"].siblings()) - CHECK(child.key() == expected_keys[count++]); - } - // iterate children using the lower-level tree index API: - { - size_t count = 0; - for(size_t child_id = tree.first_child(root_id); child_id != ryml::NONE; child_id = tree.next_sibling(child_id)) - CHECK(tree.key(child_id) == expected_keys[count++]); - } - // iterate siblings using the lower-level tree index API: - // (notice the only difference from above is in the loop - // preamble, which calls tree.first_sibling(bar_id) instead of - // tree.first_child(root_id)) - { - size_t count = 0; - for(size_t child_id = tree.first_sibling(bar_id); child_id != ryml::NONE; child_id = tree.next_sibling(child_id)) - CHECK(tree.key(child_id) == expected_keys[count++]); - } - } - - - //------------------------------------------------------------------ - // Gotchas: - CHECK(!tree["bar"].has_val()); // seq is a container, so no val - CHECK(!tree["bar"][0].has_key()); // belongs to a seq, so no key - CHECK(!tree["bar"][1].has_key()); // belongs to a seq, so no key - //CHECK(tree["bar"].val() == BOOM!); // ... so attempting to get a val is undefined behavior - //CHECK(tree["bar"][0].key() == BOOM!); // ... so attempting to get a key is undefined behavior - //CHECK(tree["bar"][1].key() == BOOM!); // ... so attempting to get a key is undefined behavior - - - //------------------------------------------------------------------ - // Deserializing: use operator>> - { - int foo = 0, bar0 = 0, bar1 = 0; - std::string john; - root["foo"] >> foo; - root["bar"][0] >> bar0; - root["bar"][1] >> bar1; - root["john"] >> john; // requires from_chars(std::string). see serialization samples below. - CHECK(foo == 1); - CHECK(bar0 == 2); - CHECK(bar1 == 3); - CHECK(john == "doe"); - } - - - //------------------------------------------------------------------ - // Modifying existing nodes: operator<< vs operator= - - // As implied by its name, ConstNodeRef is a reference to a const - // node. It can be used to read from the node, but not write to it - // or modify the hierarchy of the node. If any modification is - // desired then a NodeRef must be used instead: - ryml::NodeRef wroot = tree.rootref(); - - // operator= assigns an existing string to the receiving node. - // This pointer will be in effect until the tree goes out of scope - // so beware to only assign from strings outliving the tree. - wroot["foo"] = "says you"; - wroot["bar"][0] = "-2"; - wroot["bar"][1] = "-3"; - wroot["john"] = "ron"; - // Now the tree is _pointing_ at the memory of the strings above. - // That is OK because those are static strings and will outlive - // the tree. - CHECK(root["foo"].val() == "says you"); - CHECK(root["bar"][0].val() == "-2"); - CHECK(root["bar"][1].val() == "-3"); - CHECK(root["john"].val() == "ron"); - // WATCHOUT: do not assign from temporary objects: - // { - // std::string crash("will dangle"); - // root["john"] = ryml::to_csubstr(crash); - // } - // CHECK(root["john"] == "dangling"); // CRASH! the string was deallocated - - // operator<< first serializes the input to the tree's arena, then - // assigns the serialized string to the receiving node. This avoids - // constraints with the lifetime, since the arena lives with the tree. - CHECK(tree.arena().empty()); - wroot["foo"] << "says who"; // requires to_chars(). see serialization samples below. - wroot["bar"][0] << 20; - wroot["bar"][1] << 30; - wroot["john"] << "deere"; - CHECK(root["foo"].val() == "says who"); - CHECK(root["bar"][0].val() == "20"); - CHECK(root["bar"][1].val() == "30"); - CHECK(root["john"].val() == "deere"); - CHECK(tree.arena() == "says who2030deere"); // the result of serializations to the tree arena - // using operator<< instead of operator=, the crash above is avoided: - { - std::string ok("in_scope"); - // root["john"] = ryml::to_csubstr(ok); // don't, will dangle - wroot["john"] << ryml::to_csubstr(ok); // OK, copy to the tree's arena - } - CHECK(root["john"] == "in_scope"); // OK! - CHECK(tree.arena() == "says who2030deerein_scope"); // the result of serializations to the tree arena - - - //------------------------------------------------------------------ - // Adding new nodes: - - // adding a keyval node to a map: - CHECK(root.num_children() == 3); - wroot["newkeyval"] = "shiny and new"; // using these strings - wroot.append_child() << ryml::key("newkeyval (serialized)") << "shiny and new (serialized)"; // serializes and assigns the serialization - CHECK(root.num_children() == 5); - CHECK(root["newkeyval"].key() == "newkeyval"); - CHECK(root["newkeyval"].val() == "shiny and new"); - CHECK(root["newkeyval (serialized)"].key() == "newkeyval (serialized)"); - CHECK(root["newkeyval (serialized)"].val() == "shiny and new (serialized)"); - CHECK( ! tree.in_arena(root["newkeyval"].key())); // it's using directly the static string above - CHECK( ! tree.in_arena(root["newkeyval"].val())); // it's using directly the static string above - CHECK( tree.in_arena(root["newkeyval (serialized)"].key())); // it's using a serialization of the string above - CHECK( tree.in_arena(root["newkeyval (serialized)"].val())); // it's using a serialization of the string above - // adding a val node to a seq: - CHECK(root["bar"].num_children() == 2); - wroot["bar"][2] = "oh so nice"; - wroot["bar"][3] << "oh so nice (serialized)"; - CHECK(root["bar"].num_children() == 4); - CHECK(root["bar"][2].val() == "oh so nice"); - CHECK(root["bar"][3].val() == "oh so nice (serialized)"); - // adding a seq node: - CHECK(root.num_children() == 5); - wroot["newseq"] |= ryml::SEQ; - wroot.append_child() << ryml::key("newseq (serialized)") |= ryml::SEQ; - CHECK(root.num_children() == 7); - CHECK(root["newseq"].num_children() == 0); - CHECK(root["newseq"].is_seq()); - CHECK(root["newseq (serialized)"].num_children() == 0); - CHECK(root["newseq (serialized)"].is_seq()); - // adding a map node: - CHECK(root.num_children() == 7); - wroot["newmap"] |= ryml::MAP; - wroot.append_child() << ryml::key("newmap (serialized)") |= ryml::MAP; - CHECK(root.num_children() == 9); - CHECK(root["newmap"].num_children() == 0); - CHECK(root["newmap"].is_map()); - CHECK(root["newmap (serialized)"].num_children() == 0); - CHECK(root["newmap (serialized)"].is_map()); - // - // When the tree is mutable, operator[] does not mutate the tree - // until the returned node is written to. - // - // Until such time, the NodeRef object keeps in itself the required - // information to write to the proper place in the tree. This is - // called being in a "seed" state. - // - // This means that passing a key/index which does not exist will - // not mutate the tree, but will instead store (in the node) the - // proper place of the tree to be able to do so, if and when it is - // required. - // - // This is a significant difference from eg, the behavior of - // std::map, which mutates the map immediately within the call to - // operator[]. - // - // All of the points above apply only if the tree is mutable. If - // the tree is const, then a NodeRef cannot be obtained from it; - // only a ConstNodeRef, which can never be used to mutate the - // tree. - CHECK(!root.has_child("I am not nothing")); - ryml::NodeRef nothing = wroot["I am nothing"]; - CHECK(nothing.valid()); // points at the tree, and a specific place in the tree - CHECK(nothing.is_seed()); // ... but nothing is there yet. - CHECK(!root.has_child("I am nothing")); // same as above - ryml::NodeRef something = wroot["I am something"]; - ryml::ConstNodeRef constsomething = wroot["I am something"]; - CHECK(!root.has_child("I am something")); // same as above - CHECK(something.valid()); - CHECK(something.is_seed()); // same as above - CHECK(!constsomething.valid()); // NOTE: because a ConstNodeRef - // cannot be used to mutate a - // tree, it is only valid() if it - // is pointing at an existing - // node. - something = "indeed"; // this will commit to the tree, mutating at the proper place - CHECK(root.has_child("I am something")); - CHECK(root["I am something"].val() == "indeed"); - CHECK(something.valid()); - CHECK(!something.is_seed()); // now the tree has this node, so the - // ref is no longer a seed - // now the constref is also valid (but it needs to be reassigned): - ryml::ConstNodeRef constsomethingnew = wroot["I am something"]; - CHECK(constsomethingnew.valid()); - // note that the old constref is now stale, because it only keeps - // the state at creation: - CHECK(!constsomething.valid()); - - - //------------------------------------------------------------------ - // Emitting: - - // emit to a FILE* - ryml::emit_yaml(tree, stdout); - // emit to a stream - std::stringstream ss; - ss << tree; - std::string stream_result = ss.str(); - // emit to a buffer: - std::string str_result = ryml::emitrs_yaml(tree); - // can emit to any given buffer: - char buf[1024]; - ryml::csubstr buf_result = ryml::emit_yaml(tree, buf); - // now check - ryml::csubstr expected_result = R"(foo: says who -bar: - - 20 - - 30 - - oh so nice - - oh so nice (serialized) -john: in_scope -newkeyval: shiny and new -newkeyval (serialized): shiny and new (serialized) -newseq: [] -newseq (serialized): [] -newmap: {} -newmap (serialized): {} -I am something: indeed -)"; - CHECK(buf_result == expected_result); - CHECK(str_result == expected_result); - CHECK(stream_result == expected_result); - // There are many possibilities to emit to buffer; - // please look at the emit sample functions below. - - //------------------------------------------------------------------ - // ConstNodeRef vs NodeRef - - ryml::NodeRef noderef = tree["bar"][0]; - ryml::ConstNodeRef constnoderef = tree["bar"][0]; - - // ConstNodeRef cannot be used to mutate the tree, but a NodeRef can: - //constnoderef = "21"; // compile error - //constnoderef << "22"; // compile error - noderef = "21"; // ok, can assign because it's not const - CHECK(tree["bar"][0].val() == "21"); - noderef << "22"; // ok, can serialize and assign because it's not const - CHECK(tree["bar"][0].val() == "22"); - - // it is not possible to obtain a NodeRef from a ConstNodeRef: - // noderef = constnoderef; // compile error - - // it is always possible to obtain a ConstNodeRef from a NodeRef: - constnoderef = noderef; // ok can assign const <- nonconst - - // If a tree is const, then only ConstNodeRef's can be - // obtained from that tree: - ryml::Tree const& consttree = tree; - //noderef = consttree["bar"][0]; // compile error - noderef = tree["bar"][0]; // ok - constnoderef = consttree["bar"][0]; // ok - - // ConstNodeRef and NodeRef can be compared for equality. - // Equality means they point at the same node. - CHECK(constnoderef == noderef); - CHECK(!(constnoderef != noderef)); - - //------------------------------------------------------------------ - // Dealing with UTF8 - ryml::Tree langs = ryml::parse_in_arena(R"( -en: Planet (Gas) -fr: Planète (Gazeuse) -ru: Планета (Газ) -ja: 惑星(ガス) -zh: 行星(气体) -# UTF8 decoding only happens in double-quoted strings,\ -# as per the YAML standard -decode this: "\u263A \xE2\x98\xBA" -and this as well: "\u2705 \U0001D11E" -)"); - // in-place UTF8 just works: - CHECK(langs["en"].val() == "Planet (Gas)"); - CHECK(langs["fr"].val() == "Planète (Gazeuse)"); - CHECK(langs["ru"].val() == "Планета (Газ)"); - CHECK(langs["ja"].val() == "惑星(ガス)"); - CHECK(langs["zh"].val() == "行星(气体)"); - // and \x \u \U codepoints are decoded (but only when they appear - // inside double-quoted strings, as dictated by the YAML - // standard): - CHECK(langs["decode this"].val() == "☺ ☺"); - CHECK(langs["and this as well"].val() == "✅ 𝄞"); - - //------------------------------------------------------------------ - // Getting the location of nodes in the source: - // - // Location tracking is opt-in: - ryml::Parser parser(ryml::ParserOptions().locations(true)); - // Now the parser will start by building the accelerator structure: - ryml::Tree tree2 = parser.parse_in_arena("expected.yml", expected_result); - // ... and use it when querying - ryml::Location loc = parser.location(tree2["bar"][1]); - CHECK(parser.location_contents(loc).begins_with("30")); - CHECK(loc.line == 3u); - CHECK(loc.col == 4u); - // For further details in location tracking, - // refer to the sample function below. -} - - -//----------------------------------------------------------------------------- - -/** demonstrate usage of ryml::substr/ryml::csubstr - * - * These types are imported from the c4core library into the ryml - * namespace You may have noticed above the use of a `csubstr` - * class. This class is defined in another library, - * [c4core](https://github.com/biojppm/c4core), which is imported by - * ryml. This is a library I use with my projects consisting of - * multiplatform low-level utilities. One of these is `c4::csubstr` - * (the name comes from "constant substring") which is a non-owning - * read-only string view, with many methods that make it practical to - * use (I would certainly argue more practical than `std::string`). In - * fact, `c4::csubstr` and its writeable counterpart `c4::substr` are - * the workhorses of the ryml parsing and serialization code. - * - * @see https://c4core.docsforge.com/master/api/c4/basic_substring/ - * @see https://c4core.docsforge.com/master/api/c4/#substr - * @see https://c4core.docsforge.com/master/api/c4/#csubstr - */ -void sample_substr() -{ - // substr is a mutable view: pointer and length to a string in memory. - // csubstr is a const-substr (immutable). - - // construct from explicit args - { - const char foobar_str[] = "foobar"; - auto s = ryml::csubstr(foobar_str, strlen(foobar_str)); - CHECK(s == "foobar"); - CHECK(s.size() == 6); - CHECK(s.data() == foobar_str); - CHECK(s.size() == s.len); - CHECK(s.data() == s.str); - } - - // construct from a string array - { - const char foobar_str[] = "foobar"; - ryml::csubstr s = foobar_str; - CHECK(s == "foobar"); - CHECK(s != "foobar0"); - CHECK(s.size() == 6); - CHECK(s.data() == foobar_str); - CHECK(s.size() == s.len); - CHECK(s.data() == s.str); - } - // you can also declare directly in-place from an array: - { - ryml::csubstr s = "foobar"; - CHECK(s == "foobar"); - CHECK(s != "foobar0"); - CHECK(s.size() == 6); - CHECK(s.size() == s.len); - CHECK(s.data() == s.str); - } - - // construct from a C-string: - // - // Since the input is only a pointer, the string length can only - // be found with a call to strlen(). To make this cost evident, we - // require a call to to_csubstr(): - { - const char *foobar_str = "foobar"; - ryml::csubstr s = ryml::to_csubstr(foobar_str); - CHECK(s == "foobar"); - CHECK(s != "foobar0"); - CHECK(s.size() == 6); - CHECK(s.size() == s.len); - CHECK(s.data() == s.str); - } - - // construct from a std::string: same approach as above. - // requires inclusion of the header - // or of the umbrella header . - // this was a deliberate design choice to avoid requiring - // the heavy std:: allocation machinery - { - std::string foobar_str = "foobar"; - ryml::csubstr s = ryml::to_csubstr(foobar_str); // defined in - CHECK(s == "foobar"); - CHECK(s != "foobar0"); - CHECK(s.size() == 6); - CHECK(s.size() == s.len); - CHECK(s.data() == s.str); - } - - // convert substr -> csubstr - { - char buf[] = "foo"; - ryml::substr foo = buf; - CHECK(foo.len == 3); - CHECK(foo.data() == buf); - ryml::csubstr cfoo = foo; - CHECK(cfoo.data() == buf); - } - // cannot convert csubstr -> substr: - { - // ryml::substr foo2 = cfoo; // compile error: cannot write to csubstr - } - - // construct from char[]/const char[]: mutable vs immutable memory - { - char const foobar_str_ro[] = "foobar"; // ro := read-only - char foobar_str_rw[] = "foobar"; // rw := read-write - static_assert(std::is_array::value, "this is an array"); - static_assert(std::is_array::value, "this is an array"); - // csubstr <- read-only memory - { - ryml::csubstr foobar = foobar_str_ro; - CHECK(foobar.data() == foobar_str_ro); - CHECK(foobar.size() == strlen(foobar_str_ro)); - CHECK(foobar == "foobar"); // AKA strcmp - } - // csubstr <- read-write memory: you can create an immutable csubstr from mutable memory - { - ryml::csubstr foobar = foobar_str_rw; - CHECK(foobar.data() == foobar_str_rw); - CHECK(foobar.size() == strlen(foobar_str_rw)); - CHECK(foobar == "foobar"); // AKA strcmp - } - // substr <- read-write memory. - { - ryml::substr foobar = foobar_str_rw; - CHECK(foobar.data() == foobar_str_rw); - CHECK(foobar.size() == strlen(foobar_str_rw)); - CHECK(foobar == "foobar"); // AKA strcmp - } - // substr <- ro is impossible. - { - //ryml::substr foobar = foobar_str_ro; // compile error! - } - } - - // construct from char*/const char*: mutable vs immutable memory. - // use to_substr()/to_csubstr() - { - char const* foobar_str_ro = "foobar"; // ro := read-only - char foobar_str_rw_[] = "foobar"; // rw := read-write - char * foobar_str_rw = foobar_str_rw_; // rw := read-write - static_assert(!std::is_array::value, "this is a decayed pointer"); - static_assert(!std::is_array::value, "this is a decayed pointer"); - // csubstr <- read-only memory - { - //ryml::csubstr foobar = foobar_str_ro; // compile error: length is not known - ryml::csubstr foobar = ryml::to_csubstr(foobar_str_ro); - CHECK(foobar.data() == foobar_str_ro); - CHECK(foobar.size() == strlen(foobar_str_ro)); - CHECK(foobar == "foobar"); // AKA strcmp - } - // csubstr <- read-write memory: you can create an immutable csubstr from mutable memory - { - ryml::csubstr foobar = ryml::to_csubstr(foobar_str_rw); - CHECK(foobar.data() == foobar_str_rw); - CHECK(foobar.size() == strlen(foobar_str_rw)); - CHECK(foobar == "foobar"); // AKA strcmp - } - // substr <- read-write memory. - { - ryml::substr foobar = ryml::to_substr(foobar_str_rw); - CHECK(foobar.data() == foobar_str_rw); - CHECK(foobar.size() == strlen(foobar_str_rw)); - CHECK(foobar == "foobar"); // AKA strcmp - } - // substr <- read-only is impossible. - { - //ryml::substr foobar = ryml::to_substr(foobar_str_ro); // compile error! - } - } - - // substr is mutable, without changing the size: - { - char buf[] = "foobar"; - ryml::substr foobar = buf; - CHECK(foobar == "foobar"); - foobar[0] = 'F'; CHECK(foobar == "Foobar"); - foobar.back() = 'R'; CHECK(foobar == "FoobaR"); - foobar.reverse(); CHECK(foobar == "RabooF"); - foobar.reverse(); CHECK(foobar == "FoobaR"); - foobar.reverse_sub(1, 4); CHECK(foobar == "FabooR"); - foobar.reverse_sub(1, 4); CHECK(foobar == "FoobaR"); - foobar.reverse_range(2, 5); CHECK(foobar == "FoaboR"); - foobar.reverse_range(2, 5); CHECK(foobar == "FoobaR"); - foobar.replace('o', '0'); CHECK(foobar == "F00baR"); - foobar.replace('a', '_'); CHECK(foobar == "F00b_R"); - foobar.replace("_0b", 'a'); CHECK(foobar == "FaaaaR"); - foobar.toupper(); CHECK(foobar == "FAAAAR"); - foobar.tolower(); CHECK(foobar == "faaaar"); - foobar.fill('.'); CHECK(foobar == "......"); - // see also: - // - .erase() - // - .replace_all() - } - - // sub-views - { - ryml::csubstr s = "fooFOObarBAR"; - CHECK(s.len == 12u); - // sub(): <- first,[num] - CHECK(s.sub(0) == "fooFOObarBAR"); - CHECK(s.sub(0, 12) == "fooFOObarBAR"); - CHECK(s.sub(0, 3) == "foo" ); - CHECK(s.sub(3) == "FOObarBAR"); - CHECK(s.sub(3, 3) == "FOO" ); - CHECK(s.sub(6) == "barBAR"); - CHECK(s.sub(6, 3) == "bar" ); - CHECK(s.sub(9) == "BAR"); - CHECK(s.sub(9, 3) == "BAR"); - // first(): <- length - CHECK(s.first(0) == "" ); - CHECK(s.first(1) == "f" ); - CHECK(s.first(2) != "f" ); - CHECK(s.first(2) == "fo" ); - CHECK(s.first(3) == "foo"); - // last(): <- length - CHECK(s.last(0) == ""); - CHECK(s.last(1) == "R"); - CHECK(s.last(2) == "AR"); - CHECK(s.last(3) == "BAR"); - // range(): <- first, last - CHECK(s.range(0, 12) == "fooFOObarBAR"); - CHECK(s.range(1, 12) == "ooFOObarBAR"); - CHECK(s.range(1, 11) == "ooFOObarBA" ); - CHECK(s.range(2, 10) == "oFOObarB" ); - CHECK(s.range(3, 9) == "FOObar" ); - // offs(): offset from beginning, end - CHECK(s.offs(0, 0) == "fooFOObarBAR"); - CHECK(s.offs(1, 0) == "ooFOObarBAR"); - CHECK(s.offs(1, 1) == "ooFOObarBA" ); - CHECK(s.offs(2, 1) == "oFOObarBA" ); - CHECK(s.offs(2, 2) == "oFOObarB" ); - CHECK(s.offs(3, 3) == "FOObar" ); - // right_of(): <- pos, include_pos - CHECK(s.right_of(0, true) == "fooFOObarBAR"); - CHECK(s.right_of(0, false) == "ooFOObarBAR"); - CHECK(s.right_of(1, true) == "ooFOObarBAR"); - CHECK(s.right_of(1, false) == "oFOObarBAR"); - CHECK(s.right_of(2, true) == "oFOObarBAR"); - CHECK(s.right_of(2, false) == "FOObarBAR"); - CHECK(s.right_of(3, true) == "FOObarBAR"); - CHECK(s.right_of(3, false) == "OObarBAR"); - // left_of() <- pos, include_pos - CHECK(s.left_of(12, false) == "fooFOObarBAR"); - CHECK(s.left_of(11, true) == "fooFOObarBAR"); - CHECK(s.left_of(11, false) == "fooFOObarBA" ); - CHECK(s.left_of(10, true) == "fooFOObarBA" ); - CHECK(s.left_of(10, false) == "fooFOObarB" ); - CHECK(s.left_of( 9, true) == "fooFOObarB" ); - CHECK(s.left_of( 9, false) == "fooFOObar" ); - // left_of(),right_of() <- substr - ryml::csubstr FOO = s.sub(3, 3); - CHECK(s.is_super(FOO)); // required for the following - CHECK(s.left_of(FOO) == "foo"); - CHECK(s.right_of(FOO) == "barBAR"); - } - - // is_sub(),is_super() - { - ryml::csubstr foobar = "foobar"; - ryml::csubstr foo = foobar.first(3); - CHECK(foo.is_sub(foobar)); - CHECK(foo.is_sub(foo)); - CHECK(!foo.is_super(foobar)); - CHECK(!foobar.is_sub(foo)); - // identity comparison is true: - CHECK(foo.is_super(foo)); - CHECK(foo.is_sub(foo)); - CHECK(foobar.is_sub(foobar)); - CHECK(foobar.is_super(foobar)); - } - - // overlaps() - { - ryml::csubstr foobar = "foobar"; - ryml::csubstr foo = foobar.first(3); - ryml::csubstr oba = foobar.offs(2, 1); - ryml::csubstr abc = "abc"; - CHECK(foobar.overlaps(foo)); - CHECK(foobar.overlaps(oba)); - CHECK(foo.overlaps(foobar)); - CHECK(foo.overlaps(oba)); - CHECK(!foo.overlaps(abc)); - CHECK(!abc.overlaps(foo)); - } - - // triml(): trim characters from the left - // trimr(): trim characters from the right - // trim(): trim characters from left AND right - { - CHECK(ryml::csubstr(" \t\n\rcontents without whitespace\t \n\r").trim("\t \n\r") == "contents without whitespace"); - ryml::csubstr aaabbb = "aaabbb"; - ryml::csubstr aaa___bbb = "aaa___bbb"; - // trim a character: - CHECK(aaabbb.triml('a') == aaabbb.last(3)); // bbb - CHECK(aaabbb.trimr('a') == aaabbb); - CHECK(aaabbb.trim ('a') == aaabbb.last(3)); // bbb - CHECK(aaabbb.triml('b') == aaabbb); - CHECK(aaabbb.trimr('b') == aaabbb.first(3)); // aaa - CHECK(aaabbb.trim ('b') == aaabbb.first(3)); // aaa - CHECK(aaabbb.triml('c') == aaabbb); - CHECK(aaabbb.trimr('c') == aaabbb); - CHECK(aaabbb.trim ('c') == aaabbb); - CHECK(aaa___bbb.triml('a') == aaa___bbb.last(6)); // ___bbb - CHECK(aaa___bbb.trimr('a') == aaa___bbb); - CHECK(aaa___bbb.trim ('a') == aaa___bbb.last(6)); // ___bbb - CHECK(aaa___bbb.triml('b') == aaa___bbb); - CHECK(aaa___bbb.trimr('b') == aaa___bbb.first(6)); // aaa___ - CHECK(aaa___bbb.trim ('b') == aaa___bbb.first(6)); // aaa___ - CHECK(aaa___bbb.triml('c') == aaa___bbb); - CHECK(aaa___bbb.trimr('c') == aaa___bbb); - CHECK(aaa___bbb.trim ('c') == aaa___bbb); - // trim ANY of the characters: - CHECK(aaabbb.triml("ab") == ""); - CHECK(aaabbb.trimr("ab") == ""); - CHECK(aaabbb.trim ("ab") == ""); - CHECK(aaabbb.triml("ba") == ""); - CHECK(aaabbb.trimr("ba") == ""); - CHECK(aaabbb.trim ("ba") == ""); - CHECK(aaabbb.triml("cd") == aaabbb); - CHECK(aaabbb.trimr("cd") == aaabbb); - CHECK(aaabbb.trim ("cd") == aaabbb); - CHECK(aaa___bbb.triml("ab") == aaa___bbb.last(6)); // ___bbb - CHECK(aaa___bbb.triml("ba") == aaa___bbb.last(6)); // ___bbb - CHECK(aaa___bbb.triml("cd") == aaa___bbb); - CHECK(aaa___bbb.trimr("ab") == aaa___bbb.first(6)); // aaa___ - CHECK(aaa___bbb.trimr("ba") == aaa___bbb.first(6)); // aaa___ - CHECK(aaa___bbb.trimr("cd") == aaa___bbb); - CHECK(aaa___bbb.trim ("ab") == aaa___bbb.range(3, 6)); // ___ - CHECK(aaa___bbb.trim ("ba") == aaa___bbb.range(3, 6)); // ___ - CHECK(aaa___bbb.trim ("cd") == aaa___bbb); - } - - // unquoted(): - { - CHECK(ryml::csubstr(R"('this is is single quoted')").unquoted() == "this is is single quoted"); - CHECK(ryml::csubstr(R"("this is is double quoted")").unquoted() == "this is is double quoted"); - } - - // stripl(): remove pattern from the left - // stripr(): remove pattern from the right - { - ryml::csubstr abc___cba = "abc___cba"; - ryml::csubstr abc___abc = "abc___abc"; - CHECK(abc___cba.stripl("abc") == abc___cba.last(6)); // ___cba - CHECK(abc___cba.stripr("abc") == abc___cba); - CHECK(abc___cba.stripl("ab") == abc___cba.last(7)); // c___cba - CHECK(abc___cba.stripr("ab") == abc___cba); - CHECK(abc___cba.stripl("a") == abc___cba.last(8)); // bc___cba, same as triml('a') - CHECK(abc___cba.stripr("a") == abc___cba.first(8)); - CHECK(abc___abc.stripl("abc") == abc___abc.last(6)); // ___abc - CHECK(abc___abc.stripr("abc") == abc___abc.first(6)); // abc___ - CHECK(abc___abc.stripl("ab") == abc___abc.last(7)); // c___cba - CHECK(abc___abc.stripr("ab") == abc___abc); - CHECK(abc___abc.stripl("a") == abc___abc.last(8)); // bc___cba, same as triml('a') - CHECK(abc___abc.stripr("a") == abc___abc); - } - - // begins_with()/ends_with() - // begins_with_any()/ends_with_any() - { - ryml::csubstr s = "foobar123"; - // char overloads - CHECK(s.begins_with('f')); - CHECK(s.ends_with('3')); - CHECK(!s.ends_with('2')); - CHECK(!s.ends_with('o')); - // char[] overloads - CHECK(s.begins_with("foobar")); - CHECK(s.begins_with("foo")); - CHECK(s.begins_with_any("foo")); - CHECK(!s.begins_with("oof")); - CHECK(s.begins_with_any("oof")); - CHECK(s.ends_with("23")); - CHECK(s.ends_with("123")); - CHECK(s.ends_with_any("123")); - CHECK(!s.ends_with("321")); - CHECK(s.ends_with_any("231")); - } - - // select() - { - ryml::csubstr s = "0123456789"; - CHECK(s.select('0') == s.sub(0, 1)); - CHECK(s.select('1') == s.sub(1, 1)); - CHECK(s.select('2') == s.sub(2, 1)); - CHECK(s.select('8') == s.sub(8, 1)); - CHECK(s.select('9') == s.sub(9, 1)); - CHECK(s.select("0123") == s.range(0, 4)); - CHECK(s.select("012" ) == s.range(0, 3)); - CHECK(s.select("01" ) == s.range(0, 2)); - CHECK(s.select("0" ) == s.range(0, 1)); - CHECK(s.select( "123") == s.range(1, 4)); - CHECK(s.select( "23") == s.range(2, 4)); - CHECK(s.select( "3") == s.range(3, 4)); - } - - // find() - { - ryml::csubstr s012345 = "012345"; - // find single characters: - CHECK(s012345.find('a') == ryml::npos); - CHECK(s012345.find('0' ) == 0u); - CHECK(s012345.find('0', 1u) == ryml::npos); - CHECK(s012345.find('1' ) == 1u); - CHECK(s012345.find('1', 2u) == ryml::npos); - CHECK(s012345.find('2' ) == 2u); - CHECK(s012345.find('2', 3u) == ryml::npos); - CHECK(s012345.find('3' ) == 3u); - CHECK(s012345.find('3', 4u) == ryml::npos); - // find patterns - CHECK(s012345.find("ab" ) == ryml::npos); - CHECK(s012345.find("01" ) == 0u); - CHECK(s012345.find("01", 1u) == ryml::npos); - CHECK(s012345.find("12" ) == 1u); - CHECK(s012345.find("12", 2u) == ryml::npos); - CHECK(s012345.find("23" ) == 2u); - CHECK(s012345.find("23", 3u) == ryml::npos); - } - - // count(): count the number of occurrences of a character - { - ryml::csubstr buf = "00110022003300440055"; - CHECK(buf.count('1' ) == 2u); - CHECK(buf.count('1', 0u) == 2u); - CHECK(buf.count('1', 1u) == 2u); - CHECK(buf.count('1', 2u) == 2u); - CHECK(buf.count('1', 3u) == 1u); - CHECK(buf.count('1', 4u) == 0u); - CHECK(buf.count('1', 5u) == 0u); - CHECK(buf.count('0' ) == 10u); - CHECK(buf.count('0', 0u) == 10u); - CHECK(buf.count('0', 1u) == 9u); - CHECK(buf.count('0', 2u) == 8u); - CHECK(buf.count('0', 3u) == 8u); - CHECK(buf.count('0', 4u) == 8u); - CHECK(buf.count('0', 5u) == 7u); - CHECK(buf.count('0', 6u) == 6u); - CHECK(buf.count('0', 7u) == 6u); - CHECK(buf.count('0', 8u) == 6u); - CHECK(buf.count('0', 9u) == 5u); - CHECK(buf.count('0', 10u) == 4u); - CHECK(buf.count('0', 11u) == 4u); - CHECK(buf.count('0', 12u) == 4u); - CHECK(buf.count('0', 13u) == 3u); - CHECK(buf.count('0', 14u) == 2u); - CHECK(buf.count('0', 15u) == 2u); - CHECK(buf.count('0', 16u) == 2u); - CHECK(buf.count('0', 17u) == 1u); - CHECK(buf.count('0', 18u) == 0u); - CHECK(buf.count('0', 19u) == 0u); - CHECK(buf.count('0', 20u) == 0u); - } - - // first_of(),last_of() - { - ryml::csubstr s012345 = "012345"; - CHECK(s012345.first_of('a') == ryml::npos); - CHECK(s012345.first_of("ab") == ryml::npos); - CHECK(s012345.first_of('0') == 0u); - CHECK(s012345.first_of("0") == 0u); - CHECK(s012345.first_of("01") == 0u); - CHECK(s012345.first_of("10") == 0u); - CHECK(s012345.first_of("012") == 0u); - CHECK(s012345.first_of("210") == 0u); - CHECK(s012345.first_of("0123") == 0u); - CHECK(s012345.first_of("3210") == 0u); - CHECK(s012345.first_of("01234") == 0u); - CHECK(s012345.first_of("43210") == 0u); - CHECK(s012345.first_of("012345") == 0u); - CHECK(s012345.first_of("543210") == 0u); - CHECK(s012345.first_of('5') == 5u); - CHECK(s012345.first_of("5") == 5u); - CHECK(s012345.first_of("45") == 4u); - CHECK(s012345.first_of("54") == 4u); - CHECK(s012345.first_of("345") == 3u); - CHECK(s012345.first_of("543") == 3u); - CHECK(s012345.first_of("2345") == 2u); - CHECK(s012345.first_of("5432") == 2u); - CHECK(s012345.first_of("12345") == 1u); - CHECK(s012345.first_of("54321") == 1u); - CHECK(s012345.first_of("012345") == 0u); - CHECK(s012345.first_of("543210") == 0u); - CHECK(s012345.first_of('0', 6u) == ryml::npos); - CHECK(s012345.first_of('5', 6u) == ryml::npos); - CHECK(s012345.first_of("012345", 6u) == ryml::npos); - // - CHECK(s012345.last_of('a') == ryml::npos); - CHECK(s012345.last_of("ab") == ryml::npos); - CHECK(s012345.last_of('0') == 0u); - CHECK(s012345.last_of("0") == 0u); - CHECK(s012345.last_of("01") == 1u); - CHECK(s012345.last_of("10") == 1u); - CHECK(s012345.last_of("012") == 2u); - CHECK(s012345.last_of("210") == 2u); - CHECK(s012345.last_of("0123") == 3u); - CHECK(s012345.last_of("3210") == 3u); - CHECK(s012345.last_of("01234") == 4u); - CHECK(s012345.last_of("43210") == 4u); - CHECK(s012345.last_of("012345") == 5u); - CHECK(s012345.last_of("543210") == 5u); - CHECK(s012345.last_of('5') == 5u); - CHECK(s012345.last_of("5") == 5u); - CHECK(s012345.last_of("45") == 5u); - CHECK(s012345.last_of("54") == 5u); - CHECK(s012345.last_of("345") == 5u); - CHECK(s012345.last_of("543") == 5u); - CHECK(s012345.last_of("2345") == 5u); - CHECK(s012345.last_of("5432") == 5u); - CHECK(s012345.last_of("12345") == 5u); - CHECK(s012345.last_of("54321") == 5u); - CHECK(s012345.last_of("012345") == 5u); - CHECK(s012345.last_of("543210") == 5u); - CHECK(s012345.last_of('0', 6u) == 0u); - CHECK(s012345.last_of('5', 6u) == 5u); - CHECK(s012345.last_of("012345", 6u) == 5u); - } - - // first_not_of(), last_not_of() - { - ryml::csubstr s012345 = "012345"; - CHECK(s012345.first_not_of('a') == 0u); - CHECK(s012345.first_not_of("ab") == 0u); - CHECK(s012345.first_not_of('0') == 1u); - CHECK(s012345.first_not_of("0") == 1u); - CHECK(s012345.first_not_of("01") == 2u); - CHECK(s012345.first_not_of("10") == 2u); - CHECK(s012345.first_not_of("012") == 3u); - CHECK(s012345.first_not_of("210") == 3u); - CHECK(s012345.first_not_of("0123") == 4u); - CHECK(s012345.first_not_of("3210") == 4u); - CHECK(s012345.first_not_of("01234") == 5u); - CHECK(s012345.first_not_of("43210") == 5u); - CHECK(s012345.first_not_of("012345") == ryml::npos); - CHECK(s012345.first_not_of("543210") == ryml::npos); - CHECK(s012345.first_not_of('5') == 0u); - CHECK(s012345.first_not_of("5") == 0u); - CHECK(s012345.first_not_of("45") == 0u); - CHECK(s012345.first_not_of("54") == 0u); - CHECK(s012345.first_not_of("345") == 0u); - CHECK(s012345.first_not_of("543") == 0u); - CHECK(s012345.first_not_of("2345") == 0u); - CHECK(s012345.first_not_of("5432") == 0u); - CHECK(s012345.first_not_of("12345") == 0u); - CHECK(s012345.first_not_of("54321") == 0u); - CHECK(s012345.first_not_of("012345") == ryml::npos); - CHECK(s012345.first_not_of("543210") == ryml::npos); - CHECK(s012345.last_not_of('a') == 5u); - CHECK(s012345.last_not_of("ab") == 5u); - CHECK(s012345.last_not_of('5') == 4u); - CHECK(s012345.last_not_of("5") == 4u); - CHECK(s012345.last_not_of("45") == 3u); - CHECK(s012345.last_not_of("54") == 3u); - CHECK(s012345.last_not_of("345") == 2u); - CHECK(s012345.last_not_of("543") == 2u); - CHECK(s012345.last_not_of("2345") == 1u); - CHECK(s012345.last_not_of("5432") == 1u); - CHECK(s012345.last_not_of("12345") == 0u); - CHECK(s012345.last_not_of("54321") == 0u); - CHECK(s012345.last_not_of("012345") == ryml::npos); - CHECK(s012345.last_not_of("543210") == ryml::npos); - CHECK(s012345.last_not_of('0') == 5u); - CHECK(s012345.last_not_of("0") == 5u); - CHECK(s012345.last_not_of("01") == 5u); - CHECK(s012345.last_not_of("10") == 5u); - CHECK(s012345.last_not_of("012") == 5u); - CHECK(s012345.last_not_of("210") == 5u); - CHECK(s012345.last_not_of("0123") == 5u); - CHECK(s012345.last_not_of("3210") == 5u); - CHECK(s012345.last_not_of("01234") == 5u); - CHECK(s012345.last_not_of("43210") == 5u); - CHECK(s012345.last_not_of("012345") == ryml::npos); - CHECK(s012345.last_not_of("543210") == ryml::npos); - } - - // first_non_empty_span() - { - CHECK(ryml::csubstr("foo bar").first_non_empty_span() == "foo"); - CHECK(ryml::csubstr(" foo bar").first_non_empty_span() == "foo"); - CHECK(ryml::csubstr("\n \r \t foo bar").first_non_empty_span() == "foo"); - CHECK(ryml::csubstr("\n \r \t foo\n\r\t bar").first_non_empty_span() == "foo"); - CHECK(ryml::csubstr("\n \r \t foo\n\r\t bar").first_non_empty_span() == "foo"); - CHECK(ryml::csubstr(",\n \r \t foo\n\r\t bar").first_non_empty_span() == ","); - } - // first_uint_span() - { - CHECK(ryml::csubstr("1234 asdkjh").first_uint_span() == "1234"); - CHECK(ryml::csubstr("1234\rasdkjh").first_uint_span() == "1234"); - CHECK(ryml::csubstr("1234\tasdkjh").first_uint_span() == "1234"); - CHECK(ryml::csubstr("1234\nasdkjh").first_uint_span() == "1234"); - CHECK(ryml::csubstr("1234]asdkjh").first_uint_span() == "1234"); - CHECK(ryml::csubstr("1234)asdkjh").first_uint_span() == "1234"); - CHECK(ryml::csubstr("1234gasdkjh").first_uint_span() == ""); - } - // first_int_span() - { - CHECK(ryml::csubstr("-1234 asdkjh").first_int_span() == "-1234"); - CHECK(ryml::csubstr("-1234\rasdkjh").first_int_span() == "-1234"); - CHECK(ryml::csubstr("-1234\tasdkjh").first_int_span() == "-1234"); - CHECK(ryml::csubstr("-1234\nasdkjh").first_int_span() == "-1234"); - CHECK(ryml::csubstr("-1234]asdkjh").first_int_span() == "-1234"); - CHECK(ryml::csubstr("-1234)asdkjh").first_int_span() == "-1234"); - CHECK(ryml::csubstr("-1234gasdkjh").first_int_span() == ""); - } - // first_real_span() - { - CHECK(ryml::csubstr("-1234 asdkjh").first_real_span() == "-1234"); - CHECK(ryml::csubstr("-1234\rasdkjh").first_real_span() == "-1234"); - CHECK(ryml::csubstr("-1234\tasdkjh").first_real_span() == "-1234"); - CHECK(ryml::csubstr("-1234\nasdkjh").first_real_span() == "-1234"); - CHECK(ryml::csubstr("-1234]asdkjh").first_real_span() == "-1234"); - CHECK(ryml::csubstr("-1234)asdkjh").first_real_span() == "-1234"); - CHECK(ryml::csubstr("-1234gasdkjh").first_real_span() == ""); - CHECK(ryml::csubstr("1.234 asdkjh").first_real_span() == "1.234"); - CHECK(ryml::csubstr("1.234e+5 asdkjh").first_real_span() == "1.234e+5"); - CHECK(ryml::csubstr("1.234e-5 asdkjh").first_real_span() == "1.234e-5"); - CHECK(ryml::csubstr("1.234 asdkjh").first_real_span() == "1.234"); - CHECK(ryml::csubstr("1.234e+5 asdkjh").first_real_span() == "1.234e+5"); - CHECK(ryml::csubstr("1.234e-5 asdkjh").first_real_span() == "1.234e-5"); - CHECK(ryml::csubstr("-1.234 asdkjh").first_real_span() == "-1.234"); - CHECK(ryml::csubstr("-1.234e+5 asdkjh").first_real_span() == "-1.234e+5"); - CHECK(ryml::csubstr("-1.234e-5 asdkjh").first_real_span() == "-1.234e-5"); - // hexadecimal real numbers - CHECK(ryml::csubstr("0x1.e8480p+19 asdkjh").first_real_span() == "0x1.e8480p+19"); - CHECK(ryml::csubstr("0x1.e8480p-19 asdkjh").first_real_span() == "0x1.e8480p-19"); - CHECK(ryml::csubstr("-0x1.e8480p+19 asdkjh").first_real_span() == "-0x1.e8480p+19"); - CHECK(ryml::csubstr("-0x1.e8480p-19 asdkjh").first_real_span() == "-0x1.e8480p-19"); - CHECK(ryml::csubstr("+0x1.e8480p+19 asdkjh").first_real_span() == "+0x1.e8480p+19"); - CHECK(ryml::csubstr("+0x1.e8480p-19 asdkjh").first_real_span() == "+0x1.e8480p-19"); - // binary real numbers - CHECK(ryml::csubstr("0b101.011p+19 asdkjh").first_real_span() == "0b101.011p+19"); - CHECK(ryml::csubstr("0b101.011p-19 asdkjh").first_real_span() == "0b101.011p-19"); - CHECK(ryml::csubstr("-0b101.011p+19 asdkjh").first_real_span() == "-0b101.011p+19"); - CHECK(ryml::csubstr("-0b101.011p-19 asdkjh").first_real_span() == "-0b101.011p-19"); - CHECK(ryml::csubstr("+0b101.011p+19 asdkjh").first_real_span() == "+0b101.011p+19"); - CHECK(ryml::csubstr("+0b101.011p-19 asdkjh").first_real_span() == "+0b101.011p-19"); - // octal real numbers - CHECK(ryml::csubstr("0o173.045p+19 asdkjh").first_real_span() == "0o173.045p+19"); - CHECK(ryml::csubstr("0o173.045p-19 asdkjh").first_real_span() == "0o173.045p-19"); - CHECK(ryml::csubstr("-0o173.045p+19 asdkjh").first_real_span() == "-0o173.045p+19"); - CHECK(ryml::csubstr("-0o173.045p-19 asdkjh").first_real_span() == "-0o173.045p-19"); - CHECK(ryml::csubstr("+0o173.045p+19 asdkjh").first_real_span() == "+0o173.045p+19"); - CHECK(ryml::csubstr("+0o173.045p-19 asdkjh").first_real_span() == "+0o173.045p-19"); - } - // see also is_number() - - // basename(), dirname(), extshort(), extlong() - { - CHECK(ryml::csubstr("/path/to/file.tar.gz").basename() == "file.tar.gz"); - CHECK(ryml::csubstr("/path/to/file.tar.gz").dirname() == "/path/to/"); - CHECK(ryml::csubstr("C:\\path\\to\\file.tar.gz").basename('\\') == "file.tar.gz"); - CHECK(ryml::csubstr("C:\\path\\to\\file.tar.gz").dirname('\\') == "C:\\path\\to\\"); - CHECK(ryml::csubstr("/path/to/file.tar.gz").extshort() == "gz"); - CHECK(ryml::csubstr("/path/to/file.tar.gz").extlong() == "tar.gz"); - CHECK(ryml::csubstr("/path/to/file.tar.gz").name_wo_extshort() == "/path/to/file.tar"); - CHECK(ryml::csubstr("/path/to/file.tar.gz").name_wo_extlong() == "/path/to/file"); - } - - // split() - { - using namespace ryml; - csubstr parts[] = {"aa", "bb", "cc", "dd", "ee", "ff"}; - { - size_t count = 0; - for(csubstr part : csubstr("aa/bb/cc/dd/ee/ff").split('/')) - CHECK(part == parts[count++]); - CHECK(count == 6u); - } - { - size_t count = 0; - for(csubstr part : csubstr("aa.bb.cc.dd.ee.ff").split('.')) - CHECK(part == parts[count++]); - CHECK(count == 6u); - } - { - size_t count = 0; - for(csubstr part : csubstr("aa-bb-cc-dd-ee-ff").split('-')) - CHECK(part == parts[count++]); - CHECK(count == 6u); - } - // see also next_split() - } - - // pop_left(), pop_right() --- non-greedy version - // gpop_left(), gpop_right() --- greedy version - { - const bool skip_empty = true; - // pop_left(): pop the last element from the left - CHECK(ryml::csubstr( "0/1/2" ). pop_left('/' ) == "0" ); - CHECK(ryml::csubstr( "/0/1/2" ). pop_left('/' ) == "" ); - CHECK(ryml::csubstr("//0/1/2" ). pop_left('/' ) == "" ); - CHECK(ryml::csubstr( "0/1/2" ). pop_left('/', skip_empty) == "0" ); - CHECK(ryml::csubstr( "/0/1/2" ). pop_left('/', skip_empty) == "/0" ); - CHECK(ryml::csubstr("//0/1/2" ). pop_left('/', skip_empty) == "//0" ); - // gpop_left(): pop all but the first element (greedy pop) - CHECK(ryml::csubstr( "0/1/2" ).gpop_left('/' ) == "0/1" ); - CHECK(ryml::csubstr( "/0/1/2" ).gpop_left('/' ) == "/0/1" ); - CHECK(ryml::csubstr("//0/1/2" ).gpop_left('/' ) == "//0/1" ); - CHECK(ryml::csubstr( "0/1/2/" ).gpop_left('/' ) == "0/1/2"); - CHECK(ryml::csubstr( "/0/1/2/" ).gpop_left('/' ) == "/0/1/2"); - CHECK(ryml::csubstr("//0/1/2/" ).gpop_left('/' ) == "//0/1/2"); - CHECK(ryml::csubstr( "0/1/2//" ).gpop_left('/' ) == "0/1/2/"); - CHECK(ryml::csubstr( "/0/1/2//" ).gpop_left('/' ) == "/0/1/2/"); - CHECK(ryml::csubstr("//0/1/2//" ).gpop_left('/' ) == "//0/1/2/"); - CHECK(ryml::csubstr( "0/1/2" ).gpop_left('/', skip_empty) == "0/1" ); - CHECK(ryml::csubstr( "/0/1/2" ).gpop_left('/', skip_empty) == "/0/1" ); - CHECK(ryml::csubstr("//0/1/2" ).gpop_left('/', skip_empty) == "//0/1" ); - CHECK(ryml::csubstr( "0/1/2/" ).gpop_left('/', skip_empty) == "0/1" ); - CHECK(ryml::csubstr( "/0/1/2/" ).gpop_left('/', skip_empty) == "/0/1" ); - CHECK(ryml::csubstr("//0/1/2/" ).gpop_left('/', skip_empty) == "//0/1" ); - CHECK(ryml::csubstr( "0/1/2//" ).gpop_left('/', skip_empty) == "0/1" ); - CHECK(ryml::csubstr( "/0/1/2//" ).gpop_left('/', skip_empty) == "/0/1" ); - CHECK(ryml::csubstr("//0/1/2//" ).gpop_left('/', skip_empty) == "//0/1" ); - // pop_right(): pop the last element from the right - CHECK(ryml::csubstr( "0/1/2" ). pop_right('/' ) == "2" ); - CHECK(ryml::csubstr( "0/1/2/" ). pop_right('/' ) == "" ); - CHECK(ryml::csubstr( "0/1/2//" ). pop_right('/' ) == "" ); - CHECK(ryml::csubstr( "0/1/2" ). pop_right('/', skip_empty) == "2" ); - CHECK(ryml::csubstr( "0/1/2/" ). pop_right('/', skip_empty) == "2/" ); - CHECK(ryml::csubstr( "0/1/2//" ). pop_right('/', skip_empty) == "2//" ); - // gpop_right(): pop all but the first element (greedy pop) - CHECK(ryml::csubstr( "0/1/2" ).gpop_right('/' ) == "1/2"); - CHECK(ryml::csubstr( "0/1/2/" ).gpop_right('/' ) == "1/2/" ); - CHECK(ryml::csubstr( "0/1/2//" ).gpop_right('/' ) == "1/2//" ); - CHECK(ryml::csubstr( "/0/1/2" ).gpop_right('/' ) == "0/1/2"); - CHECK(ryml::csubstr( "/0/1/2/" ).gpop_right('/' ) == "0/1/2/" ); - CHECK(ryml::csubstr( "/0/1/2//" ).gpop_right('/' ) == "0/1/2//" ); - CHECK(ryml::csubstr("//0/1/2" ).gpop_right('/' ) == "/0/1/2"); - CHECK(ryml::csubstr("//0/1/2/" ).gpop_right('/' ) == "/0/1/2/" ); - CHECK(ryml::csubstr("//0/1/2//" ).gpop_right('/' ) == "/0/1/2//" ); - CHECK(ryml::csubstr( "0/1/2" ).gpop_right('/', skip_empty) == "1/2"); - CHECK(ryml::csubstr( "0/1/2/" ).gpop_right('/', skip_empty) == "1/2/" ); - CHECK(ryml::csubstr( "0/1/2//" ).gpop_right('/', skip_empty) == "1/2//" ); - CHECK(ryml::csubstr( "/0/1/2" ).gpop_right('/', skip_empty) == "1/2"); - CHECK(ryml::csubstr( "/0/1/2/" ).gpop_right('/', skip_empty) == "1/2/" ); - CHECK(ryml::csubstr( "/0/1/2//" ).gpop_right('/', skip_empty) == "1/2//" ); - CHECK(ryml::csubstr("//0/1/2" ).gpop_right('/', skip_empty) == "1/2"); - CHECK(ryml::csubstr("//0/1/2/" ).gpop_right('/', skip_empty) == "1/2/" ); - CHECK(ryml::csubstr("//0/1/2//" ).gpop_right('/', skip_empty) == "1/2//" ); - } - - // see the docs: - // https://c4core.docsforge.com/master/api/c4/basic_substring/ -} - - -//----------------------------------------------------------------------------- - -// helper functions for sample_parse_file() -template CharContainer file_get_contents(const char *filename); -template size_t file_get_contents(const char *filename, CharContainer *v); -template void file_put_contents(const char *filename, CharContainer const& v, const char* access="wb"); -void file_put_contents(const char *filename, const char *buf, size_t sz, const char* access); - - -/** demonstrate how to load a YAML file from disk to parse with ryml. - * - * ryml offers no overload to directly parse files from disk; it only - * parses source buffers (which may be mutable or immutable). It is - * up to the caller to load the file contents into a buffer before - * parsing with ryml. - * - * But that does not mean that loading a file is unimportant. There - * are many ways to achieve this in C++, but for convenience and to - * enable you to quickly get up to speed, here is an example - * implementation loading a file from disk and then parsing the - * resulting buffer with ryml. */ -void sample_parse_file() -{ - const char filename[] = "ryml_example.yml"; - - // because this is a minimal sample, it assumes nothing on the - // environment/OS (other than that it can read/write files). So we - // create the file on the fly: - file_put_contents(filename, ryml::csubstr("foo: 1\nbar:\n - 2\n - 3\n")); - - // now we can load it into a std::string (for example): - { - std::string contents = file_get_contents(filename); - ryml::Tree tree = ryml::parse_in_arena(ryml::to_csubstr(contents)); // immutable (csubstr) overload - CHECK(tree["foo"].val() == "1"); - CHECK(tree["bar"][0].val() == "2"); - CHECK(tree["bar"][1].val() == "3"); - } - - // or we can use a vector instead: - { - std::vector contents = file_get_contents>(filename); - ryml::Tree tree = ryml::parse_in_place(ryml::to_substr(contents)); // mutable (csubstr) overload - CHECK(tree["foo"].val() == "1"); - CHECK(tree["bar"][0].val() == "2"); - CHECK(tree["bar"][1].val() == "3"); - } - - // generally, any contiguous char container can be used with ryml, - // provided that the ryml::substr/ryml::csubstr view can be - // created out of it. - // - // ryml provides the overloads above for these two containers, but - // if you are using another container it should be very easy (only - // requires pointer and length). -} - - -//----------------------------------------------------------------------------- - -/** demonstrate in-place parsing of a mutable YAML source buffer. */ -void sample_parse_in_place() -{ - // Like the name suggests, parse_in_place() directly mutates the - // source buffer in place - char src[] = "{foo: 1, bar: [2, 3]}"; // ryml can parse in situ - ryml::substr srcview = src; // a mutable view to the source buffer - ryml::Tree tree = ryml::parse_in_place(srcview); // you can also reuse the tree and/or parser - ryml::ConstNodeRef root = tree.crootref(); // get a reference to the root - - CHECK(root.is_map()); - CHECK(root["foo"].is_keyval()); - CHECK(root["foo"].key() == "foo"); - CHECK(root["foo"].val() == "1"); - CHECK(root["bar"].is_seq()); - CHECK(root["bar"].has_key()); - CHECK(root["bar"].key() == "bar"); - CHECK(root["bar"][0].val() == "2"); - CHECK(root["bar"][1].val() == "3"); - - // deserializing: - int foo = 0, bar0 = 0, bar1 = 0; - root["foo"] >> foo; - root["bar"][0] >> bar0; - root["bar"][1] >> bar1; - CHECK(foo == 1); - CHECK(bar0 == 2); - CHECK(bar1 == 3); - - // after parsing, the tree holds views to the source buffer: - CHECK(root["foo"].val().data() == src + strlen("{foo: ")); - CHECK(root["foo"].val().begin() == src + strlen("{foo: ")); - CHECK(root["foo"].val().end() == src + strlen("{foo: 1")); - CHECK(root["foo"].val().is_sub(srcview)); // equivalent to the previous three assertions - CHECK(root["bar"][0].val().data() == src + strlen("{foo: 1, bar: [")); - CHECK(root["bar"][0].val().begin() == src + strlen("{foo: 1, bar: [")); - CHECK(root["bar"][0].val().end() == src + strlen("{foo: 1, bar: [2")); - CHECK(root["bar"][0].val().is_sub(srcview)); // equivalent to the previous three assertions - CHECK(root["bar"][1].val().data() == src + strlen("{foo: 1, bar: [2, ")); - CHECK(root["bar"][1].val().begin() == src + strlen("{foo: 1, bar: [2, ")); - CHECK(root["bar"][1].val().end() == src + strlen("{foo: 1, bar: [2, 3")); - CHECK(root["bar"][1].val().is_sub(srcview)); // equivalent to the previous three assertions - - // NOTE. parse_in_place() cannot accept ryml::csubstr - // so this will cause a /compile/ error: - ryml::csubstr csrcview = srcview; // ok, can assign from mutable to immutable - //tree = ryml::parse_in_place(csrcview); // compile error, cannot mutate an immutable view - (void)csrcview; -} - - -//----------------------------------------------------------------------------- - -/** demonstrate parsing of a read-only YAML source buffer */ -void sample_parse_in_arena() -{ - // to parse read-only memory, ryml will copy first to the tree's - // arena, and then parse the copied buffer: - ryml::Tree tree = ryml::parse_in_arena("{foo: 1, bar: [2, 3]}"); - ryml::ConstNodeRef root = tree.crootref(); // get a reference to the root - - CHECK(root.is_map()); - CHECK(root["foo"].is_keyval()); - CHECK(root["foo"].key() == "foo"); - CHECK(root["foo"].val() == "1"); - CHECK(root["bar"].is_seq()); - CHECK(root["bar"].has_key()); - CHECK(root["bar"].key() == "bar"); - CHECK(root["bar"][0].val() == "2"); - CHECK(root["bar"][1].val() == "3"); - - // deserializing: - int foo = 0, bar0 = 0, bar1 = 0; - root["foo"] >> foo; - root["bar"][0] >> bar0; - root["bar"][1] >> bar1; - CHECK(foo == 1); - CHECK(bar0 == 2); - CHECK(bar1 == 3); - - // NOTE. parse_in_arena() cannot accept ryml::substr. Overloads - // receiving substr buffers are declared, but intentionally left - // undefined, so this will cause a /linker/ error - char src[] = "{foo: is it really true}"; - ryml::substr srcview = src; - //tree = ryml::parse_in_place(srcview); // linker error, overload intentionally undefined - - // If you really intend to parse a mutable buffer in the arena, - // then simply convert it to immutable prior to calling - // parse_in_arena(): - ryml::csubstr csrcview = srcview; // assigning from src also works - tree = ryml::parse_in_arena(csrcview); // OK! csrcview is immutable - CHECK(tree["foo"].val() == "is it really true"); -} - - -//----------------------------------------------------------------------------- - -/** demonstrate reuse/modification of tree when parsing */ -void sample_parse_reuse_tree() -{ - ryml::Tree tree; - - // it will always be faster if the tree's size is conveniently reserved: - tree.reserve(30); // reserve 30 nodes (good enough for this sample) - // if you are using the tree's arena to serialize data, - // then reserve also the arena's size: - tree.reserve_arena(256); // reserve 256 characters (good enough for this sample) - - // now parse into the tree: - ryml::parse_in_arena("{foo: 1, bar: [2, 3]}", &tree); - - ryml::ConstNodeRef root = tree.crootref(); - CHECK(root.num_children() == 2); - CHECK(root.is_map()); - CHECK(root["foo"].is_keyval()); - CHECK(root["foo"].key() == "foo"); - CHECK(root["foo"].val() == "1"); - CHECK(root["bar"].is_seq()); - CHECK(root["bar"].has_key()); - CHECK(root["bar"].key() == "bar"); - CHECK(root["bar"][0].val() == "2"); - CHECK(root["bar"][1].val() == "3"); - CHECK(ryml::emitrs_yaml(tree) == R"(foo: 1 -bar: - - 2 - - 3 -)"); - - // WATCHOUT: parsing into an existing tree will APPEND to it: - ryml::parse_in_arena("{foo2: 12, bar2: [22, 32]}", &tree); - CHECK(ryml::emitrs_yaml(tree) == R"(foo: 1 -bar: - - 2 - - 3 -foo2: 12 -bar2: - - 22 - - 32 -)"); - CHECK(root.num_children() == 4); - CHECK(root["foo2"].is_keyval()); - CHECK(root["foo2"].key() == "foo2"); - CHECK(root["foo2"].val() == "12"); - CHECK(root["bar2"].is_seq()); - CHECK(root["bar2"].has_key()); - CHECK(root["bar2"].key() == "bar2"); - CHECK(root["bar2"][0].val() == "22"); - CHECK(root["bar2"][1].val() == "32"); - - // clear first before parsing into an existing tree. - tree.clear(); - tree.clear_arena(); // you may or may not want to clear the arena - ryml::parse_in_arena("[a, b, {x0: 1, x1: 2}]", &tree); - CHECK(ryml::emitrs_yaml(tree) == R"(- a -- b -- x0: 1 - x1: 2 -)"); - CHECK(root.is_seq()); - CHECK(root[0].val() == "a"); - CHECK(root[1].val() == "b"); - CHECK(root[2].is_map()); - CHECK(root[2]["x0"].val() == "1"); - CHECK(root[2]["x1"].val() == "2"); - - // we can parse directly into a node nested deep in an existing tree: - ryml::NodeRef mroot = tree.rootref(); // modifiable root - ryml::parse_in_arena("{champagne: Dom Perignon, coffee: Arabica}", mroot.append_child()); - CHECK(ryml::emitrs_yaml(tree) == R"(- a -- b -- x0: 1 - x1: 2 -- champagne: Dom Perignon - coffee: Arabica -)"); - CHECK(root.is_seq()); - CHECK(root[0].val() == "a"); - CHECK(root[1].val() == "b"); - CHECK(root[2].is_map()); - CHECK(root[2]["x0"].val() == "1"); - CHECK(root[2]["x1"].val() == "2"); - CHECK(root[3].is_map()); - CHECK(root[3]["champagne"].val() == "Dom Perignon"); - CHECK(root[3]["coffee"].val() == "Arabica"); - - // watchout: to add to an existing node within a map, the node's key must first be set: - ryml::NodeRef more = mroot[3].append_child({ryml::KEYMAP, "more"}); - ryml::NodeRef beer = mroot[3].append_child({ryml::KEYSEQ, "beer"}); - ryml::parse_in_arena("{vinho verde: Soalheiro, vinho tinto: Redoma 2017}", more); - ryml::parse_in_arena("[Rochefort 10, Busch, Leffe Rituel]", beer); - CHECK(ryml::emitrs_yaml(tree) == R"(- a -- b -- x0: 1 - x1: 2 -- champagne: Dom Perignon - coffee: Arabica - more: - vinho verde: Soalheiro - vinho tinto: Redoma 2017 - beer: - - Rochefort 10 - - Busch - - Leffe Rituel -)"); - - ryml::parse_in_arena("[foo, bar, baz, bat]", mroot); - CHECK(ryml::emitrs_yaml(tree) == R"(- a -- b -- x0: 1 - x1: 2 -- champagne: Dom Perignon - coffee: Arabica - more: - vinho verde: Soalheiro - vinho tinto: Redoma 2017 - beer: - - Rochefort 10 - - Busch - - Leffe Rituel -- foo -- bar -- baz -- bat -)"); - - ryml::parse_in_arena("[Kasteel Donker]", beer); - CHECK(ryml::emitrs_yaml(tree) == R"(- a -- b -- x0: 1 - x1: 2 -- champagne: Dom Perignon - coffee: Arabica - more: - vinho verde: Soalheiro - vinho tinto: Redoma 2017 - beer: - - Rochefort 10 - - Busch - - Leffe Rituel - - Kasteel Donker -- foo -- bar -- baz -- bat -)"); -} - - -//----------------------------------------------------------------------------- - -/** Demonstrates reuse of an existing parser. Doing this is - recommended when multiple files are parsed. */ -void sample_parse_reuse_parser() -{ - ryml::Parser parser; - - // it is also advised to reserve the parser depth - // to the expected depth of the data tree: - parser.reserve_stack(10); // uses small storage optimization - // defaulting to 16 depth, so this - // instruction is a no-op, and the stack - // will located in the parser object. - parser.reserve_stack(20); // But this will cause an allocation - // because it is above 16. - - auto champagnes = parser.parse_in_arena("champagnes.yml", "[Dom Perignon, Gosset Grande Reserve, Ruinart Blanc de Blancs, Jacquesson 742]"); - CHECK(ryml::emitrs_yaml(champagnes) == R"(- Dom Perignon -- Gosset Grande Reserve -- Ruinart Blanc de Blancs -- Jacquesson 742 -)"); - - auto beers = parser.parse_in_arena("beers.yml", "[Rochefort 10, Busch, Leffe Rituel, Kasteel Donker]"); - CHECK(ryml::emitrs_yaml(beers) == R"(- Rochefort 10 -- Busch -- Leffe Rituel -- Kasteel Donker -)"); - -} - - -//----------------------------------------------------------------------------- - -/** for ultimate speed when parsing multiple times, reuse both the - tree and parser */ -void sample_parse_reuse_tree_and_parser() -{ - ryml::Tree tree; - ryml::Parser parser; - - // it will always be faster if the tree's size is conveniently reserved: - tree.reserve(30); // reserve 30 nodes (good enough for this sample) - // if you are using the tree's arena to serialize data, - // then reserve also the arena's size: - tree.reserve(256); // reserve 256 characters (good enough for this sample) - // it is also advised to reserve the parser depth - // to the expected depth of the data tree: - parser.reserve_stack(10); // the parser uses small storage - // optimization defaulting to 16 depth, - // so this instruction is a no-op, and - // the stack will be located in the - // parser object. - parser.reserve_stack(20); // But this will cause an allocation - // because it is above 16. - - ryml::csubstr champagnes = "[Dom Perignon, Gosset Grande Reserve, Ruinart Blanc de Blancs, Jacquesson 742]"; - ryml::csubstr beers = "[Rochefort 10, Busch, Leffe Rituel, Kasteel Donker]"; - ryml::csubstr wines = "[Soalheiro, Niepoort Redoma 2017, Vina Esmeralda]"; - - parser.parse_in_arena("champagnes.yml", champagnes, &tree); - CHECK(ryml::emitrs_yaml(tree) == R"(- Dom Perignon -- Gosset Grande Reserve -- Ruinart Blanc de Blancs -- Jacquesson 742 -)"); - - // watchout: this will APPEND to the given tree: - parser.parse_in_arena("beers.yml", beers, &tree); - CHECK(ryml::emitrs_yaml(tree) == R"(- Dom Perignon -- Gosset Grande Reserve -- Ruinart Blanc de Blancs -- Jacquesson 742 -- Rochefort 10 -- Busch -- Leffe Rituel -- Kasteel Donker -)"); - - // if you don't wish to append, clear the tree first: - tree.clear(); - parser.parse_in_arena("wines.yml", wines, &tree); - CHECK(ryml::emitrs_yaml(tree) == R"(- Soalheiro -- Niepoort Redoma 2017 -- Vina Esmeralda -)"); -} - - -//----------------------------------------------------------------------------- - -/** shows how to programatically iterate through trees */ -void sample_iterate_trees() -{ - const ryml::Tree tree = ryml::parse_in_arena(R"(doe: "a deer, a female deer" -ray: "a drop of golden sun" -pi: 3.14159 -xmas: true -french-hens: 3 -calling-birds: - - huey - - dewey - - louie - - fred -xmas-fifth-day: - calling-birds: four - french-hens: 3 - golden-rings: 5 - partridges: - count: 1 - location: a pear tree - turtle-doves: two -cars: GTO -)"); - ryml::ConstNodeRef root = tree.crootref(); - - // iterate children - { - std::vector keys, vals; // to store all the root-level keys, vals - for(ryml::ConstNodeRef n : root.children()) - { - keys.emplace_back(n.key()); - vals.emplace_back(n.has_val() ? n.val() : ryml::csubstr{}); - } - CHECK(keys[0] == "doe"); - CHECK(vals[0] == "a deer, a female deer"); - CHECK(keys[1] == "ray"); - CHECK(vals[1] == "a drop of golden sun"); - CHECK(keys[2] == "pi"); - CHECK(vals[2] == "3.14159"); - CHECK(keys[3] == "xmas"); - CHECK(vals[3] == "true"); - CHECK(root[5].has_key()); - CHECK(root[5].is_seq()); - CHECK(root[5].key() == "calling-birds"); - CHECK(!root[5].has_val()); // it is a map, so not a val - //CHECK(root[5].val() == ""); // ERROR! node does not have a val. - CHECK(keys[5] == "calling-birds"); - CHECK(vals[5] == ""); - } - - // iterate siblings - { - size_t count = 0; - ryml::csubstr calling_birds[] = {"huey", "dewey", "louie", "fred"}; - for(ryml::ConstNodeRef n : root["calling-birds"][2].siblings()) - CHECK(n.val() == calling_birds[count++]); - CHECK(count == 4u); - } -} - - -//----------------------------------------------------------------------------- - -/** shows how to programatically create trees */ -void sample_create_trees() -{ - ryml::NodeRef doe; - CHECK(!doe.valid()); // it's pointing at nowhere - - ryml::Tree tree; - ryml::NodeRef root = tree.rootref(); - root |= ryml::MAP; // mark root as a map - doe = root["doe"]; - CHECK(doe.valid()); // it's now pointing at the tree - CHECK(doe.is_seed()); // but the tree has nothing there, so this is only a seed - - // set the value of the node - const char a_deer[] = "a deer, a female deer"; - doe = a_deer; - // now the node really exists in the tree, and this ref is no - // longer a seed: - CHECK(!doe.is_seed()); - // WATCHOUT for lifetimes: - CHECK(doe.val().str == a_deer); // it is pointing at the initial string - // If you need to avoid lifetime dependency, serialize the data: - { - std::string a_drop = "a drop of golden sun"; - // this will copy the string to the tree's arena: - // (see the serialization samples below) - root["ray"] << a_drop; - // and now you can modify the original string without changing - // the tree: - a_drop[0] = 'Z'; - a_drop[1] = 'Z'; - } - CHECK(root["ray"].val() == "a drop of golden sun"); - - // etc. - root["pi"] << ryml::fmt::real(3.141592654, 5); - root["xmas"] << ryml::fmt::boolalpha(true); - root["french-hens"] << 3; - ryml::NodeRef calling_birds = root["calling-birds"]; - calling_birds |= ryml::SEQ; - calling_birds.append_child() = "huey"; - calling_birds.append_child() = "dewey"; - calling_birds.append_child() = "louie"; - calling_birds.append_child() = "fred"; - ryml::NodeRef xmas5 = root["xmas-fifth-day"]; - xmas5 |= ryml::MAP; - xmas5["calling-birds"] = "four"; - xmas5["french-hens"] << 3; - xmas5["golden-rings"] << 5; - xmas5["partridges"] |= ryml::MAP; - xmas5["partridges"]["count"] << 1; - xmas5["partridges"]["location"] = "a pear tree"; - xmas5["turtle-doves"] = "two"; - root["cars"] = "GTO"; - - std::cout << tree; - CHECK(ryml::emitrs_yaml(tree) == R"(doe: 'a deer, a female deer' -ray: a drop of golden sun -pi: 3.14159 -xmas: true -'french-hens': 3 -'calling-birds': - - huey - - dewey - - louie - - fred -'xmas-fifth-day': - 'calling-birds': four - 'french-hens': 3 - 'golden-rings': 5 - partridges: - count: 1 - location: a pear tree - 'turtle-doves': two -cars: GTO -)"); -} - - -//----------------------------------------------------------------------------- - -/** demonstrates explicit and implicit interaction with the tree's string arena. - * Notice that ryml only holds strings in the tree's nodes. */ -void sample_tree_arena() -{ - // mutable buffers are parsed in situ: - { - char buf[] = "[a, b, c, d]"; - ryml::substr yml = buf; - ryml::Tree tree = ryml::parse_in_place(yml); - // notice the arena is empty: - CHECK(tree.arena().empty()); - // and the tree is pointing at the original buffer: - ryml::NodeRef root = tree.rootref(); - CHECK(root[0].val().is_sub(yml)); - CHECK(root[1].val().is_sub(yml)); - CHECK(root[2].val().is_sub(yml)); - CHECK(root[3].val().is_sub(yml)); - CHECK(yml.is_super(root[0].val())); - CHECK(yml.is_super(root[1].val())); - CHECK(yml.is_super(root[2].val())); - CHECK(yml.is_super(root[3].val())); - } - - // when parsing immutable buffers, the buffer is first copied to the - // tree's arena; the copy in the arena is then the buffer which is - // actually parsed - { - ryml::csubstr yml = "[a, b, c, d]"; - ryml::Tree tree = ryml::parse_in_arena(yml); - // notice the buffer was copied to the arena: - CHECK(tree.arena().data() != yml.data()); - CHECK(tree.arena() == yml); - // and the tree is pointing at the arena instead of to the - // original buffer: - ryml::NodeRef root = tree.rootref(); - ryml::csubstr arena = tree.arena(); - CHECK(root[0].val().is_sub(arena)); - CHECK(root[1].val().is_sub(arena)); - CHECK(root[2].val().is_sub(arena)); - CHECK(root[3].val().is_sub(arena)); - CHECK(arena.is_super(root[0].val())); - CHECK(arena.is_super(root[1].val())); - CHECK(arena.is_super(root[2].val())); - CHECK(arena.is_super(root[3].val())); - } - - // the arena is also used when the data is serialized to string - // with NodeRef::operator<<(): mutable buffer - { - char buf[] = "[a, b, c, d]"; // mutable - ryml::substr yml = buf; - ryml::Tree tree = ryml::parse_in_place(yml); - // notice the arena is empty: - CHECK(tree.arena().empty()); - ryml::NodeRef root = tree.rootref(); - - // serialize an integer, and mutate the tree - CHECK(root[2].val() == "c"); - CHECK(root[2].val().is_sub(yml)); // val is first pointing at the buffer - root[2] << 12345; - CHECK(root[2].val() == "12345"); - CHECK(root[2].val().is_sub(tree.arena())); // now val is pointing at the arena - // notice the serialized string was appended to the tree's arena: - CHECK(tree.arena() == "12345"); - - // serialize an integer, and mutate the tree - CHECK(root[3].val() == "d"); - CHECK(root[3].val().is_sub(yml)); // val is first pointing at the buffer - root[3] << 67890; - CHECK(root[3].val() == "67890"); - CHECK(root[3].val().is_sub(tree.arena())); // now val is pointing at the arena - // notice the serialized string was appended to the tree's arena: - CHECK(tree.arena() == "1234567890"); - } - // the arena is also used when the data is serialized to string - // with NodeRef::operator<<(): immutable buffer - { - ryml::csubstr yml = "[a, b, c, d]"; // immutable - ryml::Tree tree = ryml::parse_in_arena(yml); - // notice the buffer was copied to the arena: - CHECK(tree.arena().data() != yml.data()); - CHECK(tree.arena() == yml); - ryml::NodeRef root = tree.rootref(); - - // serialize an integer, and mutate the tree - CHECK(root[2].val() == "c"); - root[2] << 12345; // serialize an integer - CHECK(root[2].val() == "12345"); - // notice the serialized string was appended to the tree's arena: - // notice also the previous values remain there. - // RYML DOES NOT KEEP TRACK OF REFERENCES TO THE ARENA. - CHECK(tree.arena() == "[a, b, c, d]12345"); - // old values: --------------^ - - // serialize an integer, and mutate the tree - root[3] << 67890; - CHECK(root[3].val() == "67890"); - // notice the serialized string was appended to the tree's arena: - // notice also the previous values remain there. - // RYML DOES NOT KEEP TRACK OF REFERENCES TO THE ARENA. - CHECK(tree.arena() == "[a, b, c, d]1234567890"); - // old values: --------------^ ---^^^^^ - } - - // to_arena(): directly serialize values to the arena: - { - ryml::Tree tree = ryml::parse_in_arena("{a: b}"); - ryml::csubstr c10 = tree.to_arena(10101010); - CHECK(c10 == "10101010"); - CHECK(c10.is_sub(tree.arena())); - CHECK(tree.arena() == "{a: b}10101010"); - CHECK(tree.key(1) == "a"); - CHECK(tree.val(1) == "b"); - tree.set_val(1, c10); - CHECK(tree.val(1) == c10); - // and you can also do it through a node: - ryml::NodeRef root = tree.rootref(); - root["a"].set_val_serialized(2222); - CHECK(root["a"].val() == "2222"); - CHECK(tree.arena() == "{a: b}101010102222"); - } - - // copy_to_arena(): manually copy a string to the arena: - { - ryml::Tree tree = ryml::parse_in_arena("{a: b}"); - ryml::csubstr mystr = "Gosset Grande Reserve"; - ryml::csubstr copied = tree.copy_to_arena(mystr); - CHECK(!copied.overlaps(mystr)); - CHECK(copied == mystr); - CHECK(tree.arena() == "{a: b}Gosset Grande Reserve"); - } - - // alloc_arena(): allocate a buffer from the arena: - { - ryml::Tree tree = ryml::parse_in_arena("{a: b}"); - ryml::csubstr mystr = "Gosset Grande Reserve"; - ryml::substr copied = tree.alloc_arena(mystr.size()); - CHECK(!copied.overlaps(mystr)); - memcpy(copied.str, mystr.str, mystr.len); - CHECK(copied == mystr); - CHECK(tree.arena() == "{a: b}Gosset Grande Reserve"); - } - - // reserve_arena(): ensure the arena has a certain size to avoid reallocations - { - ryml::Tree tree = ryml::parse_in_arena("{a: b}"); - CHECK(tree.arena().size() == strlen("{a: b}")); - tree.reserve_arena(100); - CHECK(tree.arena_capacity() >= 100); - CHECK(tree.arena().size() == strlen("{a: b}")); - tree.to_arena(123456); - CHECK(tree.arena().first(12) == "{a: b}123456"); - } -} - - -//----------------------------------------------------------------------------- - -/** ryml provides facilities for serializing the C++ fundamental - types. This is achieved through to_chars()/from_chars(). - See an example below for user scalar types. */ -void sample_fundamental_types() -{ - ryml::Tree tree; - CHECK(tree.arena().empty()); - CHECK(tree.to_arena('a') == "a"); CHECK(tree.arena() == "a"); - CHECK(tree.to_arena("bcde") == "bcde"); CHECK(tree.arena() == "abcde"); - CHECK(tree.to_arena(unsigned(0)) == "0"); CHECK(tree.arena() == "abcde0"); - CHECK(tree.to_arena(int(1)) == "1"); CHECK(tree.arena() == "abcde01"); - CHECK(tree.to_arena(uint8_t(0)) == "0"); CHECK(tree.arena() == "abcde010"); - CHECK(tree.to_arena(uint16_t(1)) == "1"); CHECK(tree.arena() == "abcde0101"); - CHECK(tree.to_arena(uint32_t(2)) == "2"); CHECK(tree.arena() == "abcde01012"); - CHECK(tree.to_arena(uint64_t(3)) == "3"); CHECK(tree.arena() == "abcde010123"); - CHECK(tree.to_arena(int8_t( 4)) == "4"); CHECK(tree.arena() == "abcde0101234"); - CHECK(tree.to_arena(int8_t(-4)) == "-4"); CHECK(tree.arena() == "abcde0101234-4"); - CHECK(tree.to_arena(int16_t( 5)) == "5"); CHECK(tree.arena() == "abcde0101234-45"); - CHECK(tree.to_arena(int16_t(-5)) == "-5"); CHECK(tree.arena() == "abcde0101234-45-5"); - CHECK(tree.to_arena(int32_t( 6)) == "6"); CHECK(tree.arena() == "abcde0101234-45-56"); - CHECK(tree.to_arena(int32_t(-6)) == "-6"); CHECK(tree.arena() == "abcde0101234-45-56-6"); - CHECK(tree.to_arena(int64_t( 7)) == "7"); CHECK(tree.arena() == "abcde0101234-45-56-67"); - CHECK(tree.to_arena(int64_t(-7)) == "-7"); CHECK(tree.arena() == "abcde0101234-45-56-67-7"); - CHECK(tree.to_arena((void*)1) == "0x1"); CHECK(tree.arena() == "abcde0101234-45-56-67-70x1"); - CHECK(tree.to_arena(float(0.124)) == "0.124"); CHECK(tree.arena() == "abcde0101234-45-56-67-70x10.124"); - CHECK(tree.to_arena(double(0.234)) == "0.234"); CHECK(tree.arena() == "abcde0101234-45-56-67-70x10.1240.234"); - CHECK(tree.to_arena(bool(true)) == "1"); CHECK(tree.arena() == "abcde0101234-45-56-67-70x10.1240.2341"); - CHECK(tree.to_arena(bool(false)) == "0"); CHECK(tree.arena() == "abcde0101234-45-56-67-70x10.1240.23410"); - - // write special float values - const float fnan = std::numeric_limits::quiet_NaN(); - const double dnan = std::numeric_limits::quiet_NaN(); - const float finf = std::numeric_limits::infinity(); - const double dinf = std::numeric_limits::infinity(); - CHECK(tree.to_arena( finf) == ".inf"); CHECK(tree.arena() == "abcde0101234-45-56-67-70x10.1240.23410.inf"); - CHECK(tree.to_arena( dinf) == ".inf"); CHECK(tree.arena() == "abcde0101234-45-56-67-70x10.1240.23410.inf.inf"); - CHECK(tree.to_arena(-finf) == "-.inf"); CHECK(tree.arena() == "abcde0101234-45-56-67-70x10.1240.23410.inf.inf-.inf"); - CHECK(tree.to_arena(-dinf) == "-.inf"); CHECK(tree.arena() == "abcde0101234-45-56-67-70x10.1240.23410.inf.inf-.inf-.inf"); - CHECK(tree.to_arena( fnan) == ".nan"); CHECK(tree.arena() == "abcde0101234-45-56-67-70x10.1240.23410.inf.inf-.inf-.inf.nan"); - CHECK(tree.to_arena( dnan) == ".nan"); CHECK(tree.arena() == "abcde0101234-45-56-67-70x10.1240.23410.inf.inf-.inf-.inf.nan.nan"); - // read special float values - tree = ryml::parse_in_arena(R"({ninf: -.inf, pinf: .inf, nan: .nan})"); - C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH("-Wfloat-equal"); - float f = 0.f; - double d = 0.; - CHECK(f == 0.f); - CHECK(d == 0.); - tree["ninf"] >> f; CHECK(f == -finf); - tree["ninf"] >> d; CHECK(d == -dinf); - tree["pinf"] >> f; CHECK(f == finf); - tree["pinf"] >> d; CHECK(d == dinf); - tree["nan" ] >> f; CHECK(std::isnan(f)); - tree["nan" ] >> d; CHECK(std::isnan(d)); - C4_SUPPRESS_WARNING_GCC_CLANG_POP -} - - -//----------------------------------------------------------------------------- - -/** ryml provides facilities for formatting (imported from c4core into - * the ryml namespace) - * - * @see https://c4core.docsforge.com/master/formatting-arguments/ - * @see https://c4core.docsforge.com/master/formatting-strings/ - */ -void sample_formatting() -{ - // format(), format_sub(), formatrs(): format arguments - { - char buf_[256] = {}; - ryml::substr buf = buf_; - size_t size = ryml::format(buf, "a={} foo {} {} bar {}", 0.1, 10, 11, 12); - CHECK(size == strlen("a=0.1 foo 10 11 bar 12")); - CHECK(buf.first(size) == "a=0.1 foo 10 11 bar 12"); - // it is safe to call on an empty buffer: - // returns the size needed for the result, and no overflow occurs: - size = ryml::format({} , "a={} foo {} {} bar {}", "this_is_a", 10, 11, 12); - CHECK(size == ryml::format(buf, "a={} foo {} {} bar {}", "this_is_a", 10, 11, 12)); - CHECK(size == strlen("a=this_is_a foo 10 11 bar 12")); - // it is also safe to call on an insufficient buffer: - char smallbuf[8] = {}; - size = ryml::format(smallbuf, "{} is too large {}", "this", "for the buffer"); - CHECK(size == strlen("this is too large for the buffer")); - // ... and the result is truncated at the buffer size: - CHECK(ryml::substr(smallbuf, sizeof(smallbuf)) == "this is\0"); - - // format_sub() directly returns the written string: - ryml::csubstr result = ryml::format_sub(buf, "b={}, damn it.", 1); - CHECK(result == "b=1, damn it."); - CHECK(result.is_sub(buf)); - - // formatrs() means FORMAT & ReSize: - // - // Instead of a substr, it receives any owning linear char container - // for which to_substr() is defined (using ADL). - // has to_substr() definitions for std::string and - // std::vector. - // - // formatrs() starts by calling format(), and if needed, resizes the container - // and calls format() again. - // - // Note that unless the container is previously sized, this - // may cause an allocation, which will make your code slower. - // Make sure to call .reserve() on the container for real - // production code. - std::string sbuf; - ryml::formatrs(&sbuf, "and c={} seems about right", 2); - CHECK(sbuf == "and c=2 seems about right"); - std::vector vbuf; // works with any linear char container - ryml::formatrs(&vbuf, "and c={} seems about right", 2); - CHECK(sbuf == "and c=2 seems about right"); - // with formatrs() it is also possible to append: - ryml::formatrs(ryml::append, &sbuf, ", and finally d={} - done", 3); - CHECK(sbuf == "and c=2 seems about right, and finally d=3 - done"); - } - - // unformat(): read arguments - opposite of format() - { - char buf_[256]; - - int a = 0, b = 1, c = 2; - ryml::csubstr result = ryml::format_sub(buf_, "{} and {} and {}", a, b, c); - CHECK(result == "0 and 1 and 2"); - int aa = -1, bb = -2, cc = -3; - size_t num_characters = ryml::unformat(result, "{} and {} and {}", aa, bb, cc); - CHECK(num_characters != ryml::csubstr::npos); // if a conversion fails, returns ryml::csubstr::npos - CHECK(num_characters == result.size()); - CHECK(aa == a); - CHECK(bb == b); - CHECK(cc == c); - - result = ryml::format_sub(buf_, "{} and {} and {}", 10, 20, 30); - CHECK(result == "10 and 20 and 30"); - num_characters = ryml::unformat(result, "{} and {} and {}", aa, bb, cc); - CHECK(num_characters != ryml::csubstr::npos); // if a conversion fails, returns ryml::csubstr::npos - CHECK(num_characters == result.size()); - CHECK(aa == 10); - CHECK(bb == 20); - CHECK(cc == 30); - } - - // cat(), cat_sub(), catrs(): concatenate arguments - { - char buf_[256] = {}; - ryml::substr buf = buf_; - size_t size = ryml::cat(buf, "a=", 0.1, "foo", 10, 11, "bar", 12); - CHECK(size == strlen("a=0.1foo1011bar12")); - CHECK(buf.first(size) == "a=0.1foo1011bar12"); - // it is safe to call on an empty buffer: - // returns the size needed for the result, and no overflow occurs: - CHECK(ryml::cat({}, "a=", 0) == 3); - // it is also safe to call on an insufficient buffer: - char smallbuf[8] = {}; - size = ryml::cat(smallbuf, "this", " is too large ", "for the buffer"); - CHECK(size == strlen("this is too large for the buffer")); - // ... and the result is truncated at the buffer size: - CHECK(ryml::substr(smallbuf, sizeof(smallbuf)) == "this is\0"); - - // cat_sub() directly returns the written string: - ryml::csubstr result = ryml::cat_sub(buf, "b=", 1, ", damn it."); - CHECK(result == "b=1, damn it."); - CHECK(result.is_sub(buf)); - - // catrs() means CAT & ReSize: - // - // Instead of a substr, it receives any owning linear char container - // for which to_substr() is defined (using ADL). - // has to_substr() definitions for std::string and - // std::vector. - // - // catrs() starts by calling cat(), and if needed, resizes the container - // and calls cat() again. - // - // Note that unless the container is previously sized, this - // may cause an allocation, which will make your code slower. - // Make sure to call .reserve() on the container for real - // production code. - std::string sbuf; - ryml::catrs(&sbuf, "and c=", 2, " seems about right"); - CHECK(sbuf == "and c=2 seems about right"); - std::vector vbuf; // works with any linear char container - ryml::catrs(&vbuf, "and c=", 2, " seems about right"); - CHECK(sbuf == "and c=2 seems about right"); - // with catrs() it is also possible to append: - ryml::catrs(ryml::append, &sbuf, ", and finally d=", 3, " - done"); - CHECK(sbuf == "and c=2 seems about right, and finally d=3 - done"); - } - - // uncat(): read arguments - opposite of cat() - { - char buf_[256]; - - int a = 0, b = 1, c = 2; - ryml::csubstr result = ryml::cat_sub(buf_, a, ' ', b, ' ', c); - CHECK(result == "0 1 2"); - int aa = -1, bb = -2, cc = -3; - char sep1 = 'a', sep2 = 'b'; - size_t num_characters = ryml::uncat(result, aa, sep1, bb, sep2, cc); - CHECK(num_characters == result.size()); - CHECK(aa == a); - CHECK(bb == b); - CHECK(cc == c); - CHECK(sep1 == ' '); - CHECK(sep2 == ' '); - - result = ryml::cat_sub(buf_, 10, ' ', 20, ' ', 30); - CHECK(result == "10 20 30"); - num_characters = ryml::uncat(result, aa, sep1, bb, sep2, cc); - CHECK(num_characters == result.size()); - CHECK(aa == 10); - CHECK(bb == 20); - CHECK(cc == 30); - CHECK(sep1 == ' '); - CHECK(sep2 == ' '); - } - - // catsep(), catsep_sub(), catseprs(): concatenate arguments, with a separator - { - char buf_[256] = {}; - ryml::substr buf = buf_; - // use ' ' as a separator - size_t size = ryml::catsep(buf, ' ', "a=", 0, "b=", 1, "c=", 2, 45, 67); - CHECK(buf.first(size) == "a= 0 b= 1 c= 2 45 67"); - // any separator may be used - // use " and " as a separator - size = ryml::catsep(buf, " and ", "a=0", "b=1", "c=2", 45, 67); - CHECK(buf.first(size) == "a=0 and b=1 and c=2 and 45 and 67"); - // use " ... " as a separator - size = ryml::catsep(buf, " ... ", "a=0", "b=1", "c=2", 45, 67); - CHECK(buf.first(size) == "a=0 ... b=1 ... c=2 ... 45 ... 67"); - // use '/' as a separator - size = ryml::catsep(buf, '/', "a=", 0, "b=", 1, "c=", 2, 45, 67); - CHECK(buf.first(size) == "a=/0/b=/1/c=/2/45/67"); - // use 888 as a separator - size = ryml::catsep(buf, 888, "a=0", "b=1", "c=2", 45, 67); - CHECK(buf.first(size) == "a=0888b=1888c=28884588867"); - - // it is safe to call on an empty buffer: - // returns the size needed for the result, and no overflow occurs: - CHECK(size == ryml::catsep({}, 888, "a=0", "b=1", "c=2", 45, 67)); - // it is also safe to call on an insufficient buffer: - char smallbuf[8] = {}; - CHECK(size == ryml::catsep(smallbuf, 888, "a=0", "b=1", "c=2", 45, 67)); - CHECK(size == strlen("a=0888b=1888c=28884588867")); - // ... and the result is truncated: - CHECK(ryml::substr(smallbuf, sizeof(smallbuf)) == "a=0888b\0"); - - // catsep_sub() directly returns the written substr: - ryml::csubstr result = ryml::catsep_sub(buf, " and ", "a=0", "b=1", "c=2", 45, 67); - CHECK(result == "a=0 and b=1 and c=2 and 45 and 67"); - CHECK(result.is_sub(buf)); - - // catseprs() means CATSEP & ReSize: - // - // Instead of a substr, it receives any owning linear char container - // for which to_substr() is defined (using ADL). - // has to_substr() definitions for std::string and - // std::vector. - // - // catseprs() starts by calling catsep(), and if needed, resizes the container - // and calls catsep() again. - // - // Note that unless the container is previously sized, this - // may cause an allocation, which will make your code slower. - // Make sure to call .reserve() on the container for real - // production code. - std::string sbuf; - ryml::catseprs(&sbuf, " and ", "a=0", "b=1", "c=2", 45, 67); - CHECK(sbuf == "a=0 and b=1 and c=2 and 45 and 67"); - std::vector vbuf; // works with any linear char container - ryml::catseprs(&vbuf, " and ", "a=0", "b=1", "c=2", 45, 67); - CHECK(ryml::to_csubstr(vbuf) == "a=0 and b=1 and c=2 and 45 and 67"); - - // with catseprs() it is also possible to append: - ryml::catseprs(ryml::append, &sbuf, " well ", " --- a=0", "b=11", "c=12", 145, 167); - CHECK(sbuf == "a=0 and b=1 and c=2 and 45 and 67 --- a=0 well b=11 well c=12 well 145 well 167"); - } - - // uncatsep(): read arguments with a separator - opposite of catsep() - { - char buf_[256] = {}; - - int a = 0, b = 1, c = 2; - ryml::csubstr result = ryml::catsep_sub(buf_, ' ', a, b, c); - CHECK(result == "0 1 2"); - int aa = -1, bb = -2, cc = -3; - char sep = 'b'; - size_t num_characters = ryml::uncatsep(result, sep, aa, bb, cc); - CHECK(num_characters == result.size()); - CHECK(aa == a); - CHECK(bb == b); - CHECK(cc == c); - CHECK(sep == ' '); - - sep = '_'; - result = ryml::catsep_sub(buf_, ' ', 10, 20, 30); - CHECK(result == "10 20 30"); - num_characters = ryml::uncatsep(result, sep, aa, bb, cc); - CHECK(num_characters == result.size()); - CHECK(aa == 10); - CHECK(bb == 20); - CHECK(cc == 30); - CHECK(sep == ' '); - } - - // formatting individual arguments - { - using namespace ryml; // all the symbols below are in the ryml namespace. - char buf_[256] = {}; // all the results below are written in this buffer - substr buf = buf_; - // -------------------------------------- - // fmt::boolalpha(): format as true/false - // -------------------------------------- - // just as with std streams, printing a bool will output the integer value: - CHECK("0" == cat_sub(buf, false)); - CHECK("1" == cat_sub(buf, true)); - // to force a "true"/"false", use fmt::boolalpha: - CHECK("false" == cat_sub(buf, fmt::boolalpha(false))); - CHECK("true" == cat_sub(buf, fmt::boolalpha(true))); - - // --------------------------------- - // fmt::hex(): format as hexadecimal - // --------------------------------- - CHECK("0xff" == cat_sub(buf, fmt::hex(255))); - CHECK("0x100" == cat_sub(buf, fmt::hex(256))); - CHECK("-0xff" == cat_sub(buf, fmt::hex(-255))); - CHECK("-0x100" == cat_sub(buf, fmt::hex(-256))); - CHECK("3735928559" == cat_sub(buf, UINT32_C(0xdeadbeef))); - CHECK("0xdeadbeef" == cat_sub(buf, fmt::hex(UINT32_C(0xdeadbeef)))); - // ---------------------------- - // fmt::bin(): format as binary - // ---------------------------- - CHECK("0b1000" == cat_sub(buf, fmt::bin(8))); - CHECK("0b1001" == cat_sub(buf, fmt::bin(9))); - CHECK("0b10001" == cat_sub(buf, fmt::bin(17))); - CHECK("0b11001" == cat_sub(buf, fmt::bin(25))); - CHECK("-0b1000" == cat_sub(buf, fmt::bin(-8))); - CHECK("-0b1001" == cat_sub(buf, fmt::bin(-9))); - CHECK("-0b10001" == cat_sub(buf, fmt::bin(-17))); - CHECK("-0b11001" == cat_sub(buf, fmt::bin(-25))); - // --------------------------- - // fmt::bin(): format as octal - // --------------------------- - CHECK("0o77" == cat_sub(buf, fmt::oct(63))); - CHECK("0o100" == cat_sub(buf, fmt::oct(64))); - CHECK("0o377" == cat_sub(buf, fmt::oct(255))); - CHECK("0o400" == cat_sub(buf, fmt::oct(256))); - CHECK("0o1000" == cat_sub(buf, fmt::oct(512))); - CHECK("-0o77" == cat_sub(buf, fmt::oct(-63))); - CHECK("-0o100" == cat_sub(buf, fmt::oct(-64))); - CHECK("-0o377" == cat_sub(buf, fmt::oct(-255))); - CHECK("-0o400" == cat_sub(buf, fmt::oct(-256))); - CHECK("-0o1000" == cat_sub(buf, fmt::oct(-512))); - // --------------------------- - // fmt::zpad(): pad with zeros - // --------------------------- - CHECK("000063" == cat_sub(buf, fmt::zpad(63, 6))); - CHECK( "00063" == cat_sub(buf, fmt::zpad(63, 5))); - CHECK( "0063" == cat_sub(buf, fmt::zpad(63, 4))); - CHECK( "063" == cat_sub(buf, fmt::zpad(63, 3))); - CHECK( "63" == cat_sub(buf, fmt::zpad(63, 2))); - CHECK( "63" == cat_sub(buf, fmt::zpad(63, 1))); // will never trim the result - CHECK( "63" == cat_sub(buf, fmt::zpad(63, 0))); // will never trim the result - CHECK("0x00003f" == cat_sub(buf, fmt::zpad(fmt::hex(63), 6))); - CHECK("0o000077" == cat_sub(buf, fmt::zpad(fmt::oct(63), 6))); - CHECK("0b00011001" == cat_sub(buf, fmt::zpad(fmt::bin(25), 8))); - // ------------------------------------------------ - // fmt::left(): align left with a given field width - // ------------------------------------------------ - CHECK("63 " == cat_sub(buf, fmt::left(63, 6))); - CHECK("63 " == cat_sub(buf, fmt::left(63, 5))); - CHECK("63 " == cat_sub(buf, fmt::left(63, 4))); - CHECK("63 " == cat_sub(buf, fmt::left(63, 3))); - CHECK("63" == cat_sub(buf, fmt::left(63, 2))); - CHECK("63" == cat_sub(buf, fmt::left(63, 1))); // will never trim the result - CHECK("63" == cat_sub(buf, fmt::left(63, 0))); // will never trim the result - // the fill character can be specified (defaults to ' '): - CHECK("63----" == cat_sub(buf, fmt::left(63, 6, '-'))); - CHECK("63++++" == cat_sub(buf, fmt::left(63, 6, '+'))); - CHECK("63////" == cat_sub(buf, fmt::left(63, 6, '/'))); - CHECK("630000" == cat_sub(buf, fmt::left(63, 6, '0'))); - CHECK("63@@@@" == cat_sub(buf, fmt::left(63, 6, '@'))); - CHECK("0x003f " == cat_sub(buf, fmt::left(fmt::zpad(fmt::hex(63), 4), 10))); - // -------------------------------------------------- - // fmt::right(): align right with a given field width - // -------------------------------------------------- - CHECK(" 63" == cat_sub(buf, fmt::right(63, 6))); - CHECK(" 63" == cat_sub(buf, fmt::right(63, 5))); - CHECK(" 63" == cat_sub(buf, fmt::right(63, 4))); - CHECK(" 63" == cat_sub(buf, fmt::right(63, 3))); - CHECK("63" == cat_sub(buf, fmt::right(63, 2))); - CHECK("63" == cat_sub(buf, fmt::right(63, 1))); // will never trim the result - CHECK("63" == cat_sub(buf, fmt::right(63, 0))); // will never trim the result - // the fill character can be specified (defaults to ' '): - CHECK("----63" == cat_sub(buf, fmt::right(63, 6, '-'))); - CHECK("++++63" == cat_sub(buf, fmt::right(63, 6, '+'))); - CHECK("////63" == cat_sub(buf, fmt::right(63, 6, '/'))); - CHECK("000063" == cat_sub(buf, fmt::right(63, 6, '0'))); - CHECK("@@@@63" == cat_sub(buf, fmt::right(63, 6, '@'))); - CHECK(" 0x003f" == cat_sub(buf, fmt::right(fmt::zpad(fmt::hex(63), 4), 10))); - - // ------------------------------------------ - // fmt::real(): format floating point numbers - // ------------------------------------------ - CHECK("0" == cat_sub(buf, fmt::real(0.01f, 0))); - CHECK("0.0" == cat_sub(buf, fmt::real(0.01f, 1))); - CHECK("0.01" == cat_sub(buf, fmt::real(0.01f, 2))); - CHECK("0.010" == cat_sub(buf, fmt::real(0.01f, 3))); - CHECK("0.0100" == cat_sub(buf, fmt::real(0.01f, 4))); - CHECK("0.01000" == cat_sub(buf, fmt::real(0.01f, 5))); - CHECK("1" == cat_sub(buf, fmt::real(1.01f, 0))); - CHECK("1.0" == cat_sub(buf, fmt::real(1.01f, 1))); - CHECK("1.01" == cat_sub(buf, fmt::real(1.01f, 2))); - CHECK("1.010" == cat_sub(buf, fmt::real(1.01f, 3))); - CHECK("1.0100" == cat_sub(buf, fmt::real(1.01f, 4))); - CHECK("1.01000" == cat_sub(buf, fmt::real(1.01f, 5))); - CHECK("1" == cat_sub(buf, fmt::real(1.234234234, 0))); - CHECK("1.2" == cat_sub(buf, fmt::real(1.234234234, 1))); - CHECK("1.23" == cat_sub(buf, fmt::real(1.234234234, 2))); - CHECK("1.234" == cat_sub(buf, fmt::real(1.234234234, 3))); - CHECK("1.2342" == cat_sub(buf, fmt::real(1.234234234, 4))); - CHECK("1.23423" == cat_sub(buf, fmt::real(1.234234234, 5))); - CHECK("1000000.00000" == cat_sub(buf, fmt::real(1000000.000000000, 5))); - CHECK("1234234.23423" == cat_sub(buf, fmt::real(1234234.234234234, 5))); - // AKA %f - CHECK("1000000.00000" == cat_sub(buf, fmt::real(1000000.000000000, 5, FTOA_FLOAT))); // AKA %f, same as above - CHECK("1234234.23423" == cat_sub(buf, fmt::real(1234234.234234234, 5, FTOA_FLOAT))); // AKA %f - CHECK("1234234.2342" == cat_sub(buf, fmt::real(1234234.234234234, 4, FTOA_FLOAT))); // AKA %f - CHECK("1234234.234" == cat_sub(buf, fmt::real(1234234.234234234, 3, FTOA_FLOAT))); // AKA %f - CHECK("1234234.23" == cat_sub(buf, fmt::real(1234234.234234234, 2, FTOA_FLOAT))); // AKA %f - // AKA %e - CHECK("1.00000e+06" == cat_sub(buf, fmt::real(1000000.000000000, 5, FTOA_SCIENT))); // AKA %e - CHECK("1.23423e+06" == cat_sub(buf, fmt::real(1234234.234234234, 5, FTOA_SCIENT))); // AKA %e - CHECK("1.2342e+06" == cat_sub(buf, fmt::real(1234234.234234234, 4, FTOA_SCIENT))); // AKA %e - CHECK("1.234e+06" == cat_sub(buf, fmt::real(1234234.234234234, 3, FTOA_SCIENT))); // AKA %e - CHECK("1.23e+06" == cat_sub(buf, fmt::real(1234234.234234234, 2, FTOA_SCIENT))); // AKA %e - // AKA %g - CHECK("1e+06" == cat_sub(buf, fmt::real(1000000.000000000, 5, FTOA_FLEX))); // AKA %g - CHECK("1.2342e+06" == cat_sub(buf, fmt::real(1234234.234234234, 5, FTOA_FLEX))); // AKA %g - CHECK("1.234e+06" == cat_sub(buf, fmt::real(1234234.234234234, 4, FTOA_FLEX))); // AKA %g - CHECK("1.23e+06" == cat_sub(buf, fmt::real(1234234.234234234, 3, FTOA_FLEX))); // AKA %g - CHECK("1.2e+06" == cat_sub(buf, fmt::real(1234234.234234234, 2, FTOA_FLEX))); // AKA %g - // AKA %a (hexadecimal formatting of floats) - // Earlier versions of emscripten's sprintf() (from MUSL) do not - // respect some precision values when printing in hexadecimal - // format. - // - // @see https://github.com/biojppm/c4core/pull/52 - #if defined(__EMSCRIPTEN__) && __EMSCRIPTEN_major__ < 3 - #define _c4emscripten_alt(alt1, alt2) alt2 - #else - #define _c4emscripten_alt(alt1, alt2) alt1 - #endif - CHECK("0x1.e8480p+19" == cat_sub(buf, fmt::real(1000000.000000000, 5, FTOA_HEXA))); // AKA %a - CHECK("0x1.2d53ap+20" == cat_sub(buf, fmt::real(1234234.234234234, 5, FTOA_HEXA))); // AKA %a - CHECK(_c4emscripten_alt("0x1.2d54p+20", "0x1.2d538p+20") - == cat_sub(buf, fmt::real(1234234.234234234, 4, FTOA_HEXA))); // AKA %a - CHECK("0x1.2d5p+20" == cat_sub(buf, fmt::real(1234234.234234234, 3, FTOA_HEXA))); // AKA %a - CHECK(_c4emscripten_alt("0x1.2dp+20", "0x1.2d8p+20") - == cat_sub(buf, fmt::real(1234234.234234234, 2, FTOA_HEXA))); // AKA %a - #undef _c4emscripten_alt - - // -------------------------------------------------------------- - // fmt::raw(): dump data in machine format (respecting alignment) - // -------------------------------------------------------------- - { - C4_SUPPRESS_WARNING_CLANG_WITH_PUSH("-Wcast-align") // we're casting the values directly, so alignment is strictly respected. - const uint32_t payload[] = {10, 20, 30, 40, UINT32_C(0xdeadbeef)}; - // (package payload as a substr, for comparison only) - csubstr expected = csubstr((const char *)payload, sizeof(payload)); - csubstr actual = cat_sub(buf, fmt::raw(payload)); - CHECK(!actual.overlaps(expected)); - CHECK(0 == memcmp(expected.str, actual.str, expected.len)); - // also possible with variables: - for(const uint32_t value : payload) - { - // (package payload as a substr, for comparison only) - expected = csubstr((const char *)&value, sizeof(value)); - actual = cat_sub(buf, fmt::raw(value)); - CHECK(actual.size() == sizeof(uint32_t)); - CHECK(!actual.overlaps(expected)); - CHECK(0 == memcmp(expected.str, actual.str, expected.len)); - // with non-const data, fmt::craw() may be needed for disambiguation: - actual = cat_sub(buf, fmt::craw(value)); - CHECK(actual.size() == sizeof(uint32_t)); - CHECK(!actual.overlaps(expected)); - CHECK(0 == memcmp(expected.str, actual.str, expected.len)); - // - // read back: - uint32_t result; - auto reader = fmt::raw(result); // keeps a reference to result - CHECK(&result == (uint32_t*)reader.buf); - CHECK(reader.len == sizeof(uint32_t)); - uncat(actual, reader); - // and compare: - // (vs2017/release/32bit does not reload result from cache, so force it) - result = *(uint32_t*)reader.buf; - CHECK(result == value); // roundtrip completed successfully - } - C4_SUPPRESS_WARNING_CLANG_POP - } - - // ------------------------- - // fmt::base64(): see below! - // ------------------------- - } -} - - -//----------------------------------------------------------------------------- - -/** demonstrates how to read and write base64-encoded blobs. - @see https://c4core.docsforge.com/master/base64/ - */ -void sample_base64() -{ - ryml::Tree tree; - tree.rootref() |= ryml::MAP; - struct text_and_base64 { ryml::csubstr text, base64; }; - text_and_base64 cases[] = { - {{"Love all, trust a few, do wrong to none."}, {"TG92ZSBhbGwsIHRydXN0IGEgZmV3LCBkbyB3cm9uZyB0byBub25lLg=="}}, - {{"The fool doth think he is wise, but the wise man knows himself to be a fool."}, {"VGhlIGZvb2wgZG90aCB0aGluayBoZSBpcyB3aXNlLCBidXQgdGhlIHdpc2UgbWFuIGtub3dzIGhpbXNlbGYgdG8gYmUgYSBmb29sLg=="}}, - {{"Brevity is the soul of wit."}, {"QnJldml0eSBpcyB0aGUgc291bCBvZiB3aXQu"}}, - {{"All that glitters is not gold."}, {"QWxsIHRoYXQgZ2xpdHRlcnMgaXMgbm90IGdvbGQu"}}, - {{"These violent delights have violent ends..."}, {"VGhlc2UgdmlvbGVudCBkZWxpZ2h0cyBoYXZlIHZpb2xlbnQgZW5kcy4uLg=="}}, - {{"How now, my love?"}, {"SG93IG5vdywgbXkgbG92ZT8="}}, - {{"Why is your cheek so pale?"}, {"V2h5IGlzIHlvdXIgY2hlZWsgc28gcGFsZT8="}}, - {{"How chance the roses there do fade so fast?"}, {"SG93IGNoYW5jZSB0aGUgcm9zZXMgdGhlcmUgZG8gZmFkZSBzbyBmYXN0Pw=="}}, - {{"Belike for want of rain, which I could well beteem them from the tempest of my eyes."}, {"QmVsaWtlIGZvciB3YW50IG9mIHJhaW4sIHdoaWNoIEkgY291bGQgd2VsbCBiZXRlZW0gdGhlbSBmcm9tIHRoZSB0ZW1wZXN0IG9mIG15IGV5ZXMu"}}, - }; - // to encode base64 and write the result to val: - for(text_and_base64 c : cases) - { - tree[c.text] << ryml::fmt::base64(c.text); - CHECK(tree[c.text].val() == c.base64); - } - // to encode base64 and write the result to key: - for(text_and_base64 c : cases) - { - tree.rootref().append_child() << ryml::key(ryml::fmt::base64(c.text)) << c.text; - CHECK(tree[c.base64].val() == c.text); - } - CHECK(ryml::emitrs_yaml(tree) == R"('Love all, trust a few, do wrong to none.': TG92ZSBhbGwsIHRydXN0IGEgZmV3LCBkbyB3cm9uZyB0byBub25lLg== -'The fool doth think he is wise, but the wise man knows himself to be a fool.': VGhlIGZvb2wgZG90aCB0aGluayBoZSBpcyB3aXNlLCBidXQgdGhlIHdpc2UgbWFuIGtub3dzIGhpbXNlbGYgdG8gYmUgYSBmb29sLg== -Brevity is the soul of wit.: QnJldml0eSBpcyB0aGUgc291bCBvZiB3aXQu -All that glitters is not gold.: QWxsIHRoYXQgZ2xpdHRlcnMgaXMgbm90IGdvbGQu -These violent delights have violent ends...: VGhlc2UgdmlvbGVudCBkZWxpZ2h0cyBoYXZlIHZpb2xlbnQgZW5kcy4uLg== -'How now, my love?': SG93IG5vdywgbXkgbG92ZT8= -'Why is your cheek so pale?': V2h5IGlzIHlvdXIgY2hlZWsgc28gcGFsZT8= -'How chance the roses there do fade so fast?': SG93IGNoYW5jZSB0aGUgcm9zZXMgdGhlcmUgZG8gZmFkZSBzbyBmYXN0Pw== -'Belike for want of rain, which I could well beteem them from the tempest of my eyes.': QmVsaWtlIGZvciB3YW50IG9mIHJhaW4sIHdoaWNoIEkgY291bGQgd2VsbCBiZXRlZW0gdGhlbSBmcm9tIHRoZSB0ZW1wZXN0IG9mIG15IGV5ZXMu -TG92ZSBhbGwsIHRydXN0IGEgZmV3LCBkbyB3cm9uZyB0byBub25lLg==: 'Love all, trust a few, do wrong to none.' -VGhlIGZvb2wgZG90aCB0aGluayBoZSBpcyB3aXNlLCBidXQgdGhlIHdpc2UgbWFuIGtub3dzIGhpbXNlbGYgdG8gYmUgYSBmb29sLg==: 'The fool doth think he is wise, but the wise man knows himself to be a fool.' -QnJldml0eSBpcyB0aGUgc291bCBvZiB3aXQu: Brevity is the soul of wit. -QWxsIHRoYXQgZ2xpdHRlcnMgaXMgbm90IGdvbGQu: All that glitters is not gold. -VGhlc2UgdmlvbGVudCBkZWxpZ2h0cyBoYXZlIHZpb2xlbnQgZW5kcy4uLg==: These violent delights have violent ends... -SG93IG5vdywgbXkgbG92ZT8=: 'How now, my love?' -V2h5IGlzIHlvdXIgY2hlZWsgc28gcGFsZT8=: 'Why is your cheek so pale?' -SG93IGNoYW5jZSB0aGUgcm9zZXMgdGhlcmUgZG8gZmFkZSBzbyBmYXN0Pw==: 'How chance the roses there do fade so fast?' -QmVsaWtlIGZvciB3YW50IG9mIHJhaW4sIHdoaWNoIEkgY291bGQgd2VsbCBiZXRlZW0gdGhlbSBmcm9tIHRoZSB0ZW1wZXN0IG9mIG15IGV5ZXMu: 'Belike for want of rain, which I could well beteem them from the tempest of my eyes.' -)"); - // to decode the val base64 and write the result to buf: - char buf1_[128], buf2_[128]; - ryml::substr buf1 = buf1_; // this is where we will write the result - ryml::substr buf2 = buf2_; // this is where we will write the result - for(auto c : cases) - { - // write the decoded result into the given buffer - tree[c.text] >> ryml::fmt::base64(buf1); // cannot know the needed size - size_t len = tree[c.text].deserialize_val(ryml::fmt::base64(buf2)); // returns the needed size - CHECK(len <= buf1.len); - CHECK(len <= buf2.len); - CHECK(c.text.len == len); - CHECK(buf1.first(len) == c.text); - CHECK(buf2.first(len) == c.text); - } - // to decode the val base64 and write the result to buf: - for(text_and_base64 c : cases) - { - // write the decoded result into the given buffer - tree[c.base64] >> ryml::key(ryml::fmt::base64(buf1)); // cannot know the needed size - size_t len = tree[c.base64].deserialize_key(ryml::fmt::base64(buf2)); // returns the needed size - CHECK(len <= buf1.len); - CHECK(len <= buf2.len); - CHECK(c.text.len == len); - CHECK(buf1.first(len) == c.text); - CHECK(buf2.first(len) == c.text); - } - // directly encode variables - { - const uint64_t valin = UINT64_C(0xdeadbeef); - uint64_t valout = 0; - tree["deadbeef"] << c4::fmt::base64(valin); // sometimes cbase64() is needed to avoid ambiguity - size_t len = tree["deadbeef"].deserialize_val(ryml::fmt::base64(valout)); - CHECK(len <= sizeof(valout)); - CHECK(valout == UINT64_C(0xdeadbeef)); // base64 roundtrip is bit-accurate - } - // directly encode memory ranges - { - const uint32_t data_in[11] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xdeadbeef}; - uint32_t data_out[11] = {}; - CHECK(memcmp(data_in, data_out, sizeof(data_in)) != 0); // before the roundtrip - tree["int_data"] << c4::fmt::base64(data_in); - size_t len = tree["int_data"].deserialize_val(ryml::fmt::base64(data_out)); - CHECK(len <= sizeof(data_out)); - CHECK(memcmp(data_in, data_out, sizeof(data_in)) == 0); // after the roundtrip - } -} - - -//----------------------------------------------------------------------------- - -// user scalar types: implemented in ryml through to_chars() + from_chars() - -// To harness [C++'s ADL rules](http://en.cppreference.com/w/cpp/language/adl), -// it is important to overload these functions in the namespace of the type -// you're serializing (or in the c4::yml namespace). -// -// Please take note of the following pitfall when using serialization -// functions: you have to include the header with the serialization -// before any other headers that use functions from it. see the -// include order at the top of this file. -// -// This constraint also applies to the conversion functions for your -// types; just like with the STL's headers, they should be included -// prior to ryml's headers. - -template struct vec2 { T x, y; }; -template struct vec3 { T x, y, z; }; -template struct vec4 { T x, y, z, w; }; - -template struct parse_only_vec2 { T x, y; }; -template struct parse_only_vec3 { T x, y, z; }; -template struct parse_only_vec4 { T x, y, z, w; }; - -template struct emit_only_vec2 { T x, y; }; -template struct emit_only_vec3 { T x, y, z; }; -template struct emit_only_vec4 { T x, y, z, w; }; - -// to_chars(): only needed for emitting -// -// format v to the given string view + return the number of -// characters written into it. The view size (buf.len) must -// be strictly respected. Return the number of characters -// that need to be written. So if the return value -// is larger than buf.len, ryml will resize the buffer and -// call this again with a larger buffer of the correct size. - -template size_t to_chars(ryml::substr buf, vec2 v) { return ryml::format(buf, "({},{})", v.x, v.y); } -template size_t to_chars(ryml::substr buf, vec3 v) { return ryml::format(buf, "({},{},{})", v.x, v.y, v.z); } -template size_t to_chars(ryml::substr buf, vec4 v) { return ryml::format(buf, "({},{},{},{})", v.x, v.y, v.z, v.w); } - -template size_t to_chars(ryml::substr buf, emit_only_vec2 v) { return ryml::format(buf, "({},{})", v.x, v.y); } -template size_t to_chars(ryml::substr buf, emit_only_vec3 v) { return ryml::format(buf, "({},{},{})", v.x, v.y, v.z); } -template size_t to_chars(ryml::substr buf, emit_only_vec4 v) { return ryml::format(buf, "({},{},{},{})", v.x, v.y, v.z, v.w); } - - -// from_chars(): only needed for parsing - -template bool from_chars(ryml::csubstr buf, vec2 *v) { size_t ret = ryml::unformat(buf, "({},{})", v->x, v->y); return ret != ryml::yml::npos; } -template bool from_chars(ryml::csubstr buf, vec3 *v) { size_t ret = ryml::unformat(buf, "({},{},{})", v->x, v->y, v->z); return ret != ryml::yml::npos; } -template bool from_chars(ryml::csubstr buf, vec4 *v) { size_t ret = ryml::unformat(buf, "({},{},{},{})", v->x, v->y, v->z, v->w); return ret != ryml::yml::npos; } - -template bool from_chars(ryml::csubstr buf, parse_only_vec2 *v) { size_t ret = ryml::unformat(buf, "({},{})", v->x, v->y); return ret != ryml::yml::npos; } -template bool from_chars(ryml::csubstr buf, parse_only_vec3 *v) { size_t ret = ryml::unformat(buf, "({},{},{})", v->x, v->y, v->z); return ret != ryml::yml::npos; } -template bool from_chars(ryml::csubstr buf, parse_only_vec4 *v) { size_t ret = ryml::unformat(buf, "({},{},{},{})", v->x, v->y, v->z, v->w); return ret != ryml::yml::npos; } - - -/** to add scalar types (ie leaf types converting to/from string), - define the functions above for those types. */ -void sample_user_scalar_types() -{ - ryml::Tree t; - - auto r = t.rootref(); - r |= ryml::MAP; - - vec2 v2in{10, 11}; - vec2 v2out{1, 2}; - r["v2"] << v2in; // serializes to the tree's arena, and then sets the keyval - r["v2"] >> v2out; - CHECK(v2in.x == v2out.x); - CHECK(v2in.y == v2out.y); - vec3 v3in{100, 101, 102}; - vec3 v3out{1, 2, 3}; - r["v3"] << v3in; // serializes to the tree's arena, and then sets the keyval - r["v3"] >> v3out; - CHECK(v3in.x == v3out.x); - CHECK(v3in.y == v3out.y); - CHECK(v3in.z == v3out.z); - vec4 v4in{1000, 1001, 1002, 1003}; - vec4 v4out{1, 2, 3, 4}; - r["v4"] << v4in; // serializes to the tree's arena, and then sets the keyval - r["v4"] >> v4out; - CHECK(v4in.x == v4out.x); - CHECK(v4in.y == v4out.y); - CHECK(v4in.z == v4out.z); - CHECK(v4in.w == v4out.w); - CHECK(ryml::emitrs_yaml(t) == R"(v2: '(10,11)' -v3: '(100,101,102)' -v4: '(1000,1001,1002,1003)' -)"); - - // note that only the used functions are needed: - // - if a type is only parsed, then only from_chars() is needed - // - if a type is only emitted, then only to_chars() is needed - emit_only_vec2 eov2in{20, 21}; // only has to_chars() - parse_only_vec2 pov2out{1, 2}; // only has from_chars() - r["v2"] << eov2in; // serializes to the tree's arena, and then sets the keyval - r["v2"] >> pov2out; - CHECK(eov2in.x == pov2out.x); - CHECK(eov2in.y == pov2out.y); - emit_only_vec3 eov3in{30, 31, 32}; // only has to_chars() - parse_only_vec3 pov3out{1, 2, 3}; // only has from_chars() - r["v3"] << eov3in; // serializes to the tree's arena, and then sets the keyval - r["v3"] >> pov3out; - CHECK(eov3in.x == pov3out.x); - CHECK(eov3in.y == pov3out.y); - CHECK(eov3in.z == pov3out.z); - emit_only_vec4 eov4in{40, 41, 42, 43}; // only has to_chars() - parse_only_vec4 pov4out{1, 2, 3, 4}; // only has from_chars() - r["v4"] << eov4in; // serializes to the tree's arena, and then sets the keyval - r["v4"] >> pov4out; - CHECK(eov4in.x == pov4out.x); - CHECK(eov4in.y == pov4out.y); - CHECK(eov4in.z == pov4out.z); - CHECK(ryml::emitrs_yaml(t) == R"(v2: '(20,21)' -v3: '(30,31,32)' -v4: '(40,41,42,43)' -)"); -} - - -//----------------------------------------------------------------------------- - -// user container types: implemented in ryml through write() + read() -// -// Please take note of the following pitfall when using serialization -// functions: you have to include the header with the serialization -// before any other headers that use functions from it. see the -// include order at the top of this file. -// -// This constraint also applies to the conversion functions for your -// types; just like with the STL's headers, they should be included -// prior to ryml's headers. - -// user container type: seq-like -template struct my_seq_type { std::vector seq_member; }; -template -void write(ryml::NodeRef *n, my_seq_type const& seq) -{ - *n |= ryml::SEQ; - for(auto const& v : seq.seq_member) - n->append_child() << v; -} -template -bool read(ryml::ConstNodeRef const& n, my_seq_type *seq) -{ - seq->seq_member.resize(n.num_children()); // num_children() is O(N) - size_t pos = 0; - for(auto const ch : n.children()) - ch >> seq->seq_member[pos++]; - return true; -} - - -// user container type: map-like -template struct my_map_type { std::map map_member; }; -template -void write(ryml::NodeRef *n, my_map_type const& map) -{ - *n |= ryml::MAP; - for(auto const& v : map.map_member) - n->append_child() << ryml::key(v.first) << v.second; -} -template -bool read(ryml::ConstNodeRef const& n, my_map_type *map) -{ - K k{}; - V v{}; - for(auto const ch : n) - { - ch >> c4::yml::key(k) >> v; - map->map_member.emplace(std::make_pair(std::move(k), std::move(v))); - } - return true; -} - - -// user container type: notice all the members are complex types -// defined above -struct my_type -{ - vec2 v2; - vec3 v3; - vec4 v4; - my_seq_type seq; - my_map_type map; -}; -void write(ryml::NodeRef *n, my_type const& val) -{ - *n |= ryml::MAP; - n->append_child() << ryml::key("v2") << val.v2; - n->append_child() << ryml::key("v3") << val.v3; - n->append_child() << ryml::key("v4") << val.v4; - n->append_child() << ryml::key("seq") << val.seq; - n->append_child() << ryml::key("map") << val.map; -} -bool read(ryml::ConstNodeRef const& n, my_type *val) -{ - n["v2"] >> val->v2; - n["v3"] >> val->v3; - n["v4"] >> val->v4; - n["seq"] >> val->seq; - n["map"] >> val->map; - return true; -} - - -void sample_user_container_types() -{ - my_type mt_in{ - {20, 21}, - {30, 31, 32}, - {40, 41, 42, 43}, - {{101, 102, 103, 104, 105, 106, 107}}, - {{{1001, 2001}, {1002, 2002}, {1003, 2003}}}, - }; - my_type mt_out; - - ryml::Tree t; - t.rootref() << mt_in; // read from this - t.crootref() >> mt_out; // assign here - CHECK(mt_out.v2.x == mt_in.v2.x); - CHECK(mt_out.v2.y == mt_in.v2.y); - CHECK(mt_out.v3.x == mt_in.v3.x); - CHECK(mt_out.v3.y == mt_in.v3.y); - CHECK(mt_out.v3.z == mt_in.v3.z); - CHECK(mt_out.v4.x == mt_in.v4.x); - CHECK(mt_out.v4.y == mt_in.v4.y); - CHECK(mt_out.v4.z == mt_in.v4.z); - CHECK(mt_out.v4.w == mt_in.v4.w); - CHECK(mt_in.seq.seq_member.size() > 0); - CHECK(mt_out.seq.seq_member.size() == mt_in.seq.seq_member.size()); - for(size_t i = 0; i < mt_in.seq.seq_member.size(); ++i) - { - CHECK(mt_out.seq.seq_member[i] == mt_in.seq.seq_member[i]); - } - CHECK(mt_in.map.map_member.size() > 0); - CHECK(mt_out.map.map_member.size() == mt_in.map.map_member.size()); - for(auto const& kv : mt_in.map.map_member) - { - CHECK(mt_out.map.map_member.find(kv.first) != mt_out.map.map_member.end()); - CHECK(mt_out.map.map_member[kv.first] == kv.second); - } - CHECK(ryml::emitrs_yaml(t) == R"(v2: '(20,21)' -v3: '(30,31,32)' -v4: '(40,41,42,43)' -seq: - - 101 - - 102 - - 103 - - 104 - - 105 - - 106 - - 107 -map: - 1001: 2001 - 1002: 2002 - 1003: 2003 -)"); -} - - -//----------------------------------------------------------------------------- -// -// Please take note of the following pitfall when using serialization -// functions: you have to include the header with the serialization -// before any other headers that use functions from it. see the -// include order at the top of this file. -// -// This constraint also applies to the conversion functions for your -// types; just like with the STL's headers, they should be included -// prior to ryml's headers. - -/** demonstrates usage with the std implementations provided by ryml in the ryml_std.hpp header */ -void sample_std_types() -{ - std::string yml_std_string = R"(- v2: '(20,21)' - v3: '(30,31,32)' - v4: '(40,41,42,43)' - seq: - - 101 - - 102 - - 103 - - 104 - - 105 - - 106 - - 107 - map: - 1001: 2001 - 1002: 2002 - 1003: 2003 -- v2: '(120,121)' - v3: '(130,131,132)' - v4: '(140,141,142,143)' - seq: - - 1101 - - 1102 - - 1103 - - 1104 - - 1105 - - 1106 - - 1107 - map: - 11001: 12001 - 11002: 12002 - 11003: 12003 -- v2: '(220,221)' - v3: '(230,231,232)' - v4: '(240,241,242,243)' - seq: - - 2101 - - 2102 - - 2103 - - 2104 - - 2105 - - 2106 - - 2107 - map: - 21001: 22001 - 21002: 22002 - 21003: 22003 -)"; - // parse in-place using the std::string above - auto tree = ryml::parse_in_place(ryml::to_substr(yml_std_string)); - // my_type is a container-of-containers type. see above its - // definition implementation for ryml. - std::vector vmt; - tree.rootref() >> vmt; - CHECK(vmt.size() == 3); - ryml::Tree tree_out; - tree_out.rootref() << vmt; - CHECK(ryml::emitrs_yaml(tree_out) == yml_std_string); -} - - -//----------------------------------------------------------------------------- - -/** demonstrates how to emit to a linear container of char */ -void sample_emit_to_container() -{ - // it is possible to emit to any linear container of char. - - ryml::csubstr ymla = "- 1\n- 2\n"; - ryml::csubstr ymlb = R"(- a -- b -- x0: 1 - x1: 2 -- champagne: Dom Perignon - coffee: Arabica - more: - vinho verde: Soalheiro - vinho tinto: Redoma 2017 - beer: - - Rochefort 10 - - Busch - - Leffe Rituel -- foo -- bar -- baz -- bat -)"; - auto treea = ryml::parse_in_arena(ymla); - auto treeb = ryml::parse_in_arena(ymlb); - - // eg, std::vector - { - // do a blank call on an empty buffer to find the required size. - // no overflow will occur, and returns a substr with the size - // required to output - ryml::csubstr output = ryml::emit_yaml(treea, treea.root_id(), ryml::substr{}, /*error_on_excess*/false); - CHECK(output.str == nullptr); - CHECK(output.len > 0); - size_t num_needed_chars = output.len; - std::vector buf(num_needed_chars); - // now try again with the proper buffer - output = ryml::emit_yaml(treea, treea.root_id(), ryml::to_substr(buf), /*error_on_excess*/true); - CHECK(output == ymla); - - // it is possible to reuse the buffer and grow it as needed. - // first do a blank run to find the size: - output = ryml::emit_yaml(treeb, treeb.root_id(), ryml::substr{}, /*error_on_excess*/false); - CHECK(output.str == nullptr); - CHECK(output.len > 0); - CHECK(output.len == ymlb.len); - num_needed_chars = output.len; - buf.resize(num_needed_chars); - // now try again with the proper buffer - output = ryml::emit_yaml(treeb, treeb.root_id(), ryml::to_substr(buf), /*error_on_excess*/true); - CHECK(output == ymlb); - - // there is a convenience wrapper performing the same as above: - // provided to_substr() is defined for that container. - output = ryml::emitrs_yaml(treeb, &buf); - CHECK(output == ymlb); - - // or you can just output a new container: - // provided to_substr() is defined for that container. - std::vector another = ryml::emitrs_yaml>(treeb); - CHECK(ryml::to_csubstr(another) == ymlb); - - // you can also emit nested nodes: - another = ryml::emitrs_yaml>(treeb[3][2]); - CHECK(ryml::to_csubstr(another) == R"(more: - vinho verde: Soalheiro - vinho tinto: Redoma 2017 -)"); - } - - - // eg, std::string. notice this is the same code as above - { - // do a blank call on an empty buffer to find the required size. - // no overflow will occur, and returns a substr with the size - // required to output - ryml::csubstr output = ryml::emit_yaml(treea, treea.root_id(), ryml::substr{}, /*error_on_excess*/false); - CHECK(output.str == nullptr); - CHECK(output.len > 0); - size_t num_needed_chars = output.len; - std::string buf; - buf.resize(num_needed_chars); - // now try again with the proper buffer - output = ryml::emit_yaml(treea, treea.root_id(), ryml::to_substr(buf), /*error_on_excess*/true); - CHECK(output == ymla); - - // it is possible to reuse the buffer and grow it as needed. - // first do a blank run to find the size: - output = ryml::emit_yaml(treeb, treeb.root_id(), ryml::substr{}, /*error_on_excess*/false); - CHECK(output.str == nullptr); - CHECK(output.len > 0); - CHECK(output.len == ymlb.len); - num_needed_chars = output.len; - buf.resize(num_needed_chars); - // now try again with the proper buffer - output = ryml::emit_yaml(treeb, treeb.root_id(), ryml::to_substr(buf), /*error_on_excess*/true); - CHECK(output == ymlb); - - // there is a convenience wrapper performing the above instructions: - // provided to_substr() is defined for that container - output = ryml::emitrs_yaml(treeb, &buf); - CHECK(output == ymlb); - - // or you can just output a new container: - // provided to_substr() is defined for that container. - std::string another = ryml::emitrs_yaml(treeb); - CHECK(ryml::to_csubstr(another) == ymlb); - - // you can also emit nested nodes: - another = ryml::emitrs_yaml(treeb[3][2]); - CHECK(ryml::to_csubstr(another) == R"(more: - vinho verde: Soalheiro - vinho tinto: Redoma 2017 -)"); - } -} - - -//----------------------------------------------------------------------------- - -/** demonstrates how to emit to a stream-like structure */ -void sample_emit_to_stream() -{ - ryml::csubstr ymlb = R"(- a -- b -- x0: 1 - x1: 2 -- champagne: Dom Perignon - coffee: Arabica - more: - vinho verde: Soalheiro - vinho tinto: Redoma 2017 - beer: - - Rochefort 10 - - Busch - - Leffe Rituel -- foo -- bar -- baz -- bat -)"; - auto tree = ryml::parse_in_arena(ymlb); - - std::string s; - - // emit a full tree - { - std::stringstream ss; - ss << tree; // works with any stream having .operator<<() and .write() - s = ss.str(); - CHECK(ryml::to_csubstr(s) == ymlb); - } - - // emit a full tree as json - { - std::stringstream ss; - ss << ryml::as_json(tree); // works with any stream having .operator<<() and .write() - s = ss.str(); - CHECK(ryml::to_csubstr(s) == R"(["a","b",{"x0": 1,"x1": 2},{"champagne": "Dom Perignon","coffee": "Arabica","more": {"vinho verde": "Soalheiro","vinho tinto": "Redoma 2017"},"beer": ["Rochefort 10","Busch","Leffe Rituel"]},"foo","bar","baz","bat"])"); - } - - // emit a nested node - { - std::stringstream ss; - ss << tree[3][2]; // works with any stream having .operator<<() and .write() - s = ss.str(); - CHECK(ryml::to_csubstr(s) == R"(more: - vinho verde: Soalheiro - vinho tinto: Redoma 2017 -)"); - } - - // emit a nested node as json - { - std::stringstream ss; - ss << ryml::as_json(tree[3][2]); // works with any stream having .operator<<() and .write() - s = ss.str(); - CHECK(ryml::to_csubstr(s) == R"("more": {"vinho verde": "Soalheiro","vinho tinto": "Redoma 2017"})"); - } -} - - -//----------------------------------------------------------------------------- - -/** demonstrates how to emit to a FILE* */ -void sample_emit_to_file() -{ - ryml::csubstr yml = R"(- a -- b -- x0: 1 - x1: 2 -- champagne: Dom Perignon - coffee: Arabica - more: - vinho verde: Soalheiro - vinho tinto: Redoma 2017 - beer: - - Rochefort 10 - - Busch - - Leffe Rituel -- foo -- bar -- baz -- bat -)"; - auto tree = ryml::parse_in_arena(yml); - // this is emitting to stdout, but of course you can pass in any - // FILE* obtained from fopen() - size_t len = ryml::emit_yaml(tree, tree.root_id(), stdout); - // the return value is the number of characters that were written - // to the file - CHECK(len == yml.len); -} - - -//----------------------------------------------------------------------------- - -/** just like parsing into a nested node, you can also emit from a nested node. */ -void sample_emit_nested_node() -{ - const ryml::Tree tree = ryml::parse_in_arena(R"(- a -- b -- x0: 1 - x1: 2 -- champagne: Dom Perignon - coffee: Arabica - more: - vinho verde: Soalheiro - vinho tinto: Redoma 2017 - beer: - - Rochefort 10 - - Busch - - Leffe Rituel - - - and so - - many other - - wonderful beers -- more -- seq -- members -- here -)"); - CHECK(ryml::emitrs_yaml(tree[3]["beer"]) == R"(beer: - - Rochefort 10 - - Busch - - Leffe Rituel - - - and so - - many other - - wonderful beers -)"); - CHECK(ryml::emitrs_yaml(tree[3]["beer"][0]) == "Rochefort 10\n"); - CHECK(ryml::emitrs_yaml(tree[3]["beer"][3]) == R"(- and so -- many other -- wonderful beers -)"); -} - - -//----------------------------------------------------------------------------- - - -/** shows how to parse and emit JSON. */ -void sample_json() -{ - // Since JSON is a subset of YAML, parsing JSON is just the - // same as YAML: - ryml::Tree tree = ryml::parse_in_arena(R"({ -"doe":"a deer, a female deer", -"ray":"a drop of golden sun", -"me":"a name, I call myself", -"far":"a long long way to go" -})"); - // However, emitting still defaults to YAML - CHECK(ryml::emitrs_yaml(tree) == R"('doe': 'a deer, a female deer' -'ray': 'a drop of golden sun' -'me': 'a name, I call myself' -'far': 'a long long way to go' -)"); - // to emit JSON, use the proper overload: - CHECK(ryml::emitrs_json(tree) == R"({"doe": "a deer, a female deer","ray": "a drop of golden sun","me": "a name, I call myself","far": "a long long way to go"})"); - // to emit JSON to a stream: - std::stringstream ss; - ss << ryml::as_json(tree); // <- mark it like this - CHECK(ss.str() == R"({"doe": "a deer, a female deer","ray": "a drop of golden sun","me": "a name, I call myself","far": "a long long way to go"})"); - // Note the following limitations: - // - // - YAML streams cannot be emitted as json, and are not - // allowed. But you can work around this by emitting the - // individual documents separately; see the sample_docs() - // below for such an example. - // - // - tags cannot be emitted as json, and are not allowed. - // - // - anchors and aliases cannot be emitted as json and are not allowed. -} - - -//----------------------------------------------------------------------------- - -/** demonstrates usage with anchors and alias references. - -Note that dereferencing is opt-in; after parsing, you have to call -`Tree::resolve()` explicitly if you want resolved references in the -tree. This method will resolve all references and substitute the anchored -values in place of the reference. - -The `Tree::resolve()` method first does a full traversal of the tree to -gather all anchors and references in a separate collection, then it goes -through that collection to locate the names, which it does by obeying the -YAML standard diktat that - - an alias node refers to the most recent node in - the serialization having the specified anchor - -So, depending on the number of anchor/alias nodes, this is a potentially -expensive operation, with a best-case linear complexity (from the initial -traversal) and a worst-case quadratic complexity (if every node has an -alias/anchor). This potential cost is the reason for requiring an explicit -call to `Tree::resolve()`. */ -void sample_anchors_and_aliases() -{ - std::string unresolved = R"(base: &base - name: Everyone has same name -foo: &foo - <<: *base - age: 10 -bar: &bar - <<: *base - age: 20 -bill_to: &id001 - street: |- - 123 Tornado Alley - Suite 16 - city: East Centerville - state: KS -ship_to: *id001 -&keyref key: &valref val -*valref: *keyref -)"; - - ryml::Tree tree = ryml::parse_in_arena(ryml::to_csubstr(unresolved)); - // by default, references are not resolved when parsing: - CHECK( ! tree["base"].has_key_anchor()); - CHECK( tree["base"].has_val_anchor()); - CHECK( tree["base"].val_anchor() == "base"); - CHECK( tree["key"].key_anchor() == "keyref"); - CHECK( tree["key"].val_anchor() == "valref"); - CHECK( tree["*valref"].is_key_ref()); - CHECK( tree["*valref"].is_val_ref()); - CHECK( tree["*valref"].key_ref() == "valref"); - CHECK( tree["*valref"].val_ref() == "keyref"); - - // to resolve references, simply call tree.resolve(), - // which will perform the reference instantiations: - tree.resolve(); - - // all the anchors and references are substistuted and then removed: - CHECK( ! tree["base"].has_key_anchor()); - CHECK( ! tree["base"].has_val_anchor()); - CHECK( ! tree["base"].has_val_anchor()); - CHECK( ! tree["key"].has_key_anchor()); - CHECK( ! tree["key"].has_val_anchor()); - CHECK( ! tree["val"].is_key_ref()); // notice *valref is now turned to val - CHECK( ! tree["val"].is_val_ref()); // notice *valref is now turned to val - - CHECK(tree["ship_to"]["city"] == "East Centerville"); - CHECK(tree["ship_to"]["state"] == "KS"); -} - - -//----------------------------------------------------------------------------- - -void sample_tags() -{ - std::string unresolved = R"(--- !!map -a: 0 -b: 1 ---- !map -? a -: b ---- !!seq -- a -- b ---- !!str -a - b -... ---- !!str a b -... ---- !!str a b ---- !!str -a: b ---- !!str a: b ---- -!!str a: b ---- -!!str a - b ---- -!!set -? a -? b ---- !!set -? a ---- -[!!int 0, !!str 0] -)"; - std::string resolved = R"(--- !!map -a: 0 -b: 1 ---- !map -a: b ---- !!seq -- a -- b ---- !!str a b ---- !!str a b ---- !!str a b ---- !!str 'a: b' ---- !!str 'a: b' ---- -!!str a: b ---- !!str a b ---- !!set -a: -b: ---- !!set -a: ---- -- !!int 0 -- !!str 0 -)"; - ryml::Tree tree = ryml::parse_in_arena(ryml::to_csubstr(unresolved)); - CHECK(ryml::emitrs_yaml(tree) == resolved); - const ryml::ConstNodeRef stream = tree.rootref(); - CHECK(stream.is_stream()); - CHECK(stream.num_children() == 13); - for(auto node : stream.children()) - CHECK(node.is_doc()); - CHECK(stream[11].val_tag() == "!!set"); -} - - -//----------------------------------------------------------------------------- - -void sample_docs() -{ - std::string yml = R"(--- -a: 0 -b: 1 ---- -c: 2 -d: 3 ---- -- 4 -- 5 -- 6 -- 7 -)"; - ryml::Tree tree = ryml::parse_in_place(ryml::to_substr(yml)); - CHECK(ryml::emitrs_yaml(tree) == yml); - - // iteration through docs - { - // using the node API - const ryml::ConstNodeRef stream = tree.rootref(); - CHECK(stream.is_root()); - CHECK(stream.is_stream()); - CHECK(!stream.is_doc()); - CHECK(stream.num_children() == 3); - for(const ryml::ConstNodeRef doc : stream.children()) - CHECK(doc.is_doc()); - CHECK(tree.docref(0).id() == stream.child(0).id()); - CHECK(tree.docref(1).id() == stream.child(1).id()); - CHECK(tree.docref(2).id() == stream.child(2).id()); - // equivalent: using the lower level index API - const size_t stream_id = tree.root_id(); - CHECK(tree.is_root(stream_id)); - CHECK(tree.is_stream(stream_id)); - CHECK(!tree.is_doc(stream_id)); - CHECK(tree.num_children(stream_id) == 3); - for(size_t doc_id = tree.first_child(stream_id); doc_id != ryml::NONE; doc_id = tree.next_sibling(stream_id)) - CHECK(tree.is_doc(doc_id)); - CHECK(tree.doc(0) == tree.child(stream_id, 0)); - CHECK(tree.doc(1) == tree.child(stream_id, 1)); - CHECK(tree.doc(2) == tree.child(stream_id, 2)); - - // using the node API - CHECK(stream[0].is_doc()); - CHECK(stream[0].is_map()); - CHECK(stream[0]["a"].val() == "0"); - CHECK(stream[0]["b"].val() == "1"); - // equivalent: using the index API - const size_t doc0_id = tree.first_child(stream_id); - CHECK(tree.is_doc(doc0_id)); - CHECK(tree.is_map(doc0_id)); - CHECK(tree.val(tree.find_child(doc0_id, "a")) == "0"); - CHECK(tree.val(tree.find_child(doc0_id, "b")) == "1"); - - // using the node API - CHECK(stream[1].is_doc()); - CHECK(stream[1].is_map()); - CHECK(stream[1]["c"].val() == "2"); - CHECK(stream[1]["d"].val() == "3"); - // equivalent: using the index API - const size_t doc1_id = tree.next_sibling(doc0_id); - CHECK(tree.is_doc(doc1_id)); - CHECK(tree.is_map(doc1_id)); - CHECK(tree.val(tree.find_child(doc1_id, "c")) == "2"); - CHECK(tree.val(tree.find_child(doc1_id, "d")) == "3"); - - // using the node API - CHECK(stream[2].is_doc()); - CHECK(stream[2].is_seq()); - CHECK(stream[2][0].val() == "4"); - CHECK(stream[2][1].val() == "5"); - CHECK(stream[2][2].val() == "6"); - CHECK(stream[2][3].val() == "7"); - // equivalent: using the index API - const size_t doc2_id = tree.next_sibling(doc1_id); - CHECK(tree.is_doc(doc2_id)); - CHECK(tree.is_seq(doc2_id)); - CHECK(tree.val(tree.child(doc2_id, 0)) == "4"); - CHECK(tree.val(tree.child(doc2_id, 1)) == "5"); - CHECK(tree.val(tree.child(doc2_id, 2)) == "6"); - CHECK(tree.val(tree.child(doc2_id, 3)) == "7"); - } - - // Note: since json does not have streams, you cannot emit the above - // tree as json when you start from the root: - //CHECK(ryml::emitrs_json(tree) == yml); // RUNTIME ERROR! - - // emitting streams as json is not possible, but - // you can iterate through individual documents and emit - // them separately: - { - const std::string expected_json[] = { - R"({"a": 0,"b": 1})", - R"({"c": 2,"d": 3})", - R"([4,5,6,7])", - }; - // using the node API - { - size_t count = 0; - const ryml::ConstNodeRef stream = tree.rootref(); - CHECK(stream.num_children() == C4_COUNTOF(expected_json)); - for(ryml::ConstNodeRef doc : stream.children()) - CHECK(ryml::emitrs_json(doc) == expected_json[count++]); - } - // equivalent: using the index API - { - size_t count = 0; - const size_t stream_id = tree.root_id(); - CHECK(tree.num_children(stream_id) == C4_COUNTOF(expected_json)); - for(size_t doc_id = tree.first_child(stream_id); doc_id != ryml::NONE; doc_id = tree.next_sibling(doc_id)) - CHECK(ryml::emitrs_json(tree, doc_id) == expected_json[count++]); - } - } -} - - -//----------------------------------------------------------------------------- - -// To avoid imposing a particular type of error handling, ryml accepts -// custom error handlers. This enables users to use exceptions, or -// plain calls to abort(), as they see fit. -// -// However, it is important to note that the error callback must never -// return to the caller! Otherwise, an infinite loop or program crash -// may occur. - - -struct ErrorHandlerExample -{ - // this will be called on error - void on_error(const char* msg, size_t len, ryml::Location loc) - { - throw std::runtime_error(ryml::formatrs("{}:{}:{} ({}B): ERROR: {}", - loc.name, loc.line, loc.col, loc.offset, ryml::csubstr(msg, len))); - } - - // bridge - ryml::Callbacks callbacks() - { - return ryml::Callbacks(this, nullptr, nullptr, ErrorHandlerExample::s_error); - } - static void s_error(const char* msg, size_t len, ryml::Location loc, void *this_) - { - return ((ErrorHandlerExample*)this_)->on_error(msg, len, loc); - } - - // checking - template - void check_error_occurs(Fn &&fn) const - { - bool expected_error_occurred = false; - try { fn(); } - catch(std::runtime_error const&) { expected_error_occurred = true; } - CHECK(expected_error_occurred); - } - void check_effect(bool committed) const - { - ryml::Callbacks const& current = ryml::get_callbacks(); - if(committed) - { - CHECK(current.m_error == &s_error); - } - else - { - CHECK(current.m_error != &s_error); - } - CHECK(current.m_allocate == defaults.m_allocate); - CHECK(current.m_free == defaults.m_free); - } - // save the default callbacks for checking - ErrorHandlerExample() : defaults(ryml::get_callbacks()) {} - ryml::Callbacks defaults; -}; - -/** demonstrates how to set a custom error handler for ryml */ -void sample_error_handler() -{ - ErrorHandlerExample errh; - - // set a global error handler. Note the error callback must never - // return: it must either abort or throw an exception. Otherwise, - // the parser will enter into an infinite loop, or the program may - // crash. - ryml::set_callbacks(errh.callbacks()); - errh.check_effect(/*committed*/true); - errh.check_error_occurs([]{ - ryml::Tree tree = ryml::parse_in_arena("errorhandler.yml", "[a: b\n}"); - std::cout << tree; - }); - - ryml::set_callbacks(errh.defaults); // restore defaults. - errh.check_effect(/*committed*/false); -} - - -//----------------------------------------------------------------------------- - -// Please note the following about the use of custom allocators with -// ryml. Due to [the static initialization order -// fiasco](https://en.cppreference.com/w/cpp/language/siof), if you -// use static ryml trees or parsers, you need to make sure that their -// callbacks have the same lifetime. So you can't use ryml's default -// callbacks structure, as it is declared in a ryml file, and the standard -// provides no guarantee on the relative initialization order, such -// that it is constructed before and destroyed after your -// variables (in fact you are pretty much guaranteed to see this -// fail). So please carefully consider your choices, and ponder -// whether you really need to use ryml static trees and parsers. If -// you do need this, then you will need to declare and use a ryml -// callbacks structure that outlives the tree and/or parser. - -struct GlobalAllocatorExample -{ - std::vector memory_pool = std::vector(10u * 1024u); // 10KB - size_t num_allocs = 0, alloc_size = 0; - size_t num_deallocs = 0, dealloc_size = 0; - - void *allocate(size_t len) - { - void *ptr = &memory_pool[alloc_size]; - alloc_size += len; - ++num_allocs; - if(C4_UNLIKELY(alloc_size > memory_pool.size())) - { - std::cerr << "out of memory! requested=" << alloc_size << " vs " << memory_pool.size() << " available" << std::endl; - std::abort(); - } - return ptr; - } - - void free(void *mem, size_t len) - { - CHECK((char*)mem >= &memory_pool.front() && (char*)mem < &memory_pool.back()); - CHECK((char*)mem+len >= &memory_pool.front() && (char*)mem+len <= &memory_pool.back()); - dealloc_size += len; - ++num_deallocs; - // no need to free here - } - - // bridge - ryml::Callbacks callbacks() - { - return ryml::Callbacks(this, &GlobalAllocatorExample::s_allocate, &GlobalAllocatorExample::s_free, nullptr); - } - static void* s_allocate(size_t len, void* /*hint*/, void *this_) - { - return ((GlobalAllocatorExample*)this_)->allocate(len); - } - static void s_free(void *mem, size_t len, void *this_) - { - return ((GlobalAllocatorExample*)this_)->free(mem, len); - } - - // checking - ~GlobalAllocatorExample() - { - check_and_reset(); - } - void check_and_reset() - { - std::cout << "size: alloc=" << alloc_size << " dealloc=" << dealloc_size << std::endl; - std::cout << "count: #allocs=" << num_allocs << " #deallocs=" << num_deallocs << std::endl; - CHECK(num_allocs == num_deallocs); - CHECK(alloc_size >= dealloc_size); // failure here means a double free - CHECK(alloc_size == dealloc_size); // failure here means a leak - num_allocs = 0; - num_deallocs = 0; - alloc_size = 0; - dealloc_size = 0; - } -}; - - -/** demonstrates how to set the global allocator for ryml */ -void sample_global_allocator() -{ - GlobalAllocatorExample mem; - - // save the existing callbacks for restoring - ryml::Callbacks defaults = ryml::get_callbacks(); - - // set to our callbacks - ryml::set_callbacks(mem.callbacks()); - - // verify that the allocator is in effect - ryml::Callbacks const& current = ryml::get_callbacks(); - CHECK(current.m_allocate == &mem.s_allocate); - CHECK(current.m_free == &mem.s_free); - - // so far nothing was allocated - CHECK(mem.alloc_size == 0); - - // parse one tree and check - (void)ryml::parse_in_arena(R"({foo: bar})"); - mem.check_and_reset(); - - // parse another tree and check - (void)ryml::parse_in_arena(R"([a, b, c, d, {foo: bar, money: pennys}])"); - mem.check_and_reset(); - - // verify that by reserving we save allocations - { - ryml::Parser parser; // reuse a parser - ryml::Tree tree; // reuse a tree - - tree.reserve(10); // reserve the number of nodes - tree.reserve_arena(100); // reserve the arena size - parser.reserve_stack(10); // reserve the parser depth. - - // since the parser stack uses Small Storage Optimization, - // allocations will only happen with capacities higher than 16. - CHECK(mem.num_allocs == 2); // tree, tree_arena and NOT the parser - - parser.reserve_stack(20); // reserve the parser depth. - CHECK(mem.num_allocs == 3); // tree, tree_arena and now the parser as well - - // verify that no other allocations occur when parsing - size_t size_before = mem.alloc_size; - parser.parse_in_arena("", R"([a, b, c, d, {foo: bar, money: pennys}])", &tree); - CHECK(mem.alloc_size == size_before); - CHECK(mem.num_allocs == 3); - } - mem.check_and_reset(); - - // restore defaults. - ryml::set_callbacks(defaults); -} - - -//----------------------------------------------------------------------------- - -/** an example for a per-tree memory allocator */ -struct PerTreeMemoryExample -{ - std::vector memory_pool = std::vector(10u * 1024u); // 10KB - size_t num_allocs = 0, alloc_size = 0; - size_t num_deallocs = 0, dealloc_size = 0; - - ryml::Callbacks callbacks() const - { - // Above we used static functions to bridge to our methods. - // To show a different approach, we employ lambdas here. - // Note that there can be no captures in the lambdas - // because these are C-style function pointers. - ryml::Callbacks cb; - cb.m_user_data = (void*) this; - cb.m_allocate = [](size_t len, void *, void *data){ return ((PerTreeMemoryExample*) data)->allocate(len); }; - cb.m_free = [](void *mem, size_t len, void *data){ return ((PerTreeMemoryExample*) data)->free(mem, len); }; - return cb; - } - - void *allocate(size_t len) - { - void *ptr = &memory_pool[alloc_size]; - alloc_size += len; - ++num_allocs; - if(C4_UNLIKELY(alloc_size > memory_pool.size())) - { - std::cerr << "out of memory! requested=" << alloc_size << " vs " << memory_pool.size() << " available" << std::endl; - std::abort(); - } - return ptr; - } - - void free(void *mem, size_t len) - { - CHECK((char*)mem >= &memory_pool.front() && (char*)mem < &memory_pool.back()); - CHECK((char*)mem+len >= &memory_pool.front() && (char*)mem+len <= &memory_pool.back()); - dealloc_size += len; - ++num_deallocs; - // no need to free here - } - - // checking - ~PerTreeMemoryExample() - { - check_and_reset(); - } - void check_and_reset() - { - std::cout << "size: alloc=" << alloc_size << " dealloc=" << dealloc_size << std::endl; - std::cout << "count: #allocs=" << num_allocs << " #deallocs=" << num_deallocs << std::endl; - CHECK(num_allocs == num_deallocs); - CHECK(alloc_size >= dealloc_size); // failure here means a double free - CHECK(alloc_size == dealloc_size); // failure here means a leak - num_allocs = 0; - num_deallocs = 0; - alloc_size = 0; - dealloc_size = 0; - } -}; - -void sample_per_tree_allocator() -{ - PerTreeMemoryExample mrp; - PerTreeMemoryExample mr1; - PerTreeMemoryExample mr2; - - // the trees will use the memory in the resources above, - // with each tree using a separate resource - { - // Watchout: ensure that the lifetime of the callbacks target - // exceeds the lifetime of the tree. - auto parser = ryml::Parser(mrp.callbacks()); - auto tree1 = ryml::Tree(mr1.callbacks()); - auto tree2 = ryml::Tree(mr2.callbacks()); - - ryml::csubstr yml1 = "{a: b}"; - ryml::csubstr yml2 = "{c: d, e: f, g: [h, i, 0, 1, 2, 3]}"; - - parser.parse_in_arena("file1.yml", yml1, &tree1); - parser.parse_in_arena("file2.yml", yml2, &tree2); - } - - CHECK(mrp.num_allocs == 0); // YAML depth not large enough to warrant a parser allocation - CHECK(mr1.alloc_size <= mr2.alloc_size); // because yml2 has more nodes -} - - -//----------------------------------------------------------------------------- - - -/** shows how to work around the static initialization order fiasco - * when using a static-duration ryml tree - * @see https://en.cppreference.com/w/cpp/language/siof */ -void sample_static_trees() -{ - // Using static trees incurs may incur a static initialization - // order problem. This happens because a default-constructed tree will - // obtain the callbacks from the current global setting, which may - // not have been initialized due to undefined static initialization - // order: - // - //static ryml::Tree tree; // ERROR! depends on ryml::get_callbacks() which may not have been initialized. - // - // To work around the issue, declare static callbacks - // to explicitly initialize the static tree: - static ryml::Callbacks callbacks = {}; // use default callback members - static ryml::Tree tree(callbacks); // OK - // now you can use the tree as normal: - ryml::parse_in_arena(R"(doe: "a deer, a female deer")", &tree); - CHECK(tree["doe"].val() == "a deer, a female deer"); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -/** demonstrates how to obtain the (zero-based) location of a node - * from a recently parsed tree */ -void sample_location_tracking() -{ - // NOTE: locations are zero-based. If you intend to show the - // location to a human user, you may want to pre-increment the line - // and column by 1. - ryml::csubstr yaml = R"({ -aa: contents, -foo: [one, [two, three]] -})"; - // A parser is needed to track locations, and it has to be - // explicitly set to do it. Location tracking is disabled by - // default. - ryml::ParserOptions opts = {}; - opts.locations(true); // enable locations, default is false - ryml::Parser parser(opts); - CHECK(parser.options().locations()); - // When locations are enabled, the first task while parsing will - // consist of building and caching (in the parser) a - // source-to-node lookup structure to accelerate location lookups. - // - // The cost of building the location accelerator is linear in the - // size of the source buffer. This increased cost is the reason - // for the opt-in requirement. When locations are disabled there - // is no cost. - // - // Building the location accelerator may trigger an allocation, - // but this can and should be avoided by reserving prior to - // parsing: - parser.reserve_locations(50u); // reserve for 50 lines - // Now the structure will be built during parsing: - ryml::Tree tree = parser.parse_in_arena("source.yml", yaml); - // Now we are ready to query the location from the parser: - ryml::Location loc = parser.location(tree.rootref()); - // As for the complexity of the query: for large buffers it is - // O(log(numlines)). For short source buffers (30 lines and less), - // it is O(numlines), as a plain linear search is faster in this - // case. - CHECK(parser.location_contents(loc).begins_with("{")); - CHECK(loc.offset == 0u); - CHECK(loc.line == 0u); - CHECK(loc.col == 0u); - // on the next call, we only pay O(log(numlines)) because the - // rebuild is already available: - loc = parser.location(tree["aa"]); - CHECK(parser.location_contents(loc).begins_with("aa")); - CHECK(loc.offset == 2u); - CHECK(loc.line == 1u); - CHECK(loc.col == 0u); - // KEYSEQ in flow style: points at the key - loc = parser.location(tree["foo"]); - CHECK(parser.location_contents(loc).begins_with("foo")); - CHECK(loc.offset == 16u); - CHECK(loc.line == 2u); - CHECK(loc.col == 0u); - loc = parser.location(tree["foo"][0]); - CHECK(parser.location_contents(loc).begins_with("one")); - CHECK(loc.line == 2u); - CHECK(loc.col == 6u); - // SEQ in flow style: location points at the opening '[' (there's no key) - loc = parser.location(tree["foo"][1]); - CHECK(parser.location_contents(loc).begins_with("[")); - CHECK(loc.line == 2u); - CHECK(loc.col == 11u); - loc = parser.location(tree["foo"][1][0]); - CHECK(parser.location_contents(loc).begins_with("two")); - CHECK(loc.line == 2u); - CHECK(loc.col == 12u); - loc = parser.location(tree["foo"][1][1]); - CHECK(parser.location_contents(loc).begins_with("three")); - CHECK(loc.line == 2u); - CHECK(loc.col == 17u); - // NOTE. The parser locations always point at the latest buffer to - // be parsed with the parser object, so they must be queried using - // the corresponding latest tree to be parsed. This means that if - // the parser is reused, earlier trees will loose the possibility - // of querying for location. It is undefined behavior to query the - // parser for the location of a node from an earlier tree: - ryml::Tree docval = parser.parse_in_arena("docval.yaml", "this is a docval"); - // From now on, none of the locations from the previous tree can - // be queried: - //loc = parser.location(tree.rootref()); // ERROR, undefined behavior - loc = parser.location(docval.rootref()); // OK. this is the latest tree from this parser - CHECK(parser.location_contents(loc).begins_with("this is a docval")); - CHECK(loc.line == 0u); - CHECK(loc.col == 0u); - - // NOTES ABOUT CONTAINER LOCATIONS - ryml::Tree tree2 = parser.parse_in_arena("containers.yaml", R"( -a new: buffer -to: be parsed -map with key: - first: value - second: value -seq with key: - - first value - - second value - - - - nested first value - - nested second value - - - nested first: value - nested second: value -)"); - // (Likewise, the docval tree can no longer be used to query.) - // - // For key-less block-style maps, the location of the container - // points at the first child's key. For example, in this case - // the root does not have a key, so its location is taken - // to be at the first child: - loc = parser.location(tree2.rootref()); - CHECK(parser.location_contents(loc).begins_with("a new")); - CHECK(loc.offset == 1u); - CHECK(loc.line == 1u); - CHECK(loc.col == 0u); - // note the first child points exactly at the same place: - loc = parser.location(tree2["a new"]); - CHECK(parser.location_contents(loc).begins_with("a new")); - CHECK(loc.offset == 1u); - CHECK(loc.line == 1u); - CHECK(loc.col == 0u); - loc = parser.location(tree2["to"]); - CHECK(parser.location_contents(loc).begins_with("to")); - CHECK(loc.line == 2u); - CHECK(loc.col == 0u); - // but of course, if the block-style map is a KEYMAP, then the - // location is the map's key, and not the first child's key: - loc = parser.location(tree2["map with key"]); - CHECK(parser.location_contents(loc).begins_with("map with key")); - CHECK(loc.line == 3u); - CHECK(loc.col == 0u); - loc = parser.location(tree2["map with key"]["first"]); - CHECK(parser.location_contents(loc).begins_with("first")); - CHECK(loc.line == 4u); - CHECK(loc.col == 2u); - loc = parser.location(tree2["map with key"]["second"]); - CHECK(parser.location_contents(loc).begins_with("second")); - CHECK(loc.line == 5u); - CHECK(loc.col == 2u); - // same thing for KEYSEQ: - loc = parser.location(tree2["seq with key"]); - CHECK(parser.location_contents(loc).begins_with("seq with key")); - CHECK(loc.line == 6u); - CHECK(loc.col == 0u); - loc = parser.location(tree2["seq with key"][0]); - CHECK(parser.location_contents(loc).begins_with("first value")); - CHECK(loc.line == 7u); - CHECK(loc.col == 4u); - loc = parser.location(tree2["seq with key"][1]); - CHECK(parser.location_contents(loc).begins_with("second value")); - CHECK(loc.line == 8u); - CHECK(loc.col == 4u); - // SEQ nested in SEQ: container location points at the first child's "- " dash - loc = parser.location(tree2["seq with key"][2]); - CHECK(parser.location_contents(loc).begins_with("- nested first value")); - CHECK(loc.line == 10u); - CHECK(loc.col == 4u); - loc = parser.location(tree2["seq with key"][2][0]); - CHECK(parser.location_contents(loc).begins_with("nested first value")); - CHECK(loc.line == 10u); - CHECK(loc.col == 6u); - // MAP nested in SEQ: same as above: point to key - loc = parser.location(tree2["seq with key"][3]); - CHECK(parser.location_contents(loc).begins_with("nested first: ")); - CHECK(loc.line == 13u); - CHECK(loc.col == 4u); - loc = parser.location(tree2["seq with key"][3][0]); - CHECK(parser.location_contents(loc).begins_with("nested first: ")); - CHECK(loc.line == 13u); - CHECK(loc.col == 4u); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -namespace /*anon*/ { -static int num_checks = 0; -static int num_failed_checks = 0; -} // namespace /*anon*/ - - -bool report_check(int line, const char *predicate, bool result) -{ - ++num_checks; - const char *msg = predicate ? "OK! " : "OK!"; - if(!result) - { - ++num_failed_checks; - msg = predicate ? "ERROR: " : "ERROR"; - } - std::cout << __FILE__ << ':' << line << ": " << msg << (predicate ? predicate : "") << std::endl; - return result; -} - - -int report_checks() -{ - std::cout << "Completed " << num_checks << " checks." << std::endl; - if(num_failed_checks) - std::cout << "ERROR: " << num_failed_checks << '/' << num_checks << " checks failed." << std::endl; - else - std::cout << "SUCCESS!" << std::endl; - return num_failed_checks; -} - - -// helper functions for sample_parse_file() - -C4_SUPPRESS_WARNING_MSVC_WITH_PUSH(4996) // fopen: this function or variable may be unsafe -/** load a file from disk and return a newly created CharContainer */ -template -size_t file_get_contents(const char *filename, CharContainer *v) -{ - ::FILE *fp = ::fopen(filename, "rb"); - C4_CHECK_MSG(fp != nullptr, "could not open file"); - ::fseek(fp, 0, SEEK_END); - long sz = ::ftell(fp); - v->resize(static_cast(sz)); - if(sz) - { - ::rewind(fp); - size_t ret = ::fread(&(*v)[0], 1, v->size(), fp); - C4_CHECK(ret == (size_t)sz); - } - ::fclose(fp); - return v->size(); -} - -/** load a file from disk into an existing CharContainer */ -template -CharContainer file_get_contents(const char *filename) -{ - CharContainer cc; - file_get_contents(filename, &cc); - return cc; -} - -/** save a buffer into a file */ -template -void file_put_contents(const char *filename, CharContainer const& v, const char* access) -{ - file_put_contents(filename, v.empty() ? "" : &v[0], v.size(), access); -} - -/** save a buffer into a file */ -void file_put_contents(const char *filename, const char *buf, size_t sz, const char* access) -{ - ::FILE *fp = ::fopen(filename, access); - C4_CHECK_MSG(fp != nullptr, "could not open file"); - ::fwrite(buf, 1, sz, fp); - ::fclose(fp); -} -C4_SUPPRESS_WARNING_MSVC_POP - -} // namespace sample diff --git a/thirdparty/ryml/samples/singleheader/amalgamate.cmake b/thirdparty/ryml/samples/singleheader/amalgamate.cmake deleted file mode 100644 index 6f2620a12..000000000 --- a/thirdparty/ryml/samples/singleheader/amalgamate.cmake +++ /dev/null @@ -1,18 +0,0 @@ -find_package(Python3 COMPONENTS Interpreter) - -# amalgamate ryml to get the single header -function(amalgamate_ryml header_dir header_file) - set(rymldir "${CMAKE_CURRENT_LIST_DIR}/../..") - set(singleheaderdir "${rymldir}/src_singleheader") - set(singleheader "${singleheaderdir}/ryml_all.hpp") - set(amscript "${rymldir}/tools/amalgamate.py") - file(GLOB_RECURSE srcfiles - LIST_DIRECTORIES FALSE - CONFIGURE_DEPENDS "${rymldir}/src") - add_custom_command(OUTPUT "${singleheader}" - COMMAND "${Python3_EXECUTABLE}" "${amscript}" "${singleheader}" - COMMENT "${Python3_EXECUTABLE} ${amscript} ${singleheader}" - DEPENDS ${srcfiles} "${amscript}" "${rymldir}/ext/c4core/cmake/amalgamate_utils.py") - set(${header_dir} "${singleheaderdir}" PARENT_SCOPE) - set(${header_file} "${singleheader}" PARENT_SCOPE) -endfunction() diff --git a/thirdparty/ryml/samples/singleheader/run.sh b/thirdparty/ryml/samples/singleheader/run.sh deleted file mode 100755 index fc2f7d858..000000000 --- a/thirdparty/ryml/samples/singleheader/run.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -x - -# take the build type from the command line, or default to release -cfg=${1:-Release} -# make sure to run from where this file is -cd $(dirname $0) -# configure the sample -cmake -S . -B ./build/$cfg -DCMAKE_BUILD_TYPE=$cfg -# build and run the sample -cmake --build ./build/$cfg --config $cfg --target run diff --git a/thirdparty/ryml/samples/singleheaderlib/lib.cpp b/thirdparty/ryml/samples/singleheaderlib/lib.cpp deleted file mode 100644 index aa33e6e17..000000000 --- a/thirdparty/ryml/samples/singleheaderlib/lib.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#define RYML_SINGLE_HDR_DEFINE_NOW -#include diff --git a/thirdparty/ryml/samples/singleheaderlib/run_shared.sh b/thirdparty/ryml/samples/singleheaderlib/run_shared.sh deleted file mode 100755 index 372a36772..000000000 --- a/thirdparty/ryml/samples/singleheaderlib/run_shared.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -x - -# take the build type from the command line, or default to release -cfg=${1:-Release} -# make sure to run from where this file is -cd $(dirname $0) -# configure the sample -cmake -S . -B ./build/$cfg-shared -DCMAKE_BUILD_TYPE=$cfg -DBUILD_SHARED_LIBS=ON -# build and run the sample -cmake --build ./build/$cfg-shared --config $cfg --target run diff --git a/thirdparty/ryml/samples/singleheaderlib/run_static.sh b/thirdparty/ryml/samples/singleheaderlib/run_static.sh deleted file mode 100755 index d0e570215..000000000 --- a/thirdparty/ryml/samples/singleheaderlib/run_static.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -x - -# take the build type from the command line, or default to release -cfg=${1:-Release} -# make sure to run from where this file is -cd $(dirname $0) -# configure the sample -cmake -S . -B ./build/$cfg-static -DCMAKE_BUILD_TYPE=$cfg -DBUILD_SHARED_LIBS=OFF -# build and run the sample -cmake --build ./build/$cfg-static --config $cfg --target run diff --git a/thirdparty/ryml/setup.py b/thirdparty/ryml/setup.py deleted file mode 100644 index 47a6be656..000000000 --- a/thirdparty/ryml/setup.py +++ /dev/null @@ -1,125 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# SPDX-License-Identifier: MIT - -import os -import shutil -import sys -import shlex - -from pathlib import Path -from distutils import log -from setuptools import setup, find_packages -from cmake_build_extension import BuildExtension, CMakeExtension - -TOP_DIR = (Path(__file__).parent).resolve() - -# where the Python library is actually found -PYTHON_DIR = "api/python" - - -def get_readme_for_python(): - with open(TOP_DIR / "README.md", "r", encoding="utf8") as fh: - marker = "" # get everything up to this tag - return fh.read().split(marker)[0] - - -def get_environment_cmake_flags(): - return shlex.split(os.environ.get("CMAKE_FLAGS", "")) - - -setup_kw = {} - -# read the module description from the README.md file -setup_kw['long_description'] = get_readme_for_python() -setup_kw['long_description_content_type'] = "text/markdown" - - -# read the package version when not in a git repository -VERSION_FILE = os.path.join(PYTHON_DIR, 'ryml', 'version.py') -if not (TOP_DIR / '.git').exists() and os.path.exists(VERSION_FILE): - exec(open(VERSION_FILE).read()) - setup_kw['version'] = version -else: - setup_kw['use_scm_version'] = { - "version_scheme": "post-release", - "local_scheme": "no-local-version", - "write_to": VERSION_FILE, - } - - -# define a CMake package -cmake_args = dict( - name='ryml.ryml', - install_prefix='', - source_dir='', - cmake_component='python', - cmake_configure_options=get_environment_cmake_flags() + [ - "-DRYML_BUILD_API:BOOL=ON", - # Force cmake to use the Python interpreter we are currently - # using to run setup.py - "-DPython3_EXECUTABLE:FILEPATH=" + sys.executable, - ], -) - - -try: - ext = CMakeExtension(**cmake_args) - log.info("Using standard CMakeExtension") -except TypeError: - log.info("Using custom CMakeExtension") - # If the CMakeExtension doesn't support `cmake_component` then we - # have to do some manual cleanup. - del cmake_args['cmake_component'] - ext = CMakeExtension(**cmake_args) - def _cleanup(path, mandatory): - if mandatory: - assert path.exists(), path - elif not path.exists(): - return - log.info("Removing everything under: %s", path) - shutil.rmtree(path) - _BuildExtension = BuildExtension - class BuildExtension(_BuildExtension): - def build_extension(self, ext): - _BuildExtension.build_extension(self, ext) - ext_dir = Path(self.get_ext_fullpath(ext.name)).parent.absolute() - cmake_install_prefix = ext_dir / ext.install_prefix - assert cmake_install_prefix.exists(), cmake_install_prefix - try: - _cleanup(cmake_install_prefix / "lib", mandatory=True) - _cleanup(cmake_install_prefix / "include", mandatory=True) - # Windows only - _cleanup(cmake_install_prefix / "cmake", mandatory=False) - except: - log.info('Found following installed files:') - for f in cmake_install_prefix.rglob("*"): - log.info(' - %s', f) - raise - -log.info('Compiling with CMake cfg:\n' + '\n'.join(ext.cmake_configure_options)) - -setup( - name='rapidyaml', - description='Rapid YAML - a library to parse and emit YAML, and do it fast', - url='https://github.com/biojppm/rapidyaml', - license='MIT', - license_files=['LICENSE.txt'], - author="Joao Paulo Magalhaes", - author_email="dev@jpmag.me", - # Package contents control - cmdclass={"build_ext": BuildExtension,}, - package_dir={"": PYTHON_DIR}, - packages=['ryml'], - ext_modules=[ext], - include_package_data=True, - # Requirements - python_requires=">=3.6", - setup_requires=[ - 'setuptools_scm', - 'setuptools-git', - 'setuptools', - ], - # Extra arguments - **setup_kw, -) diff --git a/thirdparty/ryml/src/c4/yml/common.cpp b/thirdparty/ryml/src/c4/yml/common.cpp deleted file mode 100644 index 75b873549..000000000 --- a/thirdparty/ryml/src/c4/yml/common.cpp +++ /dev/null @@ -1,117 +0,0 @@ -#include "c4/yml/common.hpp" - -#ifndef RYML_NO_DEFAULT_CALLBACKS -# include -# include -#endif // RYML_NO_DEFAULT_CALLBACKS - -namespace c4 { -namespace yml { - -namespace { -Callbacks s_default_callbacks; -} // anon namespace - -#ifndef RYML_NO_DEFAULT_CALLBACKS -void report_error_impl(const char* msg, size_t length, Location loc, FILE *f) -{ - if(!f) - f = stderr; - if(loc) - { - if(!loc.name.empty()) - { - fwrite(loc.name.str, 1, loc.name.len, f); - fputc(':', f); - } - fprintf(f, "%zu:", loc.line); - if(loc.col) - fprintf(f, "%zu:", loc.col); - if(loc.offset) - fprintf(f, " (%zuB):", loc.offset); - } - fprintf(f, "%.*s\n", (int)length, msg); - fflush(f); -} - -void error_impl(const char* msg, size_t length, Location loc, void * /*user_data*/) -{ - report_error_impl(msg, length, loc, nullptr); - ::abort(); -} - -void* allocate_impl(size_t length, void * /*hint*/, void * /*user_data*/) -{ - void *mem = ::malloc(length); - if(mem == nullptr) - { - const char msg[] = "could not allocate memory"; - error_impl(msg, sizeof(msg)-1, {}, nullptr); - } - return mem; -} - -void free_impl(void *mem, size_t /*length*/, void * /*user_data*/) -{ - ::free(mem); -} -#endif // RYML_NO_DEFAULT_CALLBACKS - - - -Callbacks::Callbacks() - : - m_user_data(nullptr), - #ifndef RYML_NO_DEFAULT_CALLBACKS - m_allocate(allocate_impl), - m_free(free_impl), - m_error(error_impl) - #else - m_allocate(nullptr), - m_free(nullptr), - m_error(nullptr) - #endif -{ -} - -Callbacks::Callbacks(void *user_data, pfn_allocate alloc_, pfn_free free_, pfn_error error_) - : - m_user_data(user_data), - #ifndef RYML_NO_DEFAULT_CALLBACKS - m_allocate(alloc_ ? alloc_ : allocate_impl), - m_free(free_ ? free_ : free_impl), - m_error(error_ ? error_ : error_impl) - #else - m_allocate(alloc_), - m_free(free_), - m_error(error_) - #endif -{ - C4_CHECK(m_allocate); - C4_CHECK(m_free); - C4_CHECK(m_error); -} - - -void set_callbacks(Callbacks const& c) -{ - s_default_callbacks = c; -} - -Callbacks const& get_callbacks() -{ - return s_default_callbacks; -} - -void reset_callbacks() -{ - set_callbacks(Callbacks()); -} - -void error(const char *msg, size_t msg_len, Location loc) -{ - s_default_callbacks.m_error(msg, msg_len, loc, s_default_callbacks.m_user_data); -} - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/src/c4/yml/common.hpp b/thirdparty/ryml/src/c4/yml/common.hpp deleted file mode 100644 index 21aef6ba2..000000000 --- a/thirdparty/ryml/src/c4/yml/common.hpp +++ /dev/null @@ -1,278 +0,0 @@ -#ifndef _C4_YML_COMMON_HPP_ -#define _C4_YML_COMMON_HPP_ - -#include -#include -#include - - -#ifndef RYML_USE_ASSERT -# define RYML_USE_ASSERT C4_USE_ASSERT -#endif - - -#if RYML_USE_ASSERT -# define RYML_ASSERT(cond) RYML_CHECK(cond) -# define RYML_ASSERT_MSG(cond, msg) RYML_CHECK_MSG(cond, msg) -#else -# define RYML_ASSERT(cond) -# define RYML_ASSERT_MSG(cond, msg) -#endif - - -#if defined(NDEBUG) || defined(C4_NO_DEBUG_BREAK) -# define RYML_DEBUG_BREAK() -#else -# define RYML_DEBUG_BREAK() \ - { \ - if(c4::get_error_flags() & c4::ON_ERROR_DEBUGBREAK) \ - { \ - C4_DEBUG_BREAK(); \ - } \ - } -#endif - - -#define RYML_CHECK(cond) \ - do { \ - if(!(cond)) \ - { \ - RYML_DEBUG_BREAK() \ - c4::yml::error("check failed: " #cond, c4::yml::Location(__FILE__, __LINE__, 0)); \ - } \ - } while(0) - -#define RYML_CHECK_MSG(cond, msg) \ - do \ - { \ - if(!(cond)) \ - { \ - RYML_DEBUG_BREAK() \ - c4::yml::error(msg ": check failed: " #cond, c4::yml::Location(__FILE__, __LINE__, 0)); \ - } \ - } while(0) - - -#if C4_CPP >= 14 -# define RYML_DEPRECATED(msg) [[deprecated(msg)]] -#else -# if defined(_MSC_VER) -# define RYML_DEPRECATED(msg) __declspec(deprecated(msg)) -# else // defined(__GNUC__) || defined(__clang__) -# define RYML_DEPRECATED(msg) __attribute__((deprecated(msg))) -# endif -#endif - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -namespace c4 { -namespace yml { - -enum : size_t { - /** a null position */ - npos = size_t(-1), - /** an index to none */ - NONE = size_t(-1) -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -//! holds a position into a source buffer -struct RYML_EXPORT LineCol -{ - //! number of bytes from the beginning of the source buffer - size_t offset; - //! line - size_t line; - //! column - size_t col; - - LineCol() : offset(), line(), col() {} - //! construct from line and column - LineCol(size_t l, size_t c) : offset(0), line(l), col(c) {} - //! construct from offset, line and column - LineCol(size_t o, size_t l, size_t c) : offset(o), line(l), col(c) {} -}; - - -//! a source file position -struct RYML_EXPORT Location : public LineCol -{ - csubstr name; - - operator bool () const { return !name.empty() || line != 0 || offset != 0; } - - Location() : LineCol(), name() {} - Location( size_t l, size_t c) : LineCol{ l, c}, name( ) {} - Location( csubstr n, size_t l, size_t c) : LineCol{ l, c}, name(n) {} - Location( csubstr n, size_t b, size_t l, size_t c) : LineCol{b, l, c}, name(n) {} - Location(const char *n, size_t l, size_t c) : LineCol{ l, c}, name(to_csubstr(n)) {} - Location(const char *n, size_t b, size_t l, size_t c) : LineCol{b, l, c}, name(to_csubstr(n)) {} -}; - - -//----------------------------------------------------------------------------- - -/** the type of the function used to report errors. This function must - * interrupt execution, either by raising an exception or calling - * std::abort(). - * - * @warning the error callback must never return: it must either abort - * or throw an exception. Otherwise, the parser will enter into an - * infinite loop, or the program may crash. */ -using pfn_error = void (*)(const char* msg, size_t msg_len, Location location, void *user_data); -/** the type of the function used to allocate memory */ -using pfn_allocate = void* (*)(size_t len, void* hint, void *user_data); -/** the type of the function used to free memory */ -using pfn_free = void (*)(void* mem, size_t size, void *user_data); - -/** trigger an error: call the current error callback. */ -RYML_EXPORT void error(const char *msg, size_t msg_len, Location loc); -/** @overload error */ -inline void error(const char *msg, size_t msg_len) -{ - error(msg, msg_len, Location{}); -} -/** @overload error */ -template -inline void error(const char (&msg)[N], Location loc) -{ - error(msg, N-1, loc); -} -/** @overload error */ -template -inline void error(const char (&msg)[N]) -{ - error(msg, N-1, Location{}); -} - -//----------------------------------------------------------------------------- - -/** a c-style callbacks class - * - * @warning the error callback must never return: it must either abort - * or throw an exception. Otherwise, the parser will enter into an - * infinite loop, or the program may crash. */ -struct RYML_EXPORT Callbacks -{ - void * m_user_data; - pfn_allocate m_allocate; - pfn_free m_free; - pfn_error m_error; - - Callbacks(); - Callbacks(void *user_data, pfn_allocate alloc, pfn_free free, pfn_error error_); - - bool operator!= (Callbacks const& that) const { return !operator==(that); } - bool operator== (Callbacks const& that) const - { - return (m_user_data == that.m_user_data && - m_allocate == that.m_allocate && - m_free == that.m_free && - m_error == that.m_error); - } -}; - -/** set the global callbacks. - * - * @warning the error callback must never return: it must either abort - * or throw an exception. Otherwise, the parser will enter into an - * infinite loop, or the program may crash. */ -RYML_EXPORT void set_callbacks(Callbacks const& c); -/// get the global callbacks -RYML_EXPORT Callbacks const& get_callbacks(); -/// set the global callbacks back to their defaults -RYML_EXPORT void reset_callbacks(); - -/// @cond dev -#define _RYML_CB_ERR(cb, msg_literal) \ -do \ -{ \ - const char msg[] = msg_literal; \ - RYML_DEBUG_BREAK() \ - (cb).m_error(msg, sizeof(msg), c4::yml::Location(__FILE__, 0, __LINE__, 0), (cb).m_user_data); \ -} while(0) -#define _RYML_CB_CHECK(cb, cond) \ - do \ - { \ - if(!(cond)) \ - { \ - const char msg[] = "check failed: " #cond; \ - RYML_DEBUG_BREAK() \ - (cb).m_error(msg, sizeof(msg), c4::yml::Location(__FILE__, 0, __LINE__, 0), (cb).m_user_data); \ - } \ - } while(0) -#ifdef RYML_USE_ASSERT -#define _RYML_CB_ASSERT(cb, cond) _RYML_CB_CHECK((cb), (cond)) -#else -#define _RYML_CB_ASSERT(cb, cond) do {} while(0) -#endif -#define _RYML_CB_ALLOC_HINT(cb, T, num, hint) (T*) (cb).m_allocate((num) * sizeof(T), (hint), (cb).m_user_data) -#define _RYML_CB_ALLOC(cb, T, num) _RYML_CB_ALLOC_HINT((cb), (T), (num), nullptr) -#define _RYML_CB_FREE(cb, buf, T, num) \ - do { \ - (cb).m_free((buf), (num) * sizeof(T), (cb).m_user_data); \ - (buf) = nullptr; \ - } while(0) - - - -namespace detail { -template -struct _charconstant_t - : public std::conditional::value, - std::integral_constant, - std::integral_constant>::type -{}; -#define _RYML_CHCONST(signedval, unsignedval) ::c4::yml::detail::_charconstant_t::value -} // namespace detail - - -namespace detail { -struct _SubstrWriter -{ - substr buf; - size_t pos; - _SubstrWriter(substr buf_, size_t pos_=0) : buf(buf_), pos(pos_) {} - void append(csubstr s) - { - C4_ASSERT(!s.overlaps(buf)); - if(pos + s.len <= buf.len) - memcpy(buf.str + pos, s.str, s.len); - pos += s.len; - } - void append(char c) - { - if(pos < buf.len) - buf.str[pos] = c; - ++pos; - } - void append_n(char c, size_t numtimes) - { - if(pos + numtimes < buf.len) - memset(buf.str + pos, c, numtimes); - pos += numtimes; - } - size_t slack() const { return pos <= buf.len ? buf.len - pos : 0; } - size_t excess() const { return pos > buf.len ? pos - buf.len : 0; } - //! get the part written so far - csubstr curr() const { return pos <= buf.len ? buf.first(pos) : buf; } - //! get the part that is still free to write to (the remainder) - substr rem() { return pos < buf.len ? buf.sub(pos) : buf.last(0); } - - size_t advance(size_t more) { pos += more; return pos; } -}; -} // namespace detail - -/// @endcond - -} // namespace yml -} // namespace c4 - -#endif /* _C4_YML_COMMON_HPP_ */ diff --git a/thirdparty/ryml/src/c4/yml/detail/checks.hpp b/thirdparty/ryml/src/c4/yml/detail/checks.hpp deleted file mode 100644 index 39b49e856..000000000 --- a/thirdparty/ryml/src/c4/yml/detail/checks.hpp +++ /dev/null @@ -1,200 +0,0 @@ -#ifndef C4_YML_DETAIL_CHECKS_HPP_ -#define C4_YML_DETAIL_CHECKS_HPP_ - -#include "c4/yml/tree.hpp" - -#ifdef __clang__ -# pragma clang diagnostic push -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wtype-limits" // error: comparison of unsigned expression >= 0 is always true -#elif defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable: 4296/*expression is always 'boolean_value'*/) -#endif - -namespace c4 { -namespace yml { - - -void check_invariants(Tree const& t, size_t node=NONE); -void check_free_list(Tree const& t); -void check_arena(Tree const& t); - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -inline void check_invariants(Tree const& t, size_t node) -{ - if(node == NONE) - { - if(t.size() == 0) return; - node = t.root_id(); - } - - auto const& n = *t._p(node); -#ifdef RYML_DBG - if(n.m_first_child != NONE || n.m_last_child != NONE) - { - printf("check(%zu): fc=%zu lc=%zu\n", node, n.m_first_child, n.m_last_child); - } - else - { - printf("check(%zu)\n", node); - } -#endif - - C4_CHECK(n.m_parent != node); - if(n.m_parent == NONE) - { - C4_CHECK(t.is_root(node)); - } - else //if(n.m_parent != NONE) - { - C4_CHECK(t.has_child(n.m_parent, node)); - - auto const& p = *t._p(n.m_parent); - if(n.m_prev_sibling == NONE) - { - C4_CHECK(p.m_first_child == node); - C4_CHECK(t.first_sibling(node) == node); - } - else - { - C4_CHECK(p.m_first_child != node); - C4_CHECK(t.first_sibling(node) != node); - } - - if(n.m_next_sibling == NONE) - { - C4_CHECK(p.m_last_child == node); - C4_CHECK(t.last_sibling(node) == node); - } - else - { - C4_CHECK(p.m_last_child != node); - C4_CHECK(t.last_sibling(node) != node); - } - } - - C4_CHECK(n.m_first_child != node); - C4_CHECK(n.m_last_child != node); - if(n.m_first_child != NONE || n.m_last_child != NONE) - { - C4_CHECK(n.m_first_child != NONE); - C4_CHECK(n.m_last_child != NONE); - } - - C4_CHECK(n.m_prev_sibling != node); - C4_CHECK(n.m_next_sibling != node); - if(n.m_prev_sibling != NONE) - { - C4_CHECK(t._p(n.m_prev_sibling)->m_next_sibling == node); - C4_CHECK(t._p(n.m_prev_sibling)->m_prev_sibling != node); - } - if(n.m_next_sibling != NONE) - { - C4_CHECK(t._p(n.m_next_sibling)->m_prev_sibling == node); - C4_CHECK(t._p(n.m_next_sibling)->m_next_sibling != node); - } - - size_t count = 0; - for(size_t i = n.m_first_child; i != NONE; i = t.next_sibling(i)) - { -#ifdef RYML_DBG - printf("check(%zu): descend to child[%zu]=%zu\n", node, count, i); -#endif - auto const& ch = *t._p(i); - C4_CHECK(ch.m_parent == node); - C4_CHECK(ch.m_next_sibling != i); - ++count; - } - C4_CHECK(count == t.num_children(node)); - - if(n.m_prev_sibling == NONE && n.m_next_sibling == NONE) - { - if(n.m_parent != NONE) - { - C4_CHECK(t.num_children(n.m_parent) == 1); - C4_CHECK(t.num_siblings(node) == 1); - } - } - - if(node == t.root_id()) - { - C4_CHECK(t.size() == t.m_size); - C4_CHECK(t.capacity() == t.m_cap); - C4_CHECK(t.m_cap == t.m_size + t.slack()); - check_free_list(t); - check_arena(t); - } - - for(size_t i = t.first_child(node); i != NONE; i = t.next_sibling(i)) - { - check_invariants(t, i); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -inline void check_free_list(Tree const& t) -{ - if(t.m_free_head == NONE) - { - C4_CHECK(t.m_free_tail == t.m_free_head); - return; - } - - C4_CHECK(t.m_free_head >= 0 && t.m_free_head < t.m_cap); - C4_CHECK(t.m_free_tail >= 0 && t.m_free_tail < t.m_cap); - - auto const& head = *t._p(t.m_free_head); - //auto const& tail = *t._p(t.m_free_tail); - - //C4_CHECK(head.m_prev_sibling == NONE); - //C4_CHECK(tail.m_next_sibling == NONE); - - size_t count = 0; - for(size_t i = t.m_free_head, prev = NONE; i != NONE; i = t._p(i)->m_next_sibling) - { - auto const& elm = *t._p(i); - if(&elm != &head) - { - C4_CHECK(elm.m_prev_sibling == prev); - } - prev = i; - ++count; - } - C4_CHECK(count == t.slack()); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -inline void check_arena(Tree const& t) -{ - C4_CHECK(t.m_arena.len == 0 || (t.m_arena_pos >= 0 && t.m_arena_pos <= t.m_arena.len)); - C4_CHECK(t.arena_size() == t.m_arena_pos); - C4_CHECK(t.arena_slack() + t.m_arena_pos == t.m_arena.len); -} - - -} /* namespace yml */ -} /* namespace c4 */ - -#ifdef __clang__ -# pragma clang diagnostic pop -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#elif defined(_MSC_VER) -# pragma warning(pop) -#endif - -#endif /* C4_YML_DETAIL_CHECKS_HPP_ */ diff --git a/thirdparty/ryml/src/c4/yml/detail/parser_dbg.hpp b/thirdparty/ryml/src/c4/yml/detail/parser_dbg.hpp deleted file mode 100644 index 457f1700d..000000000 --- a/thirdparty/ryml/src/c4/yml/detail/parser_dbg.hpp +++ /dev/null @@ -1,137 +0,0 @@ -#ifndef _C4_YML_DETAIL_PARSER_DBG_HPP_ -#define _C4_YML_DETAIL_PARSER_DBG_HPP_ - -#ifndef _C4_YML_COMMON_HPP_ -#include "../common.hpp" -#endif -#include - -//----------------------------------------------------------------------------- -// some debugging scaffolds - -#if defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable: 4068/*unknown pragma*/) -#endif - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunknown-pragmas" -//#pragma GCC diagnostic ignored "-Wpragma-system-header-outside-header" -#pragma GCC system_header - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Werror" -#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" - -// some debugging scaffolds -#ifdef RYML_DBG -#include -namespace c4 { -inline void _dbg_dumper(csubstr s) { fwrite(s.str, 1, s.len, stdout); }; -template -void _dbg_printf(c4::csubstr fmt, Args&& ...args) -{ - static char writebuf[256]; - auto results = c4::format_dump_resume<&_dbg_dumper>(writebuf, fmt, std::forward(args)...); - // resume writing if the results failed to fit the buffer - if(C4_UNLIKELY(results.bufsize > sizeof(writebuf))) // bufsize will be that of the largest element serialized. Eg int(1), will require 1 byte. - { - results = format_dump_resume<&_dbg_dumper>(results, writebuf, fmt, std::forward(args)...); - if(C4_UNLIKELY(results.bufsize > sizeof(writebuf))) - { - results = format_dump_resume<&_dbg_dumper>(results, writebuf, fmt, std::forward(args)...); - } - } -} -} // namespace c4 - -# define _c4dbgt(fmt, ...) this->_dbg ("{}:{}: " fmt , __FILE__, __LINE__, ## __VA_ARGS__) -# define _c4dbgpf(fmt, ...) _dbg_printf("{}:{}: " fmt "\n", __FILE__, __LINE__, ## __VA_ARGS__) -# define _c4dbgp(msg) _dbg_printf("{}:{}: " msg "\n", __FILE__, __LINE__ ) -# define _c4dbgq(msg) _dbg_printf(msg "\n") -# define _c4err(fmt, ...) \ - do { if(c4::is_debugger_attached()) { C4_DEBUG_BREAK(); } \ - this->_err("ERROR:\n" "{}:{}: " fmt, __FILE__, __LINE__, ## __VA_ARGS__); } while(0) -#else -# define _c4dbgt(fmt, ...) -# define _c4dbgpf(fmt, ...) -# define _c4dbgp(msg) -# define _c4dbgq(msg) -# define _c4err(fmt, ...) \ - do { if(c4::is_debugger_attached()) { C4_DEBUG_BREAK(); } \ - this->_err("ERROR: " fmt, ## __VA_ARGS__); } while(0) -#endif - -#define _c4prsp(sp) sp -#define _c4presc(s) __c4presc(s.str, s.len) -inline c4::csubstr _c4prc(const char &C4_RESTRICT c) -{ - switch(c) - { - case '\n': return c4::csubstr("\\n"); - case '\t': return c4::csubstr("\\t"); - case '\0': return c4::csubstr("\\0"); - case '\r': return c4::csubstr("\\r"); - case '\f': return c4::csubstr("\\f"); - case '\b': return c4::csubstr("\\b"); - case '\v': return c4::csubstr("\\v"); - case '\a': return c4::csubstr("\\a"); - default: return c4::csubstr(&c, 1); - } -} -inline void __c4presc(const char *s, size_t len) -{ - size_t prev = 0; - for(size_t i = 0; i < len; ++i) - { - switch(s[i]) - { - case '\n' : fwrite(s+prev, 1, i-prev, stdout); putchar('\\'); putchar('n'); putchar('\n'); prev = i+1; break; - case '\t' : fwrite(s+prev, 1, i-prev, stdout); putchar('\\'); putchar('t'); prev = i+1; break; - case '\0' : fwrite(s+prev, 1, i-prev, stdout); putchar('\\'); putchar('0'); prev = i+1; break; - case '\r' : fwrite(s+prev, 1, i-prev, stdout); putchar('\\'); putchar('r'); prev = i+1; break; - case '\f' : fwrite(s+prev, 1, i-prev, stdout); putchar('\\'); putchar('f'); prev = i+1; break; - case '\b' : fwrite(s+prev, 1, i-prev, stdout); putchar('\\'); putchar('b'); prev = i+1; break; - case '\v' : fwrite(s+prev, 1, i-prev, stdout); putchar('\\'); putchar('v'); prev = i+1; break; - case '\a' : fwrite(s+prev, 1, i-prev, stdout); putchar('\\'); putchar('a'); prev = i+1; break; - case '\x1b': fwrite(s+prev, 1, i-prev, stdout); putchar('\\'); putchar('e'); prev = i+1; break; - case -0x3e/*0xc2u*/: - if(i+1 < len) - { - if(s[i+1] == -0x60/*0xa0u*/) - { - fwrite(s+prev, 1, i-prev, stdout); putchar('\\'); putchar('_'); prev = i+2; ++i; - } - else if(s[i+1] == -0x7b/*0x85u*/) - { - fwrite(s+prev, 1, i-prev, stdout); putchar('\\'); putchar('N'); prev = i+2; ++i; - } - break; - } - case -0x1e/*0xe2u*/: - if(i+2 < len && s[i+1] == -0x80/*0x80u*/) - { - if(s[i+2] == -0x58/*0xa8u*/) - { - fwrite(s+prev, 1, i-prev, stdout); putchar('\\'); putchar('L'); prev = i+3; i += 2; - } - else if(s[i+2] == -0x57/*0xa9u*/) - { - fwrite(s+prev, 1, i-prev, stdout); putchar('\\'); putchar('P'); prev = i+3; i += 2; - } - break; - } - } - } - fwrite(s + prev, 1, len - prev, stdout); -} - -#pragma clang diagnostic pop -#pragma GCC diagnostic pop - -#if defined(_MSC_VER) -# pragma warning(pop) -#endif - - -#endif /* _C4_YML_DETAIL_PARSER_DBG_HPP_ */ diff --git a/thirdparty/ryml/src/c4/yml/detail/print.hpp b/thirdparty/ryml/src/c4/yml/detail/print.hpp deleted file mode 100644 index f88dc251d..000000000 --- a/thirdparty/ryml/src/c4/yml/detail/print.hpp +++ /dev/null @@ -1,128 +0,0 @@ -#ifndef C4_YML_DETAIL_PRINT_HPP_ -#define C4_YML_DETAIL_PRINT_HPP_ - -#include "c4/yml/tree.hpp" -#include "c4/yml/node.hpp" - - -namespace c4 { -namespace yml { - - -inline size_t print_node(Tree const& p, size_t node, int level, size_t count, bool print_children) -{ - printf("[%zd]%*s[%zd] %p", count, (2*level), "", node, (void*)p.get(node)); - if(p.is_root(node)) - { - printf(" [ROOT]"); - } - printf(" %s:", p.type_str(node)); - if(p.has_key(node)) - { - if(p.has_key_anchor(node)) - { - csubstr ka = p.key_anchor(node); - printf(" &%.*s", (int)ka.len, ka.str); - } - if(p.has_key_tag(node)) - { - csubstr kt = p.key_tag(node); - csubstr k = p.key(node); - printf(" %.*s '%.*s'", (int)kt.len, kt.str, (int)k.len, k.str); - } - else - { - csubstr k = p.key(node); - printf(" '%.*s'", (int)k.len, k.str); - } - } - else - { - RYML_ASSERT( ! p.has_key_tag(node)); - } - if(p.has_val(node)) - { - if(p.has_val_tag(node)) - { - csubstr vt = p.val_tag(node); - csubstr v = p.val(node); - printf(" %.*s '%.*s'", (int)vt.len, vt.str, (int)v.len, v.str); - } - else - { - csubstr v = p.val(node); - printf(" '%.*s'", (int)v.len, v.str); - } - } - else - { - if(p.has_val_tag(node)) - { - csubstr vt = p.val_tag(node); - printf(" %.*s", (int)vt.len, vt.str); - } - } - if(p.has_val_anchor(node)) - { - auto &a = p.val_anchor(node); - printf(" valanchor='&%.*s'", (int)a.len, a.str); - } - printf(" (%zd sibs)", p.num_siblings(node)); - - ++count; - - if(p.is_container(node)) - { - printf(" %zd children:\n", p.num_children(node)); - if(print_children) - { - for(size_t i = p.first_child(node); i != NONE; i = p.next_sibling(i)) - { - count = print_node(p, i, level+1, count, print_children); - } - } - } - else - { - printf("\n"); - } - - return count; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -inline void print_node(ConstNodeRef const& p, int level=0) -{ - print_node(*p.tree(), p.id(), level, 0, true); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -inline size_t print_tree(Tree const& p, size_t node=NONE) -{ - printf("--------------------------------------\n"); - size_t ret = 0; - if(!p.empty()) - { - if(node == NONE) - node = p.root_id(); - ret = print_node(p, node, 0, 0, true); - } - printf("#nodes=%zd vs #printed=%zd\n", p.size(), ret); - printf("--------------------------------------\n"); - return ret; -} - - -} /* namespace yml */ -} /* namespace c4 */ - - -#endif /* C4_YML_DETAIL_PRINT_HPP_ */ diff --git a/thirdparty/ryml/src/c4/yml/detail/stack.hpp b/thirdparty/ryml/src/c4/yml/detail/stack.hpp deleted file mode 100644 index 95677ae27..000000000 --- a/thirdparty/ryml/src/c4/yml/detail/stack.hpp +++ /dev/null @@ -1,274 +0,0 @@ -#ifndef _C4_YML_DETAIL_STACK_HPP_ -#define _C4_YML_DETAIL_STACK_HPP_ - -#ifndef _C4_YML_COMMON_HPP_ -#include "../common.hpp" -#endif - -#ifdef RYML_DBG -# include -#endif - -#include - -namespace c4 { -namespace yml { -namespace detail { - -/** A lightweight contiguous stack with SSO. This avoids a dependency on std. */ -template -class stack -{ - static_assert(std::is_trivially_copyable::value, "T must be trivially copyable"); - static_assert(std::is_trivially_destructible::value, "T must be trivially destructible"); - - enum : size_t { sso_size = N }; - -public: - - T m_buf[N]; - T * m_stack; - size_t m_size; - size_t m_capacity; - Callbacks m_callbacks; - -public: - - constexpr static bool is_contiguous() { return true; } - - stack(Callbacks const& cb) - : m_buf() - , m_stack(m_buf) - , m_size(0) - , m_capacity(N) - , m_callbacks(cb) {} - stack() : stack(get_callbacks()) {} - ~stack() - { - _free(); - } - - stack(stack const& that) noexcept : stack(that.m_callbacks) - { - resize(that.m_size); - _cp(&that); - } - - stack(stack &&that) noexcept : stack(that.m_callbacks) - { - _mv(&that); - } - - stack& operator= (stack const& that) noexcept - { - _cb(that.m_callbacks); - resize(that.m_size); - _cp(&that); - return *this; - } - - stack& operator= (stack &&that) noexcept - { - _cb(that.m_callbacks); - _mv(&that); - return *this; - } - -public: - - size_t size() const { return m_size; } - size_t empty() const { return m_size == 0; } - size_t capacity() const { return m_capacity; } - - void clear() - { - m_size = 0; - } - - void resize(size_t sz) - { - reserve(sz); - m_size = sz; - } - - void reserve(size_t sz); - - void push(T const& C4_RESTRICT n) - { - RYML_ASSERT((const char*)&n + sizeof(T) < (const char*)m_stack || &n > m_stack + m_capacity); - if(m_size == m_capacity) - { - size_t cap = m_capacity == 0 ? N : 2 * m_capacity; - reserve(cap); - } - m_stack[m_size] = n; - ++m_size; - } - - void push_top() - { - RYML_ASSERT(m_size > 0); - if(m_size == m_capacity) - { - size_t cap = m_capacity == 0 ? N : 2 * m_capacity; - reserve(cap); - } - m_stack[m_size] = m_stack[m_size - 1]; - ++m_size; - } - - T const& C4_RESTRICT pop() - { - RYML_ASSERT(m_size > 0); - --m_size; - return m_stack[m_size]; - } - - C4_ALWAYS_INLINE T const& C4_RESTRICT top() const { RYML_ASSERT(m_size > 0); return m_stack[m_size - 1]; } - C4_ALWAYS_INLINE T & C4_RESTRICT top() { RYML_ASSERT(m_size > 0); return m_stack[m_size - 1]; } - - C4_ALWAYS_INLINE T const& C4_RESTRICT bottom() const { RYML_ASSERT(m_size > 0); return m_stack[0]; } - C4_ALWAYS_INLINE T & C4_RESTRICT bottom() { RYML_ASSERT(m_size > 0); return m_stack[0]; } - - C4_ALWAYS_INLINE T const& C4_RESTRICT top(size_t i) const { RYML_ASSERT(i < m_size); return m_stack[m_size - 1 - i]; } - C4_ALWAYS_INLINE T & C4_RESTRICT top(size_t i) { RYML_ASSERT(i < m_size); return m_stack[m_size - 1 - i]; } - - C4_ALWAYS_INLINE T const& C4_RESTRICT bottom(size_t i) const { RYML_ASSERT(i < m_size); return m_stack[i]; } - C4_ALWAYS_INLINE T & C4_RESTRICT bottom(size_t i) { RYML_ASSERT(i < m_size); return m_stack[i]; } - - C4_ALWAYS_INLINE T const& C4_RESTRICT operator[](size_t i) const { RYML_ASSERT(i < m_size); return m_stack[i]; } - C4_ALWAYS_INLINE T & C4_RESTRICT operator[](size_t i) { RYML_ASSERT(i < m_size); return m_stack[i]; } - -public: - - using iterator = T *; - using const_iterator = T const *; - - iterator begin() { return m_stack; } - iterator end () { return m_stack + m_size; } - - const_iterator begin() const { return (const_iterator)m_stack; } - const_iterator end () const { return (const_iterator)m_stack + m_size; } - -public: - void _free(); - void _cp(stack const* C4_RESTRICT that); - void _mv(stack * that); - void _cb(Callbacks const& cb); -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -template -void stack::reserve(size_t sz) -{ - if(sz <= m_size) - return; - if(sz <= N) - { - m_stack = m_buf; - m_capacity = N; - return; - } - T *buf = (T*) m_callbacks.m_allocate(sz * sizeof(T), m_stack, m_callbacks.m_user_data); - memcpy(buf, m_stack, m_size * sizeof(T)); - if(m_stack != m_buf) - { - m_callbacks.m_free(m_stack, m_capacity * sizeof(T), m_callbacks.m_user_data); - } - m_stack = buf; - m_capacity = sz; -} - - -//----------------------------------------------------------------------------- - -template -void stack::_free() -{ - RYML_ASSERT(m_stack != nullptr); // this structure cannot be memset() to zero - if(m_stack != m_buf) - { - m_callbacks.m_free(m_stack, m_capacity * sizeof(T), m_callbacks.m_user_data); - m_stack = m_buf; - m_size = N; - m_capacity = N; - } - else - { - RYML_ASSERT(m_capacity == N); - } -} - - -//----------------------------------------------------------------------------- - -template -void stack::_cp(stack const* C4_RESTRICT that) -{ - if(that->m_stack != that->m_buf) - { - RYML_ASSERT(that->m_capacity > N); - RYML_ASSERT(that->m_size <= that->m_capacity); - } - else - { - RYML_ASSERT(that->m_capacity <= N); - RYML_ASSERT(that->m_size <= that->m_capacity); - } - memcpy(m_stack, that->m_stack, that->m_size * sizeof(T)); - m_size = that->m_size; - m_capacity = that->m_size < N ? N : that->m_size; - m_callbacks = that->m_callbacks; -} - - -//----------------------------------------------------------------------------- - -template -void stack::_mv(stack * that) -{ - if(that->m_stack != that->m_buf) - { - RYML_ASSERT(that->m_capacity > N); - RYML_ASSERT(that->m_size <= that->m_capacity); - m_stack = that->m_stack; - } - else - { - RYML_ASSERT(that->m_capacity <= N); - RYML_ASSERT(that->m_size <= that->m_capacity); - memcpy(m_buf, that->m_buf, that->m_size * sizeof(T)); - m_stack = m_buf; - } - m_size = that->m_size; - m_capacity = that->m_capacity; - m_callbacks = that->m_callbacks; - // make sure no deallocation happens on destruction - RYML_ASSERT(that->m_stack != m_buf); - that->m_stack = that->m_buf; - that->m_capacity = N; - that->m_size = 0; -} - - -//----------------------------------------------------------------------------- - -template -void stack::_cb(Callbacks const& cb) -{ - if(cb != m_callbacks) - { - _free(); - m_callbacks = cb; - } -} - -} // namespace detail -} // namespace yml -} // namespace c4 - -#endif /* _C4_YML_DETAIL_STACK_HPP_ */ diff --git a/thirdparty/ryml/src/c4/yml/emit.def.hpp b/thirdparty/ryml/src/c4/yml/emit.def.hpp deleted file mode 100644 index d262a9e2a..000000000 --- a/thirdparty/ryml/src/c4/yml/emit.def.hpp +++ /dev/null @@ -1,960 +0,0 @@ -#ifndef _C4_YML_EMIT_DEF_HPP_ -#define _C4_YML_EMIT_DEF_HPP_ - -#ifndef _C4_YML_EMIT_HPP_ -#include "c4/yml/emit.hpp" -#endif - -namespace c4 { -namespace yml { - -template -substr Emitter::emit_as(EmitType_e type, Tree const& t, size_t id, bool error_on_excess) -{ - if(t.empty()) - { - _RYML_CB_ASSERT(t.callbacks(), id == NONE); - return {}; - } - _RYML_CB_CHECK(t.callbacks(), id < t.size()); - m_tree = &t; - if(type == EMIT_YAML) - _emit_yaml(id); - else if(type == EMIT_JSON) - _do_visit_json(id); - else - _RYML_CB_ERR(m_tree->callbacks(), "unknown emit type"); - return this->Writer::_get(error_on_excess); -} - -template -substr Emitter::emit_as(EmitType_e type, Tree const& t, bool error_on_excess) -{ - if(t.empty()) - return {}; - return this->emit_as(type, t, t.root_id(), error_on_excess); -} - -template -substr Emitter::emit_as(EmitType_e type, ConstNodeRef const& n, bool error_on_excess) -{ - _RYML_CB_CHECK(n.tree()->callbacks(), n.valid()); - return this->emit_as(type, *n.tree(), n.id(), error_on_excess); -} - - -//----------------------------------------------------------------------------- - -template -void Emitter::_emit_yaml(size_t id) -{ - // save branches in the visitor by doing the initial stream/doc - // logic here, sparing the need to check stream/val/keyval inside - // the visitor functions - auto dispatch = [this](size_t node){ - NodeType ty = m_tree->type(node); - if(ty.marked_flow_sl()) - _do_visit_flow_sl(node, 0); - else if(ty.marked_flow_ml()) - _do_visit_flow_ml(node, 0); - else - { - _do_visit_block(node, 0); - } - }; - if(!m_tree->is_root(id)) - { - if(m_tree->is_container(id) && !m_tree->type(id).marked_flow()) - { - size_t ilevel = 0; - if(m_tree->has_key(id)) - { - this->Writer::_do_write(m_tree->key(id)); - this->Writer::_do_write(":\n"); - ++ilevel; - } - _do_visit_block_container(id, ilevel, ilevel); - return; - } - } - - auto *btd = m_tree->tag_directives().b; - auto *etd = m_tree->tag_directives().e; - auto write_tag_directives = [&btd, etd, this](size_t next_node){ - auto end = btd; - while(end < etd) - { - if(end->next_node_id > next_node) - break; - ++end; - } - for( ; btd != end; ++btd) - { - if(next_node != m_tree->first_child(m_tree->parent(next_node))) - this->Writer::_do_write("...\n"); - this->Writer::_do_write("%TAG "); - this->Writer::_do_write(btd->handle); - this->Writer::_do_write(' '); - this->Writer::_do_write(btd->prefix); - this->Writer::_do_write('\n'); - } - }; - if(m_tree->is_stream(id)) - { - if(m_tree->first_child(id) != NONE) - write_tag_directives(m_tree->first_child(id)); - for(size_t child = m_tree->first_child(id); child != NONE; child = m_tree->next_sibling(child)) - { - dispatch(child); - if(m_tree->next_sibling(child) != NONE) - write_tag_directives(m_tree->next_sibling(child)); - } - } - else if(m_tree->is_container(id)) - { - dispatch(id); - } - else if(m_tree->is_doc(id)) - { - _RYML_CB_ASSERT(m_tree->callbacks(), !m_tree->is_container(id)); // checked above - _RYML_CB_ASSERT(m_tree->callbacks(), m_tree->is_val(id)); // so it must be a val - _write_doc(id); - } - else if(m_tree->is_keyval(id)) - { - _writek(id, 0); - this->Writer::_do_write(": "); - _writev(id, 0); - if(!m_tree->type(id).marked_flow()) - this->Writer::_do_write('\n'); - } - else if(m_tree->is_val(id)) - { - //this->Writer::_do_write("- "); - _writev(id, 0); - if(!m_tree->type(id).marked_flow()) - this->Writer::_do_write('\n'); - } - else if(m_tree->type(id) == NOTYPE) - { - ; - } - else - { - _RYML_CB_ERR(m_tree->callbacks(), "unknown type"); - } -} - -template -void Emitter::_write_doc(size_t id) -{ - RYML_ASSERT(m_tree->is_doc(id)); - if(!m_tree->is_root(id)) - { - RYML_ASSERT(m_tree->is_stream(m_tree->parent(id))); - this->Writer::_do_write("---"); - } - if(!m_tree->has_val(id)) // this is more frequent - { - if(m_tree->has_val_tag(id)) - { - if(!m_tree->is_root(id)) - this->Writer::_do_write(' '); - _write_tag(m_tree->val_tag(id)); - } - if(m_tree->has_val_anchor(id)) - { - if(!m_tree->is_root(id)) - this->Writer::_do_write(' '); - this->Writer::_do_write('&'); - this->Writer::_do_write(m_tree->val_anchor(id)); - } - } - else // docval - { - RYML_ASSERT(m_tree->has_val(id)); - RYML_ASSERT(!m_tree->has_key(id)); - if(!m_tree->is_root(id)) - this->Writer::_do_write(' '); - _writev(id, 0); - } - this->Writer::_do_write('\n'); -} - -template -void Emitter::_do_visit_flow_sl(size_t node, size_t ilevel) -{ - RYML_ASSERT(!m_tree->is_stream(node)); - RYML_ASSERT(m_tree->is_container(node) || m_tree->is_doc(node)); - RYML_ASSERT(m_tree->is_root(node) || (m_tree->parent_is_map(node) || m_tree->parent_is_seq(node))); - - if(m_tree->is_doc(node)) - { - _write_doc(node); - if(!m_tree->has_children(node)) - return; - } - else if(m_tree->is_container(node)) - { - RYML_ASSERT(m_tree->is_map(node) || m_tree->is_seq(node)); - - bool spc = false; // write a space - - if(m_tree->has_key(node)) - { - _writek(node, ilevel); - this->Writer::_do_write(':'); - spc = true; - } - - if(m_tree->has_val_tag(node)) - { - if(spc) - this->Writer::_do_write(' '); - _write_tag(m_tree->val_tag(node)); - spc = true; - } - - if(m_tree->has_val_anchor(node)) - { - if(spc) - this->Writer::_do_write(' '); - this->Writer::_do_write('&'); - this->Writer::_do_write(m_tree->val_anchor(node)); - spc = true; - } - - if(spc) - this->Writer::_do_write(' '); - - if(m_tree->is_map(node)) - { - this->Writer::_do_write('{'); - } - else - { - _RYML_CB_ASSERT(m_tree->callbacks(), m_tree->is_seq(node)); - this->Writer::_do_write('['); - } - } // container - - for(size_t child = m_tree->first_child(node), count = 0; child != NONE; child = m_tree->next_sibling(child)) - { - if(count++) - this->Writer::_do_write(','); - if(m_tree->is_keyval(child)) - { - _writek(child, ilevel); - this->Writer::_do_write(": "); - _writev(child, ilevel); - } - else if(m_tree->is_val(child)) - { - _writev(child, ilevel); - } - else - { - // with single-line flow, we can never go back to block - _do_visit_flow_sl(child, ilevel + 1); - } - } - - if(m_tree->is_map(node)) - { - this->Writer::_do_write('}'); - } - else if(m_tree->is_seq(node)) - { - this->Writer::_do_write(']'); - } -} - -template -void Emitter::_do_visit_flow_ml(size_t id, size_t ilevel, size_t do_indent) -{ - C4_UNUSED(id); - C4_UNUSED(ilevel); - C4_UNUSED(do_indent); - RYML_CHECK(false/*not implemented*/); -} - -template -void Emitter::_do_visit_block_container(size_t node, size_t next_level, size_t do_indent) -{ - RepC ind = indent_to(do_indent * next_level); - - if(m_tree->is_seq(node)) - { - for(size_t child = m_tree->first_child(node); child != NONE; child = m_tree->next_sibling(child)) - { - _RYML_CB_ASSERT(m_tree->callbacks(), !m_tree->has_key(child)); - if(m_tree->is_val(child)) - { - this->Writer::_do_write(ind); - this->Writer::_do_write("- "); - _writev(child, next_level); - this->Writer::_do_write('\n'); - } - else - { - _RYML_CB_ASSERT(m_tree->callbacks(), m_tree->is_container(child)); - NodeType ty = m_tree->type(child); - if(ty.marked_flow_sl()) - { - this->Writer::_do_write(ind); - this->Writer::_do_write("- "); - _do_visit_flow_sl(child, 0u); - this->Writer::_do_write('\n'); - } - else if(ty.marked_flow_ml()) - { - this->Writer::_do_write(ind); - this->Writer::_do_write("- "); - _do_visit_flow_ml(child, next_level, do_indent); - this->Writer::_do_write('\n'); - } - else - { - _do_visit_block(child, next_level, do_indent); - } - } - do_indent = true; - ind = indent_to(do_indent * next_level); - } - } - else // map - { - _RYML_CB_ASSERT(m_tree->callbacks(), m_tree->is_map(node)); - for(size_t ich = m_tree->first_child(node); ich != NONE; ich = m_tree->next_sibling(ich)) - { - _RYML_CB_ASSERT(m_tree->callbacks(), m_tree->has_key(ich)); - if(m_tree->is_keyval(ich)) - { - this->Writer::_do_write(ind); - _writek(ich, next_level); - this->Writer::_do_write(": "); - _writev(ich, next_level); - this->Writer::_do_write('\n'); - } - else - { - _RYML_CB_ASSERT(m_tree->callbacks(), m_tree->is_container(ich)); - NodeType ty = m_tree->type(ich); - if(ty.marked_flow_sl()) - { - this->Writer::_do_write(ind); - _do_visit_flow_sl(ich, 0u); - this->Writer::_do_write('\n'); - } - else if(ty.marked_flow_ml()) - { - this->Writer::_do_write(ind); - _do_visit_flow_ml(ich, 0u); - this->Writer::_do_write('\n'); - } - else - { - _do_visit_block(ich, next_level, do_indent); - } - } - do_indent = true; - ind = indent_to(do_indent * next_level); - } - } -} - -template -void Emitter::_do_visit_block(size_t node, size_t ilevel, size_t do_indent) -{ - RYML_ASSERT(!m_tree->is_stream(node)); - RYML_ASSERT(m_tree->is_container(node) || m_tree->is_doc(node)); - RYML_ASSERT(m_tree->is_root(node) || (m_tree->parent_is_map(node) || m_tree->parent_is_seq(node))); - RepC ind = indent_to(do_indent * ilevel); - - if(m_tree->is_doc(node)) - { - _write_doc(node); - if(!m_tree->has_children(node)) - return; - } - else if(m_tree->is_container(node)) - { - RYML_ASSERT(m_tree->is_map(node) || m_tree->is_seq(node)); - - bool spc = false; // write a space - bool nl = false; // write a newline - - if(m_tree->has_key(node)) - { - this->Writer::_do_write(ind); - _writek(node, ilevel); - this->Writer::_do_write(':'); - spc = true; - } - else if(!m_tree->is_root(node)) - { - this->Writer::_do_write(ind); - this->Writer::_do_write('-'); - spc = true; - } - - if(m_tree->has_val_tag(node)) - { - if(spc) - this->Writer::_do_write(' '); - _write_tag(m_tree->val_tag(node)); - spc = true; - nl = true; - } - - if(m_tree->has_val_anchor(node)) - { - if(spc) - this->Writer::_do_write(' '); - this->Writer::_do_write('&'); - this->Writer::_do_write(m_tree->val_anchor(node)); - spc = true; - nl = true; - } - - if(m_tree->has_children(node)) - { - if(m_tree->has_key(node)) - nl = true; - else - if(!m_tree->is_root(node) && !nl) - spc = true; - } - else - { - if(m_tree->is_seq(node)) - this->Writer::_do_write(" []\n"); - else if(m_tree->is_map(node)) - this->Writer::_do_write(" {}\n"); - return; - } - - if(spc && !nl) - this->Writer::_do_write(' '); - - do_indent = 0; - if(nl) - { - this->Writer::_do_write('\n'); - do_indent = 1; - } - } // container - - size_t next_level = ilevel + 1; - if(m_tree->is_root(node) || m_tree->is_doc(node)) - next_level = ilevel; // do not indent at top level - - _do_visit_block_container(node, next_level, do_indent); -} - -template -void Emitter::_do_visit_json(size_t id) -{ - _RYML_CB_CHECK(m_tree->callbacks(), !m_tree->is_stream(id)); // JSON does not have streams - if(m_tree->is_keyval(id)) - { - _writek_json(id); - this->Writer::_do_write(": "); - _writev_json(id); - } - else if(m_tree->is_val(id)) - { - _writev_json(id); - } - else if(m_tree->is_container(id)) - { - if(m_tree->has_key(id)) - { - _writek_json(id); - this->Writer::_do_write(": "); - } - if(m_tree->is_seq(id)) - this->Writer::_do_write('['); - else if(m_tree->is_map(id)) - this->Writer::_do_write('{'); - } // container - - for(size_t ich = m_tree->first_child(id); ich != NONE; ich = m_tree->next_sibling(ich)) - { - if(ich != m_tree->first_child(id)) - this->Writer::_do_write(','); - _do_visit_json(ich); - } - - if(m_tree->is_seq(id)) - this->Writer::_do_write(']'); - else if(m_tree->is_map(id)) - this->Writer::_do_write('}'); -} - -template -void Emitter::_write(NodeScalar const& C4_RESTRICT sc, NodeType flags, size_t ilevel) -{ - if( ! sc.tag.empty()) - { - _write_tag(sc.tag); - this->Writer::_do_write(' '); - } - if(flags.has_anchor()) - { - RYML_ASSERT(flags.is_ref() != flags.has_anchor()); - RYML_ASSERT( ! sc.anchor.empty()); - this->Writer::_do_write('&'); - this->Writer::_do_write(sc.anchor); - this->Writer::_do_write(' '); - } - else if(flags.is_ref()) - { - if(sc.anchor != "<<") - this->Writer::_do_write('*'); - this->Writer::_do_write(sc.anchor); - return; - } - - // ensure the style flags only have one of KEY or VAL - _RYML_CB_ASSERT(m_tree->callbacks(), ((flags & (_WIP_KEY_STYLE|_WIP_VAL_STYLE)) == 0) || (((flags&_WIP_KEY_STYLE) == 0) != ((flags&_WIP_VAL_STYLE) == 0))); - - auto style_marks = flags & (_WIP_KEY_STYLE|_WIP_VAL_STYLE); - if(style_marks & (_WIP_KEY_LITERAL|_WIP_VAL_LITERAL)) - { - _write_scalar_literal(sc.scalar, ilevel, flags.has_key()); - } - else if(style_marks & (_WIP_KEY_FOLDED|_WIP_VAL_FOLDED)) - { - _write_scalar_folded(sc.scalar, ilevel, flags.has_key()); - } - else if(style_marks & (_WIP_KEY_SQUO|_WIP_VAL_SQUO)) - { - _write_scalar_squo(sc.scalar, ilevel); - } - else if(style_marks & (_WIP_KEY_DQUO|_WIP_VAL_DQUO)) - { - _write_scalar_dquo(sc.scalar, ilevel); - } - else if(style_marks & (_WIP_KEY_PLAIN|_WIP_VAL_PLAIN)) - { - _write_scalar_plain(sc.scalar, ilevel); - } - else if(!style_marks) - { - size_t first_non_nl = sc.scalar.first_not_of('\n'); - bool all_newlines = first_non_nl == npos; - bool has_leading_ws = (!all_newlines) && sc.scalar.sub(first_non_nl).begins_with_any(" \t"); - bool do_literal = ((!sc.scalar.empty() && all_newlines) || (has_leading_ws && !sc.scalar.trim(' ').empty())); - if(do_literal) - { - _write_scalar_literal(sc.scalar, ilevel, flags.has_key(), /*explicit_indentation*/has_leading_ws); - } - else - { - for(size_t i = 0; i < sc.scalar.len; ++i) - { - if(sc.scalar.str[i] == '\n') - { - _write_scalar_literal(sc.scalar, ilevel, flags.has_key(), /*explicit_indentation*/has_leading_ws); - goto wrote_special; - } - // todo: check for escaped characters requiring double quotes - } - _write_scalar(sc.scalar, flags.is_quoted()); - wrote_special: - ; - } - } - else - { - _RYML_CB_ERR(m_tree->callbacks(), "not implemented"); - } -} -template -void Emitter::_write_json(NodeScalar const& C4_RESTRICT sc, NodeType flags) -{ - if(C4_UNLIKELY( ! sc.tag.empty())) - _RYML_CB_ERR(m_tree->callbacks(), "JSON does not have tags"); - if(C4_UNLIKELY(flags.has_anchor())) - _RYML_CB_ERR(m_tree->callbacks(), "JSON does not have anchors"); - _write_scalar_json(sc.scalar, flags.has_key(), flags.is_quoted()); -} - -#define _rymlindent_nextline() for(size_t lv = 0; lv < ilevel+1; ++lv) { this->Writer::_do_write(' '); this->Writer::_do_write(' '); } - -template -void Emitter::_write_scalar_literal(csubstr s, size_t ilevel, bool explicit_key, bool explicit_indentation) -{ - if(explicit_key) - this->Writer::_do_write("? "); - csubstr trimmed = s.trimr("\n\r"); - size_t numnewlines_at_end = s.len - trimmed.len - s.sub(trimmed.len).count('\r'); - // - if(!explicit_indentation) - this->Writer::_do_write('|'); - else - this->Writer::_do_write("|2"); - // - if(numnewlines_at_end > 1 || (trimmed.len == 0 && s.len > 0)/*only newlines*/) - this->Writer::_do_write("+\n"); - else if(numnewlines_at_end == 1) - this->Writer::_do_write('\n'); - else - this->Writer::_do_write("-\n"); - // - if(trimmed.len) - { - size_t pos = 0; // tracks the last character that was already written - for(size_t i = 0; i < trimmed.len; ++i) - { - if(trimmed[i] != '\n') - continue; - // write everything up to this point - csubstr since_pos = trimmed.range(pos, i+1); // include the newline - _rymlindent_nextline() - this->Writer::_do_write(since_pos); - pos = i+1; // already written - } - if(pos < trimmed.len) - { - _rymlindent_nextline() - this->Writer::_do_write(trimmed.sub(pos)); - } - if(numnewlines_at_end) - { - this->Writer::_do_write('\n'); - --numnewlines_at_end; - } - } - for(size_t i = 0; i < numnewlines_at_end; ++i) - { - _rymlindent_nextline() - if(i+1 < numnewlines_at_end || explicit_key) - this->Writer::_do_write('\n'); - } - if(explicit_key && !numnewlines_at_end) - this->Writer::_do_write('\n'); -} - -template -void Emitter::_write_scalar_folded(csubstr s, size_t ilevel, bool explicit_key) -{ - if(explicit_key) - { - this->Writer::_do_write("? "); - } - RYML_ASSERT(s.find("\r") == csubstr::npos); - csubstr trimmed = s.trimr('\n'); - size_t numnewlines_at_end = s.len - trimmed.len; - if(numnewlines_at_end == 0) - { - this->Writer::_do_write(">-\n"); - } - else if(numnewlines_at_end == 1) - { - this->Writer::_do_write(">\n"); - } - else if(numnewlines_at_end > 1) - { - this->Writer::_do_write(">+\n"); - } - if(trimmed.len) - { - size_t pos = 0; // tracks the last character that was already written - for(size_t i = 0; i < trimmed.len; ++i) - { - if(trimmed[i] != '\n') - continue; - // write everything up to this point - csubstr since_pos = trimmed.range(pos, i+1); // include the newline - pos = i+1; // because of the newline - _rymlindent_nextline() - this->Writer::_do_write(since_pos); - this->Writer::_do_write('\n'); // write the newline twice - } - if(pos < trimmed.len) - { - _rymlindent_nextline() - this->Writer::_do_write(trimmed.sub(pos)); - } - if(numnewlines_at_end) - { - this->Writer::_do_write('\n'); - --numnewlines_at_end; - } - } - for(size_t i = 0; i < numnewlines_at_end; ++i) - { - _rymlindent_nextline() - if(i+1 < numnewlines_at_end || explicit_key) - this->Writer::_do_write('\n'); - } - if(explicit_key && !numnewlines_at_end) - this->Writer::_do_write('\n'); -} - -template -void Emitter::_write_scalar_squo(csubstr s, size_t ilevel) -{ - size_t pos = 0; // tracks the last character that was already written - this->Writer::_do_write('\''); - for(size_t i = 0; i < s.len; ++i) - { - if(s[i] == '\n') - { - csubstr sub = s.range(pos, i+1); - this->Writer::_do_write(sub); // write everything up to (including) this char - this->Writer::_do_write('\n'); // write the character again - if(i + 1 < s.len) - _rymlindent_nextline() // indent the next line - pos = i+1; - } - else if(s[i] == '\'') - { - csubstr sub = s.range(pos, i+1); - this->Writer::_do_write(sub); // write everything up to (including) this char - this->Writer::_do_write('\''); // write the character again - pos = i+1; - } - } - // write missing characters at the end of the string - if(pos < s.len) - this->Writer::_do_write(s.sub(pos)); - this->Writer::_do_write('\''); -} - -template -void Emitter::_write_scalar_dquo(csubstr s, size_t ilevel) -{ - size_t pos = 0; // tracks the last character that was already written - this->Writer::_do_write('"'); - for(size_t i = 0; i < s.len; ++i) - { - const char curr = s.str[i]; - if(curr == '"' || curr == '\\') - { - csubstr sub = s.range(pos, i); - this->Writer::_do_write(sub); // write everything up to (excluding) this char - this->Writer::_do_write('\\'); // write the escape - this->Writer::_do_write(curr); // write the char - pos = i+1; - } - else if(s[i] == '\n') - { - csubstr sub = s.range(pos, i+1); - this->Writer::_do_write(sub); // write everything up to (including) this newline - this->Writer::_do_write('\n'); // write the newline again - if(i + 1 < s.len) - _rymlindent_nextline() // indent the next line - pos = i+1; - if(i+1 < s.len) // escape leading whitespace after the newline - { - const char next = s.str[i+1]; - if(next == ' ' || next == '\t') - this->Writer::_do_write('\\'); - } - } - else if(curr == ' ' || curr == '\t') - { - // escape trailing whitespace before a newline - size_t next = s.first_not_of(" \t\r", i); - if(next != npos && s[next] == '\n') - { - csubstr sub = s.range(pos, i); - this->Writer::_do_write(sub); // write everything up to (excluding) this char - this->Writer::_do_write('\\'); // escape the whitespace - pos = i; - } - } - else if(C4_UNLIKELY(curr == '\r')) - { - csubstr sub = s.range(pos, i); - this->Writer::_do_write(sub); // write everything up to (excluding) this char - this->Writer::_do_write("\\r"); // write the escaped char - pos = i+1; - } - } - // write missing characters at the end of the string - if(pos < s.len) - { - csubstr sub = s.sub(pos); - this->Writer::_do_write(sub); - } - this->Writer::_do_write('"'); -} - -template -void Emitter::_write_scalar_plain(csubstr s, size_t ilevel) -{ - size_t pos = 0; // tracks the last character that was already written - for(size_t i = 0; i < s.len; ++i) - { - const char curr = s.str[i]; - if(curr == '\n') - { - csubstr sub = s.range(pos, i+1); - this->Writer::_do_write(sub); // write everything up to (including) this newline - this->Writer::_do_write('\n'); // write the newline again - if(i + 1 < s.len) - _rymlindent_nextline() // indent the next line - pos = i+1; - } - } - // write missing characters at the end of the string - if(pos < s.len) - { - csubstr sub = s.sub(pos); - this->Writer::_do_write(sub); - } -} - -#undef _rymlindent_nextline - -template -void Emitter::_write_scalar(csubstr s, bool was_quoted) -{ - // this block of code needed to be moved to before the needs_quotes - // assignment to work around a g++ optimizer bug where (s.str != nullptr) - // was evaluated as true even if s.str was actually a nullptr (!!!) - if(s.len == size_t(0)) - { - if(was_quoted || s.str != nullptr) - this->Writer::_do_write("''"); - return; - } - - const bool needs_quotes = ( - was_quoted - || - ( - ( ! s.is_number()) - && - ( - // has leading whitespace - // looks like reference or anchor - // would be treated as a directive - // see https://www.yaml.info/learn/quote.html#noplain - s.begins_with_any(" \n\t\r*&%@`") - || - s.begins_with("<<") - || - // has trailing whitespace - s.ends_with_any(" \n\t\r") - || - // has special chars - (s.first_of("#:-?,\n{}[]'\"") != npos) - ) - ) - ); - - if( ! needs_quotes) - { - this->Writer::_do_write(s); - } - else - { - const bool has_dquotes = s.first_of( '"') != npos; - const bool has_squotes = s.first_of('\'') != npos; - if(!has_squotes && has_dquotes) - { - this->Writer::_do_write('\''); - this->Writer::_do_write(s); - this->Writer::_do_write('\''); - } - else if(has_squotes && !has_dquotes) - { - RYML_ASSERT(s.count('\n') == 0); - this->Writer::_do_write('"'); - this->Writer::_do_write(s); - this->Writer::_do_write('"'); - } - else - { - _write_scalar_squo(s, /*FIXME FIXME FIXME*/0); - } - } -} -template -void Emitter::_write_scalar_json(csubstr s, bool as_key, bool use_quotes) -{ - if((!use_quotes) - // json keys require quotes - && (!as_key) - && ( - // do not quote special cases - (s == "true" || s == "false" || s == "null") - || ( - // do not quote numbers - (s.is_number() - && ( - // quote integral numbers if they have a leading 0 - // https://github.com/biojppm/rapidyaml/issues/291 - (!(s.len > 1 && s.begins_with('0'))) - // do not quote reals with leading 0 - // https://github.com/biojppm/rapidyaml/issues/313 - || (s.find('.') != csubstr::npos) )) - ) - ) - ) - { - this->Writer::_do_write(s); - } - else - { - size_t pos = 0; - this->Writer::_do_write('"'); - for(size_t i = 0; i < s.len; ++i) - { - switch(s.str[i]) - { - case '"': - this->Writer ::_do_write(s.range(pos, i)); - this->Writer ::_do_write("\\\""); - pos = i + 1; - break; - case '\n': - this->Writer ::_do_write(s.range(pos, i)); - this->Writer ::_do_write("\\n"); - pos = i + 1; - break; - case '\t': - this->Writer ::_do_write(s.range(pos, i)); - this->Writer ::_do_write("\\t"); - pos = i + 1; - break; - case '\\': - this->Writer ::_do_write(s.range(pos, i)); - this->Writer ::_do_write("\\\\"); - pos = i + 1; - break; - case '\r': - this->Writer ::_do_write(s.range(pos, i)); - this->Writer ::_do_write("\\r"); - pos = i + 1; - break; - case '\b': - this->Writer ::_do_write(s.range(pos, i)); - this->Writer ::_do_write("\\b"); - pos = i + 1; - break; - case '\f': - this->Writer ::_do_write(s.range(pos, i)); - this->Writer ::_do_write("\\f"); - pos = i + 1; - break; - } - } - if(pos < s.len) - { - csubstr sub = s.sub(pos); - this->Writer::_do_write(sub); - } - this->Writer::_do_write('"'); - } -} - -} // namespace yml -} // namespace c4 - -#endif /* _C4_YML_EMIT_DEF_HPP_ */ diff --git a/thirdparty/ryml/src/c4/yml/emit.hpp b/thirdparty/ryml/src/c4/yml/emit.hpp deleted file mode 100644 index c7cdd2a1a..000000000 --- a/thirdparty/ryml/src/c4/yml/emit.hpp +++ /dev/null @@ -1,490 +0,0 @@ -#ifndef _C4_YML_EMIT_HPP_ -#define _C4_YML_EMIT_HPP_ - -#ifndef _C4_YML_WRITER_HPP_ -#include "./writer.hpp" -#endif - -#ifndef _C4_YML_TREE_HPP_ -#include "./tree.hpp" -#endif - -#ifndef _C4_YML_NODE_HPP_ -#include "./node.hpp" -#endif - - -#define RYML_DEPRECATE_EMIT \ - RYML_DEPRECATED("use emit_yaml() instead. See https://github.com/biojppm/rapidyaml/issues/120") -#ifdef emit -#error "emit is defined, likely from a Qt include. This will cause a compilation error. See https://github.com/biojppm/rapidyaml/issues/120" -#endif -#define RYML_DEPRECATE_EMITRS \ - RYML_DEPRECATED("use emitrs_yaml() instead. See https://github.com/biojppm/rapidyaml/issues/120") - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -namespace c4 { -namespace yml { - -template class Emitter; - -template -using EmitterOStream = Emitter>; -using EmitterFile = Emitter; -using EmitterBuf = Emitter; - -typedef enum { - EMIT_YAML = 0, - EMIT_JSON = 1 -} EmitType_e; - - -/** mark a tree or node to be emitted as json */ -struct as_json -{ - Tree const* tree; - size_t node; - as_json(Tree const& t) : tree(&t), node(t.empty() ? NONE : t.root_id()) {} - as_json(Tree const& t, size_t id) : tree(&t), node(id) {} - as_json(ConstNodeRef const& n) : tree(n.tree()), node(n.id()) {} -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -template -class Emitter : public Writer -{ -public: - - using Writer::Writer; - - /** emit! - * - * When writing to a buffer, returns a substr of the emitted YAML. - * If the given buffer has insufficient space, the returned span will - * be null and its size will be the needed space. No writes are done - * after the end of the buffer. - * - * When writing to a file, the returned substr will be null, but its - * length will be set to the number of bytes written. */ - substr emit_as(EmitType_e type, Tree const& t, size_t id, bool error_on_excess); - /** emit starting at the root node */ - substr emit_as(EmitType_e type, Tree const& t, bool error_on_excess=true); - /** emit the given node */ - substr emit_as(EmitType_e type, ConstNodeRef const& n, bool error_on_excess=true); - -private: - - Tree const* C4_RESTRICT m_tree; - - void _emit_yaml(size_t id); - void _do_visit_flow_sl(size_t id, size_t ilevel=0); - void _do_visit_flow_ml(size_t id, size_t ilevel=0, size_t do_indent=1); - void _do_visit_block(size_t id, size_t ilevel=0, size_t do_indent=1); - void _do_visit_block_container(size_t id, size_t next_level, size_t do_indent); - void _do_visit_json(size_t id); - -private: - - void _write(NodeScalar const& C4_RESTRICT sc, NodeType flags, size_t level); - void _write_json(NodeScalar const& C4_RESTRICT sc, NodeType flags); - - void _write_doc(size_t id); - void _write_scalar(csubstr s, bool was_quoted); - void _write_scalar_json(csubstr s, bool as_key, bool was_quoted); - void _write_scalar_literal(csubstr s, size_t level, bool as_key, bool explicit_indentation=false); - void _write_scalar_folded(csubstr s, size_t level, bool as_key); - void _write_scalar_squo(csubstr s, size_t level); - void _write_scalar_dquo(csubstr s, size_t level); - void _write_scalar_plain(csubstr s, size_t level); - - void _write_tag(csubstr tag) - { - if(!tag.begins_with('!')) - this->Writer::_do_write('!'); - this->Writer::_do_write(tag); - } - - enum : type_bits { - _keysc = (KEY|KEYREF|KEYANCH|KEYQUO|_WIP_KEY_STYLE) | ~(VAL|VALREF|VALANCH|VALQUO|_WIP_VAL_STYLE), - _valsc = ~(KEY|KEYREF|KEYANCH|KEYQUO|_WIP_KEY_STYLE) | (VAL|VALREF|VALANCH|VALQUO|_WIP_VAL_STYLE), - _keysc_json = (KEY) | ~(VAL), - _valsc_json = ~(KEY) | (VAL), - }; - - C4_ALWAYS_INLINE void _writek(size_t id, size_t level) { _write(m_tree->keysc(id), m_tree->_p(id)->m_type.type & ~_valsc, level); } - C4_ALWAYS_INLINE void _writev(size_t id, size_t level) { _write(m_tree->valsc(id), m_tree->_p(id)->m_type.type & ~_keysc, level); } - - C4_ALWAYS_INLINE void _writek_json(size_t id) { _write_json(m_tree->keysc(id), m_tree->_p(id)->m_type.type & ~(VAL)); } - C4_ALWAYS_INLINE void _writev_json(size_t id) { _write_json(m_tree->valsc(id), m_tree->_p(id)->m_type.type & ~(KEY)); } - -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -/** emit YAML to the given file. A null file defaults to stdout. - * Return the number of bytes written. */ -inline size_t emit_yaml(Tree const& t, size_t id, FILE *f) -{ - EmitterFile em(f); - return em.emit_as(EMIT_YAML, t, id, /*error_on_excess*/true).len; -} -RYML_DEPRECATE_EMIT inline size_t emit(Tree const& t, size_t id, FILE *f) -{ - return emit_yaml(t, id, f); -} - -/** emit JSON to the given file. A null file defaults to stdout. - * Return the number of bytes written. */ -inline size_t emit_json(Tree const& t, size_t id, FILE *f) -{ - EmitterFile em(f); - return em.emit_as(EMIT_JSON, t, id, /*error_on_excess*/true).len; -} - - -/** emit YAML to the given file. A null file defaults to stdout. - * Return the number of bytes written. - * @overload */ -inline size_t emit_yaml(Tree const& t, FILE *f=nullptr) -{ - EmitterFile em(f); - return em.emit_as(EMIT_YAML, t, /*error_on_excess*/true).len; -} -RYML_DEPRECATE_EMIT inline size_t emit(Tree const& t, FILE *f=nullptr) -{ - return emit_yaml(t, f); -} - -/** emit JSON to the given file. A null file defaults to stdout. - * Return the number of bytes written. - * @overload */ -inline size_t emit_json(Tree const& t, FILE *f=nullptr) -{ - EmitterFile em(f); - return em.emit_as(EMIT_JSON, t, /*error_on_excess*/true).len; -} - - -/** emit YAML to the given file. A null file defaults to stdout. - * Return the number of bytes written. - * @overload */ -inline size_t emit_yaml(ConstNodeRef const& r, FILE *f=nullptr) -{ - EmitterFile em(f); - return em.emit_as(EMIT_YAML, r, /*error_on_excess*/true).len; -} -RYML_DEPRECATE_EMIT inline size_t emit(ConstNodeRef const& r, FILE *f=nullptr) -{ - return emit_yaml(r, f); -} - -/** emit JSON to the given file. A null file defaults to stdout. - * Return the number of bytes written. - * @overload */ -inline size_t emit_json(ConstNodeRef const& r, FILE *f=nullptr) -{ - EmitterFile em(f); - return em.emit_as(EMIT_JSON, r, /*error_on_excess*/true).len; -} - - -//----------------------------------------------------------------------------- - -/** emit YAML to an STL-like ostream */ -template -inline OStream& operator<< (OStream& s, Tree const& t) -{ - EmitterOStream em(s); - em.emit_as(EMIT_YAML, t); - return s; -} - -/** emit YAML to an STL-like ostream - * @overload */ -template -inline OStream& operator<< (OStream& s, ConstNodeRef const& n) -{ - EmitterOStream em(s); - em.emit_as(EMIT_YAML, n); - return s; -} - -/** emit json to an STL-like stream */ -template -inline OStream& operator<< (OStream& s, as_json const& j) -{ - EmitterOStream em(s); - em.emit_as(EMIT_JSON, *j.tree, j.node, true); - return s; -} - - -//----------------------------------------------------------------------------- - - -/** emit YAML to the given buffer. Return a substr trimmed to the emitted YAML. - * @param error_on_excess Raise an error if the space in the buffer is insufficient. - * @overload */ -inline substr emit_yaml(Tree const& t, size_t id, substr buf, bool error_on_excess=true) -{ - EmitterBuf em(buf); - return em.emit_as(EMIT_YAML, t, id, error_on_excess); -} -RYML_DEPRECATE_EMIT inline substr emit(Tree const& t, size_t id, substr buf, bool error_on_excess=true) -{ - return emit_yaml(t, id, buf, error_on_excess); -} - -/** emit JSON to the given buffer. Return a substr trimmed to the emitted JSON. - * @param error_on_excess Raise an error if the space in the buffer is insufficient. - * @overload */ -inline substr emit_json(Tree const& t, size_t id, substr buf, bool error_on_excess=true) -{ - EmitterBuf em(buf); - return em.emit_as(EMIT_JSON, t, id, error_on_excess); -} - - -/** emit YAML to the given buffer. Return a substr trimmed to the emitted YAML. - * @param error_on_excess Raise an error if the space in the buffer is insufficient. - * @overload */ -inline substr emit_yaml(Tree const& t, substr buf, bool error_on_excess=true) -{ - EmitterBuf em(buf); - return em.emit_as(EMIT_YAML, t, error_on_excess); -} -RYML_DEPRECATE_EMIT inline substr emit(Tree const& t, substr buf, bool error_on_excess=true) -{ - return emit_yaml(t, buf, error_on_excess); -} - -/** emit JSON to the given buffer. Return a substr trimmed to the emitted JSON. - * @param error_on_excess Raise an error if the space in the buffer is insufficient. - * @overload */ -inline substr emit_json(Tree const& t, substr buf, bool error_on_excess=true) -{ - EmitterBuf em(buf); - return em.emit_as(EMIT_JSON, t, error_on_excess); -} - - -/** emit YAML to the given buffer. Return a substr trimmed to the emitted YAML. - * @param error_on_excess Raise an error if the space in the buffer is insufficient. - * @overload - */ -inline substr emit_yaml(ConstNodeRef const& r, substr buf, bool error_on_excess=true) -{ - EmitterBuf em(buf); - return em.emit_as(EMIT_YAML, r, error_on_excess); -} -RYML_DEPRECATE_EMIT inline substr emit(ConstNodeRef const& r, substr buf, bool error_on_excess=true) -{ - return emit_yaml(r, buf, error_on_excess); -} - -/** emit JSON to the given buffer. Return a substr trimmed to the emitted JSON. - * @param error_on_excess Raise an error if the space in the buffer is insufficient. - * @overload - */ -inline substr emit_json(ConstNodeRef const& r, substr buf, bool error_on_excess=true) -{ - EmitterBuf em(buf); - return em.emit_as(EMIT_JSON, r, error_on_excess); -} - - -//----------------------------------------------------------------------------- - -/** emit+resize: emit YAML to the given std::string/std::vector-like - * container, resizing it as needed to fit the emitted YAML. */ -template -substr emitrs_yaml(Tree const& t, size_t id, CharOwningContainer * cont) -{ - substr buf = to_substr(*cont); - substr ret = emit_yaml(t, id, buf, /*error_on_excess*/false); - if(ret.str == nullptr && ret.len > 0) - { - cont->resize(ret.len); - buf = to_substr(*cont); - ret = emit_yaml(t, id, buf, /*error_on_excess*/true); - } - return ret; -} -template -RYML_DEPRECATE_EMITRS substr emitrs(Tree const& t, size_t id, CharOwningContainer * cont) -{ - return emitrs_yaml(t, id, cont); -} - -/** emit+resize: emit JSON to the given std::string/std::vector-like - * container, resizing it as needed to fit the emitted JSON. */ -template -substr emitrs_json(Tree const& t, size_t id, CharOwningContainer * cont) -{ - substr buf = to_substr(*cont); - substr ret = emit_json(t, id, buf, /*error_on_excess*/false); - if(ret.str == nullptr && ret.len > 0) - { - cont->resize(ret.len); - buf = to_substr(*cont); - ret = emit_json(t, id, buf, /*error_on_excess*/true); - } - return ret; -} - - -/** emit+resize: emit YAML to the given std::string/std::vector-like - * container, resizing it as needed to fit the emitted YAML. */ -template -CharOwningContainer emitrs_yaml(Tree const& t, size_t id) -{ - CharOwningContainer c; - emitrs_yaml(t, id, &c); - return c; -} -template -RYML_DEPRECATE_EMITRS CharOwningContainer emitrs(Tree const& t, size_t id) -{ - CharOwningContainer c; - emitrs_yaml(t, id, &c); - return c; -} - -/** emit+resize: emit JSON to the given std::string/std::vector-like - * container, resizing it as needed to fit the emitted JSON. */ -template -CharOwningContainer emitrs_json(Tree const& t, size_t id) -{ - CharOwningContainer c; - emitrs_json(t, id, &c); - return c; -} - - -/** emit+resize: YAML to the given std::string/std::vector-like - * container, resizing it as needed to fit the emitted YAML. */ -template -substr emitrs_yaml(Tree const& t, CharOwningContainer * cont) -{ - if(t.empty()) - return {}; - return emitrs_yaml(t, t.root_id(), cont); -} -template -RYML_DEPRECATE_EMITRS substr emitrs(Tree const& t, CharOwningContainer * cont) -{ - return emitrs_yaml(t, cont); -} - -/** emit+resize: JSON to the given std::string/std::vector-like - * container, resizing it as needed to fit the emitted JSON. */ -template -substr emitrs_json(Tree const& t, CharOwningContainer * cont) -{ - if(t.empty()) - return {}; - return emitrs_json(t, t.root_id(), cont); -} - - -/** emit+resize: YAML to the given std::string/std::vector-like container, - * resizing it as needed to fit the emitted YAML. */ -template -CharOwningContainer emitrs_yaml(Tree const& t) -{ - CharOwningContainer c; - if(t.empty()) - return c; - emitrs_yaml(t, t.root_id(), &c); - return c; -} -template -RYML_DEPRECATE_EMITRS CharOwningContainer emitrs(Tree const& t) -{ - return emitrs_yaml(t); -} - -/** emit+resize: JSON to the given std::string/std::vector-like container, - * resizing it as needed to fit the emitted JSON. */ -template -CharOwningContainer emitrs_json(Tree const& t) -{ - CharOwningContainer c; - if(t.empty()) - return c; - emitrs_json(t, t.root_id(), &c); - return c; -} - - -/** emit+resize: YAML to the given std::string/std::vector-like container, - * resizing it as needed to fit the emitted YAML. */ -template -substr emitrs_yaml(ConstNodeRef const& n, CharOwningContainer * cont) -{ - _RYML_CB_CHECK(n.tree()->callbacks(), n.valid()); - return emitrs_yaml(*n.tree(), n.id(), cont); -} -template -RYML_DEPRECATE_EMITRS substr emitrs(ConstNodeRef const& n, CharOwningContainer * cont) -{ - return emitrs_yaml(n, cont); -} - -/** emit+resize: JSON to the given std::string/std::vector-like container, - * resizing it as needed to fit the emitted JSON. */ -template -substr emitrs_json(ConstNodeRef const& n, CharOwningContainer * cont) -{ - _RYML_CB_CHECK(n.tree()->callbacks(), n.valid()); - return emitrs_json(*n.tree(), n.id(), cont); -} - - -/** emit+resize: YAML to the given std::string/std::vector-like container, - * resizing it as needed to fit the emitted YAML. */ -template -CharOwningContainer emitrs_yaml(ConstNodeRef const& n) -{ - _RYML_CB_CHECK(n.tree()->callbacks(), n.valid()); - CharOwningContainer c; - emitrs_yaml(*n.tree(), n.id(), &c); - return c; -} -template -RYML_DEPRECATE_EMITRS CharOwningContainer emitrs(ConstNodeRef const& n) -{ - return emitrs_yaml(n); -} - -/** emit+resize: JSON to the given std::string/std::vector-like container, - * resizing it as needed to fit the emitted JSON. */ -template -CharOwningContainer emitrs_json(ConstNodeRef const& n) -{ - _RYML_CB_CHECK(n.tree()->callbacks(), n.valid()); - CharOwningContainer c; - emitrs_json(*n.tree(), n.id(), &c); - return c; -} - -} // namespace yml -} // namespace c4 - -#undef RYML_DEPRECATE_EMIT -#undef RYML_DEPRECATE_EMITRS - -#include "c4/yml/emit.def.hpp" - -#endif /* _C4_YML_EMIT_HPP_ */ diff --git a/thirdparty/ryml/src/c4/yml/export.hpp b/thirdparty/ryml/src/c4/yml/export.hpp deleted file mode 100644 index 6b77f3f8d..000000000 --- a/thirdparty/ryml/src/c4/yml/export.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef C4_YML_EXPORT_HPP_ -#define C4_YML_EXPORT_HPP_ - -#ifdef _WIN32 - #ifdef RYML_SHARED - #ifdef RYML_EXPORTS - #define RYML_EXPORT __declspec(dllexport) - #else - #define RYML_EXPORT __declspec(dllimport) - #endif - #else - #define RYML_EXPORT - #endif -#else - #define RYML_EXPORT -#endif - -#endif /* C4_YML_EXPORT_HPP_ */ diff --git a/thirdparty/ryml/src/c4/yml/node.cpp b/thirdparty/ryml/src/c4/yml/node.cpp deleted file mode 100644 index 50c7a0b60..000000000 --- a/thirdparty/ryml/src/c4/yml/node.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include "c4/yml/node.hpp" - -namespace c4 { -namespace yml { - - - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -size_t NodeRef::set_key_serialized(c4::fmt::const_base64_wrapper w) -{ - _apply_seed(); - csubstr encoded = this->to_arena(w); - this->set_key(encoded); - return encoded.len; -} - -size_t NodeRef::set_val_serialized(c4::fmt::const_base64_wrapper w) -{ - _apply_seed(); - csubstr encoded = this->to_arena(w); - this->set_val(encoded); - return encoded.len; -} - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/src/c4/yml/node.hpp b/thirdparty/ryml/src/c4/yml/node.hpp deleted file mode 100644 index 42ed50442..000000000 --- a/thirdparty/ryml/src/c4/yml/node.hpp +++ /dev/null @@ -1,1276 +0,0 @@ -#ifndef _C4_YML_NODE_HPP_ -#define _C4_YML_NODE_HPP_ - -/** @file node.hpp - * @see NodeRef */ - -#include - -#include "c4/yml/tree.hpp" -#include "c4/base64.hpp" - -#ifdef __GNUC__ -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wtype-limits" -#endif - -#if defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable: 4251/*needs to have dll-interface to be used by clients of struct*/) -# pragma warning(disable: 4296/*expression is always 'boolean_value'*/) -#endif - -namespace c4 { -namespace yml { - -template struct Key { K & k; }; -template<> struct Key { fmt::const_base64_wrapper wrapper; }; -template<> struct Key { fmt::base64_wrapper wrapper; }; - -template C4_ALWAYS_INLINE Key key(K & k) { return Key{k}; } -C4_ALWAYS_INLINE Key key(fmt::const_base64_wrapper w) { return {w}; } -C4_ALWAYS_INLINE Key key(fmt::base64_wrapper w) { return {w}; } - -template void write(NodeRef *n, T const& v); - -template -typename std::enable_if< ! std::is_floating_point::value, bool>::type -read(NodeRef const& n, T *v); - -template -typename std::enable_if< std::is_floating_point::value, bool>::type -read(NodeRef const& n, T *v); - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -// forward decls -class NodeRef; -class ConstNodeRef; - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -namespace detail { - -template -struct child_iterator -{ - using value_type = NodeRefType; - using tree_type = typename NodeRefType::tree_type; - - tree_type * C4_RESTRICT m_tree; - size_t m_child_id; - - child_iterator(tree_type * t, size_t id) : m_tree(t), m_child_id(id) {} - - child_iterator& operator++ () { RYML_ASSERT(m_child_id != NONE); m_child_id = m_tree->next_sibling(m_child_id); return *this; } - child_iterator& operator-- () { RYML_ASSERT(m_child_id != NONE); m_child_id = m_tree->prev_sibling(m_child_id); return *this; } - - NodeRefType operator* () const { return NodeRefType(m_tree, m_child_id); } - NodeRefType operator-> () const { return NodeRefType(m_tree, m_child_id); } - - bool operator!= (child_iterator that) const { RYML_ASSERT(m_tree == that.m_tree); return m_child_id != that.m_child_id; } - bool operator== (child_iterator that) const { RYML_ASSERT(m_tree == that.m_tree); return m_child_id == that.m_child_id; } -}; - -template -struct children_view_ -{ - using n_iterator = child_iterator; - - n_iterator b, e; - - inline children_view_(n_iterator const& C4_RESTRICT b_, - n_iterator const& C4_RESTRICT e_) : b(b_), e(e_) {} - - inline n_iterator begin() const { return b; } - inline n_iterator end () const { return e; } -}; - -template -bool _visit(NodeRefType &node, Visitor fn, size_t indentation_level, bool skip_root=false) -{ - size_t increment = 0; - if( ! (node.is_root() && skip_root)) - { - if(fn(node, indentation_level)) - return true; - ++increment; - } - if(node.has_children()) - { - for(auto ch : node.children()) - { - if(_visit(ch, fn, indentation_level + increment, false)) // no need to forward skip_root as it won't be root - { - return true; - } - } - } - return false; -} - -template -bool _visit_stacked(NodeRefType &node, Visitor fn, size_t indentation_level, bool skip_root=false) -{ - size_t increment = 0; - if( ! (node.is_root() && skip_root)) - { - if(fn(node, indentation_level)) - { - return true; - } - ++increment; - } - if(node.has_children()) - { - fn.push(node, indentation_level); - for(auto ch : node.children()) - { - if(_visit_stacked(ch, fn, indentation_level + increment, false)) // no need to forward skip_root as it won't be root - { - fn.pop(node, indentation_level); - return true; - } - } - fn.pop(node, indentation_level); - } - return false; -} - - -//----------------------------------------------------------------------------- - -/** a CRTP base for read-only node methods */ -template -struct RoNodeMethods -{ - C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH("-Wcast-align") - // helper CRTP macros, undefined at the end - #define tree_ ((ConstImpl const* C4_RESTRICT)this)->m_tree - #define id_ ((ConstImpl const* C4_RESTRICT)this)->m_id - #define tree__ ((Impl const* C4_RESTRICT)this)->m_tree - #define id__ ((Impl const* C4_RESTRICT)this)->m_id - // require valid - #define _C4RV() \ - RYML_ASSERT(tree_ != nullptr); \ - _RYML_CB_ASSERT(tree_->m_callbacks, id_ != NONE) - #define _C4_IF_MUTABLE(ty) typename std::enable_if::value, ty>::type - -public: - - /** @name node property getters */ - /** @{ */ - - /** returns the data or null when the id is NONE */ - C4_ALWAYS_INLINE C4_PURE NodeData const* get() const noexcept { RYML_ASSERT(tree_ != nullptr); return tree_->get(id_); } - /** returns the data or null when the id is NONE */ - template - C4_ALWAYS_INLINE C4_PURE auto get() noexcept -> _C4_IF_MUTABLE(NodeData*) { RYML_ASSERT(tree_ != nullptr); return tree__->get(id__); } - - C4_ALWAYS_INLINE C4_PURE NodeType type() const noexcept { _C4RV(); return tree_->type(id_); } - C4_ALWAYS_INLINE C4_PURE const char* type_str() const noexcept { return tree_->type_str(id_); } - - C4_ALWAYS_INLINE C4_PURE csubstr key() const noexcept { _C4RV(); return tree_->key(id_); } - C4_ALWAYS_INLINE C4_PURE csubstr key_tag() const noexcept { _C4RV(); return tree_->key_tag(id_); } - C4_ALWAYS_INLINE C4_PURE csubstr key_ref() const noexcept { _C4RV(); return tree_->key_ref(id_); } - C4_ALWAYS_INLINE C4_PURE csubstr key_anchor() const noexcept { _C4RV(); return tree_->key_anchor(id_); } - - C4_ALWAYS_INLINE C4_PURE csubstr val() const noexcept { _C4RV(); return tree_->val(id_); } - C4_ALWAYS_INLINE C4_PURE csubstr val_tag() const noexcept { _C4RV(); return tree_->val_tag(id_); } - C4_ALWAYS_INLINE C4_PURE csubstr val_ref() const noexcept { _C4RV(); return tree_->val_ref(id_); } - C4_ALWAYS_INLINE C4_PURE csubstr val_anchor() const noexcept { _C4RV(); return tree_->val_anchor(id_); } - - C4_ALWAYS_INLINE C4_PURE NodeScalar const& keysc() const noexcept { _C4RV(); return tree_->keysc(id_); } - C4_ALWAYS_INLINE C4_PURE NodeScalar const& valsc() const noexcept { _C4RV(); return tree_->valsc(id_); } - - C4_ALWAYS_INLINE C4_PURE bool key_is_null() const noexcept { _C4RV(); return tree_->key_is_null(id_); } - C4_ALWAYS_INLINE C4_PURE bool val_is_null() const noexcept { _C4RV(); return tree_->val_is_null(id_); } - - /** @} */ - -public: - - /** @name node property predicates */ - /** @{ */ - - C4_ALWAYS_INLINE C4_PURE bool empty() const noexcept { _C4RV(); return tree_->empty(id_); } - C4_ALWAYS_INLINE C4_PURE bool is_stream() const noexcept { _C4RV(); return tree_->is_stream(id_); } - C4_ALWAYS_INLINE C4_PURE bool is_doc() const noexcept { _C4RV(); return tree_->is_doc(id_); } - C4_ALWAYS_INLINE C4_PURE bool is_container() const noexcept { _C4RV(); return tree_->is_container(id_); } - C4_ALWAYS_INLINE C4_PURE bool is_map() const noexcept { _C4RV(); return tree_->is_map(id_); } - C4_ALWAYS_INLINE C4_PURE bool is_seq() const noexcept { _C4RV(); return tree_->is_seq(id_); } - C4_ALWAYS_INLINE C4_PURE bool has_val() const noexcept { _C4RV(); return tree_->has_val(id_); } - C4_ALWAYS_INLINE C4_PURE bool has_key() const noexcept { _C4RV(); return tree_->has_key(id_); } - C4_ALWAYS_INLINE C4_PURE bool is_val() const noexcept { _C4RV(); return tree_->is_val(id_); } - C4_ALWAYS_INLINE C4_PURE bool is_keyval() const noexcept { _C4RV(); return tree_->is_keyval(id_); } - C4_ALWAYS_INLINE C4_PURE bool has_key_tag() const noexcept { _C4RV(); return tree_->has_key_tag(id_); } - C4_ALWAYS_INLINE C4_PURE bool has_val_tag() const noexcept { _C4RV(); return tree_->has_val_tag(id_); } - C4_ALWAYS_INLINE C4_PURE bool has_key_anchor() const noexcept { _C4RV(); return tree_->has_key_anchor(id_); } - C4_ALWAYS_INLINE C4_PURE bool is_key_anchor() const noexcept { _C4RV(); return tree_->is_key_anchor(id_); } - C4_ALWAYS_INLINE C4_PURE bool has_val_anchor() const noexcept { _C4RV(); return tree_->has_val_anchor(id_); } - C4_ALWAYS_INLINE C4_PURE bool is_val_anchor() const noexcept { _C4RV(); return tree_->is_val_anchor(id_); } - C4_ALWAYS_INLINE C4_PURE bool has_anchor() const noexcept { _C4RV(); return tree_->has_anchor(id_); } - C4_ALWAYS_INLINE C4_PURE bool is_anchor() const noexcept { _C4RV(); return tree_->is_anchor(id_); } - C4_ALWAYS_INLINE C4_PURE bool is_key_ref() const noexcept { _C4RV(); return tree_->is_key_ref(id_); } - C4_ALWAYS_INLINE C4_PURE bool is_val_ref() const noexcept { _C4RV(); return tree_->is_val_ref(id_); } - C4_ALWAYS_INLINE C4_PURE bool is_ref() const noexcept { _C4RV(); return tree_->is_ref(id_); } - C4_ALWAYS_INLINE C4_PURE bool is_anchor_or_ref() const noexcept { _C4RV(); return tree_->is_anchor_or_ref(id_); } - C4_ALWAYS_INLINE C4_PURE bool is_key_quoted() const noexcept { _C4RV(); return tree_->is_key_quoted(id_); } - C4_ALWAYS_INLINE C4_PURE bool is_val_quoted() const noexcept { _C4RV(); return tree_->is_val_quoted(id_); } - C4_ALWAYS_INLINE C4_PURE bool is_quoted() const noexcept { _C4RV(); return tree_->is_quoted(id_); } - C4_ALWAYS_INLINE C4_PURE bool parent_is_seq() const noexcept { _C4RV(); return tree_->parent_is_seq(id_); } - C4_ALWAYS_INLINE C4_PURE bool parent_is_map() const noexcept { _C4RV(); return tree_->parent_is_map(id_); } - - /** @} */ - -public: - - /** @name hierarchy predicates */ - /** @{ */ - - C4_ALWAYS_INLINE C4_PURE bool is_root() const noexcept { _C4RV(); return tree_->is_root(id_); } - C4_ALWAYS_INLINE C4_PURE bool has_parent() const noexcept { _C4RV(); return tree_->has_parent(id_); } - - C4_ALWAYS_INLINE C4_PURE bool has_child(ConstImpl const& ch) const noexcept { _C4RV(); return tree_->has_child(id_, ch.m_id); } - C4_ALWAYS_INLINE C4_PURE bool has_child(csubstr name) const noexcept { _C4RV(); return tree_->has_child(id_, name); } - C4_ALWAYS_INLINE C4_PURE bool has_children() const noexcept { _C4RV(); return tree_->has_children(id_); } - - C4_ALWAYS_INLINE C4_PURE bool has_sibling(ConstImpl const& n) const noexcept { _C4RV(); return tree_->has_sibling(id_, n.m_id); } - C4_ALWAYS_INLINE C4_PURE bool has_sibling(csubstr name) const noexcept { _C4RV(); return tree_->has_sibling(id_, name); } - /** counts with this */ - C4_ALWAYS_INLINE C4_PURE bool has_siblings() const noexcept { _C4RV(); return tree_->has_siblings(id_); } - /** does not count with this */ - C4_ALWAYS_INLINE C4_PURE bool has_other_siblings() const noexcept { _C4RV(); return tree_->has_other_siblings(id_); } - - /** @} */ - -public: - - /** @name hierarchy getters */ - /** @{ */ - - - template - C4_ALWAYS_INLINE C4_PURE auto doc(size_t num) noexcept -> _C4_IF_MUTABLE(Impl) { _C4RV(); return {tree__, tree__->doc(num)}; } - C4_ALWAYS_INLINE C4_PURE ConstImpl doc(size_t num) const noexcept { _C4RV(); return {tree_, tree_->doc(num)}; } - - - template - C4_ALWAYS_INLINE C4_PURE auto parent() noexcept -> _C4_IF_MUTABLE(Impl) { _C4RV(); return {tree__, tree__->parent(id__)}; } - C4_ALWAYS_INLINE C4_PURE ConstImpl parent() const noexcept { _C4RV(); return {tree_, tree_->parent(id_)}; } - - - /** O(#num_children) */ - C4_ALWAYS_INLINE C4_PURE size_t child_pos(ConstImpl const& n) const noexcept { _C4RV(); return tree_->child_pos(id_, n.m_id); } - C4_ALWAYS_INLINE C4_PURE size_t num_children() const noexcept { _C4RV(); return tree_->num_children(id_); } - - template - C4_ALWAYS_INLINE C4_PURE auto first_child() noexcept -> _C4_IF_MUTABLE(Impl) { _C4RV(); return {tree__, tree__->first_child(id__)}; } - C4_ALWAYS_INLINE C4_PURE ConstImpl first_child() const noexcept { _C4RV(); return {tree_, tree_->first_child(id_)}; } - - template - C4_ALWAYS_INLINE C4_PURE auto last_child() noexcept -> _C4_IF_MUTABLE(Impl) { _C4RV(); return {tree__, tree__->last_child(id__)}; } - C4_ALWAYS_INLINE C4_PURE ConstImpl last_child () const noexcept { _C4RV(); return {tree_, tree_->last_child (id_)}; } - - template - C4_ALWAYS_INLINE C4_PURE auto child(size_t pos) noexcept -> _C4_IF_MUTABLE(Impl) { _C4RV(); return {tree__, tree__->child(id__, pos)}; } - C4_ALWAYS_INLINE C4_PURE ConstImpl child(size_t pos) const noexcept { _C4RV(); return {tree_, tree_->child(id_, pos)}; } - - template - C4_ALWAYS_INLINE C4_PURE auto find_child(csubstr name) noexcept -> _C4_IF_MUTABLE(Impl) { _C4RV(); return {tree__, tree__->find_child(id__, name)}; } - C4_ALWAYS_INLINE C4_PURE ConstImpl find_child(csubstr name) const noexcept { _C4RV(); return {tree_, tree_->find_child(id_, name)}; } - - - /** O(#num_siblings) */ - C4_ALWAYS_INLINE C4_PURE size_t num_siblings() const noexcept { _C4RV(); return tree_->num_siblings(id_); } - C4_ALWAYS_INLINE C4_PURE size_t num_other_siblings() const noexcept { _C4RV(); return tree_->num_other_siblings(id_); } - C4_ALWAYS_INLINE C4_PURE size_t sibling_pos(ConstImpl const& n) const noexcept { _C4RV(); return tree_->child_pos(tree_->parent(id_), n.m_id); } - - template - C4_ALWAYS_INLINE C4_PURE auto prev_sibling() noexcept -> _C4_IF_MUTABLE(Impl) { _C4RV(); return {tree__, tree__->prev_sibling(id__)}; } - C4_ALWAYS_INLINE C4_PURE ConstImpl prev_sibling() const noexcept { _C4RV(); return {tree_, tree_->prev_sibling(id_)}; } - - template - C4_ALWAYS_INLINE C4_PURE auto next_sibling() noexcept -> _C4_IF_MUTABLE(Impl) { _C4RV(); return {tree__, tree__->next_sibling(id__)}; } - C4_ALWAYS_INLINE C4_PURE ConstImpl next_sibling() const noexcept { _C4RV(); return {tree_, tree_->next_sibling(id_)}; } - - template - C4_ALWAYS_INLINE C4_PURE auto first_sibling() noexcept -> _C4_IF_MUTABLE(Impl) { _C4RV(); return {tree__, tree__->first_sibling(id__)}; } - C4_ALWAYS_INLINE C4_PURE ConstImpl first_sibling() const noexcept { _C4RV(); return {tree_, tree_->first_sibling(id_)}; } - - template - C4_ALWAYS_INLINE C4_PURE auto last_sibling() noexcept -> _C4_IF_MUTABLE(Impl) { _C4RV(); return {tree__, tree__->last_sibling(id__)}; } - C4_ALWAYS_INLINE C4_PURE ConstImpl last_sibling () const noexcept { _C4RV(); return {tree_, tree_->last_sibling(id_)}; } - - template - C4_ALWAYS_INLINE C4_PURE auto sibling(size_t pos) noexcept -> _C4_IF_MUTABLE(Impl) { _C4RV(); return {tree__, tree__->sibling(id__, pos)}; } - C4_ALWAYS_INLINE C4_PURE ConstImpl sibling(size_t pos) const noexcept { _C4RV(); return {tree_, tree_->sibling(id_, pos)}; } - - template - C4_ALWAYS_INLINE C4_PURE auto find_sibling(csubstr name) noexcept -> _C4_IF_MUTABLE(Impl) { _C4RV(); return {tree__, tree__->find_sibling(id__, name)}; } - C4_ALWAYS_INLINE C4_PURE ConstImpl find_sibling(csubstr name) const noexcept { _C4RV(); return {tree_, tree_->find_sibling(id_, name)}; } - - - /** O(num_children) */ - C4_ALWAYS_INLINE C4_PURE ConstImpl operator[] (csubstr k) const noexcept - { - _C4RV(); - size_t ch = tree_->find_child(id_, k); - _RYML_CB_ASSERT(tree_->m_callbacks, ch != NONE); - return {tree_, ch}; - } - /** Find child by key. O(num_children). returns a seed node if no such child is found. */ - template - C4_ALWAYS_INLINE C4_PURE auto operator[] (csubstr k) noexcept -> _C4_IF_MUTABLE(Impl) - { - _C4RV(); - size_t ch = tree__->find_child(id__, k); - return ch != NONE ? Impl(tree__, ch) : NodeRef(tree__, id__, k); - } - - /** O(num_children) */ - C4_ALWAYS_INLINE C4_PURE ConstImpl operator[] (size_t pos) const noexcept - { - _C4RV(); - size_t ch = tree_->child(id_, pos); - _RYML_CB_ASSERT(tree_->m_callbacks, ch != NONE); - return {tree_, ch}; - } - - /** Find child by position. O(pos). returns a seed node if no such child is found. */ - template - C4_ALWAYS_INLINE C4_PURE auto operator[] (size_t pos) noexcept -> _C4_IF_MUTABLE(Impl) - { - _C4RV(); - size_t ch = tree__->child(id__, pos); - return ch != NONE ? Impl(tree__, ch) : NodeRef(tree__, id__, pos); - } - - /** @} */ - -public: - - /** deserialization */ - /** @{ */ - - template - ConstImpl const& operator>> (T &v) const - { - _C4RV(); - if( ! read((ConstImpl const&)*this, &v)) - _RYML_CB_ERR(tree_->m_callbacks, "could not deserialize value"); - return *((ConstImpl const*)this); - } - - /** deserialize the node's key to the given variable */ - template - ConstImpl const& operator>> (Key v) const - { - _C4RV(); - if( ! from_chars(key(), &v.k)) - _RYML_CB_ERR(tree_->m_callbacks, "could not deserialize key"); - return *((ConstImpl const*)this); - } - - /** deserialize the node's key as base64 */ - ConstImpl const& operator>> (Key w) const - { - deserialize_key(w.wrapper); - return *((ConstImpl const*)this); - } - - /** deserialize the node's val as base64 */ - ConstImpl const& operator>> (fmt::base64_wrapper w) const - { - deserialize_val(w); - return *((ConstImpl const*)this); - } - - /** decode the base64-encoded key and assign the - * decoded blob to the given buffer/ - * @return the size of base64-decoded blob */ - size_t deserialize_key(fmt::base64_wrapper v) const - { - _C4RV(); - return from_chars(key(), &v); - } - /** decode the base64-encoded key and assign the - * decoded blob to the given buffer/ - * @return the size of base64-decoded blob */ - size_t deserialize_val(fmt::base64_wrapper v) const - { - _C4RV(); - return from_chars(val(), &v); - }; - - template - bool get_if(csubstr name, T *var) const - { - auto ch = find_child(name); - if(!ch.valid()) - return false; - ch >> *var; - return true; - } - - template - bool get_if(csubstr name, T *var, T const& fallback) const - { - auto ch = find_child(name); - if(ch.valid()) - { - ch >> *var; - return true; - } - else - { - *var = fallback; - return false; - } - } - - /** @} */ - -public: - - #if defined(__clang__) - # pragma clang diagnostic push - # pragma clang diagnostic ignored "-Wnull-dereference" - #elif defined(__GNUC__) - # pragma GCC diagnostic push - # if __GNUC__ >= 6 - # pragma GCC diagnostic ignored "-Wnull-dereference" - # endif - #endif - - /** @name iteration */ - /** @{ */ - - using iterator = detail::child_iterator; - using const_iterator = detail::child_iterator; - using children_view = detail::children_view_; - using const_children_view = detail::children_view_; - - template - C4_ALWAYS_INLINE C4_PURE auto begin() noexcept -> _C4_IF_MUTABLE(iterator) { _C4RV(); return iterator(tree__, tree__->first_child(id__)); } - C4_ALWAYS_INLINE C4_PURE const_iterator begin() const noexcept { _C4RV(); return const_iterator(tree_, tree_->first_child(id_)); } - C4_ALWAYS_INLINE C4_PURE const_iterator cbegin() const noexcept { _C4RV(); return const_iterator(tree_, tree_->first_child(id_)); } - - template - C4_ALWAYS_INLINE C4_PURE auto end() noexcept -> _C4_IF_MUTABLE(iterator) { _C4RV(); return iterator(tree__, NONE); } - C4_ALWAYS_INLINE C4_PURE const_iterator end() const noexcept { _C4RV(); return const_iterator(tree_, NONE); } - C4_ALWAYS_INLINE C4_PURE const_iterator cend() const noexcept { _C4RV(); return const_iterator(tree_, tree_->first_child(id_)); } - - /** get an iterable view over children */ - template - C4_ALWAYS_INLINE C4_PURE auto children() noexcept -> _C4_IF_MUTABLE(children_view) { _C4RV(); return children_view(begin(), end()); } - /** get an iterable view over children */ - C4_ALWAYS_INLINE C4_PURE const_children_view children() const noexcept { _C4RV(); return const_children_view(begin(), end()); } - /** get an iterable view over children */ - C4_ALWAYS_INLINE C4_PURE const_children_view cchildren() const noexcept { _C4RV(); return const_children_view(begin(), end()); } - - /** get an iterable view over all siblings (including the calling node) */ - template - C4_ALWAYS_INLINE C4_PURE auto siblings() noexcept -> _C4_IF_MUTABLE(children_view) - { - _C4RV(); - NodeData const *nd = tree__->get(id__); - return (nd->m_parent != NONE) ? // does it have a parent? - children_view(iterator(tree__, tree_->get(nd->m_parent)->m_first_child), iterator(tree__, NONE)) - : - children_view(end(), end()); - } - /** get an iterable view over all siblings (including the calling node) */ - C4_ALWAYS_INLINE C4_PURE const_children_view siblings() const noexcept - { - _C4RV(); - NodeData const *nd = tree_->get(id_); - return (nd->m_parent != NONE) ? // does it have a parent? - const_children_view(const_iterator(tree_, tree_->get(nd->m_parent)->m_first_child), const_iterator(tree_, NONE)) - : - const_children_view(end(), end()); - } - /** get an iterable view over all siblings (including the calling node) */ - C4_ALWAYS_INLINE C4_PURE const_children_view csiblings() const noexcept { return siblings(); } - - /** visit every child node calling fn(node) */ - template - C4_ALWAYS_INLINE C4_PURE bool visit(Visitor fn, size_t indentation_level=0, bool skip_root=true) const noexcept - { - return detail::_visit(*(ConstImpl*)this, fn, indentation_level, skip_root); - } - /** visit every child node calling fn(node) */ - template - auto visit(Visitor fn, size_t indentation_level=0, bool skip_root=true) noexcept - -> _C4_IF_MUTABLE(bool) - { - return detail::_visit(*(Impl*)this, fn, indentation_level, skip_root); - } - - /** visit every child node calling fn(node, level) */ - template - C4_ALWAYS_INLINE C4_PURE bool visit_stacked(Visitor fn, size_t indentation_level=0, bool skip_root=true) const noexcept - { - return detail::_visit_stacked(*(ConstImpl*)this, fn, indentation_level, skip_root); - } - /** visit every child node calling fn(node, level) */ - template - auto visit_stacked(Visitor fn, size_t indentation_level=0, bool skip_root=true) noexcept - -> _C4_IF_MUTABLE(bool) - { - return detail::_visit_stacked(*(Impl*)this, fn, indentation_level, skip_root); - } - - /** @} */ - - #if defined(__clang__) - # pragma clang diagnostic pop - #elif defined(__GNUC__) - # pragma GCC diagnostic pop - #endif - - #undef _C4_IF_MUTABLE - #undef _C4RV - #undef tree_ - #undef tree__ - #undef id_ - #undef id__ - - C4_SUPPRESS_WARNING_GCC_CLANG_POP -}; - -} // namespace detail - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -class RYML_EXPORT ConstNodeRef : public detail::RoNodeMethods -{ -public: - - using tree_type = Tree const; - -public: - - Tree const* C4_RESTRICT m_tree; - size_t m_id; - - friend NodeRef; - friend struct detail::RoNodeMethods; - -public: - - /** @name construction */ - /** @{ */ - - ConstNodeRef() : m_tree(nullptr), m_id(NONE) {} - ConstNodeRef(Tree const &t) : m_tree(&t), m_id(t .root_id()) {} - ConstNodeRef(Tree const *t) : m_tree(t ), m_id(t->root_id()) {} - ConstNodeRef(Tree const *t, size_t id) : m_tree(t), m_id(id) {} - ConstNodeRef(std::nullptr_t) : m_tree(nullptr), m_id(NONE) {} - - ConstNodeRef(ConstNodeRef const&) = default; - ConstNodeRef(ConstNodeRef &&) = default; - - ConstNodeRef(NodeRef const&); - ConstNodeRef(NodeRef &&); - - /** @} */ - -public: - - /** @name assignment */ - /** @{ */ - - ConstNodeRef& operator= (std::nullptr_t) { m_tree = nullptr; m_id = NONE; return *this; } - - ConstNodeRef& operator= (ConstNodeRef const&) = default; - ConstNodeRef& operator= (ConstNodeRef &&) = default; - - ConstNodeRef& operator= (NodeRef const&); - ConstNodeRef& operator= (NodeRef &&); - - - /** @} */ - -public: - - /** @name state queries */ - /** @{ */ - - C4_ALWAYS_INLINE C4_PURE bool valid() const noexcept { return m_tree != nullptr && m_id != NONE; } - - /** @} */ - -public: - - /** @name member getters */ - /** @{ */ - - C4_ALWAYS_INLINE C4_PURE Tree const* tree() const noexcept { return m_tree; } - C4_ALWAYS_INLINE C4_PURE size_t id() const noexcept { return m_id; } - - /** @} */ - -public: - - /** @name comparisons */ - /** @{ */ - - C4_ALWAYS_INLINE C4_PURE bool operator== (ConstNodeRef const& that) const noexcept { RYML_ASSERT(that.m_tree == m_tree); return m_id == that.m_id; } - C4_ALWAYS_INLINE C4_PURE bool operator!= (ConstNodeRef const& that) const noexcept { RYML_ASSERT(that.m_tree == m_tree); return ! this->operator==(that); } - - C4_ALWAYS_INLINE C4_PURE bool operator== (std::nullptr_t) const noexcept { return m_tree == nullptr || m_id == NONE; } - C4_ALWAYS_INLINE C4_PURE bool operator!= (std::nullptr_t) const noexcept { return ! this->operator== (nullptr); } - - C4_ALWAYS_INLINE C4_PURE bool operator== (csubstr val) const noexcept { RYML_ASSERT(has_val()); return m_tree->val(m_id) == val; } - C4_ALWAYS_INLINE C4_PURE bool operator!= (csubstr val) const noexcept { RYML_ASSERT(has_val()); return m_tree->val(m_id) != val; } - - /** @} */ - -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -/** a reference to a node in an existing yaml tree, offering a more - * convenient API than the index-based API used in the tree. */ -class RYML_EXPORT NodeRef : public detail::RoNodeMethods -{ -public: - - using tree_type = Tree; - using base_type = detail::RoNodeMethods; - -private: - - Tree *C4_RESTRICT m_tree; - size_t m_id; - - /** This member is used to enable lazy operator[] writing. When a child - * with a key or index is not found, m_id is set to the id of the parent - * and the asked-for key or index are stored in this member until a write - * does happen. Then it is given as key or index for creating the child. - * When a key is used, the csubstr stores it (so the csubstr's string is - * non-null and the csubstr's size is different from NONE). When an index is - * used instead, the csubstr's string is set to null, and only the csubstr's - * size is set to a value different from NONE. Otherwise, when operator[] - * does find the child then this member is empty: the string is null and - * the size is NONE. */ - csubstr m_seed; - - friend ConstNodeRef; - friend struct detail::RoNodeMethods; - - // require valid: a helper macro, undefined at the end - #define _C4RV() \ - RYML_ASSERT(m_tree != nullptr); \ - _RYML_CB_ASSERT(m_tree->m_callbacks, m_id != NONE && !is_seed()) - -public: - - /** @name construction */ - /** @{ */ - - NodeRef() : m_tree(nullptr), m_id(NONE), m_seed() { _clear_seed(); } - NodeRef(Tree &t) : m_tree(&t), m_id(t .root_id()), m_seed() { _clear_seed(); } - NodeRef(Tree *t) : m_tree(t ), m_id(t->root_id()), m_seed() { _clear_seed(); } - NodeRef(Tree *t, size_t id) : m_tree(t), m_id(id), m_seed() { _clear_seed(); } - NodeRef(Tree *t, size_t id, size_t seed_pos) : m_tree(t), m_id(id), m_seed() { m_seed.str = nullptr; m_seed.len = seed_pos; } - NodeRef(Tree *t, size_t id, csubstr seed_key) : m_tree(t), m_id(id), m_seed(seed_key) {} - NodeRef(std::nullptr_t) : m_tree(nullptr), m_id(NONE), m_seed() {} - - /** @} */ - -public: - - /** @name assignment */ - /** @{ */ - - NodeRef(NodeRef const&) = default; - NodeRef(NodeRef &&) = default; - - NodeRef& operator= (NodeRef const&) = default; - NodeRef& operator= (NodeRef &&) = default; - - /** @} */ - -public: - - /** @name state queries */ - /** @{ */ - - inline bool valid() const { return m_tree != nullptr && m_id != NONE; } - inline bool is_seed() const { return m_seed.str != nullptr || m_seed.len != NONE; } - - inline void _clear_seed() { /*do this manually or an assert is triggered*/ m_seed.str = nullptr; m_seed.len = NONE; } - - /** @} */ - -public: - - /** @name comparisons */ - /** @{ */ - - inline bool operator== (NodeRef const& that) const { _C4RV(); RYML_ASSERT(that.valid() && !that.is_seed()); RYML_ASSERT(that.m_tree == m_tree); return m_id == that.m_id; } - inline bool operator!= (NodeRef const& that) const { return ! this->operator==(that); } - - inline bool operator== (ConstNodeRef const& that) const { _C4RV(); RYML_ASSERT(that.valid()); RYML_ASSERT(that.m_tree == m_tree); return m_id == that.m_id; } - inline bool operator!= (ConstNodeRef const& that) const { return ! this->operator==(that); } - - inline bool operator== (std::nullptr_t) const { return m_tree == nullptr || m_id == NONE || is_seed(); } - inline bool operator!= (std::nullptr_t) const { return m_tree != nullptr && m_id != NONE && !is_seed(); } - - inline bool operator== (csubstr val) const { _C4RV(); RYML_ASSERT(has_val()); return m_tree->val(m_id) == val; } - inline bool operator!= (csubstr val) const { _C4RV(); RYML_ASSERT(has_val()); return m_tree->val(m_id) != val; } - - //inline operator bool () const { return m_tree == nullptr || m_id == NONE || is_seed(); } - - /** @} */ - -public: - - /** @name node property getters */ - /** @{ */ - - C4_ALWAYS_INLINE C4_PURE Tree * tree() noexcept { return m_tree; } - C4_ALWAYS_INLINE C4_PURE Tree const* tree() const noexcept { return m_tree; } - - C4_ALWAYS_INLINE C4_PURE size_t id() const noexcept { return m_id; } - - /** @} */ - -public: - - /** @name node modifiers */ - /** @{ */ - - void change_type(NodeType t) { _C4RV(); m_tree->change_type(m_id, t); } - - void set_type(NodeType t) { _C4RV(); m_tree->_set_flags(m_id, t); } - void set_key(csubstr key) { _C4RV(); m_tree->_set_key(m_id, key); } - void set_val(csubstr val) { _C4RV(); m_tree->_set_val(m_id, val); } - void set_key_tag(csubstr key_tag) { _C4RV(); m_tree->set_key_tag(m_id, key_tag); } - void set_val_tag(csubstr val_tag) { _C4RV(); m_tree->set_val_tag(m_id, val_tag); } - void set_key_anchor(csubstr key_anchor) { _C4RV(); m_tree->set_key_anchor(m_id, key_anchor); } - void set_val_anchor(csubstr val_anchor) { _C4RV(); m_tree->set_val_anchor(m_id, val_anchor); } - void set_key_ref(csubstr key_ref) { _C4RV(); m_tree->set_key_ref(m_id, key_ref); } - void set_val_ref(csubstr val_ref) { _C4RV(); m_tree->set_val_ref(m_id, val_ref); } - - template - size_t set_key_serialized(T const& C4_RESTRICT k) - { - _C4RV(); - csubstr s = m_tree->to_arena(k); - m_tree->_set_key(m_id, s); - return s.len; - } - template - size_t set_val_serialized(T const& C4_RESTRICT v) - { - _C4RV(); - csubstr s = m_tree->to_arena(v); - m_tree->_set_val(m_id, s); - return s.len; - } - size_t set_val_serialized(std::nullptr_t) - { - _C4RV(); - m_tree->_set_val(m_id, csubstr{}); - return 0; - } - - /** encode a blob as base64, then assign the result to the node's key - * @return the size of base64-encoded blob */ - size_t set_key_serialized(fmt::const_base64_wrapper w); - /** encode a blob as base64, then assign the result to the node's val - * @return the size of base64-encoded blob */ - size_t set_val_serialized(fmt::const_base64_wrapper w); - -public: - - inline void clear() - { - if(is_seed()) - return; - m_tree->remove_children(m_id); - m_tree->_clear(m_id); - } - - inline void clear_key() - { - if(is_seed()) - return; - m_tree->_clear_key(m_id); - } - - inline void clear_val() - { - if(is_seed()) - return; - m_tree->_clear_val(m_id); - } - - inline void clear_children() - { - if(is_seed()) - return; - m_tree->remove_children(m_id); - } - - void create() { _apply_seed(); } - - inline void operator= (NodeType_e t) - { - _apply_seed(); - m_tree->_add_flags(m_id, t); - } - - inline void operator|= (NodeType_e t) - { - _apply_seed(); - m_tree->_add_flags(m_id, t); - } - - inline void operator= (NodeInit const& v) - { - _apply_seed(); - _apply(v); - } - - inline void operator= (NodeScalar const& v) - { - _apply_seed(); - _apply(v); - } - - inline void operator= (std::nullptr_t) - { - _apply_seed(); - _apply(csubstr{}); - } - - inline void operator= (csubstr v) - { - _apply_seed(); - _apply(v); - } - - template - inline void operator= (const char (&v)[N]) - { - _apply_seed(); - csubstr sv; - sv.assign(v); - _apply(sv); - } - - /** @} */ - -public: - - /** @name serialization */ - /** @{ */ - - /** serialize a variable to the arena */ - template - inline csubstr to_arena(T const& C4_RESTRICT s) - { - _C4RV(); - return m_tree->to_arena(s); - } - - /** serialize a variable, then assign the result to the node's val */ - inline NodeRef& operator<< (csubstr s) - { - // this overload is needed to prevent ambiguity (there's also - // operator<< for writing a substr to a stream) - _apply_seed(); - write(this, s); - RYML_ASSERT(val() == s); - return *this; - } - - template - inline NodeRef& operator<< (T const& C4_RESTRICT v) - { - _apply_seed(); - write(this, v); - return *this; - } - - /** serialize a variable, then assign the result to the node's key */ - template - inline NodeRef& operator<< (Key const& C4_RESTRICT v) - { - _apply_seed(); - set_key_serialized(v.k); - return *this; - } - - /** serialize a variable, then assign the result to the node's key */ - template - inline NodeRef& operator<< (Key const& C4_RESTRICT v) - { - _apply_seed(); - set_key_serialized(v.k); - return *this; - } - - NodeRef& operator<< (Key w) - { - set_key_serialized(w.wrapper); - return *this; - } - - NodeRef& operator<< (fmt::const_base64_wrapper w) - { - set_val_serialized(w); - return *this; - } - - /** @} */ - -private: - - void _apply_seed() - { - if(m_seed.str) // we have a seed key: use it to create the new child - { - //RYML_ASSERT(i.key.scalar.empty() || m_key == i.key.scalar || m_key.empty()); - m_id = m_tree->append_child(m_id); - m_tree->_set_key(m_id, m_seed); - m_seed.str = nullptr; - m_seed.len = NONE; - } - else if(m_seed.len != NONE) // we have a seed index: create a child at that position - { - RYML_ASSERT(m_tree->num_children(m_id) == m_seed.len); - m_id = m_tree->append_child(m_id); - m_seed.str = nullptr; - m_seed.len = NONE; - } - else - { - RYML_ASSERT(valid()); - } - } - - inline void _apply(csubstr v) - { - m_tree->_set_val(m_id, v); - } - - inline void _apply(NodeScalar const& v) - { - m_tree->_set_val(m_id, v); - } - - inline void _apply(NodeInit const& i) - { - m_tree->_set(m_id, i); - } - -public: - - /** @name modification of hierarchy */ - /** @{ */ - - inline NodeRef insert_child(NodeRef after) - { - _C4RV(); - RYML_ASSERT(after.m_tree == m_tree); - NodeRef r(m_tree, m_tree->insert_child(m_id, after.m_id)); - return r; - } - - inline NodeRef insert_child(NodeInit const& i, NodeRef after) - { - _C4RV(); - RYML_ASSERT(after.m_tree == m_tree); - NodeRef r(m_tree, m_tree->insert_child(m_id, after.m_id)); - r._apply(i); - return r; - } - - inline NodeRef prepend_child() - { - _C4RV(); - NodeRef r(m_tree, m_tree->insert_child(m_id, NONE)); - return r; - } - - inline NodeRef prepend_child(NodeInit const& i) - { - _C4RV(); - NodeRef r(m_tree, m_tree->insert_child(m_id, NONE)); - r._apply(i); - return r; - } - - inline NodeRef append_child() - { - _C4RV(); - NodeRef r(m_tree, m_tree->append_child(m_id)); - return r; - } - - inline NodeRef append_child(NodeInit const& i) - { - _C4RV(); - NodeRef r(m_tree, m_tree->append_child(m_id)); - r._apply(i); - return r; - } - -public: - - inline NodeRef insert_sibling(ConstNodeRef const& after) - { - _C4RV(); - RYML_ASSERT(after.m_tree == m_tree); - NodeRef r(m_tree, m_tree->insert_sibling(m_id, after.m_id)); - return r; - } - - inline NodeRef insert_sibling(NodeInit const& i, ConstNodeRef const& after) - { - _C4RV(); - RYML_ASSERT(after.m_tree == m_tree); - NodeRef r(m_tree, m_tree->insert_sibling(m_id, after.m_id)); - r._apply(i); - return r; - } - - inline NodeRef prepend_sibling() - { - _C4RV(); - NodeRef r(m_tree, m_tree->prepend_sibling(m_id)); - return r; - } - - inline NodeRef prepend_sibling(NodeInit const& i) - { - _C4RV(); - NodeRef r(m_tree, m_tree->prepend_sibling(m_id)); - r._apply(i); - return r; - } - - inline NodeRef append_sibling() - { - _C4RV(); - NodeRef r(m_tree, m_tree->append_sibling(m_id)); - return r; - } - - inline NodeRef append_sibling(NodeInit const& i) - { - _C4RV(); - NodeRef r(m_tree, m_tree->append_sibling(m_id)); - r._apply(i); - return r; - } - -public: - - inline void remove_child(NodeRef & child) - { - _C4RV(); - RYML_ASSERT(has_child(child)); - RYML_ASSERT(child.parent().id() == id()); - m_tree->remove(child.id()); - child.clear(); - } - - //! remove the nth child of this node - inline void remove_child(size_t pos) - { - _C4RV(); - RYML_ASSERT(pos >= 0 && pos < num_children()); - size_t child = m_tree->child(m_id, pos); - RYML_ASSERT(child != NONE); - m_tree->remove(child); - } - - //! remove a child by name - inline void remove_child(csubstr key) - { - _C4RV(); - size_t child = m_tree->find_child(m_id, key); - RYML_ASSERT(child != NONE); - m_tree->remove(child); - } - -public: - - /** change the node's position within its parent, placing it after - * @p after. To move to the first position in the parent, simply - * pass an empty or default-constructed reference like this: - * `n.move({})`. */ - inline void move(ConstNodeRef const& after) - { - _C4RV(); - m_tree->move(m_id, after.m_id); - } - - /** move the node to a different @p parent (which may belong to a - * different tree), placing it after @p after. When the - * destination parent is in a new tree, then this node's tree - * pointer is reset to the tree of the parent node. */ - inline void move(NodeRef const& parent, ConstNodeRef const& after) - { - _C4RV(); - if(parent.m_tree == m_tree) - { - m_tree->move(m_id, parent.m_id, after.m_id); - } - else - { - parent.m_tree->move(m_tree, m_id, parent.m_id, after.m_id); - m_tree = parent.m_tree; - } - } - - /** duplicate the current node somewhere within its parent, and - * place it after the node @p after. To place into the first - * position of the parent, simply pass an empty or - * default-constructed reference like this: `n.move({})`. */ - inline NodeRef duplicate(ConstNodeRef const& after) const - { - _C4RV(); - RYML_ASSERT(m_tree == after.m_tree || after.m_id == NONE); - size_t dup = m_tree->duplicate(m_id, m_tree->parent(m_id), after.m_id); - NodeRef r(m_tree, dup); - return r; - } - - /** duplicate the current node somewhere into a different @p parent - * (possibly from a different tree), and place it after the node - * @p after. To place into the first position of the parent, - * simply pass an empty or default-constructed reference like - * this: `n.move({})`. */ - inline NodeRef duplicate(NodeRef const& parent, ConstNodeRef const& after) const - { - _C4RV(); - RYML_ASSERT(parent.m_tree == after.m_tree || after.m_id == NONE); - if(parent.m_tree == m_tree) - { - size_t dup = m_tree->duplicate(m_id, parent.m_id, after.m_id); - NodeRef r(m_tree, dup); - return r; - } - else - { - size_t dup = parent.m_tree->duplicate(m_tree, m_id, parent.m_id, after.m_id); - NodeRef r(parent.m_tree, dup); - return r; - } - } - - inline void duplicate_children(NodeRef const& parent, ConstNodeRef const& after) const - { - _C4RV(); - RYML_ASSERT(parent.m_tree == after.m_tree); - if(parent.m_tree == m_tree) - { - m_tree->duplicate_children(m_id, parent.m_id, after.m_id); - } - else - { - parent.m_tree->duplicate_children(m_tree, m_id, parent.m_id, after.m_id); - } - } - - /** @} */ - -#undef _C4RV -}; - - -//----------------------------------------------------------------------------- - -inline ConstNodeRef::ConstNodeRef(NodeRef const& that) - : m_tree(that.m_tree) - , m_id(!that.is_seed() ? that.id() : NONE) -{ -} - -inline ConstNodeRef::ConstNodeRef(NodeRef && that) - : m_tree(that.m_tree) - , m_id(!that.is_seed() ? that.id() : NONE) -{ -} - - -inline ConstNodeRef& ConstNodeRef::operator= (NodeRef const& that) -{ - m_tree = (that.m_tree); - m_id = (!that.is_seed() ? that.id() : NONE); - return *this; -} - -inline ConstNodeRef& ConstNodeRef::operator= (NodeRef && that) -{ - m_tree = (that.m_tree); - m_id = (!that.is_seed() ? that.id() : NONE); - return *this; -} - - -//----------------------------------------------------------------------------- - -template -inline void write(NodeRef *n, T const& v) -{ - n->set_val_serialized(v); -} - -template -typename std::enable_if< ! std::is_floating_point::value, bool>::type -inline read(NodeRef const& n, T *v) -{ - return from_chars(n.val(), v); -} -template -typename std::enable_if< ! std::is_floating_point::value, bool>::type -inline read(ConstNodeRef const& n, T *v) -{ - return from_chars(n.val(), v); -} - -template -typename std::enable_if::value, bool>::type -inline read(NodeRef const& n, T *v) -{ - return from_chars_float(n.val(), v); -} -template -typename std::enable_if::value, bool>::type -inline read(ConstNodeRef const& n, T *v) -{ - return from_chars_float(n.val(), v); -} - - -} // namespace yml -} // namespace c4 - - -#if defined(_MSC_VER) -# pragma warning(pop) -#endif - -#ifdef __GNUC__ -# pragma GCC diagnostic pop -#endif - -#endif /* _C4_YML_NODE_HPP_ */ diff --git a/thirdparty/ryml/src/c4/yml/parse.cpp b/thirdparty/ryml/src/c4/yml/parse.cpp deleted file mode 100644 index 7b038e672..000000000 --- a/thirdparty/ryml/src/c4/yml/parse.cpp +++ /dev/null @@ -1,5724 +0,0 @@ -#include "c4/yml/parse.hpp" -#include "c4/error.hpp" -#include "c4/utf.hpp" -#include - -#include -#include -#include - -#include "c4/yml/detail/parser_dbg.hpp" -#ifdef RYML_DBG -#include "c4/yml/detail/print.hpp" -#endif - -#ifndef RYML_ERRMSG_SIZE - #define RYML_ERRMSG_SIZE 1024 -#endif - -//#define RYML_WITH_TAB_TOKENS -#ifdef RYML_WITH_TAB_TOKENS -#define _RYML_WITH_TAB_TOKENS(...) __VA_ARGS__ -#define _RYML_WITH_OR_WITHOUT_TAB_TOKENS(with, without) with -#else -#define _RYML_WITH_TAB_TOKENS(...) -#define _RYML_WITH_OR_WITHOUT_TAB_TOKENS(with, without) without -#endif - - -#if defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable: 4296/*expression is always 'boolean_value'*/) -#elif defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wtype-limits" // to remove a warning on an assertion that a size_t >= 0. Later on, this size_t will turn into a template argument, and then it can become < 0. -# pragma clang diagnostic ignored "-Wformat-nonliteral" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wtype-limits" // to remove a warning on an assertion that a size_t >= 0. Later on, this size_t will turn into a template argument, and then it can become < 0. -# pragma GCC diagnostic ignored "-Wformat-nonliteral" -# if __GNUC__ >= 7 -# pragma GCC diagnostic ignored "-Wduplicated-branches" -# endif -#endif - -namespace c4 { -namespace yml { - -namespace { - -template -void _parse_dump(DumpFn dumpfn, c4::csubstr fmt, Args&& ...args) -{ - char writebuf[256]; - auto results = c4::format_dump_resume(dumpfn, writebuf, fmt, std::forward(args)...); - // resume writing if the results failed to fit the buffer - if(C4_UNLIKELY(results.bufsize > sizeof(writebuf))) // bufsize will be that of the largest element serialized. Eg int(1), will require 1 byte. - { - results = format_dump_resume(dumpfn, results, writebuf, fmt, std::forward(args)...); - if(C4_UNLIKELY(results.bufsize > sizeof(writebuf))) - { - results = format_dump_resume(dumpfn, results, writebuf, fmt, std::forward(args)...); - } - } -} - -bool _is_scalar_next__runk(csubstr s) -{ - return !(s.begins_with(": ") || s.begins_with_any("#,{}[]%&") || s.begins_with("? ") || s == "-" || s.begins_with("- ") || s.begins_with(":\"") || s.begins_with(":'")); -} - -bool _is_scalar_next__rseq_rval(csubstr s) -{ - return !(s.begins_with_any("[{!&") || s.begins_with("? ") || s.begins_with("- ") || s == "-"); -} - -bool _is_scalar_next__rmap(csubstr s) -{ - return !(s.begins_with(": ") || s.begins_with_any("#,!&") || s.begins_with("? ") _RYML_WITH_TAB_TOKENS(|| s.begins_with(":\t"))); -} - -bool _is_scalar_next__rmap_val(csubstr s) -{ - return !(s.begins_with("- ") || s.begins_with_any("{[") || s == "-"); -} - -bool _is_doc_sep(csubstr s) -{ - constexpr const csubstr dashes = "---"; - constexpr const csubstr ellipsis = "..."; - constexpr const csubstr whitesp = " \t"; - if(s.begins_with(dashes)) - return s == dashes || s.sub(3).begins_with_any(whitesp); - else if(s.begins_with(ellipsis)) - return s == ellipsis || s.sub(3).begins_with_any(whitesp); - return false; -} - -/** @p i is set to the first non whitespace character after the line - * @return the number of empty lines after the initial position */ -size_t count_following_newlines(csubstr r, size_t *C4_RESTRICT i, size_t indentation) -{ - RYML_ASSERT(r[*i] == '\n'); - size_t numnl_following = 0; - ++(*i); - for( ; *i < r.len; ++(*i)) - { - if(r.str[*i] == '\n') - { - ++numnl_following; - if(indentation) // skip the indentation after the newline - { - size_t stop = *i + indentation; - for( ; *i < r.len; ++(*i)) - { - if(r.str[*i] != ' ' && r.str[*i] != '\r') - break; - RYML_ASSERT(*i < stop); - } - C4_UNUSED(stop); - } - } - else if(r.str[*i] == ' ' || r.str[*i] == '\t' || r.str[*i] == '\r') // skip leading whitespace - ; - else - break; - } - return numnl_following; -} - -} // anon namespace - - -//----------------------------------------------------------------------------- - -Parser::~Parser() -{ - _free(); - _clr(); -} - -Parser::Parser(Callbacks const& cb, ParserOptions opts) - : m_options(opts) - , m_file() - , m_buf() - , m_root_id(NONE) - , m_tree() - , m_stack(cb) - , m_state() - , m_key_tag_indentation(0) - , m_key_tag2_indentation(0) - , m_key_tag() - , m_key_tag2() - , m_val_tag_indentation(0) - , m_val_tag() - , m_key_anchor_was_before(false) - , m_key_anchor_indentation(0) - , m_key_anchor() - , m_val_anchor_indentation(0) - , m_val_anchor() - , m_filter_arena() - , m_newline_offsets() - , m_newline_offsets_size(0) - , m_newline_offsets_capacity(0) - , m_newline_offsets_buf() -{ - m_stack.push(State{}); - m_state = &m_stack.top(); -} - -Parser::Parser(Parser &&that) - : m_options(that.m_options) - , m_file(that.m_file) - , m_buf(that.m_buf) - , m_root_id(that.m_root_id) - , m_tree(that.m_tree) - , m_stack(std::move(that.m_stack)) - , m_state(&m_stack.top()) - , m_key_tag_indentation(that.m_key_tag_indentation) - , m_key_tag2_indentation(that.m_key_tag2_indentation) - , m_key_tag(that.m_key_tag) - , m_key_tag2(that.m_key_tag2) - , m_val_tag_indentation(that.m_val_tag_indentation) - , m_val_tag(that.m_val_tag) - , m_key_anchor_was_before(that.m_key_anchor_was_before) - , m_key_anchor_indentation(that.m_key_anchor_indentation) - , m_key_anchor(that.m_key_anchor) - , m_val_anchor_indentation(that.m_val_anchor_indentation) - , m_val_anchor(that.m_val_anchor) - , m_filter_arena(that.m_filter_arena) - , m_newline_offsets(that.m_newline_offsets) - , m_newline_offsets_size(that.m_newline_offsets_size) - , m_newline_offsets_capacity(that.m_newline_offsets_capacity) - , m_newline_offsets_buf(that.m_newline_offsets_buf) -{ - that._clr(); -} - -Parser::Parser(Parser const& that) - : m_options(that.m_options) - , m_file(that.m_file) - , m_buf(that.m_buf) - , m_root_id(that.m_root_id) - , m_tree(that.m_tree) - , m_stack(that.m_stack) - , m_state(&m_stack.top()) - , m_key_tag_indentation(that.m_key_tag_indentation) - , m_key_tag2_indentation(that.m_key_tag2_indentation) - , m_key_tag(that.m_key_tag) - , m_key_tag2(that.m_key_tag2) - , m_val_tag_indentation(that.m_val_tag_indentation) - , m_val_tag(that.m_val_tag) - , m_key_anchor_was_before(that.m_key_anchor_was_before) - , m_key_anchor_indentation(that.m_key_anchor_indentation) - , m_key_anchor(that.m_key_anchor) - , m_val_anchor_indentation(that.m_val_anchor_indentation) - , m_val_anchor(that.m_val_anchor) - , m_filter_arena() - , m_newline_offsets() - , m_newline_offsets_size() - , m_newline_offsets_capacity() - , m_newline_offsets_buf() -{ - if(that.m_newline_offsets_capacity) - { - _resize_locations(that.m_newline_offsets_capacity); - _RYML_CB_CHECK(m_stack.m_callbacks, m_newline_offsets_capacity == that.m_newline_offsets_capacity); - memcpy(m_newline_offsets, that.m_newline_offsets, that.m_newline_offsets_size * sizeof(size_t)); - m_newline_offsets_size = that.m_newline_offsets_size; - } - if(that.m_filter_arena.len) - { - _resize_filter_arena(that.m_filter_arena.len); - } -} - -Parser& Parser::operator=(Parser &&that) -{ - _free(); - m_options = (that.m_options); - m_file = (that.m_file); - m_buf = (that.m_buf); - m_root_id = (that.m_root_id); - m_tree = (that.m_tree); - m_stack = std::move(that.m_stack); - m_state = (&m_stack.top()); - m_key_tag_indentation = (that.m_key_tag_indentation); - m_key_tag2_indentation = (that.m_key_tag2_indentation); - m_key_tag = (that.m_key_tag); - m_key_tag2 = (that.m_key_tag2); - m_val_tag_indentation = (that.m_val_tag_indentation); - m_val_tag = (that.m_val_tag); - m_key_anchor_was_before = (that.m_key_anchor_was_before); - m_key_anchor_indentation = (that.m_key_anchor_indentation); - m_key_anchor = (that.m_key_anchor); - m_val_anchor_indentation = (that.m_val_anchor_indentation); - m_val_anchor = (that.m_val_anchor); - m_filter_arena = that.m_filter_arena; - m_newline_offsets = (that.m_newline_offsets); - m_newline_offsets_size = (that.m_newline_offsets_size); - m_newline_offsets_capacity = (that.m_newline_offsets_capacity); - m_newline_offsets_buf = (that.m_newline_offsets_buf); - that._clr(); - return *this; -} - -Parser& Parser::operator=(Parser const& that) -{ - _free(); - m_options = (that.m_options); - m_file = (that.m_file); - m_buf = (that.m_buf); - m_root_id = (that.m_root_id); - m_tree = (that.m_tree); - m_stack = that.m_stack; - m_state = &m_stack.top(); - m_key_tag_indentation = (that.m_key_tag_indentation); - m_key_tag2_indentation = (that.m_key_tag2_indentation); - m_key_tag = (that.m_key_tag); - m_key_tag2 = (that.m_key_tag2); - m_val_tag_indentation = (that.m_val_tag_indentation); - m_val_tag = (that.m_val_tag); - m_key_anchor_was_before = (that.m_key_anchor_was_before); - m_key_anchor_indentation = (that.m_key_anchor_indentation); - m_key_anchor = (that.m_key_anchor); - m_val_anchor_indentation = (that.m_val_anchor_indentation); - m_val_anchor = (that.m_val_anchor); - if(that.m_filter_arena.len > 0) - _resize_filter_arena(that.m_filter_arena.len); - if(that.m_newline_offsets_capacity > m_newline_offsets_capacity) - _resize_locations(that.m_newline_offsets_capacity); - _RYML_CB_CHECK(m_stack.m_callbacks, m_newline_offsets_capacity >= that.m_newline_offsets_capacity); - _RYML_CB_CHECK(m_stack.m_callbacks, m_newline_offsets_capacity >= that.m_newline_offsets_size); - memcpy(m_newline_offsets, that.m_newline_offsets, that.m_newline_offsets_size * sizeof(size_t)); - m_newline_offsets_size = that.m_newline_offsets_size; - m_newline_offsets_buf = that.m_newline_offsets_buf; - return *this; -} - -void Parser::_clr() -{ - m_options = {}; - m_file = {}; - m_buf = {}; - m_root_id = {}; - m_tree = {}; - m_stack.clear(); - m_state = {}; - m_key_tag_indentation = {}; - m_key_tag2_indentation = {}; - m_key_tag = {}; - m_key_tag2 = {}; - m_val_tag_indentation = {}; - m_val_tag = {}; - m_key_anchor_was_before = {}; - m_key_anchor_indentation = {}; - m_key_anchor = {}; - m_val_anchor_indentation = {}; - m_val_anchor = {}; - m_filter_arena = {}; - m_newline_offsets = {}; - m_newline_offsets_size = {}; - m_newline_offsets_capacity = {}; - m_newline_offsets_buf = {}; -} - -void Parser::_free() -{ - if(m_newline_offsets) - { - _RYML_CB_FREE(m_stack.m_callbacks, m_newline_offsets, size_t, m_newline_offsets_capacity); - m_newline_offsets = nullptr; - m_newline_offsets_size = 0u; - m_newline_offsets_capacity = 0u; - m_newline_offsets_buf = 0u; - } - if(m_filter_arena.len) - { - _RYML_CB_FREE(m_stack.m_callbacks, m_filter_arena.str, char, m_filter_arena.len); - m_filter_arena = {}; - } - m_stack._free(); -} - - -//----------------------------------------------------------------------------- -void Parser::_reset() -{ - _RYML_CB_ASSERT(m_stack.m_callbacks, m_stack.size() == 1); - m_stack.clear(); - m_stack.push({}); - m_state = &m_stack.top(); - m_state->reset(m_file.str, m_root_id); - - m_key_tag_indentation = 0; - m_key_tag2_indentation = 0; - m_key_tag.clear(); - m_key_tag2.clear(); - m_val_tag_indentation = 0; - m_val_tag.clear(); - m_key_anchor_was_before = false; - m_key_anchor_indentation = 0; - m_key_anchor.clear(); - m_val_anchor_indentation = 0; - m_val_anchor.clear(); - - if(m_options.locations()) - { - _prepare_locations(); - } -} - -//----------------------------------------------------------------------------- -template -void Parser::_fmt_msg(DumpFn &&dumpfn) const -{ - auto const& lc = m_state->line_contents; - csubstr contents = lc.stripped; - if(contents.len) - { - // print the yaml src line - size_t offs = 3u + to_chars(substr{}, m_state->pos.line) + to_chars(substr{}, m_state->pos.col); - if(m_file.len) - { - _parse_dump(dumpfn, "{}:", m_file); - offs += m_file.len + 1; - } - _parse_dump(dumpfn, "{}:{}: ", m_state->pos.line, m_state->pos.col); - csubstr maybe_full_content = (contents.len < 80u ? contents : contents.first(80u)); - csubstr maybe_ellipsis = (contents.len < 80u ? csubstr{} : csubstr("...")); - _parse_dump(dumpfn, "{}{} (size={})\n", maybe_full_content, maybe_ellipsis, contents.len); - // highlight the remaining portion of the previous line - size_t firstcol = (size_t)(lc.rem.begin() - lc.full.begin()); - size_t lastcol = firstcol + lc.rem.len; - for(size_t i = 0; i < offs + firstcol; ++i) - dumpfn(" "); - dumpfn("^"); - for(size_t i = 1, e = (lc.rem.len < 80u ? lc.rem.len : 80u); i < e; ++i) - dumpfn("~"); - _parse_dump(dumpfn, "{} (cols {}-{})\n", maybe_ellipsis, firstcol+1, lastcol+1); - } - else - { - dumpfn("\n"); - } - -#ifdef RYML_DBG - // next line: print the state flags - { - char flagbuf_[64]; - _parse_dump(dumpfn, "top state: {}\n", _prfl(flagbuf_, m_state->flags)); - } -#endif -} - - -//----------------------------------------------------------------------------- -template -void Parser::_err(csubstr fmt, Args const& C4_RESTRICT ...args) const -{ - char errmsg[RYML_ERRMSG_SIZE]; - detail::_SubstrWriter writer(errmsg); - auto dumpfn = [&writer](csubstr s){ writer.append(s); }; - _parse_dump(dumpfn, fmt, args...); - writer.append('\n'); - _fmt_msg(dumpfn); - size_t len = writer.pos < RYML_ERRMSG_SIZE ? writer.pos : RYML_ERRMSG_SIZE; - m_tree->m_callbacks.m_error(errmsg, len, m_state->pos, m_tree->m_callbacks.m_user_data); -} - -//----------------------------------------------------------------------------- -#ifdef RYML_DBG -template -void Parser::_dbg(csubstr fmt, Args const& C4_RESTRICT ...args) const -{ - auto dumpfn = [](csubstr s){ fwrite(s.str, 1, s.len, stdout); }; - _parse_dump(dumpfn, fmt, args...); - dumpfn("\n"); - _fmt_msg(dumpfn); -} -#endif - -//----------------------------------------------------------------------------- -bool Parser::_finished_file() const -{ - bool ret = m_state->pos.offset >= m_buf.len; - if(ret) - { - _c4dbgp("finished file!!!"); - } - return ret; -} - -//----------------------------------------------------------------------------- -bool Parser::_finished_line() const -{ - return m_state->line_contents.rem.empty(); -} - -//----------------------------------------------------------------------------- -void Parser::parse_in_place(csubstr file, substr buf, Tree *t, size_t node_id) -{ - m_file = file; - m_buf = buf; - m_root_id = node_id; - m_tree = t; - _reset(); - while( ! _finished_file()) - { - _scan_line(); - while( ! _finished_line()) - _handle_line(); - if(_finished_file()) - break; // it may have finished because of multiline blocks - _line_ended(); - } - _handle_finished_file(); -} - -//----------------------------------------------------------------------------- -void Parser::_handle_finished_file() -{ - _end_stream(); -} - -//----------------------------------------------------------------------------- -void Parser::_handle_line() -{ - _c4dbgq("\n-----------"); - _c4dbgt("handling line={}, offset={}B", m_state->pos.line, m_state->pos.offset); - _RYML_CB_ASSERT(m_stack.m_callbacks, ! m_state->line_contents.rem.empty()); - if(has_any(RSEQ)) - { - if(has_any(FLOW)) - { - if(_handle_seq_flow()) - return; - } - else - { - if(_handle_seq_blck()) - return; - } - } - else if(has_any(RMAP)) - { - if(has_any(FLOW)) - { - if(_handle_map_flow()) - return; - } - else - { - if(_handle_map_blck()) - return; - } - } - else if(has_any(RUNK)) - { - if(_handle_unk()) - return; - } - - if(_handle_top()) - return; -} - - -//----------------------------------------------------------------------------- -bool Parser::_handle_unk() -{ - _c4dbgp("handle_unk"); - - csubstr rem = m_state->line_contents.rem; - const bool start_as_child = (node(m_state) == nullptr); - - if(C4_UNLIKELY(has_any(NDOC))) - { - if(rem == "---" || rem.begins_with("--- ")) - { - _start_new_doc(rem); - return true; - } - auto trimmed = rem.triml(' '); - if(trimmed == "---" || trimmed.begins_with("--- ")) - { - _RYML_CB_ASSERT(m_stack.m_callbacks, rem.len >= trimmed.len); - _line_progressed(rem.len - trimmed.len); - _start_new_doc(trimmed); - _save_indentation(); - return true; - } - else if(trimmed.begins_with("...")) - { - _end_stream(); - } - else if(trimmed.first_of("#%") == csubstr::npos) // neither a doc nor a tag - { - _c4dbgpf("starting implicit doc to accomodate unexpected tokens: '{}'", rem); - size_t indref = m_state->indref; - _push_level(); - _start_doc(); - _set_indentation(indref); - } - _RYML_CB_ASSERT(m_stack.m_callbacks, !trimmed.empty()); - } - - _RYML_CB_ASSERT(m_stack.m_callbacks, has_none(RNXT|RSEQ|RMAP)); - if(m_state->indref > 0) - { - csubstr ws = rem.left_of(rem.first_not_of(' ')); - if(m_state->indref <= ws.len) - { - _c4dbgpf("skipping base indentation of {}", m_state->indref); - _line_progressed(m_state->indref); - rem = rem.sub(m_state->indref); - } - } - - if(rem.begins_with("- ") _RYML_WITH_TAB_TOKENS( || rem.begins_with("-\t"))) - { - _c4dbgpf("it's a seq (as_child={})", start_as_child); - _move_key_anchor_to_val_anchor(); - _move_key_tag_to_val_tag(); - _push_level(); - _start_seq(start_as_child); - _save_indentation(); - _line_progressed(2); - return true; - } - else if(rem == '-') - { - _c4dbgpf("it's a seq (as_child={})", start_as_child); - _move_key_anchor_to_val_anchor(); - _move_key_tag_to_val_tag(); - _push_level(); - _start_seq(start_as_child); - _save_indentation(); - _line_progressed(1); - return true; - } - else if(rem.begins_with('[')) - { - _c4dbgpf("it's a seq, flow (as_child={})", start_as_child); - _move_key_anchor_to_val_anchor(); - _move_key_tag_to_val_tag(); - _push_level(/*explicit flow*/true); - _start_seq(start_as_child); - add_flags(FLOW); - _line_progressed(1); - return true; - } - else if(rem.begins_with('{')) - { - _c4dbgpf("it's a map, flow (as_child={})", start_as_child); - _move_key_anchor_to_val_anchor(); - _move_key_tag_to_val_tag(); - _push_level(/*explicit flow*/true); - _start_map(start_as_child); - addrem_flags(FLOW|RKEY, RVAL); - _line_progressed(1); - return true; - } - else if(rem.begins_with("? ")) - { - _c4dbgpf("it's a map (as_child={}) + this key is complex", start_as_child); - _move_key_anchor_to_val_anchor(); - _move_key_tag_to_val_tag(); - _push_level(); - _start_map(start_as_child); - addrem_flags(RKEY|QMRK, RVAL); - _save_indentation(); - _line_progressed(2); - return true; - } - else if(rem.begins_with(": ") && !has_all(SSCL)) - { - _c4dbgp("it's a map with an empty key"); - _move_key_anchor_to_val_anchor(); - _move_key_tag_to_val_tag(); - _push_level(); - _start_map(start_as_child); - _store_scalar_null(rem.str); - addrem_flags(RVAL, RKEY); - _save_indentation(); - _line_progressed(2); - return true; - } - else if(rem == ':' && !has_all(SSCL)) - { - _c4dbgp("it's a map with an empty key"); - _move_key_anchor_to_val_anchor(); - _move_key_tag_to_val_tag(); - _push_level(); - _start_map(start_as_child); - _store_scalar_null(rem.str); - addrem_flags(RVAL, RKEY); - _save_indentation(); - _line_progressed(1); - return true; - } - else if(_handle_types()) - { - return true; - } - else if(!rem.begins_with('*') && _handle_key_anchors_and_refs()) - { - return true; - } - else if(has_all(SSCL)) - { - _c4dbgpf("there's a stored scalar: '{}'", m_state->scalar); - - csubstr saved_scalar; - bool is_quoted; - if(_scan_scalar_unk(&saved_scalar, &is_quoted)) - { - rem = m_state->line_contents.rem; - _c4dbgpf("... and there's also a scalar next! '{}'", saved_scalar); - if(rem.begins_with_any(" \t")) - { - size_t n = rem.first_not_of(" \t"); - _c4dbgpf("skipping {} spaces/tabs", n); - rem = rem.sub(n); - _line_progressed(n); - } - } - - _c4dbgpf("rem='{}'", rem); - - if(rem.begins_with(", ")) - { - _c4dbgpf("got a ',' -- it's a seq (as_child={})", start_as_child); - _start_seq(start_as_child); - add_flags(FLOW); - _append_val(_consume_scalar()); - _line_progressed(2); - } - else if(rem.begins_with(',')) - { - _c4dbgpf("got a ',' -- it's a seq (as_child={})", start_as_child); - _start_seq(start_as_child); - add_flags(FLOW); - _append_val(_consume_scalar()); - _line_progressed(1); - } - else if(rem.begins_with(": ") _RYML_WITH_TAB_TOKENS( || rem.begins_with(":\t"))) - { - _c4dbgpf("got a ': ' -- it's a map (as_child={})", start_as_child); - _start_map_unk(start_as_child); // wait for the val scalar to append the key-val pair - _line_progressed(2); - } - else if(rem == ":" || rem.begins_with(":\"") || rem.begins_with(":'")) - { - if(rem == ":") { _c4dbgpf("got a ':' -- it's a map (as_child={})", start_as_child); } - else { _c4dbgpf("got a '{}' -- it's a map (as_child={})", rem.first(2), start_as_child); } - _start_map_unk(start_as_child); // wait for the val scalar to append the key-val pair - _line_progressed(1); // advance only 1 - } - else if(rem.begins_with('}')) - { - if(!has_all(RMAP|FLOW)) - { - _c4err("invalid token: not reading a map"); - } - if(!has_all(SSCL)) - { - _c4err("no scalar stored"); - } - _append_key_val(saved_scalar); - _stop_map(); - _line_progressed(1); - } - else if(rem.begins_with("...")) - { - _c4dbgp("got stream end '...'"); - _end_stream(); - _line_progressed(3); - } - else if(rem.begins_with('#')) - { - _c4dbgpf("it's a comment: '{}'", rem); - _scan_comment(); - return true; - } - else if(_handle_key_anchors_and_refs()) - { - return true; - } - else if(rem.begins_with(" ") || rem.begins_with("\t")) - { - size_t n = rem.first_not_of(" \t"); - if(n == npos) - n = rem.len; - _c4dbgpf("has {} spaces/tabs, skip...", n); - _line_progressed(n); - return true; - } - else if(rem.empty()) - { - // nothing to do - } - else if(rem == "---" || rem.begins_with("--- ")) - { - _c4dbgp("caught ---: starting doc"); - _start_new_doc(rem); - return true; - } - else if(rem.begins_with('%')) - { - _c4dbgp("caught a directive: ignoring..."); - _line_progressed(rem.len); - return true; - } - else - { - _c4err("parse error"); - } - - if( ! saved_scalar.empty()) - { - _store_scalar(saved_scalar, is_quoted); - } - - return true; - } - else - { - _RYML_CB_ASSERT(m_stack.m_callbacks, ! has_any(SSCL)); - csubstr scalar; - size_t indentation = m_state->line_contents.indentation; // save - bool is_quoted; - if(_scan_scalar_unk(&scalar, &is_quoted)) - { - _c4dbgpf("got a {} scalar", is_quoted ? "quoted" : ""); - rem = m_state->line_contents.rem; - { - size_t first = rem.first_not_of(" \t"); - if(first && first != npos) - { - _c4dbgpf("skip {} whitespace characters", first); - _line_progressed(first); - rem = rem.sub(first); - } - } - _store_scalar(scalar, is_quoted); - if(rem.begins_with(": ") _RYML_WITH_TAB_TOKENS( || rem.begins_with(":\t"))) - { - _c4dbgpf("got a ': ' next -- it's a map (as_child={})", start_as_child); - _push_level(); - _start_map(start_as_child); // wait for the val scalar to append the key-val pair - _set_indentation(indentation); - _line_progressed(2); // call this AFTER saving the indentation - } - else if(rem == ":") - { - _c4dbgpf("got a ':' next -- it's a map (as_child={})", start_as_child); - _push_level(); - _start_map(start_as_child); // wait for the val scalar to append the key-val pair - _set_indentation(indentation); - _line_progressed(1); // call this AFTER saving the indentation - } - else - { - // we still don't know whether it's a seq or a map - // so just store the scalar - } - return true; - } - else if(rem.begins_with_any(" \t")) - { - csubstr ws = rem.left_of(rem.first_not_of(" \t")); - rem = rem.right_of(ws); - if(has_all(RTOP) && rem.begins_with("---")) - { - _c4dbgp("there's a doc starting, and it's indented"); - _set_indentation(ws.len); - } - _c4dbgpf("skipping {} spaces/tabs", ws.len); - _line_progressed(ws.len); - return true; - } - } - - return false; -} - - -//----------------------------------------------------------------------------- -C4_ALWAYS_INLINE void Parser::_skipchars(char c) -{ - _RYML_CB_ASSERT(m_stack.m_callbacks, m_state->line_contents.rem.begins_with(c)); - size_t pos = m_state->line_contents.rem.first_not_of(c); - if(pos == npos) - pos = m_state->line_contents.rem.len; // maybe the line is just whitespace - _c4dbgpf("skip {} '{}'", pos, c); - _line_progressed(pos); -} - -template -C4_ALWAYS_INLINE void Parser::_skipchars(const char (&chars)[N]) -{ - _RYML_CB_ASSERT(m_stack.m_callbacks, m_state->line_contents.rem.begins_with_any(chars)); - size_t pos = m_state->line_contents.rem.first_not_of(chars); - if(pos == npos) - pos = m_state->line_contents.rem.len; // maybe the line is just whitespace - _c4dbgpf("skip {} characters", pos); - _line_progressed(pos); -} - - -//----------------------------------------------------------------------------- -bool Parser::_handle_seq_flow() -{ - _c4dbgpf("handle_seq_flow: node_id={} level={}", m_state->node_id, m_state->level); - csubstr rem = m_state->line_contents.rem; - - _RYML_CB_ASSERT(m_stack.m_callbacks, has_none(RKEY)); - _RYML_CB_ASSERT(m_stack.m_callbacks, has_all(RSEQ|FLOW)); - - if(rem.begins_with(' ')) - { - // with explicit flow, indentation does not matter - _c4dbgp("starts with spaces"); - _skipchars(' '); - return true; - } - _RYML_WITH_TAB_TOKENS(else if(rem.begins_with('\t')) - { - _c4dbgp("starts with tabs"); - _skipchars('\t'); - return true; - }) - else if(rem.begins_with('#')) - { - _c4dbgp("it's a comment"); - rem = _scan_comment(); // also progresses the line - return true; - } - else if(rem.begins_with(']')) - { - _c4dbgp("end the sequence"); - _pop_level(); - _line_progressed(1); - if(has_all(RSEQIMAP)) - { - _stop_seqimap(); - _pop_level(); - } - return true; - } - - if(has_any(RVAL)) - { - _RYML_CB_ASSERT(m_stack.m_callbacks, has_none(RNXT)); - bool is_quoted; - if(_scan_scalar_seq_flow(&rem, &is_quoted)) - { - _c4dbgp("it's a scalar"); - addrem_flags(RNXT, RVAL); - _append_val(rem, is_quoted); - return true; - } - else if(rem.begins_with('[')) - { - _c4dbgp("val is a child seq"); - addrem_flags(RNXT, RVAL); // before _push_level! - _push_level(/*explicit flow*/true); - _start_seq(); - add_flags(FLOW); - _line_progressed(1); - return true; - } - else if(rem.begins_with('{')) - { - _c4dbgp("val is a child map"); - addrem_flags(RNXT, RVAL); // before _push_level! - _push_level(/*explicit flow*/true); - _start_map(); - addrem_flags(FLOW|RKEY, RVAL); - _line_progressed(1); - return true; - } - else if(rem == ':') - { - _c4dbgpf("found ':' -- there's an implicit map in the seq node[{}]", m_state->node_id); - _start_seqimap(); - _line_progressed(1); - return true; - } - else if(rem.begins_with(": ") _RYML_WITH_TAB_TOKENS( || rem.begins_with(":\t"))) - { - _c4dbgpf("found ': ' -- there's an implicit map in the seq node[{}]", m_state->node_id); - _start_seqimap(); - _line_progressed(2); - return true; - } - else if(rem.begins_with("? ")) - { - _c4dbgpf("found '? ' -- there's an implicit map in the seq node[{}]", m_state->node_id); - _start_seqimap(); - _line_progressed(2); - _RYML_CB_ASSERT(m_stack.m_callbacks, has_any(SSCL) && m_state->scalar == ""); - addrem_flags(QMRK|RKEY, RVAL|SSCL); - return true; - } - else if(_handle_types()) - { - return true; - } - else if(_handle_val_anchors_and_refs()) - { - return true; - } - else if(rem.begins_with(", ")) - { - _c4dbgp("found ',' -- the value was null"); - _append_val_null(rem.str - 1); - _line_progressed(2); - return true; - } - else if(rem.begins_with(',')) - { - _c4dbgp("found ',' -- the value was null"); - _append_val_null(rem.str - 1); - _line_progressed(1); - return true; - } - else if(rem.begins_with('\t')) - { - _skipchars('\t'); - return true; - } - else - { - _c4err("parse error"); - } - } - else if(has_any(RNXT)) - { - _RYML_CB_ASSERT(m_stack.m_callbacks, has_none(RVAL)); - if(rem.begins_with(", ")) - { - _RYML_CB_ASSERT(m_stack.m_callbacks, has_all(FLOW)); - _c4dbgp("seq: expect next val"); - addrem_flags(RVAL, RNXT); - _line_progressed(2); - return true; - } - else if(rem.begins_with(',')) - { - _RYML_CB_ASSERT(m_stack.m_callbacks, has_all(FLOW)); - _c4dbgp("seq: expect next val"); - addrem_flags(RVAL, RNXT); - _line_progressed(1); - return true; - } - else if(rem == ':') - { - _c4dbgpf("found ':' -- there's an implicit map in the seq node[{}]", m_state->node_id); - _start_seqimap(); - _line_progressed(1); - return true; - } - else if(rem.begins_with(": ") _RYML_WITH_TAB_TOKENS( || rem.begins_with(":\t"))) - { - _c4dbgpf("found ': ' -- there's an implicit map in the seq node[{}]", m_state->node_id); - _start_seqimap(); - _line_progressed(2); - return true; - } - else - { - _c4err("was expecting a comma"); - } - } - else - { - _c4err("internal error"); - } - - return true; -} - -//----------------------------------------------------------------------------- -bool Parser::_handle_seq_blck() -{ - _c4dbgpf("handle_seq_impl: node_id={} level={}", m_state->node_id, m_state->level); - csubstr rem = m_state->line_contents.rem; - - _RYML_CB_ASSERT(m_stack.m_callbacks, has_all(RSEQ)); - _RYML_CB_ASSERT(m_stack.m_callbacks, has_none(RKEY)); - _RYML_CB_ASSERT(m_stack.m_callbacks, has_none(FLOW)); - - if(rem.begins_with('#')) - { - _c4dbgp("it's a comment"); - rem = _scan_comment(); - return true; - } - if(has_any(RNXT)) - { - _RYML_CB_ASSERT(m_stack.m_callbacks, has_none(RVAL)); - - if(_handle_indentation()) - return true; - - if(rem.begins_with("- ") _RYML_WITH_TAB_TOKENS( || rem.begins_with("-\t"))) - { - _c4dbgp("expect another val"); - addrem_flags(RVAL, RNXT); - _line_progressed(2); - return true; - } - else if(rem == '-') - { - _c4dbgp("expect another val"); - addrem_flags(RVAL, RNXT); - _line_progressed(1); - return true; - } - else if(rem.begins_with_any(" \t")) - { - _RYML_CB_ASSERT(m_stack.m_callbacks, ! _at_line_begin()); - _skipchars(" \t"); - return true; - } - else if(rem.begins_with("...")) - { - _c4dbgp("got stream end '...'"); - _end_stream(); - _line_progressed(3); - return true; - } - else if(rem.begins_with("---")) - { - _c4dbgp("got document start '---'"); - _start_new_doc(rem); - return true; - } - else - { - _c4err("parse error"); - } - } - else if(has_any(RVAL)) - { - // there can be empty values - if(_handle_indentation()) - return true; - - csubstr s; - bool is_quoted; - if(_scan_scalar_seq_blck(&s, &is_quoted)) // this also progresses the line - { - _c4dbgpf("it's a{} scalar", is_quoted ? " quoted" : ""); - - rem = m_state->line_contents.rem; - if(_RYML_WITH_OR_WITHOUT_TAB_TOKENS(rem.begins_with_any(" \t"), rem.begins_with(' '))) - { - _c4dbgp("skipping whitespace..."); - size_t skip = rem.first_not_of(_RYML_WITH_OR_WITHOUT_TAB_TOKENS(" \t", ' ')); - if(skip == csubstr::npos) - skip = rem.len; // maybe the line is just whitespace - _line_progressed(skip); - rem = rem.sub(skip); - } - - _c4dbgpf("rem=[{}]~~~{}~~~", rem.len, rem); - if(!rem.begins_with('#') && (rem.ends_with(':') || rem.begins_with(": ") _RYML_WITH_TAB_TOKENS( || rem.begins_with(":\t")))) - { - _c4dbgp("actually, the scalar is the first key of a map, and it opens a new scope"); - if(m_key_anchor.empty()) - _move_val_anchor_to_key_anchor(); - if(m_key_tag.empty()) - _move_val_tag_to_key_tag(); - addrem_flags(RNXT, RVAL); // before _push_level! This prepares the current level for popping by setting it to RNXT - _push_level(); - _start_map(); - _store_scalar(s, is_quoted); - if( ! _maybe_set_indentation_from_anchor_or_tag()) - { - _c4dbgpf("set indentation from scalar: {}", m_state->scalar_col); - _set_indentation(m_state->scalar_col); // this is the column where the scalar starts - } - _move_key_tag2_to_key_tag(); - addrem_flags(RVAL, RKEY); - _line_progressed(1); - } - else - { - _c4dbgp("appending val to current seq"); - _append_val(s, is_quoted); - addrem_flags(RNXT, RVAL); - } - return true; - } - else if(rem.begins_with("- ") _RYML_WITH_TAB_TOKENS( || rem.begins_with("-\t"))) - { - if(_rval_dash_start_or_continue_seq()) - _line_progressed(2); - return true; - } - else if(rem == '-') - { - if(_rval_dash_start_or_continue_seq()) - _line_progressed(1); - return true; - } - else if(rem.begins_with('[')) - { - _c4dbgp("val is a child seq, flow"); - addrem_flags(RNXT, RVAL); // before _push_level! - _push_level(/*explicit flow*/true); - _start_seq(); - add_flags(FLOW); - _line_progressed(1); - return true; - } - else if(rem.begins_with('{')) - { - _c4dbgp("val is a child map, flow"); - addrem_flags(RNXT, RVAL); // before _push_level! - _push_level(/*explicit flow*/true); - _start_map(); - addrem_flags(FLOW|RKEY, RVAL); - _line_progressed(1); - return true; - } - else if(rem.begins_with("? ")) - { - _c4dbgp("val is a child map + this key is complex"); - addrem_flags(RNXT, RVAL); // before _push_level! - _push_level(); - _start_map(); - addrem_flags(QMRK|RKEY, RVAL); - _save_indentation(); - _line_progressed(2); - return true; - } - else if(rem.begins_with(' ')) - { - csubstr spc = rem.left_of(rem.first_not_of(' ')); - if(_at_line_begin()) - { - _c4dbgpf("skipping value indentation: {} spaces", spc.len); - _line_progressed(spc.len); - return true; - } - else - { - _c4dbgpf("skipping {} spaces", spc.len); - _line_progressed(spc.len); - return true; - } - } - else if(_handle_types()) - { - return true; - } - else if(_handle_val_anchors_and_refs()) - { - return true; - } - /* pathological case: - * - &key : val - * - &key : - * - : val - */ - else if((!has_all(SSCL)) && - (rem.begins_with(": ") || rem.left_of(rem.find("#")).trimr("\t") == ":")) - { - if(!m_val_anchor.empty() || !m_val_tag.empty()) - { - _c4dbgp("val is a child map + this key is empty, with anchors or tags"); - addrem_flags(RNXT, RVAL); // before _push_level! - _move_val_tag_to_key_tag(); - _move_val_anchor_to_key_anchor(); - _push_level(); - _start_map(); - _store_scalar_null(rem.str); - addrem_flags(RVAL, RKEY); - RYML_CHECK(_maybe_set_indentation_from_anchor_or_tag()); // one of them must exist - _line_progressed(rem.begins_with(": ") ? 2u : 1u); - return true; - } - else - { - _c4dbgp("val is a child map + this key is empty, no anchors or tags"); - addrem_flags(RNXT, RVAL); // before _push_level! - size_t ind = m_state->indref; - _push_level(); - _start_map(); - _store_scalar_null(rem.str); - addrem_flags(RVAL, RKEY); - _c4dbgpf("set indentation from map anchor: {}", ind + 2); - _set_indentation(ind + 2); // this is the column where the map starts - _line_progressed(rem.begins_with(": ") ? 2u : 1u); - return true; - } - } - else - { - _c4err("parse error"); - } - } - - return false; -} - -//----------------------------------------------------------------------------- - -bool Parser::_rval_dash_start_or_continue_seq() -{ - size_t ind = m_state->line_contents.current_col(); - _RYML_CB_ASSERT(m_stack.m_callbacks, ind >= m_state->indref); - size_t delta_ind = ind - m_state->indref; - if( ! delta_ind) - { - _c4dbgp("prev val was empty"); - addrem_flags(RNXT, RVAL); - _append_val_null(&m_state->line_contents.full[ind]); - return false; - } - _c4dbgp("val is a nested seq, indented"); - addrem_flags(RNXT, RVAL); // before _push_level! - _push_level(); - _start_seq(); - _save_indentation(); - return true; -} - -//----------------------------------------------------------------------------- -bool Parser::_handle_map_flow() -{ - // explicit flow, ie, inside {}, separated by commas - _c4dbgpf("handle_map_flow: node_id={} level={}", m_state->node_id, m_state->level); - csubstr rem = m_state->line_contents.rem; - - _RYML_CB_ASSERT(m_stack.m_callbacks, has_all(RMAP|FLOW)); - - if(rem.begins_with(' ')) - { - // with explicit flow, indentation does not matter - _c4dbgp("starts with spaces"); - _skipchars(' '); - return true; - } - _RYML_WITH_TAB_TOKENS(else if(rem.begins_with('\t')) - { - // with explicit flow, indentation does not matter - _c4dbgp("starts with tabs"); - _skipchars('\t'); - return true; - }) - else if(rem.begins_with('#')) - { - _c4dbgp("it's a comment"); - rem = _scan_comment(); // also progresses the line - return true; - } - else if(rem.begins_with('}')) - { - _c4dbgp("end the map"); - if(has_all(SSCL)) - { - _c4dbgp("the last val was null"); - _append_key_val_null(rem.str - 1); - rem_flags(RVAL); - } - _pop_level(); - _line_progressed(1); - if(has_all(RSEQIMAP)) - { - _c4dbgp("stopping implicitly nested 1x map"); - _stop_seqimap(); - _pop_level(); - } - return true; - } - - if(has_any(RNXT)) - { - _RYML_CB_ASSERT(m_stack.m_callbacks, has_none(RKEY)); - _RYML_CB_ASSERT(m_stack.m_callbacks, has_none(RVAL)); - _RYML_CB_ASSERT(m_stack.m_callbacks, has_none(RSEQIMAP)); - - if(rem.begins_with(", ")) - { - _c4dbgp("seq: expect next keyval"); - addrem_flags(RKEY, RNXT); - _line_progressed(2); - return true; - } - else if(rem.begins_with(',')) - { - _c4dbgp("seq: expect next keyval"); - addrem_flags(RKEY, RNXT); - _line_progressed(1); - return true; - } - else - { - _c4err("parse error"); - } - } - else if(has_any(RKEY)) - { - _RYML_CB_ASSERT(m_stack.m_callbacks, has_none(RNXT)); - _RYML_CB_ASSERT(m_stack.m_callbacks, has_none(RVAL)); - - bool is_quoted; - if(has_none(SSCL) && _scan_scalar_map_flow(&rem, &is_quoted)) - { - _c4dbgp("it's a scalar"); - _store_scalar(rem, is_quoted); - rem = m_state->line_contents.rem; - csubstr trimmed = rem.triml(" \t"); - if(trimmed.len && (trimmed.begins_with(": ") || trimmed.begins_with_any(":,}") _RYML_WITH_TAB_TOKENS( || rem.begins_with(":\t")))) - { - _RYML_CB_ASSERT(m_stack.m_callbacks, trimmed.str >= rem.str); - size_t num = static_cast(trimmed.str - rem.str); - _c4dbgpf("trimming {} whitespace after the scalar: '{}' --> '{}'", num, rem, rem.sub(num)); - rem = rem.sub(num); - _line_progressed(num); - } - } - - if(rem.begins_with(": ") _RYML_WITH_TAB_TOKENS( || rem.begins_with(":\t"))) - { - _c4dbgp("wait for val"); - addrem_flags(RVAL, RKEY|QMRK); - _line_progressed(2); - if(!has_all(SSCL)) - { - _c4dbgp("no key was found, defaulting to empty key ''"); - _store_scalar_null(rem.str); - } - return true; - } - else if(rem == ':') - { - _c4dbgp("wait for val"); - addrem_flags(RVAL, RKEY|QMRK); - _line_progressed(1); - if(!has_all(SSCL)) - { - _c4dbgp("no key was found, defaulting to empty key ''"); - _store_scalar_null(rem.str); - } - return true; - } - else if(rem.begins_with('?')) - { - _c4dbgp("complex key"); - add_flags(QMRK); - _line_progressed(1); - return true; - } - else if(rem.begins_with(',')) - { - _c4dbgp("prev scalar was a key with null value"); - _append_key_val_null(rem.str - 1); - _line_progressed(1); - return true; - } - else if(rem.begins_with('}')) - { - _c4dbgp("map terminates after a key..."); - _RYML_CB_ASSERT(m_stack.m_callbacks, has_all(SSCL)); - _c4dbgp("the last val was null"); - _append_key_val_null(rem.str - 1); - rem_flags(RVAL); - if(has_all(RSEQIMAP)) - { - _c4dbgp("stopping implicitly nested 1x map"); - _stop_seqimap(); - _pop_level(); - } - _pop_level(); - _line_progressed(1); - return true; - } - else if(_handle_types()) - { - return true; - } - else if(_handle_key_anchors_and_refs()) - { - return true; - } - else if(rem == "") - { - return true; - } - else - { - size_t pos = rem.first_not_of(" \t"); - if(pos == csubstr::npos) - pos = 0; - rem = rem.sub(pos); - if(rem.begins_with(':')) - { - _c4dbgp("wait for val"); - addrem_flags(RVAL, RKEY|QMRK); - _line_progressed(pos + 1); - if(!has_all(SSCL)) - { - _c4dbgp("no key was found, defaulting to empty key ''"); - _store_scalar_null(rem.str); - } - return true; - } - else if(rem.begins_with('#')) - { - _c4dbgp("it's a comment"); - _line_progressed(pos); - rem = _scan_comment(); // also progresses the line - return true; - } - else - { - _c4err("parse error"); - } - } - } - else if(has_any(RVAL)) - { - _RYML_CB_ASSERT(m_stack.m_callbacks, has_none(RNXT)); - _RYML_CB_ASSERT(m_stack.m_callbacks, has_none(RKEY)); - _RYML_CB_ASSERT(m_stack.m_callbacks, has_all(SSCL)); - bool is_quoted; - if(_scan_scalar_map_flow(&rem, &is_quoted)) - { - _c4dbgp("it's a scalar"); - addrem_flags(RNXT, RVAL|RKEY); - _append_key_val(rem, is_quoted); - if(has_all(RSEQIMAP)) - { - _c4dbgp("stopping implicitly nested 1x map"); - _stop_seqimap(); - _pop_level(); - } - return true; - } - else if(rem.begins_with('[')) - { - _c4dbgp("val is a child seq"); - addrem_flags(RNXT, RVAL|RKEY); // before _push_level! - _push_level(/*explicit flow*/true); - _move_scalar_from_top(); - _start_seq(); - add_flags(FLOW); - _line_progressed(1); - return true; - } - else if(rem.begins_with('{')) - { - _c4dbgp("val is a child map"); - addrem_flags(RNXT, RVAL|RKEY); // before _push_level! - _push_level(/*explicit flow*/true); - _move_scalar_from_top(); - _start_map(); - addrem_flags(FLOW|RKEY, RNXT|RVAL); - _line_progressed(1); - return true; - } - else if(_handle_types()) - { - return true; - } - else if(_handle_val_anchors_and_refs()) - { - return true; - } - else if(rem.begins_with(',')) - { - _c4dbgp("appending empty val"); - _append_key_val_null(rem.str - 1); - addrem_flags(RKEY, RVAL); - _line_progressed(1); - if(has_any(RSEQIMAP)) - { - _c4dbgp("stopping implicitly nested 1x map"); - _stop_seqimap(); - _pop_level(); - } - return true; - } - else if(has_any(RSEQIMAP) && rem.begins_with(']')) - { - _c4dbgp("stopping implicitly nested 1x map"); - if(has_any(SSCL)) - { - _append_key_val_null(rem.str - 1); - } - _stop_seqimap(); - _pop_level(); - return true; - } - else - { - _c4err("parse error"); - } - } - else - { - _c4err("internal error"); - } - - return false; -} - -//----------------------------------------------------------------------------- -bool Parser::_handle_map_blck() -{ - _c4dbgpf("handle_map_blck: node_id={} level={}", m_state->node_id, m_state->level); - csubstr rem = m_state->line_contents.rem; - - _RYML_CB_ASSERT(m_stack.m_callbacks, has_all(RMAP)); - _RYML_CB_ASSERT(m_stack.m_callbacks, has_none(FLOW)); - - if(rem.begins_with('#')) - { - _c4dbgp("it's a comment"); - rem = _scan_comment(); - return true; - } - - if(has_any(RNXT)) - { - _RYML_CB_ASSERT(m_stack.m_callbacks, has_none(RKEY)); - _RYML_CB_ASSERT(m_stack.m_callbacks, has_none(RVAL)); - // actually, we don't need RNXT in indent-based maps. - addrem_flags(RKEY, RNXT); - } - - if(_handle_indentation()) - { - _c4dbgp("indentation token"); - return true; - } - - if(has_any(RKEY)) - { - _RYML_CB_ASSERT(m_stack.m_callbacks, has_none(RNXT)); - _RYML_CB_ASSERT(m_stack.m_callbacks, has_none(RVAL)); - - _c4dbgp("RMAP|RKEY read scalar?"); - bool is_quoted; - if(_scan_scalar_map_blck(&rem, &is_quoted)) // this also progresses the line - { - _c4dbgpf("it's a{} scalar", is_quoted ? " quoted" : ""); - if(has_all(QMRK|SSCL)) - { - _c4dbgpf("current key is QMRK; SSCL is set. so take store scalar='{}' as key and add an empty val", m_state->scalar); - _append_key_val_null(rem.str - 1); - } - _store_scalar(rem, is_quoted); - if(has_all(QMRK|RSET)) - { - _c4dbgp("it's a complex key, so use null value '~'"); - _append_key_val_null(rem.str); - } - rem = m_state->line_contents.rem; - - if(rem.begins_with(':')) - { - _c4dbgp("wait for val"); - addrem_flags(RVAL, RKEY|QMRK); - _line_progressed(1); - rem = m_state->line_contents.rem; - if(rem.begins_with_any(" \t")) - { - _RYML_CB_ASSERT(m_stack.m_callbacks, ! _at_line_begin()); - rem = rem.left_of(rem.first_not_of(" \t")); - _c4dbgpf("skip {} spaces/tabs", rem.len); - _line_progressed(rem.len); - } - } - return true; - } - else if(rem.begins_with_any(" \t")) - { - size_t pos = rem.first_not_of(" \t"); - if(pos == npos) - pos = rem.len; - _c4dbgpf("skip {} spaces/tabs", pos); - _line_progressed(pos); - return true; - } - else if(rem == '?' || rem.begins_with("? ")) - { - _c4dbgp("it's a complex key"); - _line_progressed(rem.begins_with("? ") ? 2u : 1u); - if(has_any(SSCL)) - _append_key_val_null(rem.str - 1); - add_flags(QMRK); - return true; - } - else if(has_all(QMRK) && rem.begins_with(':')) - { - _c4dbgp("complex key finished"); - if(!has_any(SSCL)) - _store_scalar_null(rem.str); - addrem_flags(RVAL, RKEY|QMRK); - _line_progressed(1); - rem = m_state->line_contents.rem; - if(rem.begins_with(' ')) - { - _RYML_CB_ASSERT(m_stack.m_callbacks, ! _at_line_begin()); - _skipchars(' '); - } - return true; - } - else if(rem == ':' || rem.begins_with(": ") _RYML_WITH_TAB_TOKENS( || rem.begins_with(":\t"))) - { - _c4dbgp("key finished"); - if(!has_all(SSCL)) - { - _c4dbgp("key was empty..."); - _store_scalar_null(rem.str); - rem_flags(QMRK); - } - addrem_flags(RVAL, RKEY); - _line_progressed(rem == ':' ? 1 : 2); - return true; - } - else if(rem.begins_with("...")) - { - _c4dbgp("end current document"); - _end_stream(); - _line_progressed(3); - return true; - } - else if(rem.begins_with("---")) - { - _c4dbgp("start new document '---'"); - _start_new_doc(rem); - return true; - } - else if(_handle_types()) - { - return true; - } - else if(_handle_key_anchors_and_refs()) - { - return true; - } - else - { - _c4err("parse error"); - } - } - else if(has_any(RVAL)) - { - _RYML_CB_ASSERT(m_stack.m_callbacks, has_none(RNXT)); - _RYML_CB_ASSERT(m_stack.m_callbacks, has_none(RKEY)); - - _c4dbgp("RMAP|RVAL read scalar?"); - csubstr s; - bool is_quoted; - if(_scan_scalar_map_blck(&s, &is_quoted)) // this also progresses the line - { - _c4dbgpf("it's a{} scalar", is_quoted ? " quoted" : ""); - - rem = m_state->line_contents.rem; - - if(rem.begins_with(": ")) - { - _c4dbgp("actually, the scalar is the first key of a map"); - addrem_flags(RKEY, RVAL); // before _push_level! This prepares the current level for popping by setting it to RNXT - _push_level(); - _move_scalar_from_top(); - _move_val_anchor_to_key_anchor(); - _start_map(); - _save_indentation(m_state->scalar_col); - addrem_flags(RVAL, RKEY); - _line_progressed(2); - } - else if(rem.begins_with(':')) - { - _c4dbgp("actually, the scalar is the first key of a map, and it opens a new scope"); - addrem_flags(RKEY, RVAL); // before _push_level! This prepares the current level for popping by setting it to RNXT - _push_level(); - _move_scalar_from_top(); - _move_val_anchor_to_key_anchor(); - _start_map(); - _save_indentation(/*behind*/s.len); - addrem_flags(RVAL, RKEY); - _line_progressed(1); - } - else - { - _c4dbgp("appending keyval to current map"); - _append_key_val(s, is_quoted); - addrem_flags(RKEY, RVAL); - } - return true; - } - else if(rem.begins_with("- ") _RYML_WITH_TAB_TOKENS( || rem.begins_with("-\t"))) - { - _c4dbgp("val is a nested seq, indented"); - addrem_flags(RKEY, RVAL); // before _push_level! - _push_level(); - _move_scalar_from_top(); - _start_seq(); - _save_indentation(); - _line_progressed(2); - return true; - } - else if(rem == '-') - { - _c4dbgp("maybe a seq. start unknown, indented"); - _start_unk(); - _save_indentation(); - _line_progressed(1); - return true; - } - else if(rem.begins_with('[')) - { - _c4dbgp("val is a child seq, flow"); - addrem_flags(RKEY, RVAL); // before _push_level! - _push_level(/*explicit flow*/true); - _move_scalar_from_top(); - _start_seq(); - add_flags(FLOW); - _line_progressed(1); - return true; - } - else if(rem.begins_with('{')) - { - _c4dbgp("val is a child map, flow"); - addrem_flags(RKEY, RVAL); // before _push_level! - _push_level(/*explicit flow*/true); - _move_scalar_from_top(); - _start_map(); - addrem_flags(FLOW|RKEY, RVAL); - _line_progressed(1); - return true; - } - else if(rem.begins_with(' ')) - { - csubstr spc = rem.left_of(rem.first_not_of(' ')); - if(_at_line_begin()) - { - _c4dbgpf("skipping value indentation: {} spaces", spc.len); - _line_progressed(spc.len); - return true; - } - else - { - _c4dbgpf("skipping {} spaces", spc.len); - _line_progressed(spc.len); - return true; - } - } - else if(_handle_types()) - { - return true; - } - else if(_handle_val_anchors_and_refs()) - { - return true; - } - else if(rem.begins_with("--- ") || rem == "---" || rem.begins_with("---\t")) - { - _start_new_doc(rem); - return true; - } - else if(rem.begins_with("...")) - { - _c4dbgp("end current document"); - _end_stream(); - _line_progressed(3); - return true; - } - else - { - _c4err("parse error"); - } - } - else - { - _c4err("internal error"); - } - - return false; -} - - -//----------------------------------------------------------------------------- -bool Parser::_handle_top() -{ - _c4dbgp("handle_top"); - csubstr rem = m_state->line_contents.rem; - - if(rem.begins_with('#')) - { - _c4dbgp("a comment line"); - _scan_comment(); - return true; - } - - csubstr trimmed = rem.triml(' '); - - if(trimmed.begins_with('%')) - { - _handle_directive(trimmed); - _line_progressed(rem.len); - return true; - } - else if(trimmed.begins_with("--- ") || trimmed == "---" || trimmed.begins_with("---\t")) - { - _start_new_doc(rem); - if(trimmed.len < rem.len) - { - _line_progressed(rem.len - trimmed.len); - _save_indentation(); - } - return true; - } - else if(trimmed.begins_with("...")) - { - _c4dbgp("end current document"); - _end_stream(); - if(trimmed.len < rem.len) - { - _line_progressed(rem.len - trimmed.len); - } - _line_progressed(3); - return true; - } - else - { - _c4err("parse error"); - } - - return false; -} - - -//----------------------------------------------------------------------------- - -bool Parser::_handle_key_anchors_and_refs() -{ - _RYML_CB_ASSERT(m_stack.m_callbacks, !has_any(RVAL)); - const csubstr rem = m_state->line_contents.rem; - if(rem.begins_with('&')) - { - _c4dbgp("found a key anchor!!!"); - if(has_all(QMRK|SSCL)) - { - _RYML_CB_ASSERT(m_stack.m_callbacks, has_any(RKEY)); - _c4dbgp("there is a stored key, so this anchor is for the next element"); - _append_key_val_null(rem.str - 1); - rem_flags(QMRK); - return true; - } - csubstr anchor = rem.left_of(rem.first_of(' ')); - _line_progressed(anchor.len); - anchor = anchor.sub(1); // skip the first character - _move_key_anchor_to_val_anchor(); - _c4dbgpf("key anchor value: '{}'", anchor); - m_key_anchor = anchor; - m_key_anchor_indentation = m_state->line_contents.current_col(rem); - return true; - } - else if(C4_UNLIKELY(rem.begins_with('*'))) - { - _c4err("not implemented - this should have been catched elsewhere"); - C4_NEVER_REACH(); - return false; - } - return false; -} - -bool Parser::_handle_val_anchors_and_refs() -{ - _RYML_CB_ASSERT(m_stack.m_callbacks, !has_any(RKEY)); - const csubstr rem = m_state->line_contents.rem; - if(rem.begins_with('&')) - { - csubstr anchor = rem.left_of(rem.first_of(' ')); - _line_progressed(anchor.len); - anchor = anchor.sub(1); // skip the first character - _c4dbgpf("val: found an anchor: '{}', indentation={}!!!", anchor, m_state->line_contents.current_col(rem)); - if(m_val_anchor.empty()) - { - _c4dbgpf("save val anchor: '{}'", anchor); - m_val_anchor = anchor; - m_val_anchor_indentation = m_state->line_contents.current_col(rem); - } - else - { - _c4dbgpf("there is a pending val anchor '{}'", m_val_anchor); - if(m_tree->is_seq(m_state->node_id)) - { - if(m_tree->has_children(m_state->node_id)) - { - _c4dbgpf("current node={} is a seq, has {} children", m_state->node_id, m_tree->num_children(m_state->node_id)); - _c4dbgpf("... so take the new one as a key anchor '{}'", anchor); - m_key_anchor = anchor; - m_key_anchor_indentation = m_state->line_contents.current_col(rem); - } - else - { - _c4dbgpf("current node={} is a seq, has no children", m_state->node_id); - if(m_tree->has_val_anchor(m_state->node_id)) - { - _c4dbgpf("... node={} already has val anchor: '{}'", m_state->node_id, m_tree->val_anchor(m_state->node_id)); - _c4dbgpf("... so take the new one as a key anchor '{}'", anchor); - m_key_anchor = anchor; - m_key_anchor_indentation = m_state->line_contents.current_col(rem); - } - else - { - _c4dbgpf("... so set pending val anchor: '{}' on current node {}", m_val_anchor, m_state->node_id); - m_tree->set_val_anchor(m_state->node_id, m_val_anchor); - m_val_anchor = anchor; - m_val_anchor_indentation = m_state->line_contents.current_col(rem); - } - } - } - } - return true; - } - else if(C4_UNLIKELY(rem.begins_with('*'))) - { - _c4err("not implemented - this should have been catched elsewhere"); - C4_NEVER_REACH(); - return false; - } - return false; -} - -void Parser::_move_key_anchor_to_val_anchor() -{ - if(m_key_anchor.empty()) - return; - _c4dbgpf("move current key anchor to val slot: key='{}' -> val='{}'", m_key_anchor, m_val_anchor); - if(!m_val_anchor.empty()) - _c4err("triple-pending anchor"); - m_val_anchor = m_key_anchor; - m_val_anchor_indentation = m_key_anchor_indentation; - m_key_anchor = {}; - m_key_anchor_indentation = {}; -} - -void Parser::_move_val_anchor_to_key_anchor() -{ - if(m_val_anchor.empty()) - return; - if(!_token_is_from_this_line(m_val_anchor)) - return; - _c4dbgpf("move current val anchor to key slot: key='{}' <- val='{}'", m_key_anchor, m_val_anchor); - if(!m_key_anchor.empty()) - _c4err("triple-pending anchor"); - m_key_anchor = m_val_anchor; - m_key_anchor_indentation = m_val_anchor_indentation; - m_val_anchor = {}; - m_val_anchor_indentation = {}; -} - -void Parser::_move_key_tag_to_val_tag() -{ - if(m_key_tag.empty()) - return; - _c4dbgpf("move key tag to val tag: key='{}' -> val='{}'", m_key_tag, m_val_tag); - m_val_tag = m_key_tag; - m_val_tag_indentation = m_key_tag_indentation; - m_key_tag.clear(); - m_key_tag_indentation = 0; -} - -void Parser::_move_val_tag_to_key_tag() -{ - if(m_val_tag.empty()) - return; - if(!_token_is_from_this_line(m_val_tag)) - return; - _c4dbgpf("move val tag to key tag: key='{}' <- val='{}'", m_key_tag, m_val_tag); - m_key_tag = m_val_tag; - m_key_tag_indentation = m_val_tag_indentation; - m_val_tag.clear(); - m_val_tag_indentation = 0; -} - -void Parser::_move_key_tag2_to_key_tag() -{ - if(m_key_tag2.empty()) - return; - _c4dbgpf("move key tag2 to key tag: key='{}' <- key2='{}'", m_key_tag, m_key_tag2); - m_key_tag = m_key_tag2; - m_key_tag_indentation = m_key_tag2_indentation; - m_key_tag2.clear(); - m_key_tag2_indentation = 0; -} - - -//----------------------------------------------------------------------------- - -bool Parser::_handle_types() -{ - csubstr rem = m_state->line_contents.rem.triml(' '); - csubstr t; - - if(rem.begins_with("!!")) - { - _c4dbgp("begins with '!!'"); - t = rem.left_of(rem.first_of(" ,")); - _RYML_CB_ASSERT(m_stack.m_callbacks, t.len >= 2); - //t = t.sub(2); - if(t == "!!set") - add_flags(RSET); - } - else if(rem.begins_with("!<")) - { - _c4dbgp("begins with '!<'"); - t = rem.left_of(rem.first_of('>'), true); - _RYML_CB_ASSERT(m_stack.m_callbacks, t.len >= 2); - //t = t.sub(2, t.len-1); - } - else if(rem.begins_with("!h!")) - { - _c4dbgp("begins with '!h!'"); - t = rem.left_of(rem.first_of(' ')); - _RYML_CB_ASSERT(m_stack.m_callbacks, t.len >= 3); - //t = t.sub(3); - } - else if(rem.begins_with('!')) - { - _c4dbgp("begins with '!'"); - t = rem.left_of(rem.first_of(' ')); - _RYML_CB_ASSERT(m_stack.m_callbacks, t.len >= 1); - //t = t.sub(1); - } - - if(t.empty()) - return false; - - if(has_all(QMRK|SSCL)) - { - _RYML_CB_ASSERT(m_stack.m_callbacks, has_any(RKEY)); - _c4dbgp("there is a stored key, so this tag is for the next element"); - _append_key_val_null(rem.str - 1); - rem_flags(QMRK); - } - - #ifdef RYML_NO_COVERAGE__TO_BE_DELETED - const char *tag_beginning = rem.str; - #endif - size_t tag_indentation = m_state->line_contents.current_col(t); - _c4dbgpf("there was a tag: '{}', indentation={}", t, tag_indentation); - _RYML_CB_ASSERT(m_stack.m_callbacks, t.end() > m_state->line_contents.rem.begin()); - _line_progressed(static_cast(t.end() - m_state->line_contents.rem.begin())); - { - size_t pos = m_state->line_contents.rem.first_not_of(" \t"); - if(pos != csubstr::npos) - _line_progressed(pos); - } - - if(has_all(RMAP|RKEY)) - { - _c4dbgpf("saving map key tag '{}'", t); - _RYML_CB_ASSERT(m_stack.m_callbacks, m_key_tag.empty()); - m_key_tag = t; - m_key_tag_indentation = tag_indentation; - } - else if(has_all(RMAP|RVAL)) - { - /* foo: !!str - * !!str : bar */ - rem = m_state->line_contents.rem; - rem = rem.left_of(rem.find("#")); - rem = rem.trimr(" \t"); - _c4dbgpf("rem='{}'", rem); - #ifdef RYML_NO_COVERAGE__TO_BE_DELETED - if(rem == ':' || rem.begins_with(": ")) - { - _c4dbgp("the last val was null, and this is a tag from a null key"); - _append_key_val_null(tag_beginning - 1); - _store_scalar_null(rem.str - 1); - // do not change the flag to key, it is ~ - _RYML_CB_ASSERT(m_stack.m_callbacks, rem.begin() > m_state->line_contents.rem.begin()); - size_t token_len = rem == ':' ? 1 : 2; - _line_progressed(static_cast(token_len + rem.begin() - m_state->line_contents.rem.begin())); - } - #endif - _c4dbgpf("saving map val tag '{}'", t); - _RYML_CB_ASSERT(m_stack.m_callbacks, m_val_tag.empty()); - m_val_tag = t; - m_val_tag_indentation = tag_indentation; - } - else if(has_all(RSEQ|RVAL) || has_all(RTOP|RUNK|NDOC)) - { - if(m_val_tag.empty()) - { - _c4dbgpf("saving seq/doc val tag '{}'", t); - m_val_tag = t; - m_val_tag_indentation = tag_indentation; - } - else - { - _c4dbgpf("saving seq/doc key tag '{}'", t); - m_key_tag = t; - m_key_tag_indentation = tag_indentation; - } - } - else if(has_all(RTOP|RUNK) || has_any(RUNK)) - { - rem = m_state->line_contents.rem; - rem = rem.left_of(rem.find("#")); - rem = rem.trimr(" \t"); - if(rem.empty()) - { - _c4dbgpf("saving val tag '{}'", t); - _RYML_CB_ASSERT(m_stack.m_callbacks, m_val_tag.empty()); - m_val_tag = t; - m_val_tag_indentation = tag_indentation; - } - else - { - _c4dbgpf("saving key tag '{}'", t); - if(m_key_tag.empty()) - { - m_key_tag = t; - m_key_tag_indentation = tag_indentation; - } - else - { - /* handle this case: - * !!str foo: !!map - * !!int 1: !!float 20.0 - * !!int 3: !!float 40.0 - * - * (m_key_tag would be !!str and m_key_tag2 would be !!int) - */ - m_key_tag2 = t; - m_key_tag2_indentation = tag_indentation; - } - } - } - else - { - _c4err("internal error"); - } - - if(m_val_tag.not_empty()) - { - YamlTag_e tag = to_tag(t); - if(tag == TAG_STR) - { - _c4dbgpf("tag '{}' is a str-type tag", t); - if(has_all(RTOP|RUNK|NDOC)) - { - _c4dbgpf("docval. slurping the string. pos={}", m_state->pos.offset); - csubstr scalar = _slurp_doc_scalar(); - _c4dbgpf("docval. after slurp: {}, at node {}: '{}'", m_state->pos.offset, m_state->node_id, scalar); - m_tree->to_val(m_state->node_id, scalar, DOC); - _c4dbgpf("docval. val tag {} -> {}", m_val_tag, normalize_tag(m_val_tag)); - m_tree->set_val_tag(m_state->node_id, normalize_tag(m_val_tag)); - m_val_tag.clear(); - if(!m_val_anchor.empty()) - { - _c4dbgpf("setting val anchor[{}]='{}'", m_state->node_id, m_val_anchor); - m_tree->set_val_anchor(m_state->node_id, m_val_anchor); - m_val_anchor.clear(); - } - _end_stream(); - } - } - } - return true; -} - -//----------------------------------------------------------------------------- -csubstr Parser::_slurp_doc_scalar() -{ - csubstr s = m_state->line_contents.rem; - size_t pos = m_state->pos.offset; - _RYML_CB_ASSERT(m_stack.m_callbacks, m_state->line_contents.full.find("---") != csubstr::npos); - _c4dbgpf("slurp 0 '{}'. REM='{}'", s, m_buf.sub(m_state->pos.offset)); - if(s.len == 0) - { - _line_ended(); - _scan_line(); - s = m_state->line_contents.rem; - pos = m_state->pos.offset; - } - - size_t skipws = s.first_not_of(" \t"); - _c4dbgpf("slurp 1 '{}'. REM='{}'", s, m_buf.sub(m_state->pos.offset)); - if(skipws != npos) - { - _line_progressed(skipws); - s = m_state->line_contents.rem; - pos = m_state->pos.offset; - _c4dbgpf("slurp 2 '{}'. REM='{}'", s, m_buf.sub(m_state->pos.offset)); - } - - _RYML_CB_ASSERT(m_stack.m_callbacks, m_val_anchor.empty()); - _handle_val_anchors_and_refs(); - if(!m_val_anchor.empty()) - { - s = m_state->line_contents.rem; - skipws = s.first_not_of(" \t"); - if(skipws != npos) - { - _line_progressed(skipws); - } - s = m_state->line_contents.rem; - pos = m_state->pos.offset; - _c4dbgpf("slurp 3 '{}'. REM='{}'", s, m_buf.sub(m_state->pos.offset)); - } - - if(s.begins_with('\'')) - { - m_state->scalar_col = m_state->line_contents.current_col(s); - return _scan_squot_scalar(); - } - else if(s.begins_with('"')) - { - m_state->scalar_col = m_state->line_contents.current_col(s); - return _scan_dquot_scalar(); - } - else if(s.begins_with('|') || s.begins_with('>')) - { - return _scan_block(); - } - - _c4dbgpf("slurp 4 '{}'. REM='{}'", s, m_buf.sub(m_state->pos.offset)); - - m_state->scalar_col = m_state->line_contents.current_col(s); - _RYML_CB_ASSERT(m_stack.m_callbacks, s.end() >= m_buf.begin() + pos); - _line_progressed(static_cast(s.end() - (m_buf.begin() + pos))); - - _c4dbgpf("slurp 5 '{}'. REM='{}'", s, m_buf.sub(m_state->pos.offset)); - - if(_at_line_end()) - { - _c4dbgpf("at line end. curr='{}'", s); - s = _extend_scanned_scalar(s); - } - - _c4dbgpf("scalar was '{}'", s); - - return s; -} - - -//----------------------------------------------------------------------------- - -bool Parser::_scan_scalar_seq_blck(csubstr *C4_RESTRICT scalar, bool *C4_RESTRICT quoted) -{ - _RYML_CB_ASSERT(m_stack.m_callbacks, has_any(RSEQ)); - _RYML_CB_ASSERT(m_stack.m_callbacks, has_any(RVAL)); - _RYML_CB_ASSERT(m_stack.m_callbacks, ! has_any(RKEY)); - _RYML_CB_ASSERT(m_stack.m_callbacks, ! has_any(FLOW)); - - csubstr s = m_state->line_contents.rem; - if(s.len == 0) - return false; - s = s.trim(" \t"); - if(s.len == 0) - return false; - - if(s.begins_with('\'')) - { - _c4dbgp("got a ': scanning single-quoted scalar"); - m_state->scalar_col = m_state->line_contents.current_col(s); - *scalar = _scan_squot_scalar(); - *quoted = true; - return true; - } - else if(s.begins_with('"')) - { - _c4dbgp("got a \": scanning double-quoted scalar"); - m_state->scalar_col = m_state->line_contents.current_col(s); - *scalar = _scan_dquot_scalar(); - *quoted = true; - return true; - } - else if(s.begins_with('|') || s.begins_with('>')) - { - *scalar = _scan_block(); - *quoted = true; - return true; - } - else if(has_any(RTOP) && _is_doc_sep(s)) - { - return false; - } - - _c4dbgp("RSEQ|RVAL"); - if( ! _is_scalar_next__rseq_rval(s)) - return false; - _RYML_WITH_TAB_TOKENS(else if(s.begins_with("-\t")) - return false; - ) - - if(s.ends_with(':')) - { - --s.len; - } - else - { - auto first = s.first_of_any(": " _RYML_WITH_TAB_TOKENS( , ":\t"), " #"); - if(first) - s.len = first.pos; - } - s = s.trimr(_RYML_WITH_OR_WITHOUT_TAB_TOKENS(" \t", ' ')); - - if(s.empty()) - return false; - - m_state->scalar_col = m_state->line_contents.current_col(s); - _RYML_CB_ASSERT(m_stack.m_callbacks, s.str >= m_state->line_contents.rem.str); - _line_progressed(static_cast(s.str - m_state->line_contents.rem.str) + s.len); - - if(_at_line_end() && s != '~') - { - _c4dbgpf("at line end. curr='{}'", s); - s = _extend_scanned_scalar(s); - } - - _c4dbgpf("scalar was '{}'", s); - - *scalar = s; - *quoted = false; - return true; -} - -bool Parser::_scan_scalar_map_blck(csubstr *C4_RESTRICT scalar, bool *C4_RESTRICT quoted) -{ - _c4dbgp("_scan_scalar_map_blck"); - _RYML_CB_ASSERT(m_stack.m_callbacks, has_any(RMAP)); - _RYML_CB_ASSERT(m_stack.m_callbacks, ! has_any(FLOW)); - _RYML_CB_ASSERT(m_stack.m_callbacks, has_any(RKEY|RVAL)); - - csubstr s = m_state->line_contents.rem; - #ifdef RYML_NO_COVERAGE__TO_BE_DELETED__OR_REFACTORED - if(s.len == 0) - return false; - #endif - s = s.trim(" \t"); - if(s.len == 0) - return false; - - if(s.begins_with('\'')) - { - _c4dbgp("got a ': scanning single-quoted scalar"); - m_state->scalar_col = m_state->line_contents.current_col(s); - *scalar = _scan_squot_scalar(); - *quoted = true; - return true; - } - else if(s.begins_with('"')) - { - _c4dbgp("got a \": scanning double-quoted scalar"); - m_state->scalar_col = m_state->line_contents.current_col(s); - *scalar = _scan_dquot_scalar(); - *quoted = true; - return true; - } - else if(s.begins_with('|') || s.begins_with('>')) - { - *scalar = _scan_block(); - *quoted = true; - return true; - } - else if(has_any(RTOP) && _is_doc_sep(s)) - { - return false; - } - - if( ! _is_scalar_next__rmap(s)) - return false; - - size_t colon_token = s.find(": "); - if(colon_token == npos) - { - _RYML_WITH_OR_WITHOUT_TAB_TOKENS( - // with tab tokens - colon_token = s.find(":\t"); - if(colon_token == npos) - { - _RYML_CB_ASSERT(m_stack.m_callbacks, s.len > 0); - colon_token = s.find(':'); - if(colon_token != s.len-1) - colon_token = npos; - } - , - // without tab tokens - colon_token = s.find(':'); - _RYML_CB_ASSERT(m_stack.m_callbacks, s.len > 0); - if(colon_token != s.len-1) - colon_token = npos; - ) - } - - if(has_all(RKEY)) - { - _RYML_CB_ASSERT(m_stack.m_callbacks, !s.begins_with(' ')); - if(has_any(QMRK)) - { - _c4dbgp("RMAP|RKEY|CPLX"); - _RYML_CB_ASSERT(m_stack.m_callbacks, has_any(RMAP)); - if(s.begins_with("? ") || s == '?') - return false; - s = s.left_of(colon_token); - s = s.left_of(s.first_of("#")); - s = s.trimr(" \t"); - if(s.begins_with("---")) - return false; - else if(s.begins_with("...")) - return false; - } - else - { - _c4dbgp("RMAP|RKEY"); - _RYML_CB_CHECK(m_stack.m_callbacks, !s.begins_with('{')); - if(s.begins_with("? ") || s == '?') - return false; - s = s.left_of(colon_token); - s = s.trimr(_RYML_WITH_OR_WITHOUT_TAB_TOKENS(" \t", ' ')); - if(s.begins_with("---")) - { - return false; - } - else if(s.begins_with("...")) - { - return false; - } - } - } - else if(has_all(RVAL)) - { - _c4dbgp("RMAP|RVAL"); - _RYML_CB_ASSERT(m_stack.m_callbacks, has_none(QMRK)); - if( ! _is_scalar_next__rmap_val(s)) - return false; - _RYML_WITH_TAB_TOKENS( - else if(s.begins_with("-\t")) - return false; - ) - _c4dbgp("RMAP|RVAL: scalar"); - s = s.left_of(s.find(" #")); // is there a comment? - s = s.left_of(s.find("\t#")); // is there a comment? - s = s.trim(_RYML_WITH_OR_WITHOUT_TAB_TOKENS(" \t", ' ')); - if(s.begins_with("---")) - return false; - #ifdef RYML_NO_COVERAGE__TO_BE_DELETED__OR_REFACTORED - else if(s.begins_with("...")) - return false; - #endif - } - - if(s.empty()) - return false; - - m_state->scalar_col = m_state->line_contents.current_col(s); - _RYML_CB_ASSERT(m_stack.m_callbacks, s.str >= m_state->line_contents.rem.str); - _line_progressed(static_cast(s.str - m_state->line_contents.rem.str) + s.len); - - if(_at_line_end() && s != '~') - { - _c4dbgpf("at line end. curr='{}'", s); - s = _extend_scanned_scalar(s); - } - - _c4dbgpf("scalar was '{}'", s); - - *scalar = s; - *quoted = false; - return true; -} - -bool Parser::_scan_scalar_seq_flow(csubstr *C4_RESTRICT scalar, bool *C4_RESTRICT quoted) -{ - _RYML_CB_ASSERT(m_stack.m_callbacks, has_any(RSEQ)); - _RYML_CB_ASSERT(m_stack.m_callbacks, has_any(FLOW)); - _RYML_CB_ASSERT(m_stack.m_callbacks, has_any(RVAL)); - _RYML_CB_ASSERT(m_stack.m_callbacks, ! has_any(RKEY)); - - csubstr s = m_state->line_contents.rem; - if(s.len == 0) - return false; - s = s.trim(" \t"); - if(s.len == 0) - return false; - - if(s.begins_with('\'')) - { - _c4dbgp("got a ': scanning single-quoted scalar"); - m_state->scalar_col = m_state->line_contents.current_col(s); - *scalar = _scan_squot_scalar(); - *quoted = true; - return true; - } - else if(s.begins_with('"')) - { - _c4dbgp("got a \": scanning double-quoted scalar"); - m_state->scalar_col = m_state->line_contents.current_col(s); - *scalar = _scan_dquot_scalar(); - *quoted = true; - return true; - } - - if(has_all(RVAL)) - { - _c4dbgp("RSEQ|RVAL"); - if( ! _is_scalar_next__rseq_rval(s)) - return false; - _RYML_WITH_TAB_TOKENS(else if(s.begins_with("-\t")) - return false; - ) - _c4dbgp("RSEQ|RVAL|FLOW"); - s = s.left_of(s.first_of(",]")); - if(s.ends_with(':')) - { - --s.len; - } - else - { - auto first = s.first_of_any(": " _RYML_WITH_TAB_TOKENS( , ":\t"), " #"); - if(first) - s.len = first.pos; - } - s = s.trimr(_RYML_WITH_OR_WITHOUT_TAB_TOKENS(" \t", ' ')); - } - - if(s.empty()) - return false; - - m_state->scalar_col = m_state->line_contents.current_col(s); - _RYML_CB_ASSERT(m_stack.m_callbacks, s.str >= m_state->line_contents.rem.str); - _line_progressed(static_cast(s.str - m_state->line_contents.rem.str) + s.len); - - if(_at_line_end() && s != '~') - { - _c4dbgpf("at line end. curr='{}'", s); - s = _extend_scanned_scalar(s); - } - - _c4dbgpf("scalar was '{}'", s); - - *scalar = s; - *quoted = false; - return true; -} - -bool Parser::_scan_scalar_map_flow(csubstr *C4_RESTRICT scalar, bool *C4_RESTRICT quoted) -{ - _RYML_CB_ASSERT(m_stack.m_callbacks, has_any(RMAP)); - _RYML_CB_ASSERT(m_stack.m_callbacks, has_any(FLOW)); - _RYML_CB_ASSERT(m_stack.m_callbacks, has_any(RKEY|RVAL)); - - csubstr s = m_state->line_contents.rem; - if(s.len == 0) - return false; - s = s.trim(" \t"); - if(s.len == 0) - return false; - - if(s.begins_with('\'')) - { - _c4dbgp("got a ': scanning single-quoted scalar"); - m_state->scalar_col = m_state->line_contents.current_col(s); - *scalar = _scan_squot_scalar(); - *quoted = true; - return true; - } - else if(s.begins_with('"')) - { - _c4dbgp("got a \": scanning double-quoted scalar"); - m_state->scalar_col = m_state->line_contents.current_col(s); - *scalar = _scan_dquot_scalar(); - *quoted = true; - return true; - } - - if( ! _is_scalar_next__rmap(s)) - return false; - - if(has_all(RKEY)) - { - _RYML_CB_ASSERT(m_stack.m_callbacks, !s.begins_with(' ')); - size_t colon_token = s.find(": "); - if(colon_token == npos) - { - _RYML_WITH_OR_WITHOUT_TAB_TOKENS( - // with tab tokens - colon_token = s.find(":\t"); - if(colon_token == npos) - { - _RYML_CB_ASSERT(m_stack.m_callbacks, s.len > 0); - colon_token = s.find(':'); - if(colon_token != s.len-1) - colon_token = npos; - } - , - // without tab tokens - colon_token = s.find(':'); - _RYML_CB_ASSERT(m_stack.m_callbacks, s.len > 0); - if(colon_token != s.len-1) - colon_token = npos; - ) - } - if(s.begins_with("? ") || s == '?') - return false; - if(has_any(QMRK)) - { - _c4dbgp("RMAP|RKEY|CPLX"); - _RYML_CB_ASSERT(m_stack.m_callbacks, has_any(RMAP)); - s = s.left_of(colon_token); - s = s.left_of(s.first_of("#")); - s = s.left_of(s.first_of(':')); - s = s.trimr(" \t"); - if(s.begins_with("---")) - return false; - else if(s.begins_with("...")) - return false; - } - else - { - _RYML_CB_CHECK(m_stack.m_callbacks, !s.begins_with('{')); - _c4dbgp("RMAP|RKEY"); - s = s.left_of(colon_token); - s = s.trimr(_RYML_WITH_OR_WITHOUT_TAB_TOKENS(" \t", ' ')); - _c4dbgpf("RMAP|RKEY|FLOW: '{}'", s); - s = s.left_of(s.first_of(",}")); - if(s.ends_with(':')) - --s.len; - } - } - else if(has_all(RVAL)) - { - _c4dbgp("RMAP|RVAL"); - _RYML_CB_ASSERT(m_stack.m_callbacks, has_none(QMRK)); - if( ! _is_scalar_next__rmap_val(s)) - return false; - _RYML_WITH_TAB_TOKENS(else if(s.begins_with("-\t")) - return false; - ) - _c4dbgp("RMAP|RVAL|FLOW"); - if(has_none(RSEQIMAP)) - s = s.left_of(s.first_of(",}")); - else - s = s.left_of(s.first_of(",]")); - s = s.left_of(s.find(" #")); // is there a comment? - s = s.left_of(s.find("\t#")); // is there a comment? - s = s.trim(_RYML_WITH_OR_WITHOUT_TAB_TOKENS(" \t", ' ')); - } - - if(s.empty()) - return false; - - m_state->scalar_col = m_state->line_contents.current_col(s); - _RYML_CB_ASSERT(m_stack.m_callbacks, s.str >= m_state->line_contents.rem.str); - _line_progressed(static_cast(s.str - m_state->line_contents.rem.str) + s.len); - - if(_at_line_end() && s != '~') - { - _c4dbgpf("at line end. curr='{}'", s); - s = _extend_scanned_scalar(s); - } - - _c4dbgpf("scalar was '{}'", s); - - *scalar = s; - *quoted = false; - return true; -} - -bool Parser::_scan_scalar_unk(csubstr *C4_RESTRICT scalar, bool *C4_RESTRICT quoted) -{ - _RYML_CB_ASSERT(m_stack.m_callbacks, has_any(RUNK)); - - csubstr s = m_state->line_contents.rem; - if(s.len == 0) - return false; - s = s.trim(" \t"); - if(s.len == 0) - return false; - - if(s.begins_with('\'')) - { - _c4dbgp("got a ': scanning single-quoted scalar"); - m_state->scalar_col = m_state->line_contents.current_col(s); - *scalar = _scan_squot_scalar(); - *quoted = true; - return true; - } - else if(s.begins_with('"')) - { - _c4dbgp("got a \": scanning double-quoted scalar"); - m_state->scalar_col = m_state->line_contents.current_col(s); - *scalar = _scan_dquot_scalar(); - *quoted = true; - return true; - } - else if(s.begins_with('|') || s.begins_with('>')) - { - *scalar = _scan_block(); - *quoted = true; - return true; - } - else if(has_any(RTOP) && _is_doc_sep(s)) - { - return false; - } - - _c4dbgpf("RUNK '[{}]~~~{}~~~", s.len, s); - if( ! _is_scalar_next__runk(s)) - { - _c4dbgp("RUNK: no scalar next"); - return false; - } - size_t pos = s.find(" #"); - if(pos != npos) - s = s.left_of(pos); - pos = s.find(": "); - if(pos != npos) - s = s.left_of(pos); - else if(s.ends_with(':')) - s = s.left_of(s.len-1); - _RYML_WITH_TAB_TOKENS( - else if((pos = s.find(":\t")) != npos) // TABS - s = s.left_of(pos); - ) - else - s = s.left_of(s.first_of(',')); - s = s.trim(" \t"); - _c4dbgpf("RUNK: scalar='{}'", s); - - if(s.empty()) - return false; - - m_state->scalar_col = m_state->line_contents.current_col(s); - _RYML_CB_ASSERT(m_stack.m_callbacks, s.str >= m_state->line_contents.rem.str); - _line_progressed(static_cast(s.str - m_state->line_contents.rem.str) + s.len); - - if(_at_line_end() && s != '~') - { - _c4dbgpf("at line end. curr='{}'", s); - s = _extend_scanned_scalar(s); - } - - _c4dbgpf("scalar was '{}'", s); - - *scalar = s; - *quoted = false; - return true; -} - - -//----------------------------------------------------------------------------- - -csubstr Parser::_extend_scanned_scalar(csubstr s) -{ - if(has_all(RMAP|RKEY|QMRK)) - { - size_t scalar_indentation = has_any(FLOW) ? 0 : m_state->scalar_col; - _c4dbgpf("extend_scalar: explicit key! indref={} scalar_indentation={} scalar_col={}", m_state->indref, scalar_indentation, m_state->scalar_col); - csubstr n = _scan_to_next_nonempty_line(scalar_indentation); - if(!n.empty()) - { - substr full = _scan_complex_key(s, n).trimr(" \t\r\n"); - if(full != s) - s = _filter_plain_scalar(full, scalar_indentation); - } - } - // deal with plain (unquoted) scalars that continue to the next line - else if(!s.begins_with_any("*")) // cannot be a plain scalar if it starts with * (that's an anchor reference) - { - _c4dbgpf("extend_scalar: line ended, scalar='{}'", s); - if(has_none(FLOW)) - { - size_t scalar_indentation = m_state->indref + 1; - if(has_all(RUNK) && scalar_indentation == 1) - scalar_indentation = 0; - csubstr n = _scan_to_next_nonempty_line(scalar_indentation); - if(!n.empty()) - { - _c4dbgpf("rscalar[IMPL]: state_indref={} state_indentation={} scalar_indentation={}", m_state->indref, m_state->line_contents.indentation, scalar_indentation); - _RYML_CB_ASSERT(m_stack.m_callbacks, m_state->line_contents.full.is_super(n)); - substr full = _scan_plain_scalar_blck(s, n, scalar_indentation); - if(full.len >= s.len) - s = _filter_plain_scalar(full, scalar_indentation); - } - } - else - { - _RYML_CB_ASSERT(m_stack.m_callbacks, has_all(FLOW)); - csubstr n = _scan_to_next_nonempty_line(/*indentation*/0); - if(!n.empty()) - { - _c4dbgp("rscalar[FLOW]"); - substr full = _scan_plain_scalar_flow(s, n); - s = _filter_plain_scalar(full, /*indentation*/0); - } - } - } - - return s; -} - - -//----------------------------------------------------------------------------- - -substr Parser::_scan_plain_scalar_flow(csubstr currscalar, csubstr peeked_line) -{ - static constexpr const csubstr chars = "[]{}?#,"; - size_t pos = peeked_line.first_of(chars); - bool first = true; - while(pos != 0) - { - if(has_all(RMAP|RKEY) || has_any(RUNK)) - { - csubstr tpkl = peeked_line.triml(' ').trimr("\r\n"); - if(tpkl.begins_with(": ") || tpkl == ':') - { - _c4dbgpf("rscalar[FLOW]: map value starts on the peeked line: '{}'", peeked_line); - peeked_line = peeked_line.first(0); - break; - } - else - { - auto colon_pos = peeked_line.first_of_any(": ", ":"); - if(colon_pos && colon_pos.pos < pos) - { - peeked_line = peeked_line.first(colon_pos.pos); - _c4dbgpf("rscalar[FLOW]: found colon at {}. peeked='{}'", colon_pos.pos, peeked_line); - _RYML_CB_ASSERT(m_stack.m_callbacks, peeked_line.end() >= m_state->line_contents.rem.begin()); - _line_progressed(static_cast(peeked_line.end() - m_state->line_contents.rem.begin())); - break; - } - } - } - if(pos != npos) - { - _c4dbgpf("rscalar[FLOW]: found special character '{}' at {}, stopping: '{}'", peeked_line[pos], pos, peeked_line.left_of(pos).trimr("\r\n")); - peeked_line = peeked_line.left_of(pos); - _RYML_CB_ASSERT(m_stack.m_callbacks, peeked_line.end() >= m_state->line_contents.rem.begin()); - _line_progressed(static_cast(peeked_line.end() - m_state->line_contents.rem.begin())); - break; - } - _c4dbgpf("rscalar[FLOW]: append another line, full: '{}'", peeked_line.trimr("\r\n")); - if(!first) - { - RYML_CHECK(_advance_to_peeked()); - } - peeked_line = _scan_to_next_nonempty_line(/*indentation*/0); - if(peeked_line.empty()) - { - _c4err("expected token or continuation"); - } - pos = peeked_line.first_of(chars); - first = false; - } - substr full(m_buf.str + (currscalar.str - m_buf.str), m_buf.begin() + m_state->pos.offset); - full = full.trimr("\n\r "); - return full; -} - - -//----------------------------------------------------------------------------- - -substr Parser::_scan_plain_scalar_blck(csubstr currscalar, csubstr peeked_line, size_t indentation) -{ - _RYML_CB_ASSERT(m_stack.m_callbacks, m_buf.is_super(currscalar)); - // NOTE. there's a problem with _scan_to_next_nonempty_line(), as it counts newlines twice - // size_t offs = m_state->pos.offset; // so we workaround by directly counting from the end of the given scalar - _RYML_CB_ASSERT(m_stack.m_callbacks, currscalar.end() >= m_buf.begin()); - size_t offs = static_cast(currscalar.end() - m_buf.begin()); - _RYML_CB_ASSERT(m_stack.m_callbacks, peeked_line.begins_with(' ', indentation)); - while(true) - { - _c4dbgpf("rscalar[IMPL]: continuing... ref_indentation={}", indentation); - if(peeked_line.begins_with("...") || peeked_line.begins_with("---")) - { - _c4dbgpf("rscalar[IMPL]: document termination next -- bail now '{}'", peeked_line.trimr("\r\n")); - break; - } - else if(( ! peeked_line.begins_with(' ', indentation))) // is the line deindented? - { - if(!peeked_line.trim(" \r\n\t").empty()) // is the line not blank? - { - _c4dbgpf("rscalar[IMPL]: deindented line, not blank -- bail now '{}'", peeked_line.trimr("\r\n")); - break; - } - _c4dbgpf("rscalar[IMPL]: line is blank and has less indentation: ref={} line={}: '{}'", indentation, peeked_line.first_not_of(' ') == csubstr::npos ? 0 : peeked_line.first_not_of(' '), peeked_line.trimr("\r\n")); - _c4dbgpf("rscalar[IMPL]: ... searching for a line starting at indentation {}", indentation); - csubstr next_peeked = _scan_to_next_nonempty_line(indentation); - if(next_peeked.empty()) - { - _c4dbgp("rscalar[IMPL]: ... finished."); - break; - } - _c4dbgp("rscalar[IMPL]: ... continuing."); - peeked_line = next_peeked; - } - - _c4dbgpf("rscalar[IMPL]: line contents: '{}'", peeked_line.right_of(indentation, true).trimr("\r\n")); - size_t token_pos; - if(peeked_line.find(": ") != npos) - { - _line_progressed(peeked_line.find(": ")); - _c4err("': ' is not a valid token in plain flow (unquoted) scalars"); - } - else if(peeked_line.ends_with(':')) - { - _line_progressed(peeked_line.find(':')); - _c4err("lines cannot end with ':' in plain flow (unquoted) scalars"); - } - else if((token_pos = peeked_line.find(" #")) != npos) - { - _line_progressed(token_pos); - break; - //_c4err("' #' is not a valid token in plain flow (unquoted) scalars"); - } - - _c4dbgpf("rscalar[IMPL]: append another line: (len={})'{}'", peeked_line.len, peeked_line.trimr("\r\n")); - if(!_advance_to_peeked()) - { - _c4dbgp("rscalar[IMPL]: file finishes after the scalar"); - break; - } - peeked_line = m_state->line_contents.rem; - } - _RYML_CB_ASSERT(m_stack.m_callbacks, m_state->pos.offset >= offs); - substr full(m_buf.str + (currscalar.str - m_buf.str), - currscalar.len + (m_state->pos.offset - offs)); - full = full.trimr("\r\n "); - return full; -} - -substr Parser::_scan_complex_key(csubstr currscalar, csubstr peeked_line) -{ - _RYML_CB_ASSERT(m_stack.m_callbacks, m_buf.is_super(currscalar)); - // NOTE. there's a problem with _scan_to_next_nonempty_line(), as it counts newlines twice - // size_t offs = m_state->pos.offset; // so we workaround by directly counting from the end of the given scalar - _RYML_CB_ASSERT(m_stack.m_callbacks, currscalar.end() >= m_buf.begin()); - size_t offs = static_cast(currscalar.end() - m_buf.begin()); - while(true) - { - _c4dbgp("rcplxkey: continuing..."); - if(peeked_line.begins_with("...") || peeked_line.begins_with("---")) - { - _c4dbgpf("rcplxkey: document termination next -- bail now '{}'", peeked_line.trimr("\r\n")); - break; - } - else - { - size_t pos = peeked_line.first_of("?:[]{}"); - if(pos == csubstr::npos) - { - pos = peeked_line.find("- "); - } - if(pos != csubstr::npos) - { - _c4dbgpf("rcplxkey: found special characters at pos={}: '{}'", pos, peeked_line.trimr("\r\n")); - _line_progressed(pos); - break; - } - } - - _c4dbgpf("rcplxkey: no special chars found '{}'", peeked_line.trimr("\r\n")); - csubstr next_peeked = _scan_to_next_nonempty_line(0); - if(next_peeked.empty()) - { - _c4dbgp("rcplxkey: empty ... finished."); - break; - } - _c4dbgp("rcplxkey: ... continuing."); - peeked_line = next_peeked; - - _c4dbgpf("rcplxkey: line contents: '{}'", peeked_line.trimr("\r\n")); - size_t colpos; - if((colpos = peeked_line.find(": ")) != npos) - { - _c4dbgp("rcplxkey: found ': ', stopping."); - _line_progressed(colpos); - break; - } - #ifdef RYML_NO_COVERAGE__TO_BE_DELETED - else if((colpos = peeked_line.ends_with(':'))) - { - _c4dbgp("rcplxkey: ends with ':', stopping."); - _line_progressed(colpos); - break; - } - #endif - _c4dbgpf("rcplxkey: append another line: (len={})'{}'", peeked_line.len, peeked_line.trimr("\r\n")); - if(!_advance_to_peeked()) - { - _c4dbgp("rcplxkey: file finishes after the scalar"); - break; - } - peeked_line = m_state->line_contents.rem; - } - _RYML_CB_ASSERT(m_stack.m_callbacks, m_state->pos.offset >= offs); - substr full(m_buf.str + (currscalar.str - m_buf.str), - currscalar.len + (m_state->pos.offset - offs)); - return full; -} - -//! scans to the next non-blank line starting with the given indentation -csubstr Parser::_scan_to_next_nonempty_line(size_t indentation) -{ - csubstr next_peeked; - while(true) - { - _c4dbgpf("rscalar: ... curr offset: {} indentation={}", m_state->pos.offset, indentation); - next_peeked = _peek_next_line(m_state->pos.offset); - csubstr next_peeked_triml = next_peeked.triml(' '); - _c4dbgpf("rscalar: ... next peeked line='{}'", next_peeked.trimr("\r\n")); - if(next_peeked_triml.begins_with('#')) - { - _c4dbgp("rscalar: ... first non-space character is #"); - return {}; - } - else if(next_peeked.begins_with(' ', indentation)) - { - _c4dbgpf("rscalar: ... begins at same indentation {}, assuming continuation", indentation); - _advance_to_peeked(); - return next_peeked; - } - else // check for de-indentation - { - csubstr trimmed = next_peeked_triml.trimr("\t\r\n"); - _c4dbgpf("rscalar: ... deindented! trimmed='{}'", trimmed); - if(!trimmed.empty()) - { - _c4dbgp("rscalar: ... and not empty. bailing out."); - return {}; - } - } - if(!_advance_to_peeked()) - { - _c4dbgp("rscalar: file finished"); - return {}; - } - } - return {}; -} - -// returns false when the file finished -bool Parser::_advance_to_peeked() -{ - _line_progressed(m_state->line_contents.rem.len); - _line_ended(); // advances to the peeked-at line, consuming all remaining (probably newline) characters on the current line - _RYML_CB_ASSERT(m_stack.m_callbacks, m_state->line_contents.rem.first_of("\r\n") == csubstr::npos); - _c4dbgpf("advance to peeked: scan more... pos={} len={}", m_state->pos.offset, m_buf.len); - _scan_line(); // puts the peeked-at line in the buffer - if(_finished_file()) - { - _c4dbgp("rscalar: finished file!"); - return false; - } - return true; -} - -//----------------------------------------------------------------------------- - -C4_ALWAYS_INLINE size_t _extend_from_combined_newline(char nl, char following) -{ - return (nl == '\n' && following == '\r') || (nl == '\r' && following == '\n'); -} - -//! look for the next newline chars, and jump to the right of those -csubstr from_next_line(csubstr rem) -{ - size_t nlpos = rem.first_of("\r\n"); - if(nlpos == csubstr::npos) - return {}; - const char nl = rem[nlpos]; - rem = rem.right_of(nlpos); - if(rem.empty()) - return {}; - if(_extend_from_combined_newline(nl, rem.front())) - rem = rem.sub(1); - return rem; -} - -csubstr Parser::_peek_next_line(size_t pos) const -{ - csubstr rem{}; // declare here because of the goto - size_t nlpos{}; // declare here because of the goto - pos = pos == npos ? m_state->pos.offset : pos; - if(pos >= m_buf.len) - goto next_is_empty; - - // look for the next newline chars, and jump to the right of those - rem = from_next_line(m_buf.sub(pos)); - if(rem.empty()) - goto next_is_empty; - - // now get everything up to and including the following newline chars - nlpos = rem.first_of("\r\n"); - if((nlpos != csubstr::npos) && (nlpos + 1 < rem.len)) - nlpos += _extend_from_combined_newline(rem[nlpos], rem[nlpos+1]); - rem = rem.left_of(nlpos, /*include_pos*/true); - - _c4dbgpf("peek next line @ {}: (len={})'{}'", pos, rem.len, rem.trimr("\r\n")); - return rem; - -next_is_empty: - _c4dbgpf("peek next line @ {}: (len=0)''", pos); - return {}; -} - - -//----------------------------------------------------------------------------- -void Parser::LineContents::reset_with_next_line(csubstr buf, size_t offset) -{ - RYML_ASSERT(offset <= buf.len); - char const* C4_RESTRICT b = &buf[offset]; - char const* C4_RESTRICT e = b; - // get the current line stripped of newline chars - while(e < buf.end() && (*e != '\n' && *e != '\r')) - ++e; - RYML_ASSERT(e >= b); - const csubstr stripped_ = buf.sub(offset, static_cast(e - b)); - // advance pos to include the first line ending - if(e != buf.end() && *e == '\r') - ++e; - if(e != buf.end() && *e == '\n') - ++e; - RYML_ASSERT(e >= b); - const csubstr full_ = buf.sub(offset, static_cast(e - b)); - reset(full_, stripped_); -} - -void Parser::_scan_line() -{ - if(m_state->pos.offset >= m_buf.len) - { - m_state->line_contents.reset(m_buf.last(0), m_buf.last(0)); - return; - } - m_state->line_contents.reset_with_next_line(m_buf, m_state->pos.offset); -} - - -//----------------------------------------------------------------------------- -void Parser::_line_progressed(size_t ahead) -{ - _c4dbgpf("line[{}] ({} cols) progressed by {}: col {}-->{} offset {}-->{}", m_state->pos.line, m_state->line_contents.full.len, ahead, m_state->pos.col, m_state->pos.col+ahead, m_state->pos.offset, m_state->pos.offset+ahead); - m_state->pos.offset += ahead; - m_state->pos.col += ahead; - _RYML_CB_ASSERT(m_stack.m_callbacks, m_state->pos.col <= m_state->line_contents.stripped.len+1); - m_state->line_contents.rem = m_state->line_contents.rem.sub(ahead); -} - -void Parser::_line_ended() -{ - _c4dbgpf("line[{}] ({} cols) ended! offset {}-->{}", m_state->pos.line, m_state->line_contents.full.len, m_state->pos.offset, m_state->pos.offset+m_state->line_contents.full.len - m_state->line_contents.stripped.len); - _RYML_CB_ASSERT(m_stack.m_callbacks, m_state->pos.col == m_state->line_contents.stripped.len+1); - m_state->pos.offset += m_state->line_contents.full.len - m_state->line_contents.stripped.len; - ++m_state->pos.line; - m_state->pos.col = 1; -} - -void Parser::_line_ended_undo() -{ - _RYML_CB_ASSERT(m_stack.m_callbacks, m_state->pos.col == 1u); - _RYML_CB_ASSERT(m_stack.m_callbacks, m_state->pos.line > 0u); - _RYML_CB_ASSERT(m_stack.m_callbacks, m_state->pos.offset >= m_state->line_contents.full.len - m_state->line_contents.stripped.len); - size_t delta = m_state->line_contents.full.len - m_state->line_contents.stripped.len; - _c4dbgpf("line[{}] undo ended! line {}-->{}, offset {}-->{}", m_state->pos.line, m_state->pos.line, m_state->pos.line - 1, m_state->pos.offset, m_state->pos.offset - delta); - m_state->pos.offset -= delta; - --m_state->pos.line; - m_state->pos.col = m_state->line_contents.stripped.len + 1u; - // don't forget to undo also the changes to the remainder of the line - _RYML_CB_ASSERT(m_stack.m_callbacks, m_state->pos.offset >= m_buf.len || m_buf[m_state->pos.offset] == '\n' || m_buf[m_state->pos.offset] == '\r'); - m_state->line_contents.rem = m_buf.sub(m_state->pos.offset, 0); -} - - -//----------------------------------------------------------------------------- -void Parser::_set_indentation(size_t indentation) -{ - m_state->indref = indentation; - _c4dbgpf("state[{}]: saving indentation: {}", m_state-m_stack.begin(), m_state->indref); -} - -void Parser::_save_indentation(size_t behind) -{ - _RYML_CB_ASSERT(m_stack.m_callbacks, m_state->line_contents.rem.begin() >= m_state->line_contents.full.begin()); - m_state->indref = static_cast(m_state->line_contents.rem.begin() - m_state->line_contents.full.begin()); - _RYML_CB_ASSERT(m_stack.m_callbacks, behind <= m_state->indref); - m_state->indref -= behind; - _c4dbgpf("state[{}]: saving indentation: {}", m_state-m_stack.begin(), m_state->indref); -} - -bool Parser::_maybe_set_indentation_from_anchor_or_tag() -{ - if(m_key_anchor.not_empty()) - { - _c4dbgpf("set indentation from key anchor: {}", m_key_anchor_indentation); - _set_indentation(m_key_anchor_indentation); // this is the column where the anchor starts - return true; - } - else if(m_key_tag.not_empty()) - { - _c4dbgpf("set indentation from key tag: {}", m_key_tag_indentation); - _set_indentation(m_key_tag_indentation); // this is the column where the tag starts - return true; - } - return false; -} - - -//----------------------------------------------------------------------------- -void Parser::_write_key_anchor(size_t node_id) -{ - _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree->has_key(node_id)); - if( ! m_key_anchor.empty()) - { - _c4dbgpf("node={}: set key anchor to '{}'", node_id, m_key_anchor); - m_tree->set_key_anchor(node_id, m_key_anchor); - m_key_anchor.clear(); - m_key_anchor_was_before = false; - m_key_anchor_indentation = 0; - } - else if( ! m_tree->is_key_quoted(node_id)) - { - csubstr r = m_tree->key(node_id); - if(r.begins_with('*')) - { - _c4dbgpf("node={}: set key reference: '{}'", node_id, r); - m_tree->set_key_ref(node_id, r.sub(1)); - } - else if(r == "<<") - { - m_tree->set_key_ref(node_id, r); - _c4dbgpf("node={}: it's an inheriting reference", node_id); - if(m_tree->is_seq(node_id)) - { - _c4dbgpf("node={}: inheriting from seq of {}", node_id, m_tree->num_children(node_id)); - for(size_t i = m_tree->first_child(node_id); i != NONE; i = m_tree->next_sibling(i)) - { - if( ! (m_tree->val(i).begins_with('*'))) - _c4err("malformed reference: '{}'", m_tree->val(i)); - } - } - else if( ! m_tree->val(node_id).begins_with('*')) - { - _c4err("malformed reference: '{}'", m_tree->val(node_id)); - } - //m_tree->set_key_ref(node_id, r); - } - } -} - -//----------------------------------------------------------------------------- -void Parser::_write_val_anchor(size_t node_id) -{ - if( ! m_val_anchor.empty()) - { - _c4dbgpf("node={}: set val anchor to '{}'", node_id, m_val_anchor); - m_tree->set_val_anchor(node_id, m_val_anchor); - m_val_anchor.clear(); - } - csubstr r = m_tree->has_val(node_id) ? m_tree->val(node_id) : ""; - if(!m_tree->is_val_quoted(node_id) && r.begins_with('*')) - { - _c4dbgpf("node={}: set val reference: '{}'", node_id, r); - RYML_CHECK(!m_tree->has_val_anchor(node_id)); - m_tree->set_val_ref(node_id, r.sub(1)); - } -} - -//----------------------------------------------------------------------------- -void Parser::_push_level(bool explicit_flow_chars) -{ - _c4dbgpf("pushing level! currnode={} currlevel={} stacksize={} stackcap={}", m_state->node_id, m_state->level, m_stack.size(), m_stack.capacity()); - _RYML_CB_ASSERT(m_stack.m_callbacks, m_state == &m_stack.top()); - if(node(m_state) == nullptr) - { - _c4dbgp("pushing level! actually no, current node is null"); - //_RYML_CB_ASSERT(m_stack.m_callbacks, ! explicit_flow_chars); - return; - } - flag_t st = RUNK; - if(explicit_flow_chars || has_all(FLOW)) - { - st |= FLOW; - } - m_stack.push_top(); - m_state = &m_stack.top(); - set_flags(st); - m_state->node_id = (size_t)NONE; - m_state->indref = (size_t)NONE; - ++m_state->level; - _c4dbgpf("pushing level: now, currlevel={}", m_state->level); -} - -void Parser::_pop_level() -{ - _c4dbgpf("popping level! currnode={} currlevel={}", m_state->node_id, m_state->level); - if(has_any(RMAP) || m_tree->is_map(m_state->node_id)) - { - _stop_map(); - } - if(has_any(RSEQ) || m_tree->is_seq(m_state->node_id)) - { - _stop_seq(); - } - if(m_tree->is_doc(m_state->node_id)) - { - _stop_doc(); - } - _RYML_CB_ASSERT(m_stack.m_callbacks, m_stack.size() > 1); - _prepare_pop(); - m_stack.pop(); - m_state = &m_stack.top(); - /*if(has_any(RMAP)) - { - _toggle_key_val(); - }*/ - if(m_state->line_contents.indentation == 0) - { - //_RYML_CB_ASSERT(m_stack.m_callbacks, has_none(RTOP)); - add_flags(RTOP); - } - _c4dbgpf("popping level: now, currnode={} currlevel={}", m_state->node_id, m_state->level); -} - -//----------------------------------------------------------------------------- -void Parser::_start_unk(bool /*as_child*/) -{ - _c4dbgp("start_unk"); - _push_level(); - _move_scalar_from_top(); -} - -//----------------------------------------------------------------------------- -void Parser::_start_doc(bool as_child) -{ - _c4dbgpf("start_doc (as child={})", as_child); - _RYML_CB_ASSERT(m_stack.m_callbacks, node(m_stack.bottom()) == node(m_root_id)); - size_t parent_id = m_stack.size() < 2 ? m_root_id : m_stack.top(1).node_id; - _RYML_CB_ASSERT(m_stack.m_callbacks, parent_id != NONE); - _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree->is_root(parent_id)); - _RYML_CB_ASSERT(m_stack.m_callbacks, node(m_state) == nullptr || node(m_state) == node(m_root_id)); - if(as_child) - { - _c4dbgpf("start_doc: parent={}", parent_id); - if( ! m_tree->is_stream(parent_id)) - { - _c4dbgp("start_doc: rearranging with root as STREAM"); - m_tree->set_root_as_stream(); - } - m_state->node_id = m_tree->append_child(parent_id); - m_tree->to_doc(m_state->node_id); - } - #ifdef RYML_NO_COVERAGE__TO_BE_DELETED - else - { - _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree->is_seq(parent_id) || m_tree->empty(parent_id)); - m_state->node_id = parent_id; - if( ! m_tree->is_doc(parent_id)) - { - m_tree->to_doc(parent_id, DOC); - } - } - #endif - _c4dbgpf("start_doc: id={}", m_state->node_id); - add_flags(RUNK|RTOP|NDOC); - _handle_types(); - rem_flags(NDOC); -} - -void Parser::_stop_doc() -{ - size_t doc_node = m_state->node_id; - _c4dbgpf("stop_doc[{}]", doc_node); - _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree->is_doc(doc_node)); - if(!m_tree->is_seq(doc_node) && !m_tree->is_map(doc_node) && !m_tree->is_val(doc_node)) - { - _RYML_CB_ASSERT(m_stack.m_callbacks, has_none(SSCL)); - _c4dbgpf("stop_doc[{}]: there was nothing; adding null val", doc_node); - m_tree->to_val(doc_node, {}, DOC); - } -} - -void Parser::_end_stream() -{ - _c4dbgpf("end_stream, level={} node_id={}", m_state->level, m_state->node_id); - _RYML_CB_ASSERT(m_stack.m_callbacks, ! m_stack.empty()); - NodeData *added = nullptr; - if(has_any(SSCL)) - { - if(m_tree->is_seq(m_state->node_id)) - { - _c4dbgp("append val..."); - added = _append_val(_consume_scalar()); - } - else if(m_tree->is_map(m_state->node_id)) - { - _c4dbgp("append null key val..."); - added = _append_key_val_null(m_state->line_contents.rem.str); - #ifdef RYML_NO_COVERAGE__TO_BE_DELETED - if(has_any(RSEQIMAP)) - { - _stop_seqimap(); - _pop_level(); - } - #endif - } - else if(m_tree->is_doc(m_state->node_id) || m_tree->type(m_state->node_id) == NOTYPE) - { - NodeType_e quoted = has_any(QSCL) ? VALQUO : NOTYPE; // do this before consuming the scalar - csubstr scalar = _consume_scalar(); - _c4dbgpf("node[{}]: to docval '{}'{}", m_state->node_id, scalar, quoted == VALQUO ? ", quoted" : ""); - m_tree->to_val(m_state->node_id, scalar, DOC|quoted); - added = m_tree->get(m_state->node_id); - } - else - { - _c4err("internal error"); - } - } - else if(has_all(RSEQ|RVAL) && has_none(FLOW)) - { - _c4dbgp("add last..."); - added = _append_val_null(m_state->line_contents.rem.str); - } - else if(!m_val_tag.empty() && (m_tree->is_doc(m_state->node_id) || m_tree->type(m_state->node_id) == NOTYPE)) - { - csubstr scalar = m_state->line_contents.rem.first(0); - _c4dbgpf("node[{}]: add null scalar as docval", m_state->node_id); - m_tree->to_val(m_state->node_id, scalar, DOC); - added = m_tree->get(m_state->node_id); - } - - if(added) - { - size_t added_id = m_tree->id(added); - if(m_tree->is_seq(m_state->node_id) || m_tree->is_doc(m_state->node_id)) - { - if(!m_key_anchor.empty()) - { - _c4dbgpf("node[{}]: move key to val anchor: '{}'", added_id, m_key_anchor); - m_val_anchor = m_key_anchor; - m_key_anchor = {}; - } - if(!m_key_tag.empty()) - { - _c4dbgpf("node[{}]: move key to val tag: '{}'", added_id, m_key_tag); - m_val_tag = m_key_tag; - m_key_tag = {}; - } - } - #ifdef RYML_NO_COVERAGE__TO_BE_DELETED - if(!m_key_anchor.empty()) - { - _c4dbgpf("node[{}]: set key anchor='{}'", added_id, m_key_anchor); - m_tree->set_key_anchor(added_id, m_key_anchor); - m_key_anchor = {}; - } - #endif - if(!m_val_anchor.empty()) - { - _c4dbgpf("node[{}]: set val anchor='{}'", added_id, m_val_anchor); - m_tree->set_val_anchor(added_id, m_val_anchor); - m_val_anchor = {}; - } - #ifdef RYML_NO_COVERAGE__TO_BE_DELETED - if(!m_key_tag.empty()) - { - _c4dbgpf("node[{}]: set key tag='{}' -> '{}'", added_id, m_key_tag, normalize_tag(m_key_tag)); - m_tree->set_key_tag(added_id, normalize_tag(m_key_tag)); - m_key_tag = {}; - } - #endif - if(!m_val_tag.empty()) - { - _c4dbgpf("node[{}]: set val tag='{}' -> '{}'", added_id, m_val_tag, normalize_tag(m_val_tag)); - m_tree->set_val_tag(added_id, normalize_tag(m_val_tag)); - m_val_tag = {}; - } - } - - while(m_stack.size() > 1) - { - _c4dbgpf("popping level: {} (stack sz={})", m_state->level, m_stack.size()); - _RYML_CB_ASSERT(m_stack.m_callbacks, ! has_any(SSCL, &m_stack.top())); - if(has_all(RSEQ|FLOW)) - _err("closing ] not found"); - _pop_level(); - } - add_flags(NDOC); -} - -void Parser::_start_new_doc(csubstr rem) -{ - _c4dbgp("_start_new_doc"); - _RYML_CB_ASSERT(m_stack.m_callbacks, rem.begins_with("---")); - C4_UNUSED(rem); - - _end_stream(); - - size_t indref = m_state->indref; - _c4dbgpf("start a document, indentation={}", indref); - _line_progressed(3); - _push_level(); - _start_doc(); - _set_indentation(indref); -} - - -//----------------------------------------------------------------------------- -void Parser::_start_map(bool as_child) -{ - _c4dbgpf("start_map (as child={})", as_child); - addrem_flags(RMAP|RVAL, RKEY|RUNK); - _RYML_CB_ASSERT(m_stack.m_callbacks, node(m_stack.bottom()) == node(m_root_id)); - size_t parent_id = m_stack.size() < 2 ? m_root_id : m_stack.top(1).node_id; - _RYML_CB_ASSERT(m_stack.m_callbacks, parent_id != NONE); - _RYML_CB_ASSERT(m_stack.m_callbacks, node(m_state) == nullptr || node(m_state) == node(m_root_id)); - if(as_child) - { - m_state->node_id = m_tree->append_child(parent_id); - if(has_all(SSCL)) - { - type_bits key_quoted = NOTYPE; - if(m_state->flags & QSCL) // before consuming the scalar - key_quoted |= KEYQUO; - csubstr key = _consume_scalar(); - m_tree->to_map(m_state->node_id, key, key_quoted); - _c4dbgpf("start_map: id={} key='{}'", m_state->node_id, m_tree->key(m_state->node_id)); - _write_key_anchor(m_state->node_id); - if( ! m_key_tag.empty()) - { - _c4dbgpf("node[{}]: set key tag='{}' -> '{}'", m_state->node_id, m_key_tag, normalize_tag(m_key_tag)); - m_tree->set_key_tag(m_state->node_id, normalize_tag(m_key_tag)); - m_key_tag.clear(); - } - } - else - { - m_tree->to_map(m_state->node_id); - _c4dbgpf("start_map: id={}", m_state->node_id); - } - m_tree->_p(m_state->node_id)->m_val.scalar.str = m_state->line_contents.rem.str; - _write_val_anchor(m_state->node_id); - } - else - { - _RYML_CB_ASSERT(m_stack.m_callbacks, parent_id != NONE); - m_state->node_id = parent_id; - _c4dbgpf("start_map: id={}", m_state->node_id); - type_bits as_doc = 0; - if(m_tree->is_doc(m_state->node_id)) - as_doc |= DOC; - if(!m_tree->is_map(parent_id)) - { - RYML_CHECK(!m_tree->has_children(parent_id)); - m_tree->to_map(parent_id, as_doc); - } - else - { - m_tree->_add_flags(parent_id, as_doc); - } - _move_scalar_from_top(); - if(m_key_anchor.not_empty()) - m_key_anchor_was_before = true; - _write_val_anchor(parent_id); - if(m_stack.size() >= 2) - { - State const& parent_state = m_stack.top(1); - if(parent_state.flags & RSET) - add_flags(RSET); - } - m_tree->_p(parent_id)->m_val.scalar.str = m_state->line_contents.rem.str; - } - if( ! m_val_tag.empty()) - { - _c4dbgpf("node[{}]: set val tag='{}' -> '{}'", m_state->node_id, m_val_tag, normalize_tag(m_val_tag)); - m_tree->set_val_tag(m_state->node_id, normalize_tag(m_val_tag)); - m_val_tag.clear(); - } -} - -void Parser::_start_map_unk(bool as_child) -{ - if(!m_key_anchor_was_before) - { - _c4dbgpf("stash key anchor before starting map... '{}'", m_key_anchor); - csubstr ka = m_key_anchor; - m_key_anchor = {}; - _start_map(as_child); - m_key_anchor = ka; - } - else - { - _start_map(as_child); - m_key_anchor_was_before = false; - } - if(m_key_tag2.not_empty()) - { - m_key_tag = m_key_tag2; - m_key_tag_indentation = m_key_tag2_indentation; - m_key_tag2.clear(); - m_key_tag2_indentation = 0; - } -} - -void Parser::_stop_map() -{ - _c4dbgpf("stop_map[{}]", m_state->node_id); - _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree->is_map(m_state->node_id)); - if(has_all(QMRK|RKEY) && !has_all(SSCL)) - { - _c4dbgpf("stop_map[{}]: RKEY", m_state->node_id); - _store_scalar_null(m_state->line_contents.rem.str); - _append_key_val_null(m_state->line_contents.rem.str); - } -} - - -//----------------------------------------------------------------------------- -void Parser::_start_seq(bool as_child) -{ - _c4dbgpf("start_seq (as child={})", as_child); - if(has_all(RTOP|RUNK)) - { - _c4dbgpf("start_seq: moving key tag to val tag: '{}'", m_key_tag); - m_val_tag = m_key_tag; - m_key_tag.clear(); - } - addrem_flags(RSEQ|RVAL, RUNK); - _RYML_CB_ASSERT(m_stack.m_callbacks, node(m_stack.bottom()) == node(m_root_id)); - size_t parent_id = m_stack.size() < 2 ? m_root_id : m_stack.top(1).node_id; - _RYML_CB_ASSERT(m_stack.m_callbacks, parent_id != NONE); - _RYML_CB_ASSERT(m_stack.m_callbacks, node(m_state) == nullptr || node(m_state) == node(m_root_id)); - if(as_child) - { - m_state->node_id = m_tree->append_child(parent_id); - if(has_all(SSCL)) - { - _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree->is_map(parent_id)); - type_bits key_quoted = 0; - if(m_state->flags & QSCL) // before consuming the scalar - key_quoted |= KEYQUO; - csubstr key = _consume_scalar(); - m_tree->to_seq(m_state->node_id, key, key_quoted); - _c4dbgpf("start_seq: id={} name='{}'", m_state->node_id, m_tree->key(m_state->node_id)); - _write_key_anchor(m_state->node_id); - if( ! m_key_tag.empty()) - { - _c4dbgpf("start_seq[{}]: set key tag='{}' -> '{}'", m_state->node_id, m_key_tag, normalize_tag(m_key_tag)); - m_tree->set_key_tag(m_state->node_id, normalize_tag(m_key_tag)); - m_key_tag.clear(); - } - } - else - { - type_bits as_doc = 0; - _RYML_CB_ASSERT(m_stack.m_callbacks, !m_tree->is_doc(m_state->node_id)); - m_tree->to_seq(m_state->node_id, as_doc); - _c4dbgpf("start_seq: id={}{}", m_state->node_id, as_doc ? " as doc" : ""); - } - _write_val_anchor(m_state->node_id); - m_tree->_p(m_state->node_id)->m_val.scalar.str = m_state->line_contents.rem.str; - } - else - { - m_state->node_id = parent_id; - type_bits as_doc = 0; - if(m_tree->is_doc(m_state->node_id)) - as_doc |= DOC; - if(!m_tree->is_seq(parent_id)) - { - RYML_CHECK(!m_tree->has_children(parent_id)); - m_tree->to_seq(parent_id, as_doc); - } - else - { - m_tree->_add_flags(parent_id, as_doc); - } - _move_scalar_from_top(); - _c4dbgpf("start_seq: id={}{}", m_state->node_id, as_doc ? " as_doc" : ""); - _write_val_anchor(parent_id); - m_tree->_p(parent_id)->m_val.scalar.str = m_state->line_contents.rem.str; - } - if( ! m_val_tag.empty()) - { - _c4dbgpf("start_seq[{}]: set val tag='{}' -> '{}'", m_state->node_id, m_val_tag, normalize_tag(m_val_tag)); - m_tree->set_val_tag(m_state->node_id, normalize_tag(m_val_tag)); - m_val_tag.clear(); - } -} - -void Parser::_stop_seq() -{ - _c4dbgp("stop_seq"); - _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree->is_seq(m_state->node_id)); -} - - -//----------------------------------------------------------------------------- -void Parser::_start_seqimap() -{ - _c4dbgpf("start_seqimap at node={}. has_children={}", m_state->node_id, m_tree->has_children(m_state->node_id)); - _RYML_CB_ASSERT(m_stack.m_callbacks, has_all(RSEQ|FLOW)); - // create a map, and turn the last scalar of this sequence - // into the key of the map's first child. This scalar was - // understood to be a value in the sequence, but it is - // actually a key of a map, implicitly opened here. - // Eg [val, key: val] - // - // Yep, YAML is crazy. - if(m_tree->has_children(m_state->node_id) && m_tree->has_val(m_tree->last_child(m_state->node_id))) - { - size_t prev = m_tree->last_child(m_state->node_id); - NodeType ty = m_tree->_p(prev)->m_type; // don't use type() because it masks out the quotes - NodeScalar tmp = m_tree->valsc(prev); - _c4dbgpf("has children and last child={} has val. saving the scalars, val='{}' quoted={}", prev, tmp.scalar, ty.is_val_quoted()); - m_tree->remove(prev); - _push_level(); - _start_map(); - _store_scalar(tmp.scalar, ty.is_val_quoted()); - m_key_anchor = tmp.anchor; - m_key_tag = tmp.tag; - } - else - { - _c4dbgpf("node {} has no children yet, using empty key", m_state->node_id); - _push_level(); - _start_map(); - _store_scalar_null(m_state->line_contents.rem.str); - } - add_flags(RSEQIMAP|FLOW); -} - -void Parser::_stop_seqimap() -{ - _c4dbgp("stop_seqimap"); - _RYML_CB_ASSERT(m_stack.m_callbacks, has_all(RSEQIMAP)); -} - - -//----------------------------------------------------------------------------- -NodeData* Parser::_append_val(csubstr val, flag_t quoted) -{ - _RYML_CB_ASSERT(m_stack.m_callbacks, ! has_all(SSCL)); - _RYML_CB_ASSERT(m_stack.m_callbacks, node(m_state) != nullptr); - _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree->is_seq(m_state->node_id)); - type_bits additional_flags = quoted ? VALQUO : NOTYPE; - _c4dbgpf("append val: '{}' to parent id={} (level={}){}", val, m_state->node_id, m_state->level, quoted ? " VALQUO!" : ""); - size_t nid = m_tree->append_child(m_state->node_id); - m_tree->to_val(nid, val, additional_flags); - - _c4dbgpf("append val: id={} val='{}'", nid, m_tree->get(nid)->m_val.scalar); - if( ! m_val_tag.empty()) - { - _c4dbgpf("append val[{}]: set val tag='{}' -> '{}'", nid, m_val_tag, normalize_tag(m_val_tag)); - m_tree->set_val_tag(nid, normalize_tag(m_val_tag)); - m_val_tag.clear(); - } - _write_val_anchor(nid); - return m_tree->get(nid); -} - -NodeData* Parser::_append_key_val(csubstr val, flag_t val_quoted) -{ - _RYML_CB_ASSERT(m_stack.m_callbacks, m_tree->is_map(m_state->node_id)); - type_bits additional_flags = 0; - if(m_state->flags & QSCL) - additional_flags |= KEYQUO; - if(val_quoted) - additional_flags |= VALQUO; - - csubstr key = _consume_scalar(); - _c4dbgpf("append keyval: '{}' '{}' to parent id={} (level={}){}{}", key, val, m_state->node_id, m_state->level, (additional_flags & KEYQUO) ? " KEYQUO!" : "", (additional_flags & VALQUO) ? " VALQUO!" : ""); - size_t nid = m_tree->append_child(m_state->node_id); - m_tree->to_keyval(nid, key, val, additional_flags); - _c4dbgpf("append keyval: id={} key='{}' val='{}'", nid, m_tree->key(nid), m_tree->val(nid)); - if( ! m_key_tag.empty()) - { - _c4dbgpf("append keyval[{}]: set key tag='{}' -> '{}'", nid, m_key_tag, normalize_tag(m_key_tag)); - m_tree->set_key_tag(nid, normalize_tag(m_key_tag)); - m_key_tag.clear(); - } - if( ! m_val_tag.empty()) - { - _c4dbgpf("append keyval[{}]: set val tag='{}' -> '{}'", nid, m_val_tag, normalize_tag(m_val_tag)); - m_tree->set_val_tag(nid, normalize_tag(m_val_tag)); - m_val_tag.clear(); - } - _write_key_anchor(nid); - _write_val_anchor(nid); - rem_flags(QMRK); - return m_tree->get(nid); -} - - -//----------------------------------------------------------------------------- -void Parser::_store_scalar(csubstr s, flag_t is_quoted) -{ - _c4dbgpf("state[{}]: storing scalar '{}' (flag: {}) (old scalar='{}')", - m_state-m_stack.begin(), s, m_state->flags & SSCL, m_state->scalar); - RYML_CHECK(has_none(SSCL)); - add_flags(SSCL | (is_quoted * QSCL)); - m_state->scalar = s; -} - -csubstr Parser::_consume_scalar() -{ - _c4dbgpf("state[{}]: consuming scalar '{}' (flag: {}))", m_state-m_stack.begin(), m_state->scalar, m_state->flags & SSCL); - RYML_CHECK(m_state->flags & SSCL); - csubstr s = m_state->scalar; - rem_flags(SSCL | QSCL); - m_state->scalar.clear(); - return s; -} - -void Parser::_move_scalar_from_top() -{ - if(m_stack.size() < 2) return; - State &prev = m_stack.top(1); - _RYML_CB_ASSERT(m_stack.m_callbacks, m_state == &m_stack.top()); - _RYML_CB_ASSERT(m_stack.m_callbacks, m_state != &prev); - if(prev.flags & SSCL) - { - _c4dbgpf("moving scalar '{}' from state[{}] to state[{}] (overwriting '{}')", prev.scalar, &prev-m_stack.begin(), m_state-m_stack.begin(), m_state->scalar); - add_flags(prev.flags & (SSCL | QSCL)); - m_state->scalar = prev.scalar; - rem_flags(SSCL | QSCL, &prev); - prev.scalar.clear(); - } -} - -//----------------------------------------------------------------------------- -/** @todo this function is a monster and needs love. Likely, it needs - * to be split like _scan_scalar_*() */ -bool Parser::_handle_indentation() -{ - _RYML_CB_ASSERT(m_stack.m_callbacks, has_none(FLOW)); - if( ! _at_line_begin()) - return false; - - size_t ind = m_state->line_contents.indentation; - csubstr rem = m_state->line_contents.rem; - /** @todo instead of trimming, we should use the indentation index from above */ - csubstr remt = rem.triml(' '); - - if(remt.empty() || remt.begins_with('#')) // this is a blank or comment line - { - _line_progressed(rem.size()); - return true; - } - - _c4dbgpf("indentation? ind={} indref={}", ind, m_state->indref); - if(ind == m_state->indref) - { - _c4dbgpf("same indentation: {}", ind); - if(!rem.sub(ind).begins_with('-')) - { - _c4dbgp("does not begin with -"); - if(has_any(RMAP)) - { - if(has_all(SSCL|RVAL)) - { - _c4dbgp("add with null val"); - _append_key_val_null(rem.str + ind - 1); - addrem_flags(RKEY, RVAL); - } - } - else if(has_any(RSEQ)) - { - if(m_stack.size() > 2) // do not pop to root level - { - if(has_any(RNXT)) - { - _c4dbgp("end the indentless seq"); - _pop_level(); - return true; - } - else if(has_any(RVAL)) - { - _c4dbgp("add with null val"); - _append_val_null(rem.str); - _c4dbgp("end the indentless seq"); - _pop_level(); - return true; - } - } - } - } - _line_progressed(ind); - return ind > 0; - } - else if(ind < m_state->indref) - { - _c4dbgpf("smaller indentation ({} < {})!!!", ind, m_state->indref); - if(has_all(RVAL)) - { - _c4dbgp("there was an empty val -- appending"); - if(has_all(RMAP)) - { - _RYML_CB_ASSERT(m_stack.m_callbacks, has_all(SSCL)); - _append_key_val_null(rem.sub(ind).str - 1); - } - else if(has_all(RSEQ)) - { - _RYML_CB_ASSERT(m_stack.m_callbacks, has_none(SSCL)); - _append_val_null(rem.sub(ind).str - 1); - } - } - // search the stack frame to jump to based on its indentation - State const* popto = nullptr; - _RYML_CB_ASSERT(m_stack.m_callbacks, m_stack.is_contiguous()); // this search relies on the stack being contiguous - for(State const* s = m_state-1; s >= m_stack.begin(); --s) - { - _c4dbgpf("searching for state with indentation {}. curr={} (level={},node={})", ind, s->indref, s->level, s->node_id); - if(s->indref == ind) - { - _c4dbgpf("gotit!!! level={} node={}", s->level, s->node_id); - popto = s; - // while it may be tempting to think we're done at this - // point, we must still determine whether we're jumping to a - // parent with the same indentation. Consider this case with - // an indentless sequence: - // - // product: - // - sku: BL394D - // quantity: 4 - // description: Basketball - // price: 450.00 - // - sku: BL4438H - // quantity: 1 - // description: Super Hoop - // price: 2392.00 # jumping one level here would be wrong. - // tax: 1234.5 # we must jump two levels - if(popto > m_stack.begin()) - { - auto parent = popto - 1; - if(parent->indref == popto->indref) - { - _c4dbgpf("the parent (level={},node={}) has the same indentation ({}). is this in an indentless sequence?", parent->level, parent->node_id, popto->indref); - _c4dbgpf("isseq(popto)={} ismap(parent)={}", m_tree->is_seq(popto->node_id), m_tree->is_map(parent->node_id)); - if(m_tree->is_seq(popto->node_id) && m_tree->is_map(parent->node_id)) - { - if( ! remt.begins_with('-')) - { - _c4dbgp("this is an indentless sequence"); - popto = parent; - } - else - { - _c4dbgp("not an indentless sequence"); - } - } - } - } - break; - } - } - if(!popto || popto >= m_state || popto->level >= m_state->level) - { - _c4err("parse error: incorrect indentation?"); - } - _c4dbgpf("popping {} levels: from level {} to level {}", m_state->level-popto->level, m_state->level, popto->level); - while(m_state != popto) - { - _c4dbgpf("popping level {} (indentation={})", m_state->level, m_state->indref); - _pop_level(); - } - _RYML_CB_ASSERT(m_stack.m_callbacks, ind == m_state->indref); - _line_progressed(ind); - return true; - } - else - { - _c4dbgpf("larger indentation ({} > {})!!!", ind, m_state->indref); - _RYML_CB_ASSERT(m_stack.m_callbacks, ind > m_state->indref); - if(has_all(RMAP|RVAL)) - { - if(_is_scalar_next__rmap_val(remt) && remt.first_of(":?") == npos) - { - _c4dbgpf("actually it seems a value: '{}'", remt); - } - else - { - addrem_flags(RKEY, RVAL); - _start_unk(); - //_move_scalar_from_top(); - _line_progressed(ind); - _save_indentation(); - return true; - } - } - else if(has_all(RSEQ|RVAL)) - { - // nothing to do here - } - else - { - _c4err("parse error - indentation should not increase at this point"); - } - } - - return false; -} - -//----------------------------------------------------------------------------- -csubstr Parser::_scan_comment() -{ - csubstr s = m_state->line_contents.rem; - _RYML_CB_ASSERT(m_stack.m_callbacks, s.begins_with('#')); - _line_progressed(s.len); - // skip the # character - s = s.sub(1); - // skip leading whitespace - s = s.right_of(s.first_not_of(' '), /*include_pos*/true); - _c4dbgpf("comment was '{}'", s); - return s; -} - -//----------------------------------------------------------------------------- -csubstr Parser::_scan_squot_scalar() -{ - // quoted scalars can spread over multiple lines! - // nice explanation here: http://yaml-multiline.info/ - - // a span to the end of the file - size_t b = m_state->pos.offset; - substr s = m_buf.sub(b); - if(s.begins_with(' ')) - { - s = s.triml(' '); - _RYML_CB_ASSERT(m_stack.m_callbacks, m_buf.sub(b).is_super(s)); - _RYML_CB_ASSERT(m_stack.m_callbacks, s.begin() >= m_buf.sub(b).begin()); - _line_progressed((size_t)(s.begin() - m_buf.sub(b).begin())); - } - b = m_state->pos.offset; // take this into account - _RYML_CB_ASSERT(m_stack.m_callbacks, s.begins_with('\'')); - - // skip the opening quote - _line_progressed(1); - s = s.sub(1); - - bool needs_filter = false; - - size_t numlines = 1; // we already have one line - size_t pos = npos; // find the pos of the matching quote - while( ! _finished_file()) - { - const csubstr line = m_state->line_contents.rem; - bool line_is_blank = true; - _c4dbgpf("scanning single quoted scalar @ line[{}]: ~~~{}~~~", m_state->pos.line, line); - for(size_t i = 0; i < line.len; ++i) - { - const char curr = line.str[i]; - if(curr == '\'') // single quotes are escaped with two single quotes - { - const char next = i+1 < line.len ? line.str[i+1] : '~'; - if(next != '\'') // so just look for the first quote - { // without another after it - pos = i; - break; - } - else - { - needs_filter = true; // needs filter to remove escaped quotes - ++i; // skip the escaped quote - } - } - else if(curr != ' ') - { - line_is_blank = false; - } - } - - // leading whitespace also needs filtering - needs_filter = needs_filter - || (numlines > 1) - || line_is_blank - || (_at_line_begin() && line.begins_with(' ')); - - if(pos == npos) - { - _line_progressed(line.len); - ++numlines; - } - else - { - _RYML_CB_ASSERT(m_stack.m_callbacks, pos >= 0 && pos < m_buf.len); - _RYML_CB_ASSERT(m_stack.m_callbacks, m_buf[m_state->pos.offset + pos] == '\''); - _line_progressed(pos + 1); // progress beyond the quote - pos = m_state->pos.offset - b - 1; // but we stop before it - break; - } - - _line_ended(); - _scan_line(); - } - - if(pos == npos) - { - _c4err("reached end of file while looking for closing quote"); - } - else - { - _RYML_CB_ASSERT(m_stack.m_callbacks, pos > 0); - _RYML_CB_ASSERT(m_stack.m_callbacks, s.end() >= m_buf.begin() && s.end() <= m_buf.end()); - _RYML_CB_ASSERT(m_stack.m_callbacks, s.end() == m_buf.end() || *s.end() == '\''); - s = s.sub(0, pos-1); - } - - if(needs_filter) - { - csubstr ret = _filter_squot_scalar(s); - _RYML_CB_ASSERT(m_stack.m_callbacks, ret.len <= s.len || s.empty() || s.trim(' ').empty()); - _c4dbgpf("final scalar: \"{}\"", ret); - return ret; - } - - _c4dbgpf("final scalar: \"{}\"", s); - - return s; -} - -//----------------------------------------------------------------------------- -csubstr Parser::_scan_dquot_scalar() -{ - // quoted scalars can spread over multiple lines! - // nice explanation here: http://yaml-multiline.info/ - - // a span to the end of the file - size_t b = m_state->pos.offset; - substr s = m_buf.sub(b); - if(s.begins_with(' ')) - { - s = s.triml(' '); - _RYML_CB_ASSERT(m_stack.m_callbacks, m_buf.sub(b).is_super(s)); - _RYML_CB_ASSERT(m_stack.m_callbacks, s.begin() >= m_buf.sub(b).begin()); - _line_progressed((size_t)(s.begin() - m_buf.sub(b).begin())); - } - b = m_state->pos.offset; // take this into account - _RYML_CB_ASSERT(m_stack.m_callbacks, s.begins_with('"')); - - // skip the opening quote - _line_progressed(1); - s = s.sub(1); - - bool needs_filter = false; - - size_t numlines = 1; // we already have one line - size_t pos = npos; // find the pos of the matching quote - while( ! _finished_file()) - { - const csubstr line = m_state->line_contents.rem; - bool line_is_blank = true; - _c4dbgpf("scanning double quoted scalar @ line[{}]: line='{}'", m_state->pos.line, line); - for(size_t i = 0; i < line.len; ++i) - { - const char curr = line.str[i]; - if(curr != ' ') - line_is_blank = false; - // every \ is an escape - if(curr == '\\') - { - const char next = i+1 < line.len ? line.str[i+1] : '~'; - needs_filter = true; - if(next == '"' || next == '\\') - ++i; - } - else if(curr == '"') - { - pos = i; - break; - } - } - - // leading whitespace also needs filtering - needs_filter = needs_filter - || (numlines > 1) - || line_is_blank - || (_at_line_begin() && line.begins_with(' ')); - - if(pos == npos) - { - _line_progressed(line.len); - ++numlines; - } - else - { - _RYML_CB_ASSERT(m_stack.m_callbacks, pos >= 0 && pos < m_buf.len); - _RYML_CB_ASSERT(m_stack.m_callbacks, m_buf[m_state->pos.offset + pos] == '"'); - _line_progressed(pos + 1); // progress beyond the quote - pos = m_state->pos.offset - b - 1; // but we stop before it - break; - } - - _line_ended(); - _scan_line(); - } - - if(pos == npos) - { - _c4err("reached end of file looking for closing quote"); - } - else - { - _RYML_CB_ASSERT(m_stack.m_callbacks, pos > 0); - _RYML_CB_ASSERT(m_stack.m_callbacks, s.end() == m_buf.end() || *s.end() == '"'); - _RYML_CB_ASSERT(m_stack.m_callbacks, s.end() >= m_buf.begin() && s.end() <= m_buf.end()); - s = s.sub(0, pos-1); - } - - if(needs_filter) - { - csubstr ret = _filter_dquot_scalar(s); - _c4dbgpf("final scalar: [{}]\"{}\"", ret.len, ret); - _RYML_CB_ASSERT(m_stack.m_callbacks, ret.len <= s.len || s.empty() || s.trim(' ').empty()); - return ret; - } - - _c4dbgpf("final scalar: \"{}\"", s); - - return s; -} - -//----------------------------------------------------------------------------- -csubstr Parser::_scan_block() -{ - // nice explanation here: http://yaml-multiline.info/ - csubstr s = m_state->line_contents.rem; - csubstr trimmed = s.triml(' '); - if(trimmed.str > s.str) - { - _c4dbgp("skipping whitespace"); - _RYML_CB_ASSERT(m_stack.m_callbacks, trimmed.str >= s.str); - _line_progressed(static_cast(trimmed.str - s.str)); - s = trimmed; - } - _RYML_CB_ASSERT(m_stack.m_callbacks, s.begins_with('|') || s.begins_with('>')); - - _c4dbgpf("scanning block: specs=\"{}\"", s); - - // parse the spec - BlockStyle_e newline = s.begins_with('>') ? BLOCK_FOLD : BLOCK_LITERAL; - BlockChomp_e chomp = CHOMP_CLIP; // default to clip unless + or - are used - size_t indentation = npos; // have to find out if no spec is given - csubstr digits; - if(s.len > 1) - { - _RYML_CB_ASSERT(m_stack.m_callbacks, s.begins_with_any("|>")); - csubstr t = s.sub(1); - _c4dbgpf("scanning block: spec is multichar: '{}'", t); - _RYML_CB_ASSERT(m_stack.m_callbacks, t.len >= 1); - size_t pos = t.first_of("-+"); - _c4dbgpf("scanning block: spec chomp char at {}", pos); - if(pos != npos) - { - if(t[pos] == '-') - chomp = CHOMP_STRIP; - else if(t[pos] == '+') - chomp = CHOMP_KEEP; - if(pos == 0) - t = t.sub(1); - else - t = t.first(pos); - } - // from here to the end, only digits are considered - digits = t.left_of(t.first_not_of("0123456789")); - if( ! digits.empty()) - { - if( ! c4::atou(digits, &indentation)) - _c4err("parse error: could not read decimal"); - _c4dbgpf("scanning block: indentation specified: {}. add {} from curr state -> {}", indentation, m_state->indref, indentation+m_state->indref); - indentation += m_state->indref; - } - } - - // finish the current line - _line_progressed(s.len); - _line_ended(); - _scan_line(); - - _c4dbgpf("scanning block: style={} chomp={} indentation={}", newline==BLOCK_FOLD ? "fold" : "literal", chomp==CHOMP_CLIP ? "clip" : (chomp==CHOMP_STRIP ? "strip" : "keep"), indentation); - - // start with a zero-length block, already pointing at the right place - substr raw_block(m_buf.data() + m_state->pos.offset, size_t(0));// m_state->line_contents.full.sub(0, 0); - _RYML_CB_ASSERT(m_stack.m_callbacks, raw_block.begin() == m_state->line_contents.full.begin()); - - // read every full line into a raw block, - // from which newlines are to be stripped as needed. - // - // If no explicit indentation was given, pick it from the first - // non-empty line. See - // https://yaml.org/spec/1.2.2/#8111-block-indentation-indicator - size_t num_lines = 0, first = m_state->pos.line, provisional_indentation = npos; - LineContents lc; - while(( ! _finished_file())) - { - // peek next line, but do not advance immediately - lc.reset_with_next_line(m_buf, m_state->pos.offset); - _c4dbgpf("scanning block: peeking at '{}'", lc.stripped); - // evaluate termination conditions - if(indentation != npos) - { - // stop when the line is deindented and not empty - if(lc.indentation < indentation && ( ! lc.rem.trim(" \t\r\n").empty())) - { - _c4dbgpf("scanning block: indentation decreased ref={} thisline={}", indentation, lc.indentation); - break; - } - else if(indentation == 0) - { - if((lc.rem == "..." || lc.rem.begins_with("... ")) - || - (lc.rem == "---" || lc.rem.begins_with("--- "))) - { - _c4dbgp("scanning block: stop. indentation=0 and stream ended"); - break; - } - } - } - else - { - _c4dbgpf("scanning block: indentation ref not set. firstnonws={}", lc.stripped.first_not_of(' ')); - if(lc.stripped.first_not_of(' ') != npos) // non-empty line - { - _c4dbgpf("scanning block: line not empty. indref={} indprov={} indentation={}", m_state->indref, provisional_indentation, lc.indentation); - if(provisional_indentation == npos) - { - if(lc.indentation < m_state->indref) - { - _c4dbgpf("scanning block: block terminated indentation={} < indref={}", lc.indentation, m_state->indref); - if(raw_block.len == 0) - { - _c4dbgp("scanning block: was empty, undo next line"); - _line_ended_undo(); - } - break; - } - else if(lc.indentation == m_state->indref) - { - if(has_any(RSEQ|RMAP)) - { - _c4dbgpf("scanning block: block terminated. reading container and indentation={}==indref={}", lc.indentation, m_state->indref); - break; - } - } - _c4dbgpf("scanning block: set indentation ref from this line: ref={}", lc.indentation); - indentation = lc.indentation; - } - else - { - if(lc.indentation >= provisional_indentation) - { - _c4dbgpf("scanning block: set indentation ref from provisional indentation: provisional_ref={}, thisline={}", provisional_indentation, lc.indentation); - //indentation = provisional_indentation ? provisional_indentation : lc.indentation; - indentation = lc.indentation; - } - else - { - break; - //_c4err("parse error: first non-empty block line should have at least the original indentation"); - } - } - } - else // empty line - { - _c4dbgpf("scanning block: line empty or {} spaces. line_indentation={} prov_indentation={}", lc.stripped.len, lc.indentation, provisional_indentation); - if(provisional_indentation != npos) - { - if(lc.stripped.len >= provisional_indentation) - { - _c4dbgpf("scanning block: increase provisional_ref {} -> {}", provisional_indentation, lc.stripped.len); - provisional_indentation = lc.stripped.len; - } - #ifdef RYML_NO_COVERAGE__TO_BE_DELETED - else if(lc.indentation >= provisional_indentation && lc.indentation != npos) - { - _c4dbgpf("scanning block: increase provisional_ref {} -> {}", provisional_indentation, lc.indentation); - provisional_indentation = lc.indentation; - } - #endif - } - else - { - provisional_indentation = lc.indentation ? lc.indentation : has_any(RSEQ|RVAL); - _c4dbgpf("scanning block: initialize provisional_ref={}", provisional_indentation); - if(provisional_indentation == npos) - { - provisional_indentation = lc.stripped.len ? lc.stripped.len : has_any(RSEQ|RVAL); - _c4dbgpf("scanning block: initialize provisional_ref={}", provisional_indentation); - } - } - } - } - // advance now that we know the folded scalar continues - m_state->line_contents = lc; - _c4dbgpf("scanning block: append '{}'", m_state->line_contents.rem); - raw_block.len += m_state->line_contents.full.len; - _line_progressed(m_state->line_contents.rem.len); - _line_ended(); - ++num_lines; - } - _RYML_CB_ASSERT(m_stack.m_callbacks, m_state->pos.line == (first + num_lines) || (raw_block.len == 0)); - C4_UNUSED(num_lines); - C4_UNUSED(first); - - if(indentation == npos) - { - _c4dbgpf("scanning block: set indentation from provisional: {}", provisional_indentation); - indentation = provisional_indentation; - } - - if(num_lines) - _line_ended_undo(); - - _c4dbgpf("scanning block: raw=~~~{}~~~", raw_block); - - // ok! now we strip the newlines and spaces according to the specs - s = _filter_block_scalar(raw_block, newline, chomp, indentation); - - _c4dbgpf("scanning block: final=~~~{}~~~", s); - - return s; -} - - -//----------------------------------------------------------------------------- - -template -bool Parser::_filter_nl(substr r, size_t *C4_RESTRICT i, size_t *C4_RESTRICT pos, size_t indentation) -{ - // a debugging scaffold: - #if 0 - #define _c4dbgfnl(fmt, ...) _c4dbgpf("filter_nl[{}]: " fmt, *i, __VA_ARGS__) - #else - #define _c4dbgfnl(...) - #endif - - const char curr = r[*i]; - bool replaced = false; - - _RYML_CB_ASSERT(m_stack.m_callbacks, indentation != npos); - _RYML_CB_ASSERT(m_stack.m_callbacks, curr == '\n'); - - _c4dbgfnl("found newline. sofar=[{}]~~~{}~~~", *pos, m_filter_arena.first(*pos)); - size_t ii = *i; - size_t numnl_following = count_following_newlines(r, &ii, indentation); - if(numnl_following) - { - _c4dbgfnl("{} consecutive (empty) lines {} in the middle. totalws={}", 1+numnl_following, ii < r.len ? "in the middle" : "at the end", ii - *i); - for(size_t j = 0; j < numnl_following; ++j) - m_filter_arena.str[(*pos)++] = '\n'; - } - else - { - if(r.first_not_of(" \t", *i+1) != npos) - { - m_filter_arena.str[(*pos)++] = ' '; - _c4dbgfnl("single newline. convert to space. ii={}/{}. sofar=[{}]~~~{}~~~", ii, r.len, *pos, m_filter_arena.first(*pos)); - replaced = true; - } - else - { - if C4_IF_CONSTEXPR (keep_trailing_whitespace) - { - m_filter_arena.str[(*pos)++] = ' '; - _c4dbgfnl("single newline. convert to space. ii={}/{}. sofar=[{}]~~~{}~~~", ii, r.len, *pos, m_filter_arena.first(*pos)); - replaced = true; - } - else - { - _c4dbgfnl("last newline, everything else is whitespace. ii={}/{}", ii, r.len); - *i = r.len; - } - } - if C4_IF_CONSTEXPR (backslash_is_escape) - { - if(ii < r.len && r.str[ii] == '\\') - { - const char next = ii+1 < r.len ? r.str[ii+1] : '\0'; - if(next == ' ' || next == '\t') - { - _c4dbgfnl("extend skip to backslash{}", ""); - ++ii; - } - } - } - } - *i = ii - 1; // correct for the loop increment - - #undef _c4dbgfnl - - return replaced; -} - - -//----------------------------------------------------------------------------- - -template -void Parser::_filter_ws(substr r, size_t *C4_RESTRICT i, size_t *C4_RESTRICT pos) -{ - // a debugging scaffold: - #if 0 - #define _c4dbgfws(fmt, ...) _c4dbgpf("filt_nl[{}]: " fmt, *i, __VA_ARGS__) - #else - #define _c4dbgfws(...) - #endif - - const char curr = r[*i]; - _c4dbgfws("found whitespace '{}'", _c4prc(curr)); - _RYML_CB_ASSERT(m_stack.m_callbacks, curr == ' ' || curr == '\t'); - - size_t first = *i > 0 ? r.first_not_of(" \t", *i) : r.first_not_of(' ', *i); - if(first != npos) - { - if(r[first] == '\n' || r[first] == '\r') // skip trailing whitespace - { - _c4dbgfws("whitespace is trailing on line. firstnonws='{}'@{}", _c4prc(r[first]), first); - *i = first - 1; // correct for the loop increment - } - else // a legit whitespace - { - m_filter_arena.str[(*pos)++] = curr; - _c4dbgfws("legit whitespace. sofar=[{}]~~~{}~~~", *pos, m_filter_arena.first(*pos)); - } - } - else - { - _c4dbgfws("... everything else is trailing whitespace{}", ""); - if C4_IF_CONSTEXPR (keep_trailing_whitespace) - for(size_t j = *i; j < r.len; ++j) - m_filter_arena.str[(*pos)++] = r[j]; - *i = r.len; - } - - #undef _c4dbgfws -} - - -//----------------------------------------------------------------------------- -csubstr Parser::_filter_plain_scalar(substr s, size_t indentation) -{ - // a debugging scaffold: - #if 0 - #define _c4dbgfps(...) _c4dbgpf("filt_plain_scalar" __VA_ARGS__) - #else - #define _c4dbgfps(...) - #endif - - _c4dbgfps("before=~~~{}~~~", s); - - substr r = s.triml(" \t"); - _grow_filter_arena(r.len); - size_t pos = 0; // the filtered size - bool filtered_chars = false; - for(size_t i = 0; i < r.len; ++i) - { - const char curr = r.str[i]; - _c4dbgfps("[{}]: '{}'", i, _c4prc(curr)); - if(curr == ' ' || curr == '\t') - { - _filter_ws(r, &i, &pos); - } - else if(curr == '\n') - { - filtered_chars = _filter_nl(r, &i, &pos, indentation); - } - else if(curr == '\r') // skip \r --- https://stackoverflow.com/questions/1885900 - { - ; - } - else - { - m_filter_arena.str[pos++] = r[i]; - } - } - - _RYML_CB_ASSERT(m_stack.m_callbacks, pos <= m_filter_arena.len); - if(pos < r.len || filtered_chars) - { - r = _finish_filter_arena(r, pos); - } - - _RYML_CB_ASSERT(m_stack.m_callbacks, s.len >= r.len); - _c4dbgfps("#filteredchars={} after=~~~{}~~~", s.len - r.len, r); - - #undef _c4dbgfps - return r; -} - - -//----------------------------------------------------------------------------- -csubstr Parser::_filter_squot_scalar(substr s) -{ - // a debugging scaffold: - #if 0 - #define _c4dbgfsq(...) _c4dbgpf("filt_squo_scalar") - #else - #define _c4dbgfsq(...) - #endif - - // from the YAML spec for double-quoted scalars: - // https://yaml.org/spec/1.2-old/spec.html#style/flow/single-quoted - - _c4dbgfsq(": before=~~~{}~~~", s); - - _grow_filter_arena(s.len); - substr r = s; - size_t pos = 0; // the filtered size - bool filtered_chars = false; - for(size_t i = 0; i < r.len; ++i) - { - const char curr = r[i]; - _c4dbgfsq("[{}]: '{}'", i, _c4prc(curr)); - if(curr == ' ' || curr == '\t') - { - _filter_ws(r, &i, &pos); - } - else if(curr == '\n') - { - filtered_chars = _filter_nl(r, &i, &pos, /*indentation*/0); - } - else if(curr == '\r') // skip \r --- https://stackoverflow.com/questions/1885900 - { - ; - } - else if(curr == '\'') - { - char next = i+1 < r.len ? r[i+1] : '\0'; - if(next == '\'') - { - _c4dbgfsq("[{}]: two consecutive quotes", i); - filtered_chars = true; - m_filter_arena.str[pos++] = '\''; - ++i; - } - } - else - { - m_filter_arena.str[pos++] = curr; - } - } - - _RYML_CB_ASSERT(m_stack.m_callbacks, pos <= m_filter_arena.len); - if(pos < r.len || filtered_chars) - { - r = _finish_filter_arena(r, pos); - } - - _RYML_CB_ASSERT(m_stack.m_callbacks, s.len >= r.len); - _c4dbgpf(": #filteredchars={} after=~~~{}~~~", s.len - r.len, r); - - #undef _c4dbgfsq - return r; -} - - -//----------------------------------------------------------------------------- -csubstr Parser::_filter_dquot_scalar(substr s) -{ - // a debugging scaffold: - #if 0 - #define _c4dbgfdq(...) _c4dbgpf("filt_dquo_scalar" __VA_ARGS__) - #else - #define _c4dbgfdq(...) - #endif - - _c4dbgfdq(": before=~~~{}~~~", s); - - // from the YAML spec for double-quoted scalars: - // https://yaml.org/spec/1.2-old/spec.html#style/flow/double-quoted - // - // All leading and trailing white space characters are excluded - // from the content. Each continuation line must therefore contain - // at least one non-space character. Empty lines, if any, are - // consumed as part of the line folding. - - _grow_filter_arena(s.len + 2u * s.count('\\')); - substr r = s; - size_t pos = 0; // the filtered size - bool filtered_chars = false; - for(size_t i = 0; i < r.len; ++i) - { - const char curr = r[i]; - _c4dbgfdq("[{}]: '{}'", i, _c4prc(curr)); - if(curr == ' ' || curr == '\t') - { - _filter_ws(r, &i, &pos); - } - else if(curr == '\n') - { - filtered_chars = _filter_nl(r, &i, &pos, /*indentation*/0); - } - else if(curr == '\r') // skip \r --- https://stackoverflow.com/questions/1885900 - { - ; - } - else if(curr == '\\') - { - char next = i+1 < r.len ? r[i+1] : '\0'; - _c4dbgfdq("[{}]: backslash, next='{}'", i, _c4prc(next)); - filtered_chars = true; - if(next == '\r') - { - if(i+2 < r.len && r[i+2] == '\n') - { - ++i; // newline escaped with \ -- skip both (add only one as i is loop-incremented) - next = '\n'; - _c4dbgfdq("[{}]: was \\r\\n, now next='\\n'", i); - } - } - // remember the loop will also increment i - if(next == '\n') - { - size_t ii = i + 2; - for( ; ii < r.len; ++ii) - { - if(r.str[ii] == ' ' || r.str[ii] == '\t') // skip leading whitespace - ; - else - break; - } - i += ii - i - 1; - } - else if(next == '"' || next == '/' || next == ' ' || next == '\t') // escapes for json compatibility - { - m_filter_arena.str[pos++] = next; - ++i; - } - else if(next == '\r') - { - //++i; - } - else if(next == 'n') - { - m_filter_arena.str[pos++] = '\n'; - ++i; - } - else if(next == 'r') - { - m_filter_arena.str[pos++] = '\r'; - ++i; // skip - } - else if(next == 't') - { - m_filter_arena.str[pos++] = '\t'; - ++i; - } - else if(next == '\\') - { - m_filter_arena.str[pos++] = '\\'; - ++i; - } - else if(next == 'x') // UTF8 - { - if(i + 1u + 2u >= r.len) - _c4err("\\x requires 2 hex digits"); - uint8_t byteval = {}; - if(!read_hex(r.sub(i + 2u, 2u), &byteval)) - _c4err("failed to read \\x codepoint"); - m_filter_arena.str[pos++] = *(char*)&byteval; - i += 1u + 2u; - } - else if(next == 'u') // UTF16 - { - if(i + 1u + 4u >= r.len) - _c4err("\\u requires 4 hex digits"); - char readbuf[8]; - csubstr codepoint = r.sub(i + 2u, 4u); - uint32_t codepoint_val = {}; - if(!read_hex(codepoint, &codepoint_val)) - _c4err("failed to parse \\u codepoint"); - size_t numbytes = decode_code_point((uint8_t*)readbuf, sizeof(readbuf), codepoint_val); - C4_ASSERT(numbytes <= 4); - memcpy(m_filter_arena.str + pos, readbuf, numbytes); - pos += numbytes; - i += 1u + 4u; - } - else if(next == 'U') // UTF32 - { - if(i + 1u + 8u >= r.len) - _c4err("\\U requires 8 hex digits"); - char readbuf[8]; - csubstr codepoint = r.sub(i + 2u, 8u); - uint32_t codepoint_val = {}; - if(!read_hex(codepoint, &codepoint_val)) - _c4err("failed to parse \\U codepoint"); - size_t numbytes = decode_code_point((uint8_t*)readbuf, sizeof(readbuf), codepoint_val); - C4_ASSERT(numbytes <= 4); - memcpy(m_filter_arena.str + pos, readbuf, numbytes); - pos += numbytes; - i += 1u + 8u; - } - // https://yaml.org/spec/1.2.2/#rule-c-ns-esc-char - else if(next == '0') - { - m_filter_arena.str[pos++] = '\0'; - ++i; - } - else if(next == 'b') // backspace - { - m_filter_arena.str[pos++] = '\b'; - ++i; - } - else if(next == 'f') // form feed - { - m_filter_arena.str[pos++] = '\f'; - ++i; - } - else if(next == 'a') // bell character - { - m_filter_arena.str[pos++] = '\a'; - ++i; - } - else if(next == 'v') // vertical tab - { - m_filter_arena.str[pos++] = '\v'; - ++i; - } - else if(next == 'e') // escape character - { - m_filter_arena.str[pos++] = '\x1b'; - ++i; - } - else if(next == '_') // unicode non breaking space \u00a0 - { - // https://www.compart.com/en/unicode/U+00a0 - m_filter_arena.str[pos++] = _RYML_CHCONST(-0x3e, 0xc2); - m_filter_arena.str[pos++] = _RYML_CHCONST(-0x60, 0xa0); - ++i; - } - else if(next == 'N') // unicode next line \u0085 - { - // https://www.compart.com/en/unicode/U+0085 - m_filter_arena.str[pos++] = _RYML_CHCONST(-0x3e, 0xc2); - m_filter_arena.str[pos++] = _RYML_CHCONST(-0x7b, 0x85); - ++i; - } - else if(next == 'L') // unicode line separator \u2028 - { - // https://www.utf8-chartable.de/unicode-utf8-table.pl?start=8192&number=1024&names=-&utf8=0x&unicodeinhtml=hex - m_filter_arena.str[pos++] = _RYML_CHCONST(-0x1e, 0xe2); - m_filter_arena.str[pos++] = _RYML_CHCONST(-0x80, 0x80); - m_filter_arena.str[pos++] = _RYML_CHCONST(-0x58, 0xa8); - ++i; - } - else if(next == 'P') // unicode paragraph separator \u2029 - { - // https://www.utf8-chartable.de/unicode-utf8-table.pl?start=8192&number=1024&names=-&utf8=0x&unicodeinhtml=hex - m_filter_arena.str[pos++] = _RYML_CHCONST(-0x1e, 0xe2); - m_filter_arena.str[pos++] = _RYML_CHCONST(-0x80, 0x80); - m_filter_arena.str[pos++] = _RYML_CHCONST(-0x57, 0xa9); - ++i; - } - _c4dbgfdq("[{}]: backslash...sofar=[{}]~~~{}~~~", i, pos, m_filter_arena.first(pos)); - } - else - { - m_filter_arena.str[pos++] = curr; - } - } - - _RYML_CB_ASSERT(m_stack.m_callbacks, pos <= m_filter_arena.len); - if(pos < r.len || filtered_chars) - { - r = _finish_filter_arena(r, pos); - } - - _RYML_CB_ASSERT(m_stack.m_callbacks, s.len >= r.len); - _c4dbgpf(": #filteredchars={} after=~~~{}~~~", s.len - r.len, r); - - #undef _c4dbgfdq - - return r; -} - - -//----------------------------------------------------------------------------- -bool Parser::_apply_chomp(substr buf, size_t *C4_RESTRICT pos, BlockChomp_e chomp) -{ - substr trimmed = buf.first(*pos).trimr('\n'); - bool added_newline = false; - switch(chomp) - { - case CHOMP_KEEP: - if(trimmed.len == *pos) - { - _c4dbgpf("chomp=KEEP: add missing newline @{}", *pos); - //m_filter_arena.str[(*pos)++] = '\n'; - added_newline = true; - } - break; - case CHOMP_CLIP: - if(trimmed.len == *pos) - { - _c4dbgpf("chomp=CLIP: add missing newline @{}", *pos); - m_filter_arena.str[(*pos)++] = '\n'; - added_newline = true; - } - else - { - _c4dbgpf("chomp=CLIP: include single trailing newline @{}", trimmed.len+1); - *pos = trimmed.len + 1; - } - break; - case CHOMP_STRIP: - _c4dbgpf("chomp=STRIP: strip {}-{}-{} newlines", *pos, trimmed.len, *pos-trimmed.len); - *pos = trimmed.len; - break; - default: - _c4err("unknown chomp style"); - } - return added_newline; -} - - -//----------------------------------------------------------------------------- -csubstr Parser::_filter_block_scalar(substr s, BlockStyle_e style, BlockChomp_e chomp, size_t indentation) -{ - // a debugging scaffold: - #if 0 - #define _c4dbgfbl(fmt, ...) _c4dbgpf("filt_block" fmt, __VA_ARGS__) - #else - #define _c4dbgfbl(...) - #endif - - _c4dbgfbl(": indentation={} before=[{}]~~~{}~~~", indentation, s.len, s); - - if(chomp != CHOMP_KEEP && s.trim(" \n\r").len == 0u) - { - _c4dbgp("filt_block: empty scalar"); - return s.first(0); - } - - substr r = s; - - switch(style) - { - case BLOCK_LITERAL: - { - _c4dbgp("filt_block: style=literal"); - // trim leading whitespace up to indentation - { - size_t numws = r.first_not_of(' '); - if(numws != npos) - { - if(numws > indentation) - r = r.sub(indentation); - else - r = r.sub(numws); - _c4dbgfbl(": after triml=[{}]~~~{}~~~", r.len, r); - } - else - { - if(chomp != CHOMP_KEEP || r.len == 0) - { - _c4dbgfbl(": all spaces {}, return empty", r.len); - return r.first(0); - } - else - { - r[0] = '\n'; - return r.first(1); - } - } - } - _grow_filter_arena(s.len + 2u); // use s.len! because we may need to add a newline at the end, so the leading indentation will allow space for that newline - size_t pos = 0; // the filtered size - for(size_t i = 0; i < r.len; ++i) - { - const char curr = r.str[i]; - _c4dbgfbl("[{}]='{}' pos={}", i, _c4prc(curr), pos); - if(curr == '\r') - continue; - m_filter_arena.str[pos++] = curr; - if(curr == '\n') - { - _c4dbgfbl("[{}]: found newline", i); - // skip indentation on the next line - csubstr rem = r.sub(i+1); - size_t first = rem.first_not_of(' '); - if(first != npos) - { - _RYML_CB_ASSERT(m_stack.m_callbacks, first < rem.len); - _RYML_CB_ASSERT(m_stack.m_callbacks, i+1+first < r.len); - _c4dbgfbl("[{}]: {} spaces follow before next nonws character @ [{}]='{}'", i, first, i+1+first, rem.str[first]); - if(first < indentation) - { - _c4dbgfbl("[{}]: skip {}<{} spaces from indentation", i, first, indentation); - i += first; - } - else - { - _c4dbgfbl("[{}]: skip {} spaces from indentation", i, indentation); - i += indentation; - } - } - else - { - _RYML_CB_ASSERT(m_stack.m_callbacks, i+1 <= r.len); - first = rem.len; - _c4dbgfbl("[{}]: {} spaces to the end", i, first); - if(first) - { - if(first < indentation) - { - _c4dbgfbl("[{}]: skip everything", i); - --pos; - break; - } - else - { - _c4dbgfbl("[{}]: skip {} spaces from indentation", i, indentation); - i += indentation; - } - } - else if(i+1 == r.len) - { - if(chomp == CHOMP_STRIP) - --pos; - break; - } - } - } - } - _RYML_CB_ASSERT(m_stack.m_callbacks, s.len >= pos); - _c4dbgfbl(": #filteredchars={} after=~~~{}~~~", s.len - r.len, r); - bool changed = _apply_chomp(m_filter_arena, &pos, chomp); - _RYML_CB_ASSERT(m_stack.m_callbacks, pos <= m_filter_arena.len); - _RYML_CB_ASSERT(m_stack.m_callbacks, pos <= s.len); - if(pos < r.len || changed) - { - r = _finish_filter_arena(s, pos); // write into s - } - break; - } - case BLOCK_FOLD: - { - _c4dbgp("filt_block: style=fold"); - _grow_filter_arena(r.len + 2); - size_t pos = 0; // the filtered size - bool filtered_chars = false; - bool started = false; - bool is_indented = false; - size_t i = r.first_not_of(' '); - _c4dbgfbl(": first non space at {}", i); - if(i > indentation) - { - is_indented = true; - i = indentation; - } - _c4dbgfbl(": start folding at {}, is_indented={}", i, (int)is_indented); - auto on_change_indentation = [&](size_t numnl_following, size_t last_newl, size_t first_non_whitespace){ - _c4dbgfbl("[{}]: add 1+{} newlines", i, numnl_following); - for(size_t j = 0; j < 1 + numnl_following; ++j) - m_filter_arena.str[pos++] = '\n'; - for(i = last_newl + 1 + indentation; i < first_non_whitespace; ++i) - { - if(r.str[i] == '\r') - continue; - _c4dbgfbl("[{}]: add '{}'", i, _c4prc(r.str[i])); - m_filter_arena.str[pos++] = r.str[i]; - } - --i; - }; - for( ; i < r.len; ++i) - { - const char curr = r.str[i]; - _c4dbgfbl("[{}]='{}'", i, _c4prc(curr)); - if(curr == '\n') - { - filtered_chars = true; - // skip indentation on the next line, and advance over the next non-indented blank lines as well - size_t first_non_whitespace; - size_t numnl_following = (size_t)-1; - while(r[i] == '\n') - { - ++numnl_following; - csubstr rem = r.sub(i+1); - size_t first = rem.first_not_of(' '); - _c4dbgfbl("[{}]: found newline. first={} rem.len={}", i, first, rem.len); - if(first != npos) - { - first_non_whitespace = first + i+1; - while(first_non_whitespace < r.len && r[first_non_whitespace] == '\r') - ++first_non_whitespace; - _RYML_CB_ASSERT(m_stack.m_callbacks, first < rem.len); - _RYML_CB_ASSERT(m_stack.m_callbacks, i+1+first < r.len); - _c4dbgfbl("[{}]: {} spaces follow before next nonws character @ [{}]='{}'", i, first, i+1+first, _c4prc(rem.str[first])); - if(first < indentation) - { - _c4dbgfbl("[{}]: skip {}<{} spaces from indentation", i, first, indentation); - i += first; - } - else - { - _c4dbgfbl("[{}]: skip {} spaces from indentation", i, indentation); - i += indentation; - if(first > indentation) - { - _c4dbgfbl("[{}]: {} further indented than {}, stop newlining", i, first, indentation); - goto finished_counting_newlines; - } - } - // prepare the next while loop iteration - // by setting i at the next newline after - // an empty line - if(r[first_non_whitespace] == '\n') - i = first_non_whitespace; - else - goto finished_counting_newlines; - } - else - { - _RYML_CB_ASSERT(m_stack.m_callbacks, i+1 <= r.len); - first = rem.len; - first_non_whitespace = first + i+1; - if(first) - { - _c4dbgfbl("[{}]: {} spaces to the end", i, first); - if(first < indentation) - { - _c4dbgfbl("[{}]: skip everything", i); - i += first; - } - else - { - _c4dbgfbl("[{}]: skip {} spaces from indentation", i, indentation); - i += indentation; - if(first > indentation) - { - _c4dbgfbl("[{}]: {} spaces missing. not done yet", i, indentation - first); - goto finished_counting_newlines; - } - } - } - else // if(i+1 == r.len) - { - _c4dbgfbl("[{}]: it's the final newline", i); - _RYML_CB_ASSERT(m_stack.m_callbacks, i+1 == r.len); - _RYML_CB_ASSERT(m_stack.m_callbacks, rem.len == 0); - } - goto end_of_scalar; - } - } - end_of_scalar: - // Write all the trailing newlines. Since we're - // at the end no folding is needed, so write every - // newline (add 1). - _c4dbgfbl("[{}]: add {} trailing newlines", i, 1+numnl_following); - for(size_t j = 0; j < 1 + numnl_following; ++j) - m_filter_arena.str[pos++] = '\n'; - break; - finished_counting_newlines: - _c4dbgfbl("[{}]: #newlines={} firstnonws={}", i, numnl_following, first_non_whitespace); - while(first_non_whitespace < r.len && r[first_non_whitespace] == '\t') - ++first_non_whitespace; - _c4dbgfbl("[{}]: #newlines={} firstnonws={}", i, numnl_following, first_non_whitespace); - _RYML_CB_ASSERT(m_stack.m_callbacks, first_non_whitespace <= r.len); - size_t last_newl = r.last_of('\n', first_non_whitespace); - size_t this_indentation = first_non_whitespace - last_newl - 1; - _c4dbgfbl("[{}]: #newlines={} firstnonws={} lastnewl={} this_indentation={} vs indentation={}", i, numnl_following, first_non_whitespace, last_newl, this_indentation, indentation); - _RYML_CB_ASSERT(m_stack.m_callbacks, first_non_whitespace >= last_newl + 1); - _RYML_CB_ASSERT(m_stack.m_callbacks, this_indentation >= indentation); - if(!started) - { - _c4dbgfbl("[{}]: #newlines={}. write all leading newlines", i, numnl_following); - for(size_t j = 0; j < 1 + numnl_following; ++j) - m_filter_arena.str[pos++] = '\n'; - if(this_indentation > indentation) - { - is_indented = true; - _c4dbgfbl("[{}]: advance ->{}", i, last_newl + indentation); - i = last_newl + indentation; - } - else - { - i = first_non_whitespace - 1; - _c4dbgfbl("[{}]: advance ->{}", i, first_non_whitespace); - } - } - else if(this_indentation == indentation) - { - _c4dbgfbl("[{}]: same indentation", i); - if(!is_indented) - { - if(numnl_following == 0) - { - _c4dbgfbl("[{}]: fold!", i); - m_filter_arena.str[pos++] = ' '; - } - else - { - _c4dbgfbl("[{}]: add {} newlines", i, 1 + numnl_following); - for(size_t j = 0; j < numnl_following; ++j) - m_filter_arena.str[pos++] = '\n'; - } - i = first_non_whitespace - 1; - _c4dbgfbl("[{}]: advance {}->{}", i, i, first_non_whitespace); - } - else - { - _c4dbgfbl("[{}]: back to ref indentation", i); - is_indented = false; - on_change_indentation(numnl_following, last_newl, first_non_whitespace); - _c4dbgfbl("[{}]: advance {}->{}", i, i, first_non_whitespace); - } - } - else - { - _c4dbgfbl("[{}]: increased indentation.", i); - is_indented = true; - _RYML_CB_ASSERT(m_stack.m_callbacks, this_indentation > indentation); - on_change_indentation(numnl_following, last_newl, first_non_whitespace); - _c4dbgfbl("[{}]: advance {}->{}", i, i, first_non_whitespace); - } - } - else if(curr != '\r') - { - if(curr != '\t') - started = true; - m_filter_arena.str[pos++] = curr; - } - } - _RYML_CB_ASSERT(m_stack.m_callbacks, pos <= m_filter_arena.len); - _c4dbgfbl(": #filteredchars={} after=[{}]~~~{}~~~", (int)s.len - (int)pos, pos, m_filter_arena.first(pos)); - bool changed = _apply_chomp(m_filter_arena, &pos, chomp); - if(pos < r.len || filtered_chars || changed) - { - r = _finish_filter_arena(s, pos); // write into s - } - } - break; - default: - _c4err("unknown block style"); - } - - _c4dbgfbl(": final=[{}]~~~{}~~~", r.len, r); - - #undef _c4dbgfbl - - return r; -} - -//----------------------------------------------------------------------------- -size_t Parser::_count_nlines(csubstr src) -{ - return 1 + src.count('\n'); -} - -//----------------------------------------------------------------------------- -void Parser::_handle_directive(csubstr directive_) -{ - csubstr directive = directive_; - if(directive.begins_with("%TAG")) - { - TagDirective td; - _c4dbgpf("%TAG directive: {}", directive_); - directive = directive.sub(4); - if(!directive.begins_with(' ')) - _c4err("malformed tag directive: {}", directive_); - directive = directive.triml(' '); - size_t pos = directive.find(' '); - if(pos == npos) - _c4err("malformed tag directive: {}", directive_); - td.handle = directive.first(pos); - directive = directive.sub(td.handle.len).triml(' '); - pos = directive.find(' '); - if(pos != npos) - directive = directive.first(pos); - td.prefix = directive; - td.next_node_id = m_tree->size(); - if(m_tree->size() > 0) - { - size_t prev = m_tree->size() - 1; - if(m_tree->is_root(prev) && m_tree->type(prev) != NOTYPE && !m_tree->is_stream(prev)) - ++td.next_node_id; - } - _c4dbgpf("%TAG: handle={} prefix={} next_node={}", td.handle, td.prefix, td.next_node_id); - m_tree->add_tag_directive(td); - } - else if(directive.begins_with("%YAML")) - { - _c4dbgpf("%YAML directive! ignoring...: {}", directive); - } -} - -//----------------------------------------------------------------------------- -void Parser::set_flags(flag_t f, State * s) -{ -#ifdef RYML_DBG - char buf1_[64], buf2_[64]; - csubstr buf1 = _prfl(buf1_, f); - csubstr buf2 = _prfl(buf2_, s->flags); - _c4dbgpf("state[{}]: setting flags to {}: before={}", s-m_stack.begin(), buf1, buf2); -#endif - s->flags = f; -} - -void Parser::add_flags(flag_t on, State * s) -{ -#ifdef RYML_DBG - char buf1_[64], buf2_[64], buf3_[64]; - csubstr buf1 = _prfl(buf1_, on); - csubstr buf2 = _prfl(buf2_, s->flags); - csubstr buf3 = _prfl(buf3_, s->flags|on); - _c4dbgpf("state[{}]: adding flags {}: before={} after={}", s-m_stack.begin(), buf1, buf2, buf3); -#endif - s->flags |= on; -} - -void Parser::addrem_flags(flag_t on, flag_t off, State * s) -{ -#ifdef RYML_DBG - char buf1_[64], buf2_[64], buf3_[64], buf4_[64]; - csubstr buf1 = _prfl(buf1_, on); - csubstr buf2 = _prfl(buf2_, off); - csubstr buf3 = _prfl(buf3_, s->flags); - csubstr buf4 = _prfl(buf4_, ((s->flags|on)&(~off))); - _c4dbgpf("state[{}]: adding flags {} / removing flags {}: before={} after={}", s-m_stack.begin(), buf1, buf2, buf3, buf4); -#endif - s->flags |= on; - s->flags &= ~off; -} - -void Parser::rem_flags(flag_t off, State * s) -{ -#ifdef RYML_DBG - char buf1_[64], buf2_[64], buf3_[64]; - csubstr buf1 = _prfl(buf1_, off); - csubstr buf2 = _prfl(buf2_, s->flags); - csubstr buf3 = _prfl(buf3_, s->flags&(~off)); - _c4dbgpf("state[{}]: removing flags {}: before={} after={}", s-m_stack.begin(), buf1, buf2, buf3); -#endif - s->flags &= ~off; -} - -//----------------------------------------------------------------------------- - -csubstr Parser::_prfl(substr buf, flag_t flags) -{ - size_t pos = 0; - bool gotone = false; - - #define _prflag(fl) \ - if((flags & fl) == (fl)) \ - { \ - if(gotone) \ - { \ - if(pos + 1 < buf.len) \ - buf[pos] = '|'; \ - ++pos; \ - } \ - csubstr fltxt = #fl; \ - if(pos + fltxt.len <= buf.len) \ - memcpy(buf.str + pos, fltxt.str, fltxt.len); \ - pos += fltxt.len; \ - gotone = true; \ - } - - _prflag(RTOP); - _prflag(RUNK); - _prflag(RMAP); - _prflag(RSEQ); - _prflag(FLOW); - _prflag(QMRK); - _prflag(RKEY); - _prflag(RVAL); - _prflag(RNXT); - _prflag(SSCL); - _prflag(QSCL); - _prflag(RSET); - _prflag(NDOC); - _prflag(RSEQIMAP); - - #undef _prflag - - RYML_ASSERT(pos <= buf.len); - - return buf.first(pos); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -void Parser::_grow_filter_arena(size_t num_characters_needed) -{ - _c4dbgpf("grow: arena={} numchars={}", m_filter_arena.len, num_characters_needed); - if(num_characters_needed <= m_filter_arena.len) - return; - size_t sz = m_filter_arena.len << 1; - _c4dbgpf("grow: sz={}", sz); - sz = num_characters_needed > sz ? num_characters_needed : sz; - _c4dbgpf("grow: sz={}", sz); - sz = sz < 128u ? 128u : sz; - _c4dbgpf("grow: sz={}", sz); - _RYML_CB_ASSERT(m_stack.m_callbacks, sz >= num_characters_needed); - _resize_filter_arena(sz); -} - -void Parser::_resize_filter_arena(size_t num_characters) -{ - if(num_characters > m_filter_arena.len) - { - _c4dbgpf("resize: sz={}", num_characters); - char *prev = m_filter_arena.str; - if(m_filter_arena.str) - { - _RYML_CB_ASSERT(m_stack.m_callbacks, m_filter_arena.len > 0); - _RYML_CB_FREE(m_stack.m_callbacks, m_filter_arena.str, char, m_filter_arena.len); - } - m_filter_arena.str = _RYML_CB_ALLOC_HINT(m_stack.m_callbacks, char, num_characters, prev); - m_filter_arena.len = num_characters; - } -} - -substr Parser::_finish_filter_arena(substr dst, size_t pos) -{ - _RYML_CB_ASSERT(m_stack.m_callbacks, pos <= m_filter_arena.len); - _RYML_CB_ASSERT(m_stack.m_callbacks, pos <= dst.len); - memcpy(dst.str, m_filter_arena.str, pos); - return dst.first(pos); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -csubstr Parser::location_contents(Location const& loc) const -{ - _RYML_CB_ASSERT(m_stack.m_callbacks, loc.offset < m_buf.len); - return m_buf.sub(loc.offset); -} - -Location Parser::location(ConstNodeRef node) const -{ - _RYML_CB_ASSERT(m_stack.m_callbacks, node.valid()); - return location(*node.tree(), node.id()); -} - -Location Parser::location(Tree const& tree, size_t node) const -{ - // try hard to avoid getting the location from a null string. - Location loc; - if(_location_from_node(tree, node, &loc, 0)) - return loc; - return val_location(m_buf.str); -} - -bool Parser::_location_from_node(Tree const& tree, size_t node, Location *C4_RESTRICT loc, size_t level) const -{ - if(tree.has_key(node)) - { - csubstr k = tree.key(node); - if(C4_LIKELY(k.str != nullptr)) - { - _RYML_CB_ASSERT(m_stack.m_callbacks, k.is_sub(m_buf)); - _RYML_CB_ASSERT(m_stack.m_callbacks, m_buf.is_super(k)); - *loc = val_location(k.str); - return true; - } - } - - if(tree.has_val(node)) - { - csubstr v = tree.val(node); - if(C4_LIKELY(v.str != nullptr)) - { - _RYML_CB_ASSERT(m_stack.m_callbacks, v.is_sub(m_buf)); - _RYML_CB_ASSERT(m_stack.m_callbacks, m_buf.is_super(v)); - *loc = val_location(v.str); - return true; - } - } - - if(tree.is_container(node)) - { - if(_location_from_cont(tree, node, loc)) - return true; - } - - if(tree.type(node) != NOTYPE && level == 0) - { - // try the prev sibling - { - const size_t prev = tree.prev_sibling(node); - if(prev != NONE) - { - if(_location_from_node(tree, prev, loc, level+1)) - return true; - } - } - // try the next sibling - { - const size_t next = tree.next_sibling(node); - if(next != NONE) - { - if(_location_from_node(tree, next, loc, level+1)) - return true; - } - } - // try the parent - { - const size_t parent = tree.parent(node); - if(parent != NONE) - { - if(_location_from_node(tree, parent, loc, level+1)) - return true; - } - } - } - - return false; -} - -bool Parser::_location_from_cont(Tree const& tree, size_t node, Location *C4_RESTRICT loc) const -{ - _RYML_CB_ASSERT(m_stack.m_callbacks, tree.is_container(node)); - if(!tree.is_stream(node)) - { - const char *node_start = tree._p(node)->m_val.scalar.str; // this was stored in the container - if(tree.has_children(node)) - { - size_t child = tree.first_child(node); - if(tree.has_key(child)) - { - // when a map starts, the container was set after the key - csubstr k = tree.key(child); - if(k.str && node_start > k.str) - node_start = k.str; - } - } - *loc = val_location(node_start); - return true; - } - else // it's a stream - { - *loc = val_location(m_buf.str); // just return the front of the buffer - } - return true; -} - - -Location Parser::val_location(const char *val) const -{ - if(C4_UNLIKELY(val == nullptr)) - return {m_file, 0, 0, 0}; - - _RYML_CB_CHECK(m_stack.m_callbacks, m_options.locations()); - // NOTE: if any of these checks fails, the parser needs to be - // instantiated with locations enabled. - _RYML_CB_ASSERT(m_stack.m_callbacks, m_buf.str == m_newline_offsets_buf.str); - _RYML_CB_ASSERT(m_stack.m_callbacks, m_buf.len == m_newline_offsets_buf.len); - _RYML_CB_ASSERT(m_stack.m_callbacks, m_options.locations()); - _RYML_CB_ASSERT(m_stack.m_callbacks, !_locations_dirty()); - _RYML_CB_ASSERT(m_stack.m_callbacks, m_newline_offsets != nullptr); - _RYML_CB_ASSERT(m_stack.m_callbacks, m_newline_offsets_size > 0); - // NOTE: the pointer needs to belong to the buffer that was used to parse. - csubstr src = m_buf; - _RYML_CB_CHECK(m_stack.m_callbacks, val != nullptr || src.str == nullptr); - _RYML_CB_CHECK(m_stack.m_callbacks, (val >= src.begin() && val <= src.end()) || (src.str == nullptr && val == nullptr)); - // ok. search the first stored newline after the given ptr - using lineptr_type = size_t const* C4_RESTRICT; - lineptr_type lineptr = nullptr; - size_t offset = (size_t)(val - src.begin()); - if(m_newline_offsets_size < 30) // TODO magic number - { - // just do a linear search if the size is small. - for(lineptr_type curr = m_newline_offsets, last = m_newline_offsets + m_newline_offsets_size; curr < last; ++curr) - { - if(*curr > offset) - { - lineptr = curr; - break; - } - } - } - else - { - // do a bisection search if the size is not small. - // - // We could use std::lower_bound but this is simple enough and - // spares the include of . - size_t count = m_newline_offsets_size; - size_t step; - lineptr_type it; - lineptr = m_newline_offsets; - while(count) - { - step = count >> 1; - it = lineptr + step; - if(*it < offset) - { - lineptr = ++it; - count -= step + 1; - } - else - { - count = step; - } - } - } - _RYML_CB_ASSERT(m_stack.m_callbacks, lineptr >= m_newline_offsets); - _RYML_CB_ASSERT(m_stack.m_callbacks, lineptr <= m_newline_offsets + m_newline_offsets_size); - _RYML_CB_ASSERT(m_stack.m_callbacks, *lineptr > offset); - Location loc; - loc.name = m_file; - loc.offset = offset; - loc.line = (size_t)(lineptr - m_newline_offsets); - if(lineptr > m_newline_offsets) - loc.col = (offset - *(lineptr-1) - 1u); - else - loc.col = offset; - return loc; -} - -void Parser::_prepare_locations() -{ - m_newline_offsets_buf = m_buf; - size_t numnewlines = 1u + m_buf.count('\n'); - _resize_locations(numnewlines); - m_newline_offsets_size = 0; - for(size_t i = 0; i < m_buf.len; i++) - if(m_buf[i] == '\n') - m_newline_offsets[m_newline_offsets_size++] = i; - m_newline_offsets[m_newline_offsets_size++] = m_buf.len; - _RYML_CB_ASSERT(m_stack.m_callbacks, m_newline_offsets_size == numnewlines); -} - -void Parser::_resize_locations(size_t numnewlines) -{ - if(numnewlines > m_newline_offsets_capacity) - { - if(m_newline_offsets) - _RYML_CB_FREE(m_stack.m_callbacks, m_newline_offsets, size_t, m_newline_offsets_capacity); - m_newline_offsets = _RYML_CB_ALLOC_HINT(m_stack.m_callbacks, size_t, numnewlines, m_newline_offsets); - m_newline_offsets_capacity = numnewlines; - } -} - -bool Parser::_locations_dirty() const -{ - return !m_newline_offsets_size; -} - -} // namespace yml -} // namespace c4 - - -#if defined(_MSC_VER) -# pragma warning(pop) -#elif defined(__clang__) -# pragma clang diagnostic pop -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#endif diff --git a/thirdparty/ryml/src/c4/yml/parse.hpp b/thirdparty/ryml/src/c4/yml/parse.hpp deleted file mode 100644 index 659edf7e0..000000000 --- a/thirdparty/ryml/src/c4/yml/parse.hpp +++ /dev/null @@ -1,706 +0,0 @@ -#ifndef _C4_YML_PARSE_HPP_ -#define _C4_YML_PARSE_HPP_ - -#ifndef _C4_YML_TREE_HPP_ -#include "c4/yml/tree.hpp" -#endif - -#ifndef _C4_YML_NODE_HPP_ -#include "c4/yml/node.hpp" -#endif - -#ifndef _C4_YML_DETAIL_STACK_HPP_ -#include "c4/yml/detail/stack.hpp" -#endif - -#include - -#if defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable: 4251/*needs to have dll-interface to be used by clients of struct*/) -#endif - -namespace c4 { -namespace yml { - -struct RYML_EXPORT ParserOptions -{ -private: - - typedef enum : uint32_t { - LOCATIONS = (1 << 0), - DEFAULTS = 0, - } Flags_e; - - uint32_t flags = DEFAULTS; -public: - ParserOptions() = default; - - /** @name source location tracking */ - /** @{ */ - - /** enable/disable source location tracking */ - ParserOptions& locations(bool enabled) - { - if(enabled) - flags |= LOCATIONS; - else - flags &= ~LOCATIONS; - return *this; - } - bool locations() const { return (flags & LOCATIONS) != 0u; } - - /** @} */ -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -class RYML_EXPORT Parser -{ -public: - - /** @name construction and assignment */ - /** @{ */ - - Parser(Callbacks const& cb, ParserOptions opts={}); - Parser(ParserOptions opts={}) : Parser(get_callbacks(), opts) {} - ~Parser(); - - Parser(Parser &&); - Parser(Parser const&); - Parser& operator=(Parser &&); - Parser& operator=(Parser const&); - - /** @} */ - -public: - - /** @name modifiers */ - /** @{ */ - - /** Reserve a certain capacity for the parsing stack. - * This should be larger than the expected depth of the parsed - * YAML tree. - * - * The parsing stack is the only (potential) heap memory used by - * the parser. - * - * If the requested capacity is below the default - * stack size of 16, the memory is used directly in the parser - * object; otherwise it will be allocated from the heap. - * - * @note this reserves memory only for the parser itself; all the - * allocations for the parsed tree will go through the tree's - * allocator. - * - * @note the tree and the arena can (and should) also be reserved. */ - void reserve_stack(size_t capacity) - { - m_stack.reserve(capacity); - } - - /** Reserve a certain capacity for the array used to track node - * locations in the source buffer. */ - void reserve_locations(size_t num_source_lines) - { - _resize_locations(num_source_lines); - } - - /** Reserve a certain capacity for the character arena used to - * filter scalars. */ - void reserve_filter_arena(size_t num_characters) - { - _resize_filter_arena(num_characters); - } - - /** @} */ - -public: - - /** @name getters and modifiers */ - /** @{ */ - - /** Get the current callbacks in the parser. */ - Callbacks callbacks() const { return m_stack.m_callbacks; } - - /** Get the name of the latest file parsed by this object. */ - csubstr filename() const { return m_file; } - - /** Get the latest YAML buffer parsed by this object. */ - csubstr source() const { return m_buf; } - - size_t stack_capacity() const { return m_stack.capacity(); } - size_t locations_capacity() const { return m_newline_offsets_capacity; } - size_t filter_arena_capacity() const { return m_filter_arena.len; } - - ParserOptions const& options() const { return m_options; } - - /** @} */ - -public: - - /** @name parse_in_place */ - /** @{ */ - - /** Create a new tree and parse into its root. - * The tree is created with the callbacks currently in the parser. */ - Tree parse_in_place(csubstr filename, substr src) - { - Tree t(callbacks()); - t.reserve(_estimate_capacity(src)); - this->parse_in_place(filename, src, &t, t.root_id()); - return t; - } - - /** Parse into an existing tree, starting at its root node. - * The callbacks in the tree are kept, and used to allocate - * the tree members, if any allocation is required. */ - void parse_in_place(csubstr filename, substr src, Tree *t) - { - this->parse_in_place(filename, src, t, t->root_id()); - } - - /** Parse into an existing node. - * The callbacks in the tree are kept, and used to allocate - * the tree members, if any allocation is required. */ - void parse_in_place(csubstr filename, substr src, Tree *t, size_t node_id); - // ^^^^^^^^^^^^^ this is the workhorse overload; everything else is syntactic candy - - /** Parse into an existing node. - * The callbacks in the tree are kept, and used to allocate - * the tree members, if any allocation is required. */ - void parse_in_place(csubstr filename, substr src, NodeRef node) - { - this->parse_in_place(filename, src, node.tree(), node.id()); - } - - RYML_DEPRECATED("use parse_in_place() instead") Tree parse(csubstr filename, substr src) { return parse_in_place(filename, src); } - RYML_DEPRECATED("use parse_in_place() instead") void parse(csubstr filename, substr src, Tree *t) { parse_in_place(filename, src, t); } - RYML_DEPRECATED("use parse_in_place() instead") void parse(csubstr filename, substr src, Tree *t, size_t node_id) { parse_in_place(filename, src, t, node_id); } - RYML_DEPRECATED("use parse_in_place() instead") void parse(csubstr filename, substr src, NodeRef node) { parse_in_place(filename, src, node); } - - /** @} */ - -public: - - /** @name parse_in_arena: copy the YAML source buffer to the - * tree's arena, then parse the copy in situ - * - * @note overloads receiving a substr YAML buffer are intentionally - * left undefined, such that calling parse_in_arena() with a substr - * will cause a linker error. This is to prevent an accidental - * copy of the source buffer to the tree's arena, because substr - * is implicitly convertible to csubstr. If you really intend to parse - * a mutable buffer in the tree's arena, convert it first to immutable - * by assigning the substr to a csubstr prior to calling parse_in_arena(). - * This is not needed for parse_in_place() because csubstr is not - * implicitly convertible to substr. */ - /** @{ */ - - // READ THE NOTE ABOVE! - #define RYML_DONT_PARSE_SUBSTR_IN_ARENA "Do not pass a (mutable) substr to parse_in_arena(); if you have a substr, it should be parsed in place. Consider using parse_in_place() instead, or convert the buffer to csubstr prior to calling. This function is deliberately left undefined and will cause a linker error." - RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) Tree parse_in_arena(csubstr filename, substr csrc); - RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena(csubstr filename, substr csrc, Tree *t); - RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena(csubstr filename, substr csrc, Tree *t, size_t node_id); - RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena(csubstr filename, substr csrc, NodeRef node); - - /** Create a new tree and parse into its root. - * The immutable YAML source is first copied to the tree's arena, - * and parsed from there. - * The callbacks in the tree are kept, and used to allocate - * the tree members, if any allocation is required. */ - Tree parse_in_arena(csubstr filename, csubstr csrc) - { - Tree t(callbacks()); - substr src = t.copy_to_arena(csrc); - t.reserve(_estimate_capacity(csrc)); - this->parse_in_place(filename, src, &t, t.root_id()); - return t; - } - - /** Parse into an existing tree, starting at its root node. - * The immutable YAML source is first copied to the tree's arena, - * and parsed from there. - * The callbacks in the tree are kept, and used to allocate - * the tree members, if any allocation is required. */ - void parse_in_arena(csubstr filename, csubstr csrc, Tree *t) - { - substr src = t->copy_to_arena(csrc); - this->parse_in_place(filename, src, t, t->root_id()); - } - - /** Parse into a specific node in an existing tree. - * The immutable YAML source is first copied to the tree's arena, - * and parsed from there. - * The callbacks in the tree are kept, and used to allocate - * the tree members, if any allocation is required. */ - void parse_in_arena(csubstr filename, csubstr csrc, Tree *t, size_t node_id) - { - substr src = t->copy_to_arena(csrc); - this->parse_in_place(filename, src, t, node_id); - } - - /** Parse into a specific node in an existing tree. - * The immutable YAML source is first copied to the tree's arena, - * and parsed from there. - * The callbacks in the tree are kept, and used to allocate - * the tree members, if any allocation is required. */ - void parse_in_arena(csubstr filename, csubstr csrc, NodeRef node) - { - substr src = node.tree()->copy_to_arena(csrc); - this->parse_in_place(filename, src, node.tree(), node.id()); - } - - RYML_DEPRECATED("use parse_in_arena() instead") Tree parse(csubstr filename, csubstr csrc) { return parse_in_arena(filename, csrc); } - RYML_DEPRECATED("use parse_in_arena() instead") void parse(csubstr filename, csubstr csrc, Tree *t) { parse_in_arena(filename, csrc, t); } - RYML_DEPRECATED("use parse_in_arena() instead") void parse(csubstr filename, csubstr csrc, Tree *t, size_t node_id) { parse_in_arena(filename, csrc, t, node_id); } - RYML_DEPRECATED("use parse_in_arena() instead") void parse(csubstr filename, csubstr csrc, NodeRef node) { parse_in_arena(filename, csrc, node); } - - /** @} */ - -public: - - /** @name locations */ - /** @{ */ - - /** Get the location of a node of the last tree to be parsed by this parser. */ - Location location(Tree const& tree, size_t node_id) const; - /** Get the location of a node of the last tree to be parsed by this parser. */ - Location location(ConstNodeRef node) const; - /** Get the string starting at a particular location, to the end - * of the parsed source buffer. */ - csubstr location_contents(Location const& loc) const; - /** Given a pointer to a buffer position, get the location. @p val - * must be pointing to somewhere in the source buffer that was - * last parsed by this object. */ - Location val_location(const char *val) const; - - /** @} */ - -private: - - typedef enum { - BLOCK_LITERAL, //!< keep newlines (|) - BLOCK_FOLD //!< replace newline with single space (>) - } BlockStyle_e; - - typedef enum { - CHOMP_CLIP, //!< single newline at end (default) - CHOMP_STRIP, //!< no newline at end (-) - CHOMP_KEEP //!< all newlines from end (+) - } BlockChomp_e; - -private: - - using flag_t = int; - - static size_t _estimate_capacity(csubstr src) { size_t c = _count_nlines(src); c = c >= 16 ? c : 16; return c; } - - void _reset(); - - bool _finished_file() const; - bool _finished_line() const; - - csubstr _peek_next_line(size_t pos=npos) const; - bool _advance_to_peeked(); - void _scan_line(); - - csubstr _slurp_doc_scalar(); - - /** - * @param [out] quoted - * Will only be written to if this method returns true. - * Will be set to true if the scanned scalar was quoted, by '', "", > or |. - */ - bool _scan_scalar_seq_blck(csubstr *C4_RESTRICT scalar, bool *C4_RESTRICT quoted); - bool _scan_scalar_map_blck(csubstr *C4_RESTRICT scalar, bool *C4_RESTRICT quoted); - bool _scan_scalar_seq_flow(csubstr *C4_RESTRICT scalar, bool *C4_RESTRICT quoted); - bool _scan_scalar_map_flow(csubstr *C4_RESTRICT scalar, bool *C4_RESTRICT quoted); - bool _scan_scalar_unk(csubstr *C4_RESTRICT scalar, bool *C4_RESTRICT quoted); - - csubstr _scan_comment(); - csubstr _scan_squot_scalar(); - csubstr _scan_dquot_scalar(); - csubstr _scan_block(); - substr _scan_plain_scalar_blck(csubstr currscalar, csubstr peeked_line, size_t indentation); - substr _scan_plain_scalar_flow(csubstr currscalar, csubstr peeked_line); - substr _scan_complex_key(csubstr currscalar, csubstr peeked_line); - csubstr _scan_to_next_nonempty_line(size_t indentation); - csubstr _extend_scanned_scalar(csubstr currscalar); - - csubstr _filter_squot_scalar(const substr s); - csubstr _filter_dquot_scalar(substr s); - csubstr _filter_plain_scalar(substr s, size_t indentation); - csubstr _filter_block_scalar(substr s, BlockStyle_e style, BlockChomp_e chomp, size_t indentation); - template - bool _filter_nl(substr scalar, size_t *C4_RESTRICT pos, size_t *C4_RESTRICT filter_arena_pos, size_t indentation); - template - void _filter_ws(substr scalar, size_t *C4_RESTRICT pos, size_t *C4_RESTRICT filter_arena_pos); - bool _apply_chomp(substr buf, size_t *C4_RESTRICT pos, BlockChomp_e chomp); - - void _handle_finished_file(); - void _handle_line(); - - bool _handle_indentation(); - - bool _handle_unk(); - bool _handle_map_flow(); - bool _handle_map_blck(); - bool _handle_seq_flow(); - bool _handle_seq_blck(); - bool _handle_top(); - bool _handle_types(); - bool _handle_key_anchors_and_refs(); - bool _handle_val_anchors_and_refs(); - void _move_val_tag_to_key_tag(); - void _move_key_tag_to_val_tag(); - void _move_key_tag2_to_key_tag(); - void _move_val_anchor_to_key_anchor(); - void _move_key_anchor_to_val_anchor(); - - void _push_level(bool explicit_flow_chars = false); - void _pop_level(); - - void _start_unk(bool as_child=true); - - void _start_map(bool as_child=true); - void _start_map_unk(bool as_child); - void _stop_map(); - - void _start_seq(bool as_child=true); - void _stop_seq(); - - void _start_seqimap(); - void _stop_seqimap(); - - void _start_doc(bool as_child=true); - void _stop_doc(); - void _start_new_doc(csubstr rem); - void _end_stream(); - - NodeData* _append_val(csubstr val, flag_t quoted=false); - NodeData* _append_key_val(csubstr val, flag_t val_quoted=false); - bool _rval_dash_start_or_continue_seq(); - - void _store_scalar(csubstr s, flag_t is_quoted); - csubstr _consume_scalar(); - void _move_scalar_from_top(); - - inline NodeData* _append_val_null(const char *str) { _RYML_CB_ASSERT(m_stack.m_callbacks, str >= m_buf.begin() && str <= m_buf.end()); return _append_val({nullptr, size_t(0)}); } - inline NodeData* _append_key_val_null(const char *str) { _RYML_CB_ASSERT(m_stack.m_callbacks, str >= m_buf.begin() && str <= m_buf.end()); return _append_key_val({nullptr, size_t(0)}); } - inline void _store_scalar_null(const char *str) { _RYML_CB_ASSERT(m_stack.m_callbacks, str >= m_buf.begin() && str <= m_buf.end()); _store_scalar({nullptr, size_t(0)}, false); } - - void _set_indentation(size_t behind); - void _save_indentation(size_t behind=0); - bool _maybe_set_indentation_from_anchor_or_tag(); - - void _write_key_anchor(size_t node_id); - void _write_val_anchor(size_t node_id); - - void _handle_directive(csubstr directive); - - void _skipchars(char c); - template - void _skipchars(const char (&chars)[N]); - -private: - - static size_t _count_nlines(csubstr src); - -private: - - typedef enum : flag_t { - RTOP = 0x01 << 0, ///< reading at top level - RUNK = 0x01 << 1, ///< reading an unknown: must determine whether scalar, map or seq - RMAP = 0x01 << 2, ///< reading a map - RSEQ = 0x01 << 3, ///< reading a seq - FLOW = 0x01 << 4, ///< reading is inside explicit flow chars: [] or {} - QMRK = 0x01 << 5, ///< reading an explicit key (`? key`) - RKEY = 0x01 << 6, ///< reading a scalar as key - RVAL = 0x01 << 7, ///< reading a scalar as val - RNXT = 0x01 << 8, ///< read next val or keyval - SSCL = 0x01 << 9, ///< there's a stored scalar - QSCL = 0x01 << 10, ///< stored scalar was quoted - RSET = 0x01 << 11, ///< the (implicit) map being read is a !!set. @see https://yaml.org/type/set.html - NDOC = 0x01 << 12, ///< no document mode. a document has ended and another has not started yet. - //! reading an implicit map nested in an explicit seq. - //! eg, {key: [key2: value2, key3: value3]} - //! is parsed as {key: [{key2: value2}, {key3: value3}]} - RSEQIMAP = 0x01 << 13, - } State_e; - - struct LineContents - { - csubstr full; ///< the full line, including newlines on the right - csubstr stripped; ///< the stripped line, excluding newlines on the right - csubstr rem; ///< the stripped line remainder; initially starts at the first non-space character - size_t indentation; ///< the number of spaces on the beginning of the line - - LineContents() : full(), stripped(), rem(), indentation() {} - - void reset_with_next_line(csubstr buf, size_t pos); - - void reset(csubstr full_, csubstr stripped_) - { - full = full_; - stripped = stripped_; - rem = stripped_; - // find the first column where the character is not a space - indentation = full.first_not_of(' '); - } - - size_t current_col() const - { - return current_col(rem); - } - - size_t current_col(csubstr s) const - { - RYML_ASSERT(s.str >= full.str); - RYML_ASSERT(full.is_super(s)); - size_t col = static_cast(s.str - full.str); - return col; - } - }; - - struct State - { - flag_t flags; - size_t level; - size_t node_id; // don't hold a pointer to the node as it will be relocated during tree resizes - csubstr scalar; - size_t scalar_col; // the column where the scalar (or its quotes) begin - - Location pos; - LineContents line_contents; - size_t indref; - - State() : flags(), level(), node_id(), scalar(), scalar_col(), pos(), line_contents(), indref() {} - - void reset(const char *file, size_t node_id_) - { - flags = RUNK|RTOP; - level = 0; - pos.name = to_csubstr(file); - pos.offset = 0; - pos.line = 1; - pos.col = 1; - node_id = node_id_; - scalar_col = 0; - scalar.clear(); - indref = 0; - } - }; - - void _line_progressed(size_t ahead); - void _line_ended(); - void _line_ended_undo(); - - void _prepare_pop() - { - RYML_ASSERT(m_stack.size() > 1); - State const& curr = m_stack.top(); - State & next = m_stack.top(1); - next.pos = curr.pos; - next.line_contents = curr.line_contents; - next.scalar = curr.scalar; - } - - inline bool _at_line_begin() const - { - return m_state->line_contents.rem.begin() == m_state->line_contents.full.begin(); - } - inline bool _at_line_end() const - { - csubstr r = m_state->line_contents.rem; - return r.empty() || r.begins_with(' ', r.len); - } - inline bool _token_is_from_this_line(csubstr token) const - { - return token.is_sub(m_state->line_contents.full); - } - - inline NodeData * node(State const* s) const { return m_tree->get(s->node_id); } - inline NodeData * node(State const& s) const { return m_tree->get(s .node_id); } - inline NodeData * node(size_t node_id) const { return m_tree->get( node_id); } - - inline bool has_all(flag_t f) const { return (m_state->flags & f) == f; } - inline bool has_any(flag_t f) const { return (m_state->flags & f) != 0; } - inline bool has_none(flag_t f) const { return (m_state->flags & f) == 0; } - - static inline bool has_all(flag_t f, State const* s) { return (s->flags & f) == f; } - static inline bool has_any(flag_t f, State const* s) { return (s->flags & f) != 0; } - static inline bool has_none(flag_t f, State const* s) { return (s->flags & f) == 0; } - - inline void set_flags(flag_t f) { set_flags(f, m_state); } - inline void add_flags(flag_t on) { add_flags(on, m_state); } - inline void addrem_flags(flag_t on, flag_t off) { addrem_flags(on, off, m_state); } - inline void rem_flags(flag_t off) { rem_flags(off, m_state); } - - void set_flags(flag_t f, State * s); - void add_flags(flag_t on, State * s); - void addrem_flags(flag_t on, flag_t off, State * s); - void rem_flags(flag_t off, State * s); - - void _resize_filter_arena(size_t num_characters); - void _grow_filter_arena(size_t num_characters); - substr _finish_filter_arena(substr dst, size_t pos); - - void _prepare_locations(); - void _resize_locations(size_t sz); - bool _locations_dirty() const; - - bool _location_from_cont(Tree const& tree, size_t node, Location *C4_RESTRICT loc) const; - bool _location_from_node(Tree const& tree, size_t node, Location *C4_RESTRICT loc, size_t level) const; - -private: - - void _free(); - void _clr(); - void _cp(Parser const* that); - void _mv(Parser *that); - -#ifdef RYML_DBG - template void _dbg(csubstr fmt, Args const& C4_RESTRICT ...args) const; -#endif - template void _err(csubstr fmt, Args const& C4_RESTRICT ...args) const; - template void _fmt_msg(DumpFn &&dumpfn) const; - static csubstr _prfl(substr buf, flag_t v); - -private: - - ParserOptions m_options; - - csubstr m_file; - substr m_buf; - - size_t m_root_id; - Tree * m_tree; - - detail::stack m_stack; - State * m_state; - - size_t m_key_tag_indentation; - size_t m_key_tag2_indentation; - csubstr m_key_tag; - csubstr m_key_tag2; - size_t m_val_tag_indentation; - csubstr m_val_tag; - - bool m_key_anchor_was_before; - size_t m_key_anchor_indentation; - csubstr m_key_anchor; - size_t m_val_anchor_indentation; - csubstr m_val_anchor; - - substr m_filter_arena; - - size_t *m_newline_offsets; - size_t m_newline_offsets_size; - size_t m_newline_offsets_capacity; - csubstr m_newline_offsets_buf; -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -/** @name parse_in_place - * - * @desc parse a mutable YAML source buffer. - * - * @note These freestanding functions use a temporary parser object, - * and are convenience functions to easily parse YAML without the need - * to instantiate a separate parser. Note that some properties - * (notably node locations in the original source code) are only - * available through the parser object after it has parsed the - * code. If you need access to any of these properties, use - * Parser::parse_in_place() */ -/** @{ */ - -inline Tree parse_in_place( substr yaml ) { Parser np; return np.parse_in_place({} , yaml); } //!< parse in-situ a modifiable YAML source buffer. -inline Tree parse_in_place(csubstr filename, substr yaml ) { Parser np; return np.parse_in_place(filename, yaml); } //!< parse in-situ a modifiable YAML source buffer, providing a filename for error messages. -inline void parse_in_place( substr yaml, Tree *t ) { Parser np; np.parse_in_place({} , yaml, t); } //!< reusing the YAML tree, parse in-situ a modifiable YAML source buffer -inline void parse_in_place(csubstr filename, substr yaml, Tree *t ) { Parser np; np.parse_in_place(filename, yaml, t); } //!< reusing the YAML tree, parse in-situ a modifiable YAML source buffer, providing a filename for error messages. -inline void parse_in_place( substr yaml, Tree *t, size_t node_id) { Parser np; np.parse_in_place({} , yaml, t, node_id); } //!< reusing the YAML tree, parse in-situ a modifiable YAML source buffer -inline void parse_in_place(csubstr filename, substr yaml, Tree *t, size_t node_id) { Parser np; np.parse_in_place(filename, yaml, t, node_id); } //!< reusing the YAML tree, parse in-situ a modifiable YAML source buffer, providing a filename for error messages. -inline void parse_in_place( substr yaml, NodeRef node ) { Parser np; np.parse_in_place({} , yaml, node); } //!< reusing the YAML tree, parse in-situ a modifiable YAML source buffer -inline void parse_in_place(csubstr filename, substr yaml, NodeRef node ) { Parser np; np.parse_in_place(filename, yaml, node); } //!< reusing the YAML tree, parse in-situ a modifiable YAML source buffer, providing a filename for error messages. - -RYML_DEPRECATED("use parse_in_place() instead") inline Tree parse( substr yaml ) { Parser np; return np.parse_in_place({} , yaml); } -RYML_DEPRECATED("use parse_in_place() instead") inline Tree parse(csubstr filename, substr yaml ) { Parser np; return np.parse_in_place(filename, yaml); } -RYML_DEPRECATED("use parse_in_place() instead") inline void parse( substr yaml, Tree *t ) { Parser np; np.parse_in_place({} , yaml, t); } -RYML_DEPRECATED("use parse_in_place() instead") inline void parse(csubstr filename, substr yaml, Tree *t ) { Parser np; np.parse_in_place(filename, yaml, t); } -RYML_DEPRECATED("use parse_in_place() instead") inline void parse( substr yaml, Tree *t, size_t node_id) { Parser np; np.parse_in_place({} , yaml, t, node_id); } -RYML_DEPRECATED("use parse_in_place() instead") inline void parse(csubstr filename, substr yaml, Tree *t, size_t node_id) { Parser np; np.parse_in_place(filename, yaml, t, node_id); } -RYML_DEPRECATED("use parse_in_place() instead") inline void parse( substr yaml, NodeRef node ) { Parser np; np.parse_in_place({} , yaml, node); } -RYML_DEPRECATED("use parse_in_place() instead") inline void parse(csubstr filename, substr yaml, NodeRef node ) { Parser np; np.parse_in_place(filename, yaml, node); } - -/** @} */ - - -//----------------------------------------------------------------------------- - -/** @name parse_in_arena - * @desc parse a read-only YAML source buffer, copying it first to the tree's arena. - * - * @note These freestanding functions use a temporary parser object, - * and are convenience functions to easily parse YAML without the need - * to instantiate a separate parser. Note that some properties - * (notably node locations in the original source code) are only - * available through the parser object after it has parsed the - * code. If you need access to any of these properties, use - * Parser::parse_in_arena(). - * - * @note overloads receiving a substr YAML buffer are intentionally - * left undefined, such that calling parse_in_arena() with a substr - * will cause a linker error. This is to prevent an accidental - * copy of the source buffer to the tree's arena, because substr - * is implicitly convertible to csubstr. If you really intend to parse - * a mutable buffer in the tree's arena, convert it first to immutable - * by assigning the substr to a csubstr prior to calling parse_in_arena(). - * This is not needed for parse_in_place() because csubstr is not - * implicitly convertible to substr. */ -/** @{ */ - -/* READ THE NOTE ABOVE! */ -RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) Tree parse_in_arena( substr yaml ); -RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) Tree parse_in_arena(csubstr filename, substr yaml ); -RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena( substr yaml, Tree *t ); -RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena(csubstr filename, substr yaml, Tree *t ); -RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena( substr yaml, Tree *t, size_t node_id); -RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena(csubstr filename, substr yaml, Tree *t, size_t node_id); -RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena( substr yaml, NodeRef node ); -RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena(csubstr filename, substr yaml, NodeRef node ); - -inline Tree parse_in_arena( csubstr yaml ) { Parser np; return np.parse_in_arena({} , yaml); } //!< parse a read-only YAML source buffer, copying it first to the tree's source arena. -inline Tree parse_in_arena(csubstr filename, csubstr yaml ) { Parser np; return np.parse_in_arena(filename, yaml); } //!< parse a read-only YAML source buffer, copying it first to the tree's source arena, providing a filename for error messages. -inline void parse_in_arena( csubstr yaml, Tree *t ) { Parser np; np.parse_in_arena({} , yaml, t); } //!< reusing the YAML tree, parse a read-only YAML source buffer, copying it first to the tree's source arena. -inline void parse_in_arena(csubstr filename, csubstr yaml, Tree *t ) { Parser np; np.parse_in_arena(filename, yaml, t); } //!< reusing the YAML tree, parse a read-only YAML source buffer, copying it first to the tree's source arena, providing a filename for error messages. -inline void parse_in_arena( csubstr yaml, Tree *t, size_t node_id) { Parser np; np.parse_in_arena({} , yaml, t, node_id); } //!< reusing the YAML tree, parse a read-only YAML source buffer, copying it first to the tree's source arena. -inline void parse_in_arena(csubstr filename, csubstr yaml, Tree *t, size_t node_id) { Parser np; np.parse_in_arena(filename, yaml, t, node_id); } //!< reusing the YAML tree, parse a read-only YAML source buffer, copying it first to the tree's source arena, providing a filename for error messages. -inline void parse_in_arena( csubstr yaml, NodeRef node ) { Parser np; np.parse_in_arena({} , yaml, node); } //!< reusing the YAML tree, parse a read-only YAML source buffer, copying it first to the tree's source arena. -inline void parse_in_arena(csubstr filename, csubstr yaml, NodeRef node ) { Parser np; np.parse_in_arena(filename, yaml, node); } //!< reusing the YAML tree, parse a read-only YAML source buffer, copying it first to the tree's source arena, providing a filename for error messages. - -RYML_DEPRECATED("use parse_in_arena() instead") inline Tree parse( csubstr yaml ) { Parser np; return np.parse_in_arena({} , yaml); } //!< parse a read-only YAML source buffer, copying it first to the tree's source arena. -RYML_DEPRECATED("use parse_in_arena() instead") inline Tree parse(csubstr filename, csubstr yaml ) { Parser np; return np.parse_in_arena(filename, yaml); } //!< parse a read-only YAML source buffer, copying it first to the tree's source arena, providing a filename for error messages. -RYML_DEPRECATED("use parse_in_arena() instead") inline void parse( csubstr yaml, Tree *t ) { Parser np; np.parse_in_arena({} , yaml, t); } //!< reusing the YAML tree, parse a read-only YAML source buffer, copying it first to the tree's source arena. -RYML_DEPRECATED("use parse_in_arena() instead") inline void parse(csubstr filename, csubstr yaml, Tree *t ) { Parser np; np.parse_in_arena(filename, yaml, t); } //!< reusing the YAML tree, parse a read-only YAML source buffer, copying it first to the tree's source arena, providing a filename for error messages. -RYML_DEPRECATED("use parse_in_arena() instead") inline void parse( csubstr yaml, Tree *t, size_t node_id) { Parser np; np.parse_in_arena({} , yaml, t, node_id); } //!< reusing the YAML tree, parse a read-only YAML source buffer, copying it first to the tree's source arena. -RYML_DEPRECATED("use parse_in_arena() instead") inline void parse(csubstr filename, csubstr yaml, Tree *t, size_t node_id) { Parser np; np.parse_in_arena(filename, yaml, t, node_id); } //!< reusing the YAML tree, parse a read-only YAML source buffer, copying it first to the tree's source arena, providing a filename for error messages. -RYML_DEPRECATED("use parse_in_arena() instead") inline void parse( csubstr yaml, NodeRef node ) { Parser np; np.parse_in_arena({} , yaml, node); } //!< reusing the YAML tree, parse a read-only YAML source buffer, copying it first to the tree's source arena. -RYML_DEPRECATED("use parse_in_arena() instead") inline void parse(csubstr filename, csubstr yaml, NodeRef node ) { Parser np; np.parse_in_arena(filename, yaml, node); } //!< reusing the YAML tree, parse a read-only YAML source buffer, copying it first to the tree's source arena, providing a filename for error messages. - -/** @} */ - -} // namespace yml -} // namespace c4 - -#if defined(_MSC_VER) -# pragma warning(pop) -#endif - -#endif /* _C4_YML_PARSE_HPP_ */ diff --git a/thirdparty/ryml/src/c4/yml/preprocess.cpp b/thirdparty/ryml/src/c4/yml/preprocess.cpp deleted file mode 100644 index 2e92dce14..000000000 --- a/thirdparty/ryml/src/c4/yml/preprocess.cpp +++ /dev/null @@ -1,110 +0,0 @@ -#include "c4/yml/preprocess.hpp" -#include "c4/yml/detail/parser_dbg.hpp" - -/** @file preprocess.hpp Functions for preprocessing YAML prior to parsing. */ - -namespace c4 { -namespace yml { - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -namespace { -C4_ALWAYS_INLINE bool _is_idchar(char c) -{ - return (c >= 'a' && c <= 'z') - || (c >= 'A' && c <= 'Z') - || (c >= '0' && c <= '9') - || (c == '_' || c == '-' || c == '~' || c == '$'); -} - -typedef enum { kReadPending = 0, kKeyPending = 1, kValPending = 2 } _ppstate; -C4_ALWAYS_INLINE _ppstate _next(_ppstate s) -{ - int n = (int)s + 1; - return (_ppstate)(n <= (int)kValPending ? n : 0); -} -} // empty namespace - - -//----------------------------------------------------------------------------- - -size_t preprocess_rxmap(csubstr s, substr buf) -{ - detail::_SubstrWriter writer(buf); - _ppstate state = kReadPending; - size_t last = 0; - - if(s.begins_with('{')) - { - RYML_CHECK(s.ends_with('}')); - s = s.offs(1, 1); - } - - writer.append('{'); - - for(size_t i = 0; i < s.len; ++i) - { - const char curr = s[i]; - const char next = i+1 < s.len ? s[i+1] : '\0'; - - if(curr == '\'' || curr == '"') - { - csubstr ss = s.sub(i).pair_range_esc(curr, '\\'); - i += static_cast(ss.end() - (s.str + i)); - state = _next(state); - } - else if(state == kReadPending && _is_idchar(curr)) - { - state = _next(state); - } - - switch(state) - { - case kKeyPending: - { - if(curr == ':' && next == ' ') - { - state = _next(state); - } - else if(curr == ',' && next == ' ') - { - writer.append(s.range(last, i)); - writer.append(": 1, "); - last = i + 2; - } - break; - } - case kValPending: - { - if(curr == '[' || curr == '{' || curr == '(') - { - csubstr ss = s.sub(i).pair_range_nested(curr, '\\'); - i += static_cast(ss.end() - (s.str + i)); - state = _next(state); - } - else if(curr == ',' && next == ' ') - { - state = _next(state); - } - break; - } - default: - // nothing to do - break; - } - } - - writer.append(s.sub(last)); - if(state == kKeyPending) - writer.append(": 1"); - writer.append('}'); - - return writer.pos; -} - - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/src/c4/yml/preprocess.hpp b/thirdparty/ryml/src/c4/yml/preprocess.hpp deleted file mode 100644 index def066389..000000000 --- a/thirdparty/ryml/src/c4/yml/preprocess.hpp +++ /dev/null @@ -1,99 +0,0 @@ -#ifndef _C4_YML_PREPROCESS_HPP_ -#define _C4_YML_PREPROCESS_HPP_ - -/** @file preprocess.hpp Functions for preprocessing YAML prior to parsing. */ - -/** @defgroup Preprocessors Preprocessor functions - * - * These are the existing preprocessors: - * - * @code{.cpp} - * size_t preprocess_json(csubstr json, substr buf) - * size_t preprocess_rxmap(csubstr json, substr buf) - * @endcode - */ - -#ifndef _C4_YML_COMMON_HPP_ -#include "./common.hpp" -#endif -#include - - -namespace c4 { -namespace yml { - -namespace detail { -using Preprocessor = size_t(csubstr, substr); -template -substr preprocess_into_container(csubstr input, CharContainer *out) -{ - // try to write once. the preprocessor will stop writing at the end of - // the container, but will process all the input to determine the - // required container size. - size_t sz = PP(input, to_substr(*out)); - // if the container size is not enough, resize, and run again in the - // resized container - if(sz > out->size()) - { - out->resize(sz); - sz = PP(input, to_substr(*out)); - } - return to_substr(*out).first(sz); -} -} // namespace detail - - -//----------------------------------------------------------------------------- - -/** @name preprocess_rxmap - * Convert flow-type relaxed maps (with implicit bools) into strict YAML - * flow map. - * - * @code{.yaml} - * {a, b, c, d: [e, f], g: {a, b}} - * # is converted into this: - * {a: 1, b: 1, c: 1, d: [e, f], g: {a, b}} - * @endcode - - * @note this is NOT recursive - conversion happens only in the top-level map - * @param rxmap A relaxed map - * @param buf output buffer - * @param out output container - */ - -//@{ - -/** Write into a given output buffer. This function is safe to call with - * empty or small buffers; it won't write beyond the end of the buffer. - * - * @return the number of characters required for output - */ -RYML_EXPORT size_t preprocess_rxmap(csubstr rxmap, substr buf); - - -/** Write into an existing container. It is resized to contained the output. - * @return a substr of the container - * @overload preprocess_rxmap */ -template -substr preprocess_rxmap(csubstr rxmap, CharContainer *out) -{ - return detail::preprocess_into_container(rxmap, out); -} - - -/** Create a container with the result. - * @overload preprocess_rxmap */ -template -CharContainer preprocess_rxmap(csubstr rxmap) -{ - CharContainer out; - preprocess_rxmap(rxmap, &out); - return out; -} - -//@} - -} // namespace yml -} // namespace c4 - -#endif /* _C4_YML_PREPROCESS_HPP_ */ diff --git a/thirdparty/ryml/src/c4/yml/std/map.hpp b/thirdparty/ryml/src/c4/yml/std/map.hpp deleted file mode 100644 index fc48dc5e6..000000000 --- a/thirdparty/ryml/src/c4/yml/std/map.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef _C4_YML_STD_MAP_HPP_ -#define _C4_YML_STD_MAP_HPP_ - -/** @file map.hpp write/read std::map to/from a YAML tree. */ - -#include "c4/yml/node.hpp" -#include - -namespace c4 { -namespace yml { - -// std::map requires child nodes in the data -// tree hierarchy (a MAP node in ryml parlance). -// So it should be serialized via write()/read(). - -template -void write(c4::yml::NodeRef *n, std::map const& m) -{ - *n |= c4::yml::MAP; - for(auto const& C4_RESTRICT p : m) - { - auto ch = n->append_child(); - ch << c4::yml::key(p.first); - ch << p.second; - } -} - -template -bool read(c4::yml::ConstNodeRef const& n, std::map * m) -{ - K k{}; - V v{}; - for(auto const& C4_RESTRICT ch : n) - { - ch >> c4::yml::key(k); - ch >> v; - m->emplace(std::make_pair(std::move(k), std::move(v))); - } - return true; -} - -} // namespace yml -} // namespace c4 - -#endif // _C4_YML_STD_MAP_HPP_ diff --git a/thirdparty/ryml/src/c4/yml/std/std.hpp b/thirdparty/ryml/src/c4/yml/std/std.hpp deleted file mode 100644 index 08e80d155..000000000 --- a/thirdparty/ryml/src/c4/yml/std/std.hpp +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef _C4_YML_STD_STD_HPP_ -#define _C4_YML_STD_STD_HPP_ - -#include "c4/yml/std/string.hpp" -#include "c4/yml/std/vector.hpp" -#include "c4/yml/std/map.hpp" - -#endif // _C4_YML_STD_STD_HPP_ diff --git a/thirdparty/ryml/src/c4/yml/std/string.hpp b/thirdparty/ryml/src/c4/yml/std/string.hpp deleted file mode 100644 index e3318f91c..000000000 --- a/thirdparty/ryml/src/c4/yml/std/string.hpp +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef C4_YML_STD_STRING_HPP_ -#define C4_YML_STD_STRING_HPP_ - -/** @file string.hpp substring conversions for/from std::string */ - -// everything we need is implemented here: -#include - -#endif // C4_YML_STD_STRING_HPP_ diff --git a/thirdparty/ryml/src/c4/yml/std/vector.hpp b/thirdparty/ryml/src/c4/yml/std/vector.hpp deleted file mode 100644 index 1b6a4610a..000000000 --- a/thirdparty/ryml/src/c4/yml/std/vector.hpp +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef _C4_YML_STD_VECTOR_HPP_ -#define _C4_YML_STD_VECTOR_HPP_ - -#include "c4/yml/node.hpp" -#include -#include - -namespace c4 { -namespace yml { - -// vector is a sequence-like type, and it requires child nodes -// in the data tree hierarchy (a SEQ node in ryml parlance). -// So it should be serialized via write()/read(). - - -template -void write(c4::yml::NodeRef *n, std::vector const& vec) -{ - *n |= c4::yml::SEQ; - for(auto const& v : vec) - n->append_child() << v; -} - -template -bool read(c4::yml::ConstNodeRef const& n, std::vector *vec) -{ - vec->resize(n.num_children()); - size_t pos = 0; - for(auto const ch : n) - ch >> (*vec)[pos++]; - return true; -} - -/** specialization: std::vector uses std::vector::reference as - * the return value of its operator[]. */ -template -bool read(c4::yml::ConstNodeRef const& n, std::vector *vec) -{ - vec->resize(n.num_children()); - size_t pos = 0; - bool tmp; - for(auto const ch : n) - { - ch >> tmp; - (*vec)[pos++] = tmp; - } - return true; -} - -} // namespace yml -} // namespace c4 - -#endif // _C4_YML_STD_VECTOR_HPP_ diff --git a/thirdparty/ryml/src/c4/yml/tree.cpp b/thirdparty/ryml/src/c4/yml/tree.cpp deleted file mode 100644 index b16ff8f5d..000000000 --- a/thirdparty/ryml/src/c4/yml/tree.cpp +++ /dev/null @@ -1,2183 +0,0 @@ -#include "c4/yml/tree.hpp" -#include "c4/yml/detail/parser_dbg.hpp" -#include "c4/yml/node.hpp" -#include "c4/yml/detail/stack.hpp" - - -C4_SUPPRESS_WARNING_GCC_WITH_PUSH("-Wtype-limits") -C4_SUPPRESS_WARNING_MSVC_WITH_PUSH(4296/*expression is always 'boolean_value'*/) - -namespace c4 { -namespace yml { - - -csubstr normalize_tag(csubstr tag) -{ - YamlTag_e t = to_tag(tag); - if(t != TAG_NONE) - return from_tag(t); - if(tag.begins_with("!<")) - tag = tag.sub(1); - if(tag.begins_with(""}; - case TAG_OMAP: - return {""}; - case TAG_PAIRS: - return {""}; - case TAG_SET: - return {""}; - case TAG_SEQ: - return {""}; - case TAG_BINARY: - return {""}; - case TAG_BOOL: - return {""}; - case TAG_FLOAT: - return {""}; - case TAG_INT: - return {""}; - case TAG_MERGE: - return {""}; - case TAG_NULL: - return {""}; - case TAG_STR: - return {""}; - case TAG_TIMESTAMP: - return {""}; - case TAG_VALUE: - return {""}; - case TAG_YAML: - return {""}; - case TAG_NONE: - return {""}; - } - return {""}; -} - -csubstr from_tag(YamlTag_e tag) -{ - switch(tag) - { - case TAG_MAP: - return {"!!map"}; - case TAG_OMAP: - return {"!!omap"}; - case TAG_PAIRS: - return {"!!pairs"}; - case TAG_SET: - return {"!!set"}; - case TAG_SEQ: - return {"!!seq"}; - case TAG_BINARY: - return {"!!binary"}; - case TAG_BOOL: - return {"!!bool"}; - case TAG_FLOAT: - return {"!!float"}; - case TAG_INT: - return {"!!int"}; - case TAG_MERGE: - return {"!!merge"}; - case TAG_NULL: - return {"!!null"}; - case TAG_STR: - return {"!!str"}; - case TAG_TIMESTAMP: - return {"!!timestamp"}; - case TAG_VALUE: - return {"!!value"}; - case TAG_YAML: - return {"!!yaml"}; - case TAG_NONE: - return {""}; - } - return {""}; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -const char* NodeType::type_str(NodeType_e ty) -{ - switch(ty & _TYMASK) - { - case KEYVAL: - return "KEYVAL"; - case KEY: - return "KEY"; - case VAL: - return "VAL"; - case MAP: - return "MAP"; - case SEQ: - return "SEQ"; - case KEYMAP: - return "KEYMAP"; - case KEYSEQ: - return "KEYSEQ"; - case DOCSEQ: - return "DOCSEQ"; - case DOCMAP: - return "DOCMAP"; - case DOCVAL: - return "DOCVAL"; - case DOC: - return "DOC"; - case STREAM: - return "STREAM"; - case NOTYPE: - return "NOTYPE"; - default: - if((ty & KEYVAL) == KEYVAL) - return "KEYVAL***"; - if((ty & KEYMAP) == KEYMAP) - return "KEYMAP***"; - if((ty & KEYSEQ) == KEYSEQ) - return "KEYSEQ***"; - if((ty & DOCSEQ) == DOCSEQ) - return "DOCSEQ***"; - if((ty & DOCMAP) == DOCMAP) - return "DOCMAP***"; - if((ty & DOCVAL) == DOCVAL) - return "DOCVAL***"; - if(ty & KEY) - return "KEY***"; - if(ty & VAL) - return "VAL***"; - if(ty & MAP) - return "MAP***"; - if(ty & SEQ) - return "SEQ***"; - if(ty & DOC) - return "DOC***"; - return "(unk)"; - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -NodeRef Tree::rootref() -{ - return NodeRef(this, root_id()); -} -ConstNodeRef Tree::rootref() const -{ - return ConstNodeRef(this, root_id()); -} - -ConstNodeRef Tree::crootref() -{ - return ConstNodeRef(this, root_id()); -} -ConstNodeRef Tree::crootref() const -{ - return ConstNodeRef(this, root_id()); -} - -NodeRef Tree::ref(size_t id) -{ - _RYML_CB_ASSERT(m_callbacks, id != NONE && id >= 0 && id < m_size); - return NodeRef(this, id); -} -ConstNodeRef Tree::ref(size_t id) const -{ - _RYML_CB_ASSERT(m_callbacks, id != NONE && id >= 0 && id < m_size); - return ConstNodeRef(this, id); -} - -ConstNodeRef Tree::cref(size_t id) -{ - _RYML_CB_ASSERT(m_callbacks, id != NONE && id >= 0 && id < m_size); - return ConstNodeRef(this, id); -} -ConstNodeRef Tree::cref(size_t id) const -{ - _RYML_CB_ASSERT(m_callbacks, id != NONE && id >= 0 && id < m_size); - return ConstNodeRef(this, id); -} - -NodeRef Tree::operator[] (csubstr key) -{ - return rootref()[key]; -} -ConstNodeRef Tree::operator[] (csubstr key) const -{ - return rootref()[key]; -} - -NodeRef Tree::operator[] (size_t i) -{ - return rootref()[i]; -} -ConstNodeRef Tree::operator[] (size_t i) const -{ - return rootref()[i]; -} - -NodeRef Tree::docref(size_t i) -{ - return ref(doc(i)); -} -ConstNodeRef Tree::docref(size_t i) const -{ - return cref(doc(i)); -} - - -//----------------------------------------------------------------------------- -Tree::Tree(Callbacks const& cb) - : m_buf(nullptr) - , m_cap(0) - , m_size(0) - , m_free_head(NONE) - , m_free_tail(NONE) - , m_arena() - , m_arena_pos(0) - , m_callbacks(cb) -{ -} - -Tree::Tree(size_t node_capacity, size_t arena_capacity, Callbacks const& cb) - : Tree(cb) -{ - reserve(node_capacity); - reserve_arena(arena_capacity); -} - -Tree::~Tree() -{ - _free(); -} - - -Tree::Tree(Tree const& that) noexcept : Tree(that.m_callbacks) -{ - _copy(that); -} - -Tree& Tree::operator= (Tree const& that) noexcept -{ - _free(); - m_callbacks = that.m_callbacks; - _copy(that); - return *this; -} - -Tree::Tree(Tree && that) noexcept : Tree(that.m_callbacks) -{ - _move(that); -} - -Tree& Tree::operator= (Tree && that) noexcept -{ - _free(); - m_callbacks = that.m_callbacks; - _move(that); - return *this; -} - -void Tree::_free() -{ - if(m_buf) - { - _RYML_CB_ASSERT(m_callbacks, m_cap > 0); - _RYML_CB_FREE(m_callbacks, m_buf, NodeData, m_cap); - } - if(m_arena.str) - { - _RYML_CB_ASSERT(m_callbacks, m_arena.len > 0); - _RYML_CB_FREE(m_callbacks, m_arena.str, char, m_arena.len); - } - _clear(); -} - - -C4_SUPPRESS_WARNING_GCC_PUSH -#if defined(__GNUC__) && __GNUC__>= 8 - C4_SUPPRESS_WARNING_GCC_WITH_PUSH("-Wclass-memaccess") // error: ‘void* memset(void*, int, size_t)’ clearing an object of type ‘class c4::yml::Tree’ with no trivial copy-assignment; use assignment or value-initialization instead -#endif - -void Tree::_clear() -{ - m_buf = nullptr; - m_cap = 0; - m_size = 0; - m_free_head = 0; - m_free_tail = 0; - m_arena = {}; - m_arena_pos = 0; - for(size_t i = 0; i < RYML_MAX_TAG_DIRECTIVES; ++i) - m_tag_directives[i] = {}; -} - -void Tree::_copy(Tree const& that) -{ - _RYML_CB_ASSERT(m_callbacks, m_buf == nullptr); - _RYML_CB_ASSERT(m_callbacks, m_arena.str == nullptr); - _RYML_CB_ASSERT(m_callbacks, m_arena.len == 0); - m_buf = _RYML_CB_ALLOC_HINT(m_callbacks, NodeData, that.m_cap, that.m_buf); - memcpy(m_buf, that.m_buf, that.m_cap * sizeof(NodeData)); - m_cap = that.m_cap; - m_size = that.m_size; - m_free_head = that.m_free_head; - m_free_tail = that.m_free_tail; - m_arena_pos = that.m_arena_pos; - m_arena = that.m_arena; - if(that.m_arena.str) - { - _RYML_CB_ASSERT(m_callbacks, that.m_arena.len > 0); - substr arena; - arena.str = _RYML_CB_ALLOC_HINT(m_callbacks, char, that.m_arena.len, that.m_arena.str); - arena.len = that.m_arena.len; - _relocate(arena); // does a memcpy of the arena and updates nodes using the old arena - m_arena = arena; - } - for(size_t i = 0; i < RYML_MAX_TAG_DIRECTIVES; ++i) - m_tag_directives[i] = that.m_tag_directives[i]; -} - -void Tree::_move(Tree & that) -{ - _RYML_CB_ASSERT(m_callbacks, m_buf == nullptr); - _RYML_CB_ASSERT(m_callbacks, m_arena.str == nullptr); - _RYML_CB_ASSERT(m_callbacks, m_arena.len == 0); - m_buf = that.m_buf; - m_cap = that.m_cap; - m_size = that.m_size; - m_free_head = that.m_free_head; - m_free_tail = that.m_free_tail; - m_arena = that.m_arena; - m_arena_pos = that.m_arena_pos; - for(size_t i = 0; i < RYML_MAX_TAG_DIRECTIVES; ++i) - m_tag_directives[i] = that.m_tag_directives[i]; - that._clear(); -} - -void Tree::_relocate(substr next_arena) -{ - _RYML_CB_ASSERT(m_callbacks, next_arena.not_empty()); - _RYML_CB_ASSERT(m_callbacks, next_arena.len >= m_arena.len); - memcpy(next_arena.str, m_arena.str, m_arena_pos); - for(NodeData *C4_RESTRICT n = m_buf, *e = m_buf + m_cap; n != e; ++n) - { - if(in_arena(n->m_key.scalar)) - n->m_key.scalar = _relocated(n->m_key.scalar, next_arena); - if(in_arena(n->m_key.tag)) - n->m_key.tag = _relocated(n->m_key.tag, next_arena); - if(in_arena(n->m_key.anchor)) - n->m_key.anchor = _relocated(n->m_key.anchor, next_arena); - if(in_arena(n->m_val.scalar)) - n->m_val.scalar = _relocated(n->m_val.scalar, next_arena); - if(in_arena(n->m_val.tag)) - n->m_val.tag = _relocated(n->m_val.tag, next_arena); - if(in_arena(n->m_val.anchor)) - n->m_val.anchor = _relocated(n->m_val.anchor, next_arena); - } - for(TagDirective &C4_RESTRICT td : m_tag_directives) - { - if(in_arena(td.prefix)) - td.prefix = _relocated(td.prefix, next_arena); - if(in_arena(td.handle)) - td.handle = _relocated(td.handle, next_arena); - } -} - - -//----------------------------------------------------------------------------- -void Tree::reserve(size_t cap) -{ - if(cap > m_cap) - { - NodeData *buf = _RYML_CB_ALLOC_HINT(m_callbacks, NodeData, cap, m_buf); - if(m_buf) - { - memcpy(buf, m_buf, m_cap * sizeof(NodeData)); - _RYML_CB_FREE(m_callbacks, m_buf, NodeData, m_cap); - } - size_t first = m_cap, del = cap - m_cap; - m_cap = cap; - m_buf = buf; - _clear_range(first, del); - if(m_free_head != NONE) - { - _RYML_CB_ASSERT(m_callbacks, m_buf != nullptr); - _RYML_CB_ASSERT(m_callbacks, m_free_tail != NONE); - m_buf[m_free_tail].m_next_sibling = first; - m_buf[first].m_prev_sibling = m_free_tail; - m_free_tail = cap-1; - } - else - { - _RYML_CB_ASSERT(m_callbacks, m_free_tail == NONE); - m_free_head = first; - m_free_tail = cap-1; - } - _RYML_CB_ASSERT(m_callbacks, m_free_head == NONE || (m_free_head >= 0 && m_free_head < cap)); - _RYML_CB_ASSERT(m_callbacks, m_free_tail == NONE || (m_free_tail >= 0 && m_free_tail < cap)); - - if( ! m_size) - _claim_root(); - } -} - - -//----------------------------------------------------------------------------- -void Tree::clear() -{ - _clear_range(0, m_cap); - m_size = 0; - if(m_buf) - { - _RYML_CB_ASSERT(m_callbacks, m_cap >= 0); - m_free_head = 0; - m_free_tail = m_cap-1; - _claim_root(); - } - else - { - m_free_head = NONE; - m_free_tail = NONE; - } - for(size_t i = 0; i < RYML_MAX_TAG_DIRECTIVES; ++i) - m_tag_directives[i] = {}; -} - -void Tree::_claim_root() -{ - size_t r = _claim(); - _RYML_CB_ASSERT(m_callbacks, r == 0); - _set_hierarchy(r, NONE, NONE); -} - - -//----------------------------------------------------------------------------- -void Tree::_clear_range(size_t first, size_t num) -{ - if(num == 0) - return; // prevent overflow when subtracting - _RYML_CB_ASSERT(m_callbacks, first >= 0 && first + num <= m_cap); - memset(m_buf + first, 0, num * sizeof(NodeData)); // TODO we should not need this - for(size_t i = first, e = first + num; i < e; ++i) - { - _clear(i); - NodeData *n = m_buf + i; - n->m_prev_sibling = i - 1; - n->m_next_sibling = i + 1; - } - m_buf[first + num - 1].m_next_sibling = NONE; -} - -C4_SUPPRESS_WARNING_GCC_POP - - -//----------------------------------------------------------------------------- -void Tree::_release(size_t i) -{ - _RYML_CB_ASSERT(m_callbacks, i >= 0 && i < m_cap); - - _rem_hierarchy(i); - _free_list_add(i); - _clear(i); - - --m_size; -} - -//----------------------------------------------------------------------------- -// add to the front of the free list -void Tree::_free_list_add(size_t i) -{ - _RYML_CB_ASSERT(m_callbacks, i >= 0 && i < m_cap); - NodeData &C4_RESTRICT w = m_buf[i]; - - w.m_parent = NONE; - w.m_next_sibling = m_free_head; - w.m_prev_sibling = NONE; - if(m_free_head != NONE) - m_buf[m_free_head].m_prev_sibling = i; - m_free_head = i; - if(m_free_tail == NONE) - m_free_tail = m_free_head; -} - -void Tree::_free_list_rem(size_t i) -{ - if(m_free_head == i) - m_free_head = _p(i)->m_next_sibling; - _rem_hierarchy(i); -} - -//----------------------------------------------------------------------------- -size_t Tree::_claim() -{ - if(m_free_head == NONE || m_buf == nullptr) - { - size_t sz = 2 * m_cap; - sz = sz ? sz : 16; - reserve(sz); - _RYML_CB_ASSERT(m_callbacks, m_free_head != NONE); - } - - _RYML_CB_ASSERT(m_callbacks, m_size < m_cap); - _RYML_CB_ASSERT(m_callbacks, m_free_head >= 0 && m_free_head < m_cap); - - size_t ichild = m_free_head; - NodeData *child = m_buf + ichild; - - ++m_size; - m_free_head = child->m_next_sibling; - if(m_free_head == NONE) - { - m_free_tail = NONE; - _RYML_CB_ASSERT(m_callbacks, m_size == m_cap); - } - - _clear(ichild); - - return ichild; -} - -//----------------------------------------------------------------------------- - -C4_SUPPRESS_WARNING_GCC_PUSH -C4_SUPPRESS_WARNING_CLANG_PUSH -C4_SUPPRESS_WARNING_CLANG("-Wnull-dereference") -#if defined(__GNUC__) && (__GNUC__ >= 6) -C4_SUPPRESS_WARNING_GCC("-Wnull-dereference") -#endif - -void Tree::_set_hierarchy(size_t ichild, size_t iparent, size_t iprev_sibling) -{ - _RYML_CB_ASSERT(m_callbacks, iparent == NONE || (iparent >= 0 && iparent < m_cap)); - _RYML_CB_ASSERT(m_callbacks, iprev_sibling == NONE || (iprev_sibling >= 0 && iprev_sibling < m_cap)); - - NodeData *C4_RESTRICT child = get(ichild); - - child->m_parent = iparent; - child->m_prev_sibling = NONE; - child->m_next_sibling = NONE; - - if(iparent == NONE) - { - _RYML_CB_ASSERT(m_callbacks, ichild == 0); - _RYML_CB_ASSERT(m_callbacks, iprev_sibling == NONE); - } - - if(iparent == NONE) - return; - - size_t inext_sibling = iprev_sibling != NONE ? next_sibling(iprev_sibling) : first_child(iparent); - NodeData *C4_RESTRICT parent = get(iparent); - NodeData *C4_RESTRICT psib = get(iprev_sibling); - NodeData *C4_RESTRICT nsib = get(inext_sibling); - - if(psib) - { - _RYML_CB_ASSERT(m_callbacks, next_sibling(iprev_sibling) == id(nsib)); - child->m_prev_sibling = id(psib); - psib->m_next_sibling = id(child); - _RYML_CB_ASSERT(m_callbacks, psib->m_prev_sibling != psib->m_next_sibling || psib->m_prev_sibling == NONE); - } - - if(nsib) - { - _RYML_CB_ASSERT(m_callbacks, prev_sibling(inext_sibling) == id(psib)); - child->m_next_sibling = id(nsib); - nsib->m_prev_sibling = id(child); - _RYML_CB_ASSERT(m_callbacks, nsib->m_prev_sibling != nsib->m_next_sibling || nsib->m_prev_sibling == NONE); - } - - if(parent->m_first_child == NONE) - { - _RYML_CB_ASSERT(m_callbacks, parent->m_last_child == NONE); - parent->m_first_child = id(child); - parent->m_last_child = id(child); - } - else - { - if(child->m_next_sibling == parent->m_first_child) - parent->m_first_child = id(child); - - if(child->m_prev_sibling == parent->m_last_child) - parent->m_last_child = id(child); - } -} - -C4_SUPPRESS_WARNING_GCC_POP -C4_SUPPRESS_WARNING_CLANG_POP - - -//----------------------------------------------------------------------------- -void Tree::_rem_hierarchy(size_t i) -{ - _RYML_CB_ASSERT(m_callbacks, i >= 0 && i < m_cap); - - NodeData &C4_RESTRICT w = m_buf[i]; - - // remove from the parent - if(w.m_parent != NONE) - { - NodeData &C4_RESTRICT p = m_buf[w.m_parent]; - if(p.m_first_child == i) - { - p.m_first_child = w.m_next_sibling; - } - if(p.m_last_child == i) - { - p.m_last_child = w.m_prev_sibling; - } - } - - // remove from the used list - if(w.m_prev_sibling != NONE) - { - NodeData *C4_RESTRICT prev = get(w.m_prev_sibling); - prev->m_next_sibling = w.m_next_sibling; - } - if(w.m_next_sibling != NONE) - { - NodeData *C4_RESTRICT next = get(w.m_next_sibling); - next->m_prev_sibling = w.m_prev_sibling; - } -} - -//----------------------------------------------------------------------------- -void Tree::reorder() -{ - size_t r = root_id(); - _do_reorder(&r, 0); -} - -//----------------------------------------------------------------------------- -size_t Tree::_do_reorder(size_t *node, size_t count) -{ - // swap this node if it's not in place - if(*node != count) - { - _swap(*node, count); - *node = count; - } - ++count; // bump the count from this node - - // now descend in the hierarchy - for(size_t i = first_child(*node); i != NONE; i = next_sibling(i)) - { - // this child may have been relocated to a different index, - // so get an updated version - count = _do_reorder(&i, count); - } - return count; -} - -//----------------------------------------------------------------------------- -void Tree::_swap(size_t n_, size_t m_) -{ - _RYML_CB_ASSERT(m_callbacks, (parent(n_) != NONE) || type(n_) == NOTYPE); - _RYML_CB_ASSERT(m_callbacks, (parent(m_) != NONE) || type(m_) == NOTYPE); - NodeType tn = type(n_); - NodeType tm = type(m_); - if(tn != NOTYPE && tm != NOTYPE) - { - _swap_props(n_, m_); - _swap_hierarchy(n_, m_); - } - else if(tn == NOTYPE && tm != NOTYPE) - { - _copy_props(n_, m_); - _free_list_rem(n_); - _copy_hierarchy(n_, m_); - _clear(m_); - _free_list_add(m_); - } - else if(tn != NOTYPE && tm == NOTYPE) - { - _copy_props(m_, n_); - _free_list_rem(m_); - _copy_hierarchy(m_, n_); - _clear(n_); - _free_list_add(n_); - } - else - { - C4_NEVER_REACH(); - } -} - -//----------------------------------------------------------------------------- -void Tree::_swap_hierarchy(size_t ia, size_t ib) -{ - if(ia == ib) return; - - for(size_t i = first_child(ia); i != NONE; i = next_sibling(i)) - { - if(i == ib || i == ia) - continue; - _p(i)->m_parent = ib; - } - - for(size_t i = first_child(ib); i != NONE; i = next_sibling(i)) - { - if(i == ib || i == ia) - continue; - _p(i)->m_parent = ia; - } - - auto & C4_RESTRICT a = *_p(ia); - auto & C4_RESTRICT b = *_p(ib); - auto & C4_RESTRICT pa = *_p(a.m_parent); - auto & C4_RESTRICT pb = *_p(b.m_parent); - - if(&pa == &pb) - { - if((pa.m_first_child == ib && pa.m_last_child == ia) - || - (pa.m_first_child == ia && pa.m_last_child == ib)) - { - std::swap(pa.m_first_child, pa.m_last_child); - } - else - { - bool changed = false; - if(pa.m_first_child == ia) - { - pa.m_first_child = ib; - changed = true; - } - if(pa.m_last_child == ia) - { - pa.m_last_child = ib; - changed = true; - } - if(pb.m_first_child == ib && !changed) - { - pb.m_first_child = ia; - } - if(pb.m_last_child == ib && !changed) - { - pb.m_last_child = ia; - } - } - } - else - { - if(pa.m_first_child == ia) - pa.m_first_child = ib; - if(pa.m_last_child == ia) - pa.m_last_child = ib; - if(pb.m_first_child == ib) - pb.m_first_child = ia; - if(pb.m_last_child == ib) - pb.m_last_child = ia; - } - std::swap(a.m_first_child , b.m_first_child); - std::swap(a.m_last_child , b.m_last_child); - - if(a.m_prev_sibling != ib && b.m_prev_sibling != ia && - a.m_next_sibling != ib && b.m_next_sibling != ia) - { - if(a.m_prev_sibling != NONE && a.m_prev_sibling != ib) - _p(a.m_prev_sibling)->m_next_sibling = ib; - if(a.m_next_sibling != NONE && a.m_next_sibling != ib) - _p(a.m_next_sibling)->m_prev_sibling = ib; - if(b.m_prev_sibling != NONE && b.m_prev_sibling != ia) - _p(b.m_prev_sibling)->m_next_sibling = ia; - if(b.m_next_sibling != NONE && b.m_next_sibling != ia) - _p(b.m_next_sibling)->m_prev_sibling = ia; - std::swap(a.m_prev_sibling, b.m_prev_sibling); - std::swap(a.m_next_sibling, b.m_next_sibling); - } - else - { - if(a.m_next_sibling == ib) // n will go after m - { - _RYML_CB_ASSERT(m_callbacks, b.m_prev_sibling == ia); - if(a.m_prev_sibling != NONE) - { - _RYML_CB_ASSERT(m_callbacks, a.m_prev_sibling != ib); - _p(a.m_prev_sibling)->m_next_sibling = ib; - } - if(b.m_next_sibling != NONE) - { - _RYML_CB_ASSERT(m_callbacks, b.m_next_sibling != ia); - _p(b.m_next_sibling)->m_prev_sibling = ia; - } - size_t ns = b.m_next_sibling; - b.m_prev_sibling = a.m_prev_sibling; - b.m_next_sibling = ia; - a.m_prev_sibling = ib; - a.m_next_sibling = ns; - } - else if(a.m_prev_sibling == ib) // m will go after n - { - _RYML_CB_ASSERT(m_callbacks, b.m_next_sibling == ia); - if(b.m_prev_sibling != NONE) - { - _RYML_CB_ASSERT(m_callbacks, b.m_prev_sibling != ia); - _p(b.m_prev_sibling)->m_next_sibling = ia; - } - if(a.m_next_sibling != NONE) - { - _RYML_CB_ASSERT(m_callbacks, a.m_next_sibling != ib); - _p(a.m_next_sibling)->m_prev_sibling = ib; - } - size_t ns = b.m_prev_sibling; - a.m_prev_sibling = b.m_prev_sibling; - a.m_next_sibling = ib; - b.m_prev_sibling = ia; - b.m_next_sibling = ns; - } - else - { - C4_NEVER_REACH(); - } - } - _RYML_CB_ASSERT(m_callbacks, a.m_next_sibling != ia); - _RYML_CB_ASSERT(m_callbacks, a.m_prev_sibling != ia); - _RYML_CB_ASSERT(m_callbacks, b.m_next_sibling != ib); - _RYML_CB_ASSERT(m_callbacks, b.m_prev_sibling != ib); - - if(a.m_parent != ib && b.m_parent != ia) - { - std::swap(a.m_parent, b.m_parent); - } - else - { - if(a.m_parent == ib && b.m_parent != ia) - { - a.m_parent = b.m_parent; - b.m_parent = ia; - } - else if(a.m_parent != ib && b.m_parent == ia) - { - b.m_parent = a.m_parent; - a.m_parent = ib; - } - else - { - C4_NEVER_REACH(); - } - } -} - -//----------------------------------------------------------------------------- -void Tree::_copy_hierarchy(size_t dst_, size_t src_) -{ - auto const& C4_RESTRICT src = *_p(src_); - auto & C4_RESTRICT dst = *_p(dst_); - auto & C4_RESTRICT prt = *_p(src.m_parent); - for(size_t i = src.m_first_child; i != NONE; i = next_sibling(i)) - { - _p(i)->m_parent = dst_; - } - if(src.m_prev_sibling != NONE) - { - _p(src.m_prev_sibling)->m_next_sibling = dst_; - } - if(src.m_next_sibling != NONE) - { - _p(src.m_next_sibling)->m_prev_sibling = dst_; - } - if(prt.m_first_child == src_) - { - prt.m_first_child = dst_; - } - if(prt.m_last_child == src_) - { - prt.m_last_child = dst_; - } - dst.m_parent = src.m_parent; - dst.m_first_child = src.m_first_child; - dst.m_last_child = src.m_last_child; - dst.m_prev_sibling = src.m_prev_sibling; - dst.m_next_sibling = src.m_next_sibling; -} - -//----------------------------------------------------------------------------- -void Tree::_swap_props(size_t n_, size_t m_) -{ - NodeData &C4_RESTRICT n = *_p(n_); - NodeData &C4_RESTRICT m = *_p(m_); - std::swap(n.m_type, m.m_type); - std::swap(n.m_key, m.m_key); - std::swap(n.m_val, m.m_val); -} - -//----------------------------------------------------------------------------- -void Tree::move(size_t node, size_t after) -{ - _RYML_CB_ASSERT(m_callbacks, node != NONE); - _RYML_CB_ASSERT(m_callbacks, node != after); - _RYML_CB_ASSERT(m_callbacks, ! is_root(node)); - _RYML_CB_ASSERT(m_callbacks, (after == NONE) || (has_sibling(node, after) && has_sibling(after, node))); - - _rem_hierarchy(node); - _set_hierarchy(node, parent(node), after); -} - -//----------------------------------------------------------------------------- - -void Tree::move(size_t node, size_t new_parent, size_t after) -{ - _RYML_CB_ASSERT(m_callbacks, node != NONE); - _RYML_CB_ASSERT(m_callbacks, node != after); - _RYML_CB_ASSERT(m_callbacks, new_parent != NONE); - _RYML_CB_ASSERT(m_callbacks, new_parent != node); - _RYML_CB_ASSERT(m_callbacks, new_parent != after); - _RYML_CB_ASSERT(m_callbacks, ! is_root(node)); - - _rem_hierarchy(node); - _set_hierarchy(node, new_parent, after); -} - -size_t Tree::move(Tree *src, size_t node, size_t new_parent, size_t after) -{ - _RYML_CB_ASSERT(m_callbacks, src != nullptr); - _RYML_CB_ASSERT(m_callbacks, node != NONE); - _RYML_CB_ASSERT(m_callbacks, new_parent != NONE); - _RYML_CB_ASSERT(m_callbacks, new_parent != after); - - size_t dup = duplicate(src, node, new_parent, after); - src->remove(node); - return dup; -} - -void Tree::set_root_as_stream() -{ - size_t root = root_id(); - if(is_stream(root)) - return; - // don't use _add_flags() because it's checked and will fail - if(!has_children(root)) - { - if(is_val(root)) - { - _p(root)->m_type.add(SEQ); - size_t next_doc = append_child(root); - _copy_props_wo_key(next_doc, root); - _p(next_doc)->m_type.add(DOC); - _p(next_doc)->m_type.rem(SEQ); - } - _p(root)->m_type = STREAM; - return; - } - _RYML_CB_ASSERT(m_callbacks, !has_key(root)); - size_t next_doc = append_child(root); - _copy_props_wo_key(next_doc, root); - _add_flags(next_doc, DOC); - for(size_t prev = NONE, ch = first_child(root), next = next_sibling(ch); ch != NONE; ) - { - if(ch == next_doc) - break; - move(ch, next_doc, prev); - prev = ch; - ch = next; - next = next_sibling(next); - } - _p(root)->m_type = STREAM; -} - - -//----------------------------------------------------------------------------- -void Tree::remove_children(size_t node) -{ - _RYML_CB_ASSERT(m_callbacks, get(node) != nullptr); - size_t ich = get(node)->m_first_child; - while(ich != NONE) - { - remove_children(ich); - _RYML_CB_ASSERT(m_callbacks, get(ich) != nullptr); - size_t next = get(ich)->m_next_sibling; - _release(ich); - if(ich == get(node)->m_last_child) - break; - ich = next; - } -} - -bool Tree::change_type(size_t node, NodeType type) -{ - _RYML_CB_ASSERT(m_callbacks, type.is_val() || type.is_map() || type.is_seq()); - _RYML_CB_ASSERT(m_callbacks, type.is_val() + type.is_map() + type.is_seq() == 1); - _RYML_CB_ASSERT(m_callbacks, type.has_key() == has_key(node) || (has_key(node) && !type.has_key())); - NodeData *d = _p(node); - if(type.is_map() && is_map(node)) - return false; - else if(type.is_seq() && is_seq(node)) - return false; - else if(type.is_val() && is_val(node)) - return false; - d->m_type = (d->m_type & (~(MAP|SEQ|VAL))) | type; - remove_children(node); - return true; -} - - -//----------------------------------------------------------------------------- -size_t Tree::duplicate(size_t node, size_t parent, size_t after) -{ - return duplicate(this, node, parent, after); -} - -size_t Tree::duplicate(Tree const* src, size_t node, size_t parent, size_t after) -{ - _RYML_CB_ASSERT(m_callbacks, src != nullptr); - _RYML_CB_ASSERT(m_callbacks, node != NONE); - _RYML_CB_ASSERT(m_callbacks, parent != NONE); - _RYML_CB_ASSERT(m_callbacks, ! src->is_root(node)); - - size_t copy = _claim(); - - _copy_props(copy, src, node); - _set_hierarchy(copy, parent, after); - duplicate_children(src, node, copy, NONE); - - return copy; -} - -//----------------------------------------------------------------------------- -size_t Tree::duplicate_children(size_t node, size_t parent, size_t after) -{ - return duplicate_children(this, node, parent, after); -} - -size_t Tree::duplicate_children(Tree const* src, size_t node, size_t parent, size_t after) -{ - _RYML_CB_ASSERT(m_callbacks, src != nullptr); - _RYML_CB_ASSERT(m_callbacks, node != NONE); - _RYML_CB_ASSERT(m_callbacks, parent != NONE); - _RYML_CB_ASSERT(m_callbacks, after == NONE || has_child(parent, after)); - - size_t prev = after; - for(size_t i = src->first_child(node); i != NONE; i = src->next_sibling(i)) - { - prev = duplicate(src, i, parent, prev); - } - - return prev; -} - -//----------------------------------------------------------------------------- -void Tree::duplicate_contents(size_t node, size_t where) -{ - duplicate_contents(this, node, where); -} - -void Tree::duplicate_contents(Tree const *src, size_t node, size_t where) -{ - _RYML_CB_ASSERT(m_callbacks, src != nullptr); - _RYML_CB_ASSERT(m_callbacks, node != NONE); - _RYML_CB_ASSERT(m_callbacks, where != NONE); - _copy_props_wo_key(where, src, node); - duplicate_children(src, node, where, last_child(where)); -} - -//----------------------------------------------------------------------------- -size_t Tree::duplicate_children_no_rep(size_t node, size_t parent, size_t after) -{ - return duplicate_children_no_rep(this, node, parent, after); -} - -size_t Tree::duplicate_children_no_rep(Tree const *src, size_t node, size_t parent, size_t after) -{ - _RYML_CB_ASSERT(m_callbacks, node != NONE); - _RYML_CB_ASSERT(m_callbacks, parent != NONE); - _RYML_CB_ASSERT(m_callbacks, after == NONE || has_child(parent, after)); - - // don't loop using pointers as there may be a relocation - - // find the position where "after" is - size_t after_pos = NONE; - if(after != NONE) - { - for(size_t i = first_child(parent), icount = 0; i != NONE; ++icount, i = next_sibling(i)) - { - if(i == after) - { - after_pos = icount; - break; - } - } - _RYML_CB_ASSERT(m_callbacks, after_pos != NONE); - } - - // for each child to be duplicated... - size_t prev = after; - for(size_t i = src->first_child(node), icount = 0; i != NONE; ++icount, i = src->next_sibling(i)) - { - if(is_seq(parent)) - { - prev = duplicate(i, parent, prev); - } - else - { - _RYML_CB_ASSERT(m_callbacks, is_map(parent)); - // does the parent already have a node with key equal to that of the current duplicate? - size_t rep = NONE, rep_pos = NONE; - for(size_t j = first_child(parent), jcount = 0; j != NONE; ++jcount, j = next_sibling(j)) - { - if(key(j) == key(i)) - { - rep = j; - rep_pos = jcount; - break; - } - } - if(rep == NONE) // there is no repetition; just duplicate - { - prev = duplicate(src, i, parent, prev); - } - else // yes, there is a repetition - { - if(after_pos != NONE && rep_pos < after_pos) - { - // rep is located before the node which will be inserted, - // and will be overridden by the duplicate. So replace it. - remove(rep); - prev = duplicate(src, i, parent, prev); - } - else if(prev == NONE) - { - // first iteration with prev = after = NONE and repetition - prev = rep; - } - else if(rep != prev) - { - // rep is located after the node which will be inserted - // and overrides it. So move the rep into this node's place. - move(rep, prev); - prev = rep; - } - } // there's a repetition - } - } - - return prev; -} - - -//----------------------------------------------------------------------------- - -void Tree::merge_with(Tree const *src, size_t src_node, size_t dst_node) -{ - _RYML_CB_ASSERT(m_callbacks, src != nullptr); - if(src_node == NONE) - src_node = src->root_id(); - if(dst_node == NONE) - dst_node = root_id(); - _RYML_CB_ASSERT(m_callbacks, src->has_val(src_node) || src->is_seq(src_node) || src->is_map(src_node)); - - if(src->has_val(src_node)) - { - if( ! has_val(dst_node)) - { - if(has_children(dst_node)) - remove_children(dst_node); - } - if(src->is_keyval(src_node)) - _copy_props(dst_node, src, src_node); - else if(src->is_val(src_node)) - _copy_props_wo_key(dst_node, src, src_node); - else - C4_NEVER_REACH(); - } - else if(src->is_seq(src_node)) - { - if( ! is_seq(dst_node)) - { - if(has_children(dst_node)) - remove_children(dst_node); - _clear_type(dst_node); - if(src->has_key(src_node)) - to_seq(dst_node, src->key(src_node)); - else - to_seq(dst_node); - } - for(size_t sch = src->first_child(src_node); sch != NONE; sch = src->next_sibling(sch)) - { - size_t dch = append_child(dst_node); - _copy_props_wo_key(dch, src, sch); - merge_with(src, sch, dch); - } - } - else if(src->is_map(src_node)) - { - if( ! is_map(dst_node)) - { - if(has_children(dst_node)) - remove_children(dst_node); - _clear_type(dst_node); - if(src->has_key(src_node)) - to_map(dst_node, src->key(src_node)); - else - to_map(dst_node); - } - for(size_t sch = src->first_child(src_node); sch != NONE; sch = src->next_sibling(sch)) - { - size_t dch = find_child(dst_node, src->key(sch)); - if(dch == NONE) - { - dch = append_child(dst_node); - _copy_props(dch, src, sch); - } - merge_with(src, sch, dch); - } - } - else - { - C4_NEVER_REACH(); - } -} - - -//----------------------------------------------------------------------------- - -namespace detail { -/** @todo make this part of the public API, refactoring as appropriate - * to be able to use the same resolver to handle multiple trees (one - * at a time) */ -struct ReferenceResolver -{ - struct refdata - { - NodeType type; - size_t node; - size_t prev_anchor; - size_t target; - size_t parent_ref; - size_t parent_ref_sibling; - }; - - Tree *t; - /** from the specs: "an alias node refers to the most recent - * node in the serialization having the specified anchor". So - * we need to start looking upward from ref nodes. - * - * @see http://yaml.org/spec/1.2/spec.html#id2765878 */ - stack refs; - - ReferenceResolver(Tree *t_) : t(t_), refs(t_->callbacks()) - { - resolve(); - } - - void store_anchors_and_refs() - { - // minimize (re-)allocations by counting first - size_t num_anchors_and_refs = count_anchors_and_refs(t->root_id()); - if(!num_anchors_and_refs) - return; - refs.reserve(num_anchors_and_refs); - - // now descend through the hierarchy - _store_anchors_and_refs(t->root_id()); - - // finally connect the reference list - size_t prev_anchor = npos; - size_t count = 0; - for(auto &rd : refs) - { - rd.prev_anchor = prev_anchor; - if(rd.type.is_anchor()) - prev_anchor = count; - ++count; - } - } - - size_t count_anchors_and_refs(size_t n) - { - size_t c = 0; - c += t->has_key_anchor(n); - c += t->has_val_anchor(n); - c += t->is_key_ref(n); - c += t->is_val_ref(n); - for(size_t ch = t->first_child(n); ch != NONE; ch = t->next_sibling(ch)) - c += count_anchors_and_refs(ch); - return c; - } - - void _store_anchors_and_refs(size_t n) - { - if(t->is_key_ref(n) || t->is_val_ref(n) || (t->has_key(n) && t->key(n) == "<<")) - { - if(t->is_seq(n)) - { - // for merging multiple inheritance targets - // <<: [ *CENTER, *BIG ] - for(size_t ich = t->first_child(n); ich != NONE; ich = t->next_sibling(ich)) - { - RYML_ASSERT(t->num_children(ich) == 0); - refs.push({VALREF, ich, npos, npos, n, t->next_sibling(n)}); - } - return; - } - if(t->is_key_ref(n) && t->key(n) != "<<") // insert key refs BEFORE inserting val refs - { - RYML_CHECK((!t->has_key(n)) || t->key(n).ends_with(t->key_ref(n))); - refs.push({KEYREF, n, npos, npos, NONE, NONE}); - } - if(t->is_val_ref(n)) - { - RYML_CHECK((!t->has_val(n)) || t->val(n).ends_with(t->val_ref(n))); - refs.push({VALREF, n, npos, npos, NONE, NONE}); - } - } - if(t->has_key_anchor(n)) - { - RYML_CHECK(t->has_key(n)); - refs.push({KEYANCH, n, npos, npos, NONE, NONE}); - } - if(t->has_val_anchor(n)) - { - RYML_CHECK(t->has_val(n) || t->is_container(n)); - refs.push({VALANCH, n, npos, npos, NONE, NONE}); - } - for(size_t ch = t->first_child(n); ch != NONE; ch = t->next_sibling(ch)) - { - _store_anchors_and_refs(ch); - } - } - - size_t lookup_(refdata *C4_RESTRICT ra) - { - RYML_ASSERT(ra->type.is_key_ref() || ra->type.is_val_ref()); - RYML_ASSERT(ra->type.is_key_ref() != ra->type.is_val_ref()); - csubstr refname; - if(ra->type.is_val_ref()) - { - refname = t->val_ref(ra->node); - } - else - { - RYML_ASSERT(ra->type.is_key_ref()); - refname = t->key_ref(ra->node); - } - while(ra->prev_anchor != npos) - { - ra = &refs[ra->prev_anchor]; - if(t->has_anchor(ra->node, refname)) - return ra->node; - } - - #ifndef RYML_ERRMSG_SIZE - #define RYML_ERRMSG_SIZE 1024 - #endif - - char errmsg[RYML_ERRMSG_SIZE]; - snprintf(errmsg, RYML_ERRMSG_SIZE, "anchor does not exist: '%.*s'", - static_cast(refname.size()), refname.data()); - c4::yml::error(errmsg); - return NONE; - } - - void resolve() - { - store_anchors_and_refs(); - if(refs.empty()) - return; - - /* from the specs: "an alias node refers to the most recent - * node in the serialization having the specified anchor". So - * we need to start looking upward from ref nodes. - * - * @see http://yaml.org/spec/1.2/spec.html#id2765878 */ - for(size_t i = 0, e = refs.size(); i < e; ++i) - { - auto &C4_RESTRICT rd = refs.top(i); - if( ! rd.type.is_ref()) - continue; - rd.target = lookup_(&rd); - } - } - -}; // ReferenceResolver -} // namespace detail - -void Tree::resolve() -{ - if(m_size == 0) - return; - - detail::ReferenceResolver rr(this); - - // insert the resolved references - size_t prev_parent_ref = NONE; - size_t prev_parent_ref_after = NONE; - for(auto const& C4_RESTRICT rd : rr.refs) - { - if( ! rd.type.is_ref()) - continue; - if(rd.parent_ref != NONE) - { - _RYML_CB_ASSERT(m_callbacks, is_seq(rd.parent_ref)); - size_t after, p = parent(rd.parent_ref); - if(prev_parent_ref != rd.parent_ref) - { - after = rd.parent_ref;//prev_sibling(rd.parent_ref_sibling); - prev_parent_ref_after = after; - } - else - { - after = prev_parent_ref_after; - } - prev_parent_ref = rd.parent_ref; - prev_parent_ref_after = duplicate_children_no_rep(rd.target, p, after); - remove(rd.node); - } - else - { - if(has_key(rd.node) && is_key_ref(rd.node) && key(rd.node) == "<<") - { - _RYML_CB_ASSERT(m_callbacks, is_keyval(rd.node)); - size_t p = parent(rd.node); - size_t after = prev_sibling(rd.node); - duplicate_children_no_rep(rd.target, p, after); - remove(rd.node); - } - else if(rd.type.is_key_ref()) - { - _RYML_CB_ASSERT(m_callbacks, is_key_ref(rd.node)); - _RYML_CB_ASSERT(m_callbacks, has_key_anchor(rd.target) || has_val_anchor(rd.target)); - if(has_val_anchor(rd.target) && val_anchor(rd.target) == key_ref(rd.node)) - { - _RYML_CB_CHECK(m_callbacks, !is_container(rd.target)); - _RYML_CB_CHECK(m_callbacks, has_val(rd.target)); - _p(rd.node)->m_key.scalar = val(rd.target); - _add_flags(rd.node, KEY); - } - else - { - _RYML_CB_CHECK(m_callbacks, key_anchor(rd.target) == key_ref(rd.node)); - _p(rd.node)->m_key.scalar = key(rd.target); - _add_flags(rd.node, VAL); - } - } - else - { - _RYML_CB_ASSERT(m_callbacks, rd.type.is_val_ref()); - if(has_key_anchor(rd.target) && key_anchor(rd.target) == val_ref(rd.node)) - { - _RYML_CB_CHECK(m_callbacks, !is_container(rd.target)); - _RYML_CB_CHECK(m_callbacks, has_val(rd.target)); - _p(rd.node)->m_val.scalar = key(rd.target); - _add_flags(rd.node, VAL); - } - else - { - duplicate_contents(rd.target, rd.node); - } - } - } - } - - // clear anchors and refs - for(auto const& C4_RESTRICT ar : rr.refs) - { - rem_anchor_ref(ar.node); - if(ar.parent_ref != NONE) - if(type(ar.parent_ref) != NOTYPE) - remove(ar.parent_ref); - } - -} - -//----------------------------------------------------------------------------- - -size_t Tree::num_children(size_t node) const -{ - size_t count = 0; - for(size_t i = first_child(node); i != NONE; i = next_sibling(i)) - ++count; - return count; -} - -size_t Tree::child(size_t node, size_t pos) const -{ - _RYML_CB_ASSERT(m_callbacks, node != NONE); - size_t count = 0; - for(size_t i = first_child(node); i != NONE; i = next_sibling(i)) - { - if(count++ == pos) - return i; - } - return NONE; -} - -size_t Tree::child_pos(size_t node, size_t ch) const -{ - size_t count = 0; - for(size_t i = first_child(node); i != NONE; i = next_sibling(i)) - { - if(i == ch) - return count; - ++count; - } - return npos; -} - -#if defined(__clang__) -# pragma clang diagnostic push -# pragma GCC diagnostic ignored "-Wnull-dereference" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# if __GNUC__ >= 6 -# pragma GCC diagnostic ignored "-Wnull-dereference" -# endif -#endif - -size_t Tree::find_child(size_t node, csubstr const& name) const -{ - _RYML_CB_ASSERT(m_callbacks, node != NONE); - _RYML_CB_ASSERT(m_callbacks, is_map(node)); - if(get(node)->m_first_child == NONE) - { - _RYML_CB_ASSERT(m_callbacks, _p(node)->m_last_child == NONE); - return NONE; - } - else - { - _RYML_CB_ASSERT(m_callbacks, _p(node)->m_last_child != NONE); - } - for(size_t i = first_child(node); i != NONE; i = next_sibling(i)) - { - if(_p(i)->m_key.scalar == name) - { - return i; - } - } - return NONE; -} - -#if defined(__clang__) -# pragma clang diagnostic pop -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#endif - - -//----------------------------------------------------------------------------- - -void Tree::to_val(size_t node, csubstr val, type_bits more_flags) -{ - _RYML_CB_ASSERT(m_callbacks, ! has_children(node)); - _RYML_CB_ASSERT(m_callbacks, parent(node) == NONE || ! parent_is_map(node)); - _set_flags(node, VAL|more_flags); - _p(node)->m_key.clear(); - _p(node)->m_val = val; -} - -void Tree::to_keyval(size_t node, csubstr key, csubstr val, type_bits more_flags) -{ - _RYML_CB_ASSERT(m_callbacks, ! has_children(node)); - _RYML_CB_ASSERT(m_callbacks, parent(node) == NONE || parent_is_map(node)); - _set_flags(node, KEYVAL|more_flags); - _p(node)->m_key = key; - _p(node)->m_val = val; -} - -void Tree::to_map(size_t node, type_bits more_flags) -{ - _RYML_CB_ASSERT(m_callbacks, ! has_children(node)); - _RYML_CB_ASSERT(m_callbacks, parent(node) == NONE || ! parent_is_map(node)); // parent must not have children with keys - _set_flags(node, MAP|more_flags); - _p(node)->m_key.clear(); - _p(node)->m_val.clear(); -} - -void Tree::to_map(size_t node, csubstr key, type_bits more_flags) -{ - _RYML_CB_ASSERT(m_callbacks, ! has_children(node)); - _RYML_CB_ASSERT(m_callbacks, parent(node) == NONE || parent_is_map(node)); - _set_flags(node, KEY|MAP|more_flags); - _p(node)->m_key = key; - _p(node)->m_val.clear(); -} - -void Tree::to_seq(size_t node, type_bits more_flags) -{ - _RYML_CB_ASSERT(m_callbacks, ! has_children(node)); - _RYML_CB_ASSERT(m_callbacks, parent(node) == NONE || parent_is_seq(node)); - _set_flags(node, SEQ|more_flags); - _p(node)->m_key.clear(); - _p(node)->m_val.clear(); -} - -void Tree::to_seq(size_t node, csubstr key, type_bits more_flags) -{ - _RYML_CB_ASSERT(m_callbacks, ! has_children(node)); - _RYML_CB_ASSERT(m_callbacks, parent(node) == NONE || parent_is_map(node)); - _set_flags(node, KEY|SEQ|more_flags); - _p(node)->m_key = key; - _p(node)->m_val.clear(); -} - -void Tree::to_doc(size_t node, type_bits more_flags) -{ - _RYML_CB_ASSERT(m_callbacks, ! has_children(node)); - _set_flags(node, DOC|more_flags); - _p(node)->m_key.clear(); - _p(node)->m_val.clear(); -} - -void Tree::to_stream(size_t node, type_bits more_flags) -{ - _RYML_CB_ASSERT(m_callbacks, ! has_children(node)); - _set_flags(node, STREAM|more_flags); - _p(node)->m_key.clear(); - _p(node)->m_val.clear(); -} - - -//----------------------------------------------------------------------------- -size_t Tree::num_tag_directives() const -{ - // this assumes we have a very small number of tag directives - for(size_t i = 0; i < RYML_MAX_TAG_DIRECTIVES; ++i) - if(m_tag_directives[i].handle.empty()) - return i; - return RYML_MAX_TAG_DIRECTIVES; -} - -void Tree::clear_tag_directives() -{ - for(TagDirective &td : m_tag_directives) - td = {}; -} - -size_t Tree::add_tag_directive(TagDirective const& td) -{ - _RYML_CB_CHECK(m_callbacks, !td.handle.empty()); - _RYML_CB_CHECK(m_callbacks, !td.prefix.empty()); - _RYML_CB_ASSERT(m_callbacks, td.handle.begins_with('!')); - _RYML_CB_ASSERT(m_callbacks, td.handle.ends_with('!')); - // https://yaml.org/spec/1.2.2/#rule-ns-word-char - _RYML_CB_ASSERT(m_callbacks, td.handle == '!' || td.handle == "!!" || td.handle.trim('!').first_not_of("01234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-") == npos); - size_t pos = num_tag_directives(); - _RYML_CB_CHECK(m_callbacks, pos < RYML_MAX_TAG_DIRECTIVES); - m_tag_directives[pos] = td; - return pos; -} - -size_t Tree::resolve_tag(substr output, csubstr tag, size_t node_id) const -{ - // lookup from the end. We want to find the first directive that - // matches the tag and has a target node id leq than the given - // node_id. - for(size_t i = RYML_MAX_TAG_DIRECTIVES-1; i != (size_t)-1; --i) - { - auto const& td = m_tag_directives[i]; - if(td.handle.empty()) - continue; - if(tag.begins_with(td.handle) && td.next_node_id <= node_id) - { - _RYML_CB_ASSERT(m_callbacks, tag.len >= td.handle.len); - csubstr rest = tag.sub(td.handle.len); - size_t len = 1u + td.prefix.len + rest.len + 1u; - size_t numpc = rest.count('%'); - if(numpc == 0) - { - if(len <= output.len) - { - output.str[0] = '<'; - memcpy(1u + output.str, td.prefix.str, td.prefix.len); - memcpy(1u + output.str + td.prefix.len, rest.str, rest.len); - output.str[1u + td.prefix.len + rest.len] = '>'; - } - } - else - { - // need to decode URI % sequences - size_t pos = rest.find('%'); - _RYML_CB_ASSERT(m_callbacks, pos != npos); - do { - size_t next = rest.first_not_of("0123456789abcdefABCDEF", pos+1); - if(next == npos) - next = rest.len; - _RYML_CB_CHECK(m_callbacks, pos+1 < next); - _RYML_CB_CHECK(m_callbacks, pos+1 + 2 <= next); - size_t delta = next - (pos+1); - len -= delta; - pos = rest.find('%', pos+1); - } while(pos != npos); - if(len <= output.len) - { - size_t prev = 0, wpos = 0; - auto appendstr = [&](csubstr s) { memcpy(output.str + wpos, s.str, s.len); wpos += s.len; }; - auto appendchar = [&](char c) { output.str[wpos++] = c; }; - appendchar('<'); - appendstr(td.prefix); - pos = rest.find('%'); - _RYML_CB_ASSERT(m_callbacks, pos != npos); - do { - size_t next = rest.first_not_of("0123456789abcdefABCDEF", pos+1); - if(next == npos) - next = rest.len; - _RYML_CB_CHECK(m_callbacks, pos+1 < next); - _RYML_CB_CHECK(m_callbacks, pos+1 + 2 <= next); - uint8_t val; - if(C4_UNLIKELY(!read_hex(rest.range(pos+1, next), &val) || val > 127)) - _RYML_CB_ERR(m_callbacks, "invalid URI character"); - appendstr(rest.range(prev, pos)); - appendchar((char)val); - prev = next; - pos = rest.find('%', pos+1); - } while(pos != npos); - _RYML_CB_ASSERT(m_callbacks, pos == npos); - _RYML_CB_ASSERT(m_callbacks, prev > 0); - _RYML_CB_ASSERT(m_callbacks, rest.len >= prev); - appendstr(rest.sub(prev)); - appendchar('>'); - _RYML_CB_ASSERT(m_callbacks, wpos == len); - } - } - return len; - } - } - return 0; // return 0 to signal that the tag is local and cannot be resolved -} - -namespace { -csubstr _transform_tag(Tree *t, csubstr tag, size_t node) -{ - size_t required_size = t->resolve_tag(substr{}, tag, node); - if(!required_size) - return tag; - const char *prev_arena = t->arena().str; - substr buf = t->alloc_arena(required_size); - _RYML_CB_ASSERT(t->m_callbacks, t->arena().str == prev_arena); - size_t actual_size = t->resolve_tag(buf, tag, node); - _RYML_CB_ASSERT(t->m_callbacks, actual_size <= required_size); - return buf.first(actual_size); -} -void _resolve_tags(Tree *t, size_t node) -{ - for(size_t child = t->first_child(node); child != NONE; child = t->next_sibling(child)) - { - if(t->has_key(child) && t->has_key_tag(child)) - t->set_key_tag(child, _transform_tag(t, t->key_tag(child), child)); - if(t->has_val(child) && t->has_val_tag(child)) - t->set_val_tag(child, _transform_tag(t, t->val_tag(child), child)); - _resolve_tags(t, child); - } -} -size_t _count_resolved_tags_size(Tree const* t, size_t node) -{ - size_t sz = 0; - for(size_t child = t->first_child(node); child != NONE; child = t->next_sibling(child)) - { - if(t->has_key(child) && t->has_key_tag(child)) - sz += t->resolve_tag(substr{}, t->key_tag(child), child); - if(t->has_val(child) && t->has_val_tag(child)) - sz += t->resolve_tag(substr{}, t->val_tag(child), child); - sz += _count_resolved_tags_size(t, child); - } - return sz; -} -} // namespace - -void Tree::resolve_tags() -{ - if(empty()) - return; - if(num_tag_directives() == 0) - return; - size_t needed_size = _count_resolved_tags_size(this, root_id()); - if(needed_size) - reserve_arena(arena_size() + needed_size); - _resolve_tags(this, root_id()); -} - - -//----------------------------------------------------------------------------- - -csubstr Tree::lookup_result::resolved() const -{ - csubstr p = path.first(path_pos); - if(p.ends_with('.')) - p = p.first(p.len-1); - return p; -} - -csubstr Tree::lookup_result::unresolved() const -{ - return path.sub(path_pos); -} - -void Tree::_advance(lookup_result *r, size_t more) const -{ - r->path_pos += more; - if(r->path.sub(r->path_pos).begins_with('.')) - ++r->path_pos; -} - -Tree::lookup_result Tree::lookup_path(csubstr path, size_t start) const -{ - if(start == NONE) - start = root_id(); - lookup_result r(path, start); - if(path.empty()) - return r; - _lookup_path(&r); - if(r.target == NONE && r.closest == start) - r.closest = NONE; - return r; -} - -size_t Tree::lookup_path_or_modify(csubstr default_value, csubstr path, size_t start) -{ - size_t target = _lookup_path_or_create(path, start); - if(parent_is_map(target)) - to_keyval(target, key(target), default_value); - else - to_val(target, default_value); - return target; -} - -size_t Tree::lookup_path_or_modify(Tree const *src, size_t src_node, csubstr path, size_t start) -{ - size_t target = _lookup_path_or_create(path, start); - merge_with(src, src_node, target); - return target; -} - -size_t Tree::_lookup_path_or_create(csubstr path, size_t start) -{ - if(start == NONE) - start = root_id(); - lookup_result r(path, start); - _lookup_path(&r); - if(r.target != NONE) - { - C4_ASSERT(r.unresolved().empty()); - return r.target; - } - _lookup_path_modify(&r); - return r.target; -} - -void Tree::_lookup_path(lookup_result *r) const -{ - C4_ASSERT( ! r->unresolved().empty()); - _lookup_path_token parent{"", type(r->closest)}; - size_t node; - do - { - node = _next_node(r, &parent); - if(node != NONE) - r->closest = node; - if(r->unresolved().empty()) - { - r->target = node; - return; - } - } while(node != NONE); -} - -void Tree::_lookup_path_modify(lookup_result *r) -{ - C4_ASSERT( ! r->unresolved().empty()); - _lookup_path_token parent{"", type(r->closest)}; - size_t node; - do - { - node = _next_node_modify(r, &parent); - if(node != NONE) - r->closest = node; - if(r->unresolved().empty()) - { - r->target = node; - return; - } - } while(node != NONE); -} - -size_t Tree::_next_node(lookup_result * r, _lookup_path_token *parent) const -{ - _lookup_path_token token = _next_token(r, *parent); - if( ! token) - return NONE; - - size_t node = NONE; - csubstr prev = token.value; - if(token.type == MAP || token.type == SEQ) - { - _RYML_CB_ASSERT(m_callbacks, !token.value.begins_with('[')); - //_RYML_CB_ASSERT(m_callbacks, is_container(r->closest) || r->closest == NONE); - _RYML_CB_ASSERT(m_callbacks, is_map(r->closest)); - node = find_child(r->closest, token.value); - } - else if(token.type == KEYVAL) - { - _RYML_CB_ASSERT(m_callbacks, r->unresolved().empty()); - if(is_map(r->closest)) - node = find_child(r->closest, token.value); - } - else if(token.type == KEY) - { - _RYML_CB_ASSERT(m_callbacks, token.value.begins_with('[') && token.value.ends_with(']')); - token.value = token.value.offs(1, 1).trim(' '); - size_t idx = 0; - _RYML_CB_CHECK(m_callbacks, from_chars(token.value, &idx)); - node = child(r->closest, idx); - } - else - { - C4_NEVER_REACH(); - } - - if(node != NONE) - { - *parent = token; - } - else - { - csubstr p = r->path.sub(r->path_pos > 0 ? r->path_pos - 1 : r->path_pos); - r->path_pos -= prev.len; - if(p.begins_with('.')) - r->path_pos -= 1u; - } - - return node; -} - -size_t Tree::_next_node_modify(lookup_result * r, _lookup_path_token *parent) -{ - _lookup_path_token token = _next_token(r, *parent); - if( ! token) - return NONE; - - size_t node = NONE; - if(token.type == MAP || token.type == SEQ) - { - _RYML_CB_ASSERT(m_callbacks, !token.value.begins_with('[')); - //_RYML_CB_ASSERT(m_callbacks, is_container(r->closest) || r->closest == NONE); - if( ! is_container(r->closest)) - { - if(has_key(r->closest)) - to_map(r->closest, key(r->closest)); - else - to_map(r->closest); - } - else - { - if(is_map(r->closest)) - node = find_child(r->closest, token.value); - else - { - size_t pos = NONE; - _RYML_CB_CHECK(m_callbacks, c4::atox(token.value, &pos)); - _RYML_CB_ASSERT(m_callbacks, pos != NONE); - node = child(r->closest, pos); - } - } - if(node == NONE) - { - _RYML_CB_ASSERT(m_callbacks, is_map(r->closest)); - node = append_child(r->closest); - NodeData *n = _p(node); - n->m_key.scalar = token.value; - n->m_type.add(KEY); - } - } - else if(token.type == KEYVAL) - { - _RYML_CB_ASSERT(m_callbacks, r->unresolved().empty()); - if(is_map(r->closest)) - { - node = find_child(r->closest, token.value); - if(node == NONE) - node = append_child(r->closest); - } - else - { - _RYML_CB_ASSERT(m_callbacks, !is_seq(r->closest)); - _add_flags(r->closest, MAP); - node = append_child(r->closest); - } - NodeData *n = _p(node); - n->m_key.scalar = token.value; - n->m_val.scalar = ""; - n->m_type.add(KEYVAL); - } - else if(token.type == KEY) - { - _RYML_CB_ASSERT(m_callbacks, token.value.begins_with('[') && token.value.ends_with(']')); - token.value = token.value.offs(1, 1).trim(' '); - size_t idx; - if( ! from_chars(token.value, &idx)) - return NONE; - if( ! is_container(r->closest)) - { - if(has_key(r->closest)) - { - csubstr k = key(r->closest); - _clear_type(r->closest); - to_seq(r->closest, k); - } - else - { - _clear_type(r->closest); - to_seq(r->closest); - } - } - _RYML_CB_ASSERT(m_callbacks, is_container(r->closest)); - node = child(r->closest, idx); - if(node == NONE) - { - _RYML_CB_ASSERT(m_callbacks, num_children(r->closest) <= idx); - for(size_t i = num_children(r->closest); i <= idx; ++i) - { - node = append_child(r->closest); - if(i < idx) - { - if(is_map(r->closest)) - to_keyval(node, /*"~"*/{}, /*"~"*/{}); - else if(is_seq(r->closest)) - to_val(node, /*"~"*/{}); - } - } - } - } - else - { - C4_NEVER_REACH(); - } - - _RYML_CB_ASSERT(m_callbacks, node != NONE); - *parent = token; - return node; -} - -/** types of tokens: - * - seeing "map." ---> "map"/MAP - * - finishing "scalar" ---> "scalar"/KEYVAL - * - seeing "seq[n]" ---> "seq"/SEQ (--> "[n]"/KEY) - * - seeing "[n]" ---> "[n]"/KEY - */ -Tree::_lookup_path_token Tree::_next_token(lookup_result *r, _lookup_path_token const& parent) const -{ - csubstr unres = r->unresolved(); - if(unres.empty()) - return {}; - - // is it an indexation like [0], [1], etc? - if(unres.begins_with('[')) - { - size_t pos = unres.find(']'); - if(pos == csubstr::npos) - return {}; - csubstr idx = unres.first(pos + 1); - _advance(r, pos + 1); - return {idx, KEY}; - } - - // no. so it must be a name - size_t pos = unres.first_of(".["); - if(pos == csubstr::npos) - { - _advance(r, unres.len); - NodeType t; - if(( ! parent) || parent.type.is_seq()) - return {unres, VAL}; - return {unres, KEYVAL}; - } - - // it's either a map or a seq - _RYML_CB_ASSERT(m_callbacks, unres[pos] == '.' || unres[pos] == '['); - if(unres[pos] == '.') - { - _RYML_CB_ASSERT(m_callbacks, pos != 0); - _advance(r, pos + 1); - return {unres.first(pos), MAP}; - } - - _RYML_CB_ASSERT(m_callbacks, unres[pos] == '['); - _advance(r, pos); - return {unres.first(pos), SEQ}; -} - - -} // namespace ryml -} // namespace c4 - - -C4_SUPPRESS_WARNING_GCC_POP -C4_SUPPRESS_WARNING_MSVC_POP diff --git a/thirdparty/ryml/src/c4/yml/tree.hpp b/thirdparty/ryml/src/c4/yml/tree.hpp deleted file mode 100644 index 5adc5583a..000000000 --- a/thirdparty/ryml/src/c4/yml/tree.hpp +++ /dev/null @@ -1,1495 +0,0 @@ -#ifndef _C4_YML_TREE_HPP_ -#define _C4_YML_TREE_HPP_ - - -#include "c4/error.hpp" -#include "c4/types.hpp" -#ifndef _C4_YML_COMMON_HPP_ -#include "c4/yml/common.hpp" -#endif - -#include -#include -#include - - -C4_SUPPRESS_WARNING_MSVC_PUSH -C4_SUPPRESS_WARNING_MSVC(4251) // needs to have dll-interface to be used by clients of struct -C4_SUPPRESS_WARNING_MSVC(4296) // expression is always 'boolean_value' -C4_SUPPRESS_WARNING_GCC_CLANG_PUSH -C4_SUPPRESS_WARNING_GCC("-Wtype-limits") - - -namespace c4 { -namespace yml { - -struct NodeScalar; -struct NodeInit; -struct NodeData; -class NodeRef; -class ConstNodeRef; -class Tree; - - -/** encode a floating point value to a string. */ -template -size_t to_chars_float(substr buf, T val) -{ - C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH("-Wfloat-equal"); - static_assert(std::is_floating_point::value, "must be floating point"); - if(C4_UNLIKELY(std::isnan(val))) - return to_chars(buf, csubstr(".nan")); - else if(C4_UNLIKELY(val == std::numeric_limits::infinity())) - return to_chars(buf, csubstr(".inf")); - else if(C4_UNLIKELY(val == -std::numeric_limits::infinity())) - return to_chars(buf, csubstr("-.inf")); - return to_chars(buf, val); - C4_SUPPRESS_WARNING_GCC_CLANG_POP -} - - -/** decode a floating point from string. Accepts special values: .nan, - * .inf, -.inf */ -template -bool from_chars_float(csubstr buf, T *C4_RESTRICT val) -{ - static_assert(std::is_floating_point::value, "must be floating point"); - if(C4_LIKELY(from_chars(buf, val))) - { - return true; - } - else if(C4_UNLIKELY(buf == ".nan" || buf == ".NaN" || buf == ".NAN")) - { - *val = std::numeric_limits::quiet_NaN(); - return true; - } - else if(C4_UNLIKELY(buf == ".inf" || buf == ".Inf" || buf == ".INF")) - { - *val = std::numeric_limits::infinity(); - return true; - } - else if(C4_UNLIKELY(buf == "-.inf" || buf == "-.Inf" || buf == "-.INF")) - { - *val = -std::numeric_limits::infinity(); - return true; - } - else - { - return false; - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -/** the integral type necessary to cover all the bits marking node tags */ -using tag_bits = uint16_t; - -/** a bit mask for marking tags for types */ -typedef enum : tag_bits { - // container types - TAG_NONE = 0, - TAG_MAP = 1, /**< !!map Unordered set of key: value pairs without duplicates. @see https://yaml.org/type/map.html */ - TAG_OMAP = 2, /**< !!omap Ordered sequence of key: value pairs without duplicates. @see https://yaml.org/type/omap.html */ - TAG_PAIRS = 3, /**< !!pairs Ordered sequence of key: value pairs allowing duplicates. @see https://yaml.org/type/pairs.html */ - TAG_SET = 4, /**< !!set Unordered set of non-equal values. @see https://yaml.org/type/set.html */ - TAG_SEQ = 5, /**< !!seq Sequence of arbitrary values. @see https://yaml.org/type/seq.html */ - // scalar types - TAG_BINARY = 6, /**< !!binary A sequence of zero or more octets (8 bit values). @see https://yaml.org/type/binary.html */ - TAG_BOOL = 7, /**< !!bool Mathematical Booleans. @see https://yaml.org/type/bool.html */ - TAG_FLOAT = 8, /**< !!float Floating-point approximation to real numbers. https://yaml.org/type/float.html */ - TAG_INT = 9, /**< !!float Mathematical integers. https://yaml.org/type/int.html */ - TAG_MERGE = 10, /**< !!merge Specify one or more mapping to be merged with the current one. https://yaml.org/type/merge.html */ - TAG_NULL = 11, /**< !!null Devoid of value. https://yaml.org/type/null.html */ - TAG_STR = 12, /**< !!str A sequence of zero or more Unicode characters. https://yaml.org/type/str.html */ - TAG_TIMESTAMP = 13, /**< !!timestamp A point in time https://yaml.org/type/timestamp.html */ - TAG_VALUE = 14, /**< !!value Specify the default value of a mapping https://yaml.org/type/value.html */ - TAG_YAML = 15, /**< !!yaml Specify the default value of a mapping https://yaml.org/type/yaml.html */ -} YamlTag_e; - -YamlTag_e to_tag(csubstr tag); -csubstr from_tag(YamlTag_e tag); -csubstr from_tag_long(YamlTag_e tag); -csubstr normalize_tag(csubstr tag); -csubstr normalize_tag_long(csubstr tag); - -struct TagDirective -{ - /** Eg `!e!` in `%TAG !e! tag:example.com,2000:app/` */ - csubstr handle; - /** Eg `tag:example.com,2000:app/` in `%TAG !e! tag:example.com,2000:app/` */ - csubstr prefix; - /** The next node to which this tag directive applies */ - size_t next_node_id; -}; - -#ifndef RYML_MAX_TAG_DIRECTIVES -/** the maximum number of tag directives in a Tree */ -#define RYML_MAX_TAG_DIRECTIVES 4 -#endif - - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - - -/** the integral type necessary to cover all the bits marking node types */ -using type_bits = uint64_t; - - -/** a bit mask for marking node types */ -typedef enum : type_bits { - // a convenience define, undefined below - #define c4bit(v) (type_bits(1) << v) - NOTYPE = 0, ///< no node type is set - VAL = c4bit(0), ///< a leaf node, has a (possibly empty) value - KEY = c4bit(1), ///< is member of a map, must have non-empty key - MAP = c4bit(2), ///< a map: a parent of keyvals - SEQ = c4bit(3), ///< a seq: a parent of vals - DOC = c4bit(4), ///< a document - STREAM = c4bit(5)|SEQ, ///< a stream: a seq of docs - KEYREF = c4bit(6), ///< a *reference: the key references an &anchor - VALREF = c4bit(7), ///< a *reference: the val references an &anchor - KEYANCH = c4bit(8), ///< the key has an &anchor - VALANCH = c4bit(9), ///< the val has an &anchor - KEYTAG = c4bit(10), ///< the key has an explicit tag/type - VALTAG = c4bit(11), ///< the val has an explicit tag/type - _TYMASK = c4bit(12)-1, // all the bits up to here - VALQUO = c4bit(12), ///< the val is quoted by '', "", > or | - KEYQUO = c4bit(13), ///< the key is quoted by '', "", > or | - KEYVAL = KEY|VAL, - KEYSEQ = KEY|SEQ, - KEYMAP = KEY|MAP, - DOCMAP = DOC|MAP, - DOCSEQ = DOC|SEQ, - DOCVAL = DOC|VAL, - _KEYMASK = KEY | KEYQUO | KEYANCH | KEYREF | KEYTAG, - _VALMASK = VAL | VALQUO | VALANCH | VALREF | VALTAG, - // these flags are from a work in progress and should not be used yet - _WIP_STYLE_FLOW_SL = c4bit(14), ///< mark container with single-line flow format (seqs as '[val1,val2], maps as '{key: val, key2: val2}') - _WIP_STYLE_FLOW_ML = c4bit(15), ///< mark container with multi-line flow format (seqs as '[val1,\nval2], maps as '{key: val,\nkey2: val2}') - _WIP_STYLE_BLOCK = c4bit(16), ///< mark container with block format (seqs as '- val\n', maps as 'key: val') - _WIP_KEY_LITERAL = c4bit(17), ///< mark key scalar as multiline, block literal | - _WIP_VAL_LITERAL = c4bit(18), ///< mark val scalar as multiline, block literal | - _WIP_KEY_FOLDED = c4bit(19), ///< mark key scalar as multiline, block folded > - _WIP_VAL_FOLDED = c4bit(20), ///< mark val scalar as multiline, block folded > - _WIP_KEY_SQUO = c4bit(21), ///< mark key scalar as single quoted - _WIP_VAL_SQUO = c4bit(22), ///< mark val scalar as single quoted - _WIP_KEY_DQUO = c4bit(23), ///< mark key scalar as double quoted - _WIP_VAL_DQUO = c4bit(24), ///< mark val scalar as double quoted - _WIP_KEY_PLAIN = c4bit(25), ///< mark key scalar as plain scalar (unquoted, even when multiline) - _WIP_VAL_PLAIN = c4bit(26), ///< mark val scalar as plain scalar (unquoted, even when multiline) - _WIP_KEY_STYLE = _WIP_KEY_LITERAL|_WIP_KEY_FOLDED|_WIP_KEY_SQUO|_WIP_KEY_DQUO|_WIP_KEY_PLAIN, - _WIP_VAL_STYLE = _WIP_VAL_LITERAL|_WIP_VAL_FOLDED|_WIP_VAL_SQUO|_WIP_VAL_DQUO|_WIP_VAL_PLAIN, - _WIP_KEY_FT_NL = c4bit(27), ///< features: mark key scalar as having \n in its contents - _WIP_VAL_FT_NL = c4bit(28), ///< features: mark val scalar as having \n in its contents - _WIP_KEY_FT_SQ = c4bit(29), ///< features: mark key scalar as having single quotes in its contents - _WIP_VAL_FT_SQ = c4bit(30), ///< features: mark val scalar as having single quotes in its contents - _WIP_KEY_FT_DQ = c4bit(31), ///< features: mark key scalar as having double quotes in its contents - _WIP_VAL_FT_DQ = c4bit(32), ///< features: mark val scalar as having double quotes in its contents - #undef c4bit -} NodeType_e; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -/** wraps a NodeType_e element with some syntactic sugar and predicates */ -struct NodeType -{ -public: - - NodeType_e type; - -public: - - C4_ALWAYS_INLINE NodeType() : type(NOTYPE) {} - C4_ALWAYS_INLINE NodeType(NodeType_e t) : type(t) {} - C4_ALWAYS_INLINE NodeType(type_bits t) : type((NodeType_e)t) {} - - C4_ALWAYS_INLINE const char *type_str() const { return type_str(type); } - static const char* type_str(NodeType_e t); - - C4_ALWAYS_INLINE void set(NodeType_e t) { type = t; } - C4_ALWAYS_INLINE void set(type_bits t) { type = (NodeType_e)t; } - - C4_ALWAYS_INLINE void add(NodeType_e t) { type = (NodeType_e)(type|t); } - C4_ALWAYS_INLINE void add(type_bits t) { type = (NodeType_e)(type|t); } - - C4_ALWAYS_INLINE void rem(NodeType_e t) { type = (NodeType_e)(type & ~t); } - C4_ALWAYS_INLINE void rem(type_bits t) { type = (NodeType_e)(type & ~t); } - - C4_ALWAYS_INLINE void clear() { type = NOTYPE; } - -public: - - C4_ALWAYS_INLINE operator NodeType_e & C4_RESTRICT () { return type; } - C4_ALWAYS_INLINE operator NodeType_e const& C4_RESTRICT () const { return type; } - - C4_ALWAYS_INLINE bool operator== (NodeType_e t) const { return type == t; } - C4_ALWAYS_INLINE bool operator!= (NodeType_e t) const { return type != t; } - -public: - - #if defined(__clang__) - # pragma clang diagnostic push - # pragma clang diagnostic ignored "-Wnull-dereference" - #elif defined(__GNUC__) - # pragma GCC diagnostic push - # if __GNUC__ >= 6 - # pragma GCC diagnostic ignored "-Wnull-dereference" - # endif - #endif - - C4_ALWAYS_INLINE bool is_notype() const { return type == NOTYPE; } - C4_ALWAYS_INLINE bool is_stream() const { return ((type & STREAM) == STREAM) != 0; } - C4_ALWAYS_INLINE bool is_doc() const { return (type & DOC) != 0; } - C4_ALWAYS_INLINE bool is_container() const { return (type & (MAP|SEQ|STREAM)) != 0; } - C4_ALWAYS_INLINE bool is_map() const { return (type & MAP) != 0; } - C4_ALWAYS_INLINE bool is_seq() const { return (type & SEQ) != 0; } - C4_ALWAYS_INLINE bool has_key() const { return (type & KEY) != 0; } - C4_ALWAYS_INLINE bool has_val() const { return (type & VAL) != 0; } - C4_ALWAYS_INLINE bool is_val() const { return (type & KEYVAL) == VAL; } - C4_ALWAYS_INLINE bool is_keyval() const { return (type & KEYVAL) == KEYVAL; } - C4_ALWAYS_INLINE bool has_key_tag() const { return (type & (KEY|KEYTAG)) == (KEY|KEYTAG); } - C4_ALWAYS_INLINE bool has_val_tag() const { return ((type & VALTAG) && (type & (VAL|MAP|SEQ))); } - C4_ALWAYS_INLINE bool has_key_anchor() const { return (type & (KEY|KEYANCH)) == (KEY|KEYANCH); } - C4_ALWAYS_INLINE bool is_key_anchor() const { return (type & (KEY|KEYANCH)) == (KEY|KEYANCH); } - C4_ALWAYS_INLINE bool has_val_anchor() const { return (type & VALANCH) != 0 && (type & (VAL|SEQ|MAP)) != 0; } - C4_ALWAYS_INLINE bool is_val_anchor() const { return (type & VALANCH) != 0 && (type & (VAL|SEQ|MAP)) != 0; } - C4_ALWAYS_INLINE bool has_anchor() const { return (type & (KEYANCH|VALANCH)) != 0; } - C4_ALWAYS_INLINE bool is_anchor() const { return (type & (KEYANCH|VALANCH)) != 0; } - C4_ALWAYS_INLINE bool is_key_ref() const { return (type & KEYREF) != 0; } - C4_ALWAYS_INLINE bool is_val_ref() const { return (type & VALREF) != 0; } - C4_ALWAYS_INLINE bool is_ref() const { return (type & (KEYREF|VALREF)) != 0; } - C4_ALWAYS_INLINE bool is_anchor_or_ref() const { return (type & (KEYANCH|VALANCH|KEYREF|VALREF)) != 0; } - C4_ALWAYS_INLINE bool is_key_quoted() const { return (type & (KEY|KEYQUO)) == (KEY|KEYQUO); } - C4_ALWAYS_INLINE bool is_val_quoted() const { return (type & (VAL|VALQUO)) == (VAL|VALQUO); } - C4_ALWAYS_INLINE bool is_quoted() const { return (type & (KEY|KEYQUO)) == (KEY|KEYQUO) || (type & (VAL|VALQUO)) == (VAL|VALQUO); } - - // these predicates are a work in progress and subject to change. Don't use yet. - C4_ALWAYS_INLINE bool default_block() const { return (type & (_WIP_STYLE_BLOCK|_WIP_STYLE_FLOW_ML|_WIP_STYLE_FLOW_SL)) == 0; } - C4_ALWAYS_INLINE bool marked_block() const { return (type & (_WIP_STYLE_BLOCK)) != 0; } - C4_ALWAYS_INLINE bool marked_flow_sl() const { return (type & (_WIP_STYLE_FLOW_SL)) != 0; } - C4_ALWAYS_INLINE bool marked_flow_ml() const { return (type & (_WIP_STYLE_FLOW_ML)) != 0; } - C4_ALWAYS_INLINE bool marked_flow() const { return (type & (_WIP_STYLE_FLOW_ML|_WIP_STYLE_FLOW_SL)) != 0; } - C4_ALWAYS_INLINE bool key_marked_literal() const { return (type & (_WIP_KEY_LITERAL)) != 0; } - C4_ALWAYS_INLINE bool val_marked_literal() const { return (type & (_WIP_VAL_LITERAL)) != 0; } - C4_ALWAYS_INLINE bool key_marked_folded() const { return (type & (_WIP_KEY_FOLDED)) != 0; } - C4_ALWAYS_INLINE bool val_marked_folded() const { return (type & (_WIP_VAL_FOLDED)) != 0; } - C4_ALWAYS_INLINE bool key_marked_squo() const { return (type & (_WIP_KEY_SQUO)) != 0; } - C4_ALWAYS_INLINE bool val_marked_squo() const { return (type & (_WIP_VAL_SQUO)) != 0; } - C4_ALWAYS_INLINE bool key_marked_dquo() const { return (type & (_WIP_KEY_DQUO)) != 0; } - C4_ALWAYS_INLINE bool val_marked_dquo() const { return (type & (_WIP_VAL_DQUO)) != 0; } - C4_ALWAYS_INLINE bool key_marked_plain() const { return (type & (_WIP_KEY_PLAIN)) != 0; } - C4_ALWAYS_INLINE bool val_marked_plain() const { return (type & (_WIP_VAL_PLAIN)) != 0; } - - #if defined(__clang__) - # pragma clang diagnostic pop - #elif defined(__GNUC__) - # pragma GCC diagnostic pop - #endif - -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -/** a node scalar is a csubstr, which may be tagged and anchored. */ -struct NodeScalar -{ - csubstr tag; - csubstr scalar; - csubstr anchor; - -public: - - /// initialize as an empty scalar - inline NodeScalar() noexcept : tag(), scalar(), anchor() {} - - /// initialize as an untagged scalar - template - inline NodeScalar(const char (&s)[N]) noexcept : tag(), scalar(s), anchor() {} - inline NodeScalar(csubstr s ) noexcept : tag(), scalar(s), anchor() {} - - /// initialize as a tagged scalar - template - inline NodeScalar(const char (&t)[N], const char (&s)[N]) noexcept : tag(t), scalar(s), anchor() {} - inline NodeScalar(csubstr t , csubstr s ) noexcept : tag(t), scalar(s), anchor() {} - -public: - - ~NodeScalar() noexcept = default; - NodeScalar(NodeScalar &&) noexcept = default; - NodeScalar(NodeScalar const&) noexcept = default; - NodeScalar& operator= (NodeScalar &&) noexcept = default; - NodeScalar& operator= (NodeScalar const&) noexcept = default; - -public: - - bool empty() const noexcept { return tag.empty() && scalar.empty() && anchor.empty(); } - - void clear() noexcept { tag.clear(); scalar.clear(); anchor.clear(); } - - void set_ref_maybe_replacing_scalar(csubstr ref, bool has_scalar) noexcept - { - csubstr trimmed = ref.begins_with('*') ? ref.sub(1) : ref; - anchor = trimmed; - if((!has_scalar) || !scalar.ends_with(trimmed)) - scalar = ref; - } -}; -C4_MUST_BE_TRIVIAL_COPY(NodeScalar); - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -/** convenience class to initialize nodes */ -struct NodeInit -{ - - NodeType type; - NodeScalar key; - NodeScalar val; - -public: - - /// initialize as an empty node - NodeInit() : type(NOTYPE), key(), val() {} - /// initialize as a typed node - NodeInit(NodeType_e t) : type(t), key(), val() {} - /// initialize as a sequence member - NodeInit(NodeScalar const& v) : type(VAL), key(), val(v) { _add_flags(); } - /// initialize as a mapping member - NodeInit( NodeScalar const& k, NodeScalar const& v) : type(KEYVAL), key(k.tag, k.scalar), val(v.tag, v.scalar) { _add_flags(); } - /// initialize as a mapping member with explicit type - NodeInit(NodeType_e t, NodeScalar const& k, NodeScalar const& v) : type(t ), key(k.tag, k.scalar), val(v.tag, v.scalar) { _add_flags(); } - /// initialize as a mapping member with explicit type (eg SEQ or MAP) - NodeInit(NodeType_e t, NodeScalar const& k ) : type(t ), key(k.tag, k.scalar), val( ) { _add_flags(KEY); } - -public: - - void clear() - { - type.clear(); - key.clear(); - val.clear(); - } - - void _add_flags(type_bits more_flags=0) - { - type = (type|more_flags); - if( ! key.tag.empty()) - type = (type|KEYTAG); - if( ! val.tag.empty()) - type = (type|VALTAG); - if( ! key.anchor.empty()) - type = (type|KEYANCH); - if( ! val.anchor.empty()) - type = (type|VALANCH); - } - - bool _check() const - { - // key cannot be empty - RYML_ASSERT(key.scalar.empty() == ((type & KEY) == 0)); - // key tag cannot be empty - RYML_ASSERT(key.tag.empty() == ((type & KEYTAG) == 0)); - // val may be empty even though VAL is set. But when VAL is not set, val must be empty - RYML_ASSERT(((type & VAL) != 0) || val.scalar.empty()); - // val tag cannot be empty - RYML_ASSERT(val.tag.empty() == ((type & VALTAG) == 0)); - return true; - } -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -/** contains the data for each YAML node. */ -struct NodeData -{ - NodeType m_type; - - NodeScalar m_key; - NodeScalar m_val; - - size_t m_parent; - size_t m_first_child; - size_t m_last_child; - size_t m_next_sibling; - size_t m_prev_sibling; -}; -C4_MUST_BE_TRIVIAL_COPY(NodeData); - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -class RYML_EXPORT Tree -{ -public: - - /** @name construction and assignment */ - /** @{ */ - - Tree() : Tree(get_callbacks()) {} - Tree(Callbacks const& cb); - Tree(size_t node_capacity, size_t arena_capacity=0) : Tree(node_capacity, arena_capacity, get_callbacks()) {} - Tree(size_t node_capacity, size_t arena_capacity, Callbacks const& cb); - - ~Tree(); - - Tree(Tree const& that) noexcept; - Tree(Tree && that) noexcept; - - Tree& operator= (Tree const& that) noexcept; - Tree& operator= (Tree && that) noexcept; - - /** @} */ - -public: - - /** @name memory and sizing */ - /** @{ */ - - void reserve(size_t node_capacity); - - /** clear the tree and zero every node - * @note does NOT clear the arena - * @see clear_arena() */ - void clear(); - inline void clear_arena() { m_arena_pos = 0; } - - inline bool empty() const { return m_size == 0; } - - inline size_t size() const { return m_size; } - inline size_t capacity() const { return m_cap; } - inline size_t slack() const { RYML_ASSERT(m_cap >= m_size); return m_cap - m_size; } - - Callbacks const& callbacks() const { return m_callbacks; } - void callbacks(Callbacks const& cb) { m_callbacks = cb; } - - /** @} */ - -public: - - /** @name node getters */ - /** @{ */ - - //! get the index of a node belonging to this tree. - //! @p n can be nullptr, in which case a - size_t id(NodeData const* n) const - { - if( ! n) - { - return NONE; - } - RYML_ASSERT(n >= m_buf && n < m_buf + m_cap); - return static_cast(n - m_buf); - } - - //! get a pointer to a node's NodeData. - //! i can be NONE, in which case a nullptr is returned - inline NodeData *get(size_t i) - { - if(i == NONE) - return nullptr; - RYML_ASSERT(i >= 0 && i < m_cap); - return m_buf + i; - } - //! get a pointer to a node's NodeData. - //! i can be NONE, in which case a nullptr is returned. - inline NodeData const *get(size_t i) const - { - if(i == NONE) - return nullptr; - RYML_ASSERT(i >= 0 && i < m_cap); - return m_buf + i; - } - - //! An if-less form of get() that demands a valid node index. - //! This function is implementation only; use at your own risk. - inline NodeData * _p(size_t i) { RYML_ASSERT(i != NONE && i >= 0 && i < m_cap); return m_buf + i; } - //! An if-less form of get() that demands a valid node index. - //! This function is implementation only; use at your own risk. - inline NodeData const * _p(size_t i) const { RYML_ASSERT(i != NONE && i >= 0 && i < m_cap); return m_buf + i; } - - //! Get the id of the root node - size_t root_id() { if(m_cap == 0) { reserve(16); } RYML_ASSERT(m_cap > 0 && m_size > 0); return 0; } - //! Get the id of the root node - size_t root_id() const { RYML_ASSERT(m_cap > 0 && m_size > 0); return 0; } - - //! Get a NodeRef of a node by id - NodeRef ref(size_t id); - //! Get a NodeRef of a node by id - ConstNodeRef ref(size_t id) const; - //! Get a NodeRef of a node by id - ConstNodeRef cref(size_t id); - //! Get a NodeRef of a node by id - ConstNodeRef cref(size_t id) const; - - //! Get the root as a NodeRef - NodeRef rootref(); - //! Get the root as a NodeRef - ConstNodeRef rootref() const; - //! Get the root as a NodeRef - ConstNodeRef crootref(); - //! Get the root as a NodeRef - ConstNodeRef crootref() const; - - //! find a root child by name, return it as a NodeRef - //! @note requires the root to be a map. - NodeRef operator[] (csubstr key); - //! find a root child by name, return it as a NodeRef - //! @note requires the root to be a map. - ConstNodeRef operator[] (csubstr key) const; - - //! find a root child by index: return the root node's @p i-th child as a NodeRef - //! @note @i is NOT the node id, but the child's position - NodeRef operator[] (size_t i); - //! find a root child by index: return the root node's @p i-th child as a NodeRef - //! @note @i is NOT the node id, but the child's position - ConstNodeRef operator[] (size_t i) const; - - //! get the i-th document of the stream - //! @note @i is NOT the node id, but the doc position within the stream - NodeRef docref(size_t i); - //! get the i-th document of the stream - //! @note @i is NOT the node id, but the doc position within the stream - ConstNodeRef docref(size_t i) const; - - /** @} */ - -public: - - /** @name node property getters */ - /** @{ */ - - NodeType type(size_t node) const { return _p(node)->m_type; } - const char* type_str(size_t node) const { return NodeType::type_str(_p(node)->m_type); } - - csubstr const& key (size_t node) const { RYML_ASSERT(has_key(node)); return _p(node)->m_key.scalar; } - csubstr const& key_tag (size_t node) const { RYML_ASSERT(has_key_tag(node)); return _p(node)->m_key.tag; } - csubstr const& key_ref (size_t node) const { RYML_ASSERT(is_key_ref(node) && ! has_key_anchor(node)); return _p(node)->m_key.anchor; } - csubstr const& key_anchor(size_t node) const { RYML_ASSERT( ! is_key_ref(node) && has_key_anchor(node)); return _p(node)->m_key.anchor; } - NodeScalar const& keysc (size_t node) const { RYML_ASSERT(has_key(node)); return _p(node)->m_key; } - - csubstr const& val (size_t node) const { RYML_ASSERT(has_val(node)); return _p(node)->m_val.scalar; } - csubstr const& val_tag (size_t node) const { RYML_ASSERT(has_val_tag(node)); return _p(node)->m_val.tag; } - csubstr const& val_ref (size_t node) const { RYML_ASSERT(is_val_ref(node) && ! has_val_anchor(node)); return _p(node)->m_val.anchor; } - csubstr const& val_anchor(size_t node) const { RYML_ASSERT( ! is_val_ref(node) && has_val_anchor(node)); return _p(node)->m_val.anchor; } - NodeScalar const& valsc (size_t node) const { RYML_ASSERT(has_val(node)); return _p(node)->m_val; } - - /** @} */ - -public: - - /** @name node predicates */ - /** @{ */ - - C4_ALWAYS_INLINE bool is_stream(size_t node) const { return _p(node)->m_type.is_stream(); } - C4_ALWAYS_INLINE bool is_doc(size_t node) const { return _p(node)->m_type.is_doc(); } - C4_ALWAYS_INLINE bool is_container(size_t node) const { return _p(node)->m_type.is_container(); } - C4_ALWAYS_INLINE bool is_map(size_t node) const { return _p(node)->m_type.is_map(); } - C4_ALWAYS_INLINE bool is_seq(size_t node) const { return _p(node)->m_type.is_seq(); } - C4_ALWAYS_INLINE bool has_key(size_t node) const { return _p(node)->m_type.has_key(); } - C4_ALWAYS_INLINE bool has_val(size_t node) const { return _p(node)->m_type.has_val(); } - C4_ALWAYS_INLINE bool is_val(size_t node) const { return _p(node)->m_type.is_val(); } - C4_ALWAYS_INLINE bool is_keyval(size_t node) const { return _p(node)->m_type.is_keyval(); } - C4_ALWAYS_INLINE bool has_key_tag(size_t node) const { return _p(node)->m_type.has_key_tag(); } - C4_ALWAYS_INLINE bool has_val_tag(size_t node) const { return _p(node)->m_type.has_val_tag(); } - C4_ALWAYS_INLINE bool has_key_anchor(size_t node) const { return _p(node)->m_type.has_key_anchor(); } - C4_ALWAYS_INLINE bool is_key_anchor(size_t node) const { return _p(node)->m_type.is_key_anchor(); } - C4_ALWAYS_INLINE bool has_val_anchor(size_t node) const { return _p(node)->m_type.has_val_anchor(); } - C4_ALWAYS_INLINE bool is_val_anchor(size_t node) const { return _p(node)->m_type.is_val_anchor(); } - C4_ALWAYS_INLINE bool has_anchor(size_t node) const { return _p(node)->m_type.has_anchor(); } - C4_ALWAYS_INLINE bool is_anchor(size_t node) const { return _p(node)->m_type.is_anchor(); } - C4_ALWAYS_INLINE bool is_key_ref(size_t node) const { return _p(node)->m_type.is_key_ref(); } - C4_ALWAYS_INLINE bool is_val_ref(size_t node) const { return _p(node)->m_type.is_val_ref(); } - C4_ALWAYS_INLINE bool is_ref(size_t node) const { return _p(node)->m_type.is_ref(); } - C4_ALWAYS_INLINE bool is_anchor_or_ref(size_t node) const { return _p(node)->m_type.is_anchor_or_ref(); } - C4_ALWAYS_INLINE bool is_key_quoted(size_t node) const { return _p(node)->m_type.is_key_quoted(); } - C4_ALWAYS_INLINE bool is_val_quoted(size_t node) const { return _p(node)->m_type.is_val_quoted(); } - C4_ALWAYS_INLINE bool is_quoted(size_t node) const { return _p(node)->m_type.is_quoted(); } - - C4_ALWAYS_INLINE bool parent_is_seq(size_t node) const { RYML_ASSERT(has_parent(node)); return is_seq(_p(node)->m_parent); } - C4_ALWAYS_INLINE bool parent_is_map(size_t node) const { RYML_ASSERT(has_parent(node)); return is_map(_p(node)->m_parent); } - - /** true when key and val are empty, and has no children */ - C4_ALWAYS_INLINE bool empty(size_t node) const { return ! has_children(node) && _p(node)->m_key.empty() && (( ! (_p(node)->m_type & VAL)) || _p(node)->m_val.empty()); } - /** true when the node has an anchor named a */ - C4_ALWAYS_INLINE bool has_anchor(size_t node, csubstr a) const { return _p(node)->m_key.anchor == a || _p(node)->m_val.anchor == a; } - - C4_ALWAYS_INLINE bool key_is_null(size_t node) const { RYML_ASSERT(has_key(node)); NodeData const* C4_RESTRICT n = _p(node); return !n->m_type.is_key_quoted() && _is_null(n->m_key.scalar); } - C4_ALWAYS_INLINE bool val_is_null(size_t node) const { RYML_ASSERT(has_val(node)); NodeData const* C4_RESTRICT n = _p(node); return !n->m_type.is_val_quoted() && _is_null(n->m_val.scalar); } - static bool _is_null(csubstr s) noexcept - { - return s.str == nullptr || - s == "~" || - s == "null" || - s == "Null" || - s == "NULL"; - } - - /** @} */ - -public: - - /** @name hierarchy predicates */ - /** @{ */ - - bool is_root(size_t node) const { RYML_ASSERT(_p(node)->m_parent != NONE || node == 0); return _p(node)->m_parent == NONE; } - - bool has_parent(size_t node) const { return _p(node)->m_parent != NONE; } - - /** true if @p node has a child with id @p ch */ - bool has_child(size_t node, size_t ch) const { return _p(ch)->m_parent == node; } - /** true if @p node has a child with key @p key */ - bool has_child(size_t node, csubstr key) const { return find_child(node, key) != npos; } - /** true if @p node has any children key */ - bool has_children(size_t node) const { return _p(node)->m_first_child != NONE; } - - /** true if @p node has a sibling with id @p sib */ - bool has_sibling(size_t node, size_t sib) const { return _p(node)->m_parent == _p(sib)->m_parent; } - /** true if one of the node's siblings has the given key */ - bool has_sibling(size_t node, csubstr key) const { return find_sibling(node, key) != npos; } - /** true if node is not a single child */ - bool has_other_siblings(size_t node) const - { - NodeData const *n = _p(node); - if(C4_LIKELY(n->m_parent != NONE)) - { - n = _p(n->m_parent); - return n->m_first_child != n->m_last_child; - } - return false; - } - - RYML_DEPRECATED("use has_other_siblings()") bool has_siblings(size_t /*node*/) const { return true; } - - /** @} */ - -public: - - /** @name hierarchy getters */ - /** @{ */ - - size_t parent(size_t node) const { return _p(node)->m_parent; } - - size_t prev_sibling(size_t node) const { return _p(node)->m_prev_sibling; } - size_t next_sibling(size_t node) const { return _p(node)->m_next_sibling; } - - /** O(#num_children) */ - size_t num_children(size_t node) const; - size_t child_pos(size_t node, size_t ch) const; - size_t first_child(size_t node) const { return _p(node)->m_first_child; } - size_t last_child(size_t node) const { return _p(node)->m_last_child; } - size_t child(size_t node, size_t pos) const; - size_t find_child(size_t node, csubstr const& key) const; - - /** O(#num_siblings) */ - /** counts with this */ - size_t num_siblings(size_t node) const { return is_root(node) ? 1 : num_children(_p(node)->m_parent); } - /** does not count with this */ - size_t num_other_siblings(size_t node) const { size_t ns = num_siblings(node); RYML_ASSERT(ns > 0); return ns-1; } - size_t sibling_pos(size_t node, size_t sib) const { RYML_ASSERT( ! is_root(node) || node == root_id()); return child_pos(_p(node)->m_parent, sib); } - size_t first_sibling(size_t node) const { return is_root(node) ? node : _p(_p(node)->m_parent)->m_first_child; } - size_t last_sibling(size_t node) const { return is_root(node) ? node : _p(_p(node)->m_parent)->m_last_child; } - size_t sibling(size_t node, size_t pos) const { return child(_p(node)->m_parent, pos); } - size_t find_sibling(size_t node, csubstr const& key) const { return find_child(_p(node)->m_parent, key); } - - size_t doc(size_t i) const { size_t rid = root_id(); RYML_ASSERT(is_stream(rid)); return child(rid, i); } //!< gets the @p i document node index. requires that the root node is a stream. - - /** @} */ - -public: - - /** @name node modifiers */ - /** @{ */ - - void to_keyval(size_t node, csubstr key, csubstr val, type_bits more_flags=0); - void to_map(size_t node, csubstr key, type_bits more_flags=0); - void to_seq(size_t node, csubstr key, type_bits more_flags=0); - void to_val(size_t node, csubstr val, type_bits more_flags=0); - void to_map(size_t node, type_bits more_flags=0); - void to_seq(size_t node, type_bits more_flags=0); - void to_doc(size_t node, type_bits more_flags=0); - void to_stream(size_t node, type_bits more_flags=0); - - void set_key(size_t node, csubstr key) { RYML_ASSERT(has_key(node)); _p(node)->m_key.scalar = key; } - void set_val(size_t node, csubstr val) { RYML_ASSERT(has_val(node)); _p(node)->m_val.scalar = val; } - - void set_key_tag(size_t node, csubstr tag) { RYML_ASSERT(has_key(node)); _p(node)->m_key.tag = tag; _add_flags(node, KEYTAG); } - void set_val_tag(size_t node, csubstr tag) { RYML_ASSERT(has_val(node) || is_container(node)); _p(node)->m_val.tag = tag; _add_flags(node, VALTAG); } - - void set_key_anchor(size_t node, csubstr anchor) { RYML_ASSERT( ! is_key_ref(node)); _p(node)->m_key.anchor = anchor.triml('&'); _add_flags(node, KEYANCH); } - void set_val_anchor(size_t node, csubstr anchor) { RYML_ASSERT( ! is_val_ref(node)); _p(node)->m_val.anchor = anchor.triml('&'); _add_flags(node, VALANCH); } - void set_key_ref (size_t node, csubstr ref ) { RYML_ASSERT( ! has_key_anchor(node)); NodeData* C4_RESTRICT n = _p(node); n->m_key.set_ref_maybe_replacing_scalar(ref, n->m_type.has_key()); _add_flags(node, KEY|KEYREF); } - void set_val_ref (size_t node, csubstr ref ) { RYML_ASSERT( ! has_val_anchor(node)); NodeData* C4_RESTRICT n = _p(node); n->m_val.set_ref_maybe_replacing_scalar(ref, n->m_type.has_val()); _add_flags(node, VAL|VALREF); } - - void rem_key_anchor(size_t node) { _p(node)->m_key.anchor.clear(); _rem_flags(node, KEYANCH); } - void rem_val_anchor(size_t node) { _p(node)->m_val.anchor.clear(); _rem_flags(node, VALANCH); } - void rem_key_ref (size_t node) { _p(node)->m_key.anchor.clear(); _rem_flags(node, KEYREF); } - void rem_val_ref (size_t node) { _p(node)->m_val.anchor.clear(); _rem_flags(node, VALREF); } - void rem_anchor_ref(size_t node) { _p(node)->m_key.anchor.clear(); _p(node)->m_val.anchor.clear(); _rem_flags(node, KEYANCH|VALANCH|KEYREF|VALREF); } - - /** @} */ - -public: - - /** @name tree modifiers */ - /** @{ */ - - /** reorder the tree in memory so that all the nodes are stored - * in a linear sequence when visited in depth-first order. - * This will invalidate existing ids, since the node id is its - * position in the node array. */ - void reorder(); - - /** Resolve references (aliases <- anchors) in the tree. - * - * Dereferencing is opt-in; after parsing, Tree::resolve() - * has to be called explicitly for obtaining resolved references in the - * tree. This method will resolve all references and substitute the - * anchored values in place of the reference. - * - * This method first does a full traversal of the tree to gather all - * anchors and references in a separate collection, then it goes through - * that collection to locate the names, which it does by obeying the YAML - * standard diktat that "an alias node refers to the most recent node in - * the serialization having the specified anchor" - * - * So, depending on the number of anchor/alias nodes, this is a - * potentially expensive operation, with a best-case linear complexity - * (from the initial traversal). This potential cost is the reason for - * requiring an explicit call. - */ - void resolve(); - - /** @} */ - -public: - - /** @name tag directives */ - /** @{ */ - - void resolve_tags(); - - size_t num_tag_directives() const; - size_t add_tag_directive(TagDirective const& td); - void clear_tag_directives(); - - size_t resolve_tag(substr output, csubstr tag, size_t node_id) const; - csubstr resolve_tag_sub(substr output, csubstr tag, size_t node_id) const - { - size_t needed = resolve_tag(output, tag, node_id); - return needed <= output.len ? output.first(needed) : output; - } - - using tag_directive_const_iterator = TagDirective const*; - tag_directive_const_iterator begin_tag_directives() const { return m_tag_directives; } - tag_directive_const_iterator end_tag_directives() const { return m_tag_directives + num_tag_directives(); } - - struct TagDirectiveProxy - { - tag_directive_const_iterator b, e; - tag_directive_const_iterator begin() const { return b; } - tag_directive_const_iterator end() const { return e; } - }; - - TagDirectiveProxy tag_directives() const { return TagDirectiveProxy{begin_tag_directives(), end_tag_directives()}; } - - /** @} */ - -public: - - /** @name modifying hierarchy */ - /** @{ */ - - /** create and insert a new child of @p parent. insert after the (to-be) - * sibling @p after, which must be a child of @p parent. To insert as the - * first child, set after to NONE */ - C4_ALWAYS_INLINE size_t insert_child(size_t parent, size_t after) - { - RYML_ASSERT(parent != NONE); - RYML_ASSERT(is_container(parent) || is_root(parent)); - RYML_ASSERT(after == NONE || (_p(after)->m_parent == parent)); - size_t child = _claim(); - _set_hierarchy(child, parent, after); - return child; - } - /** create and insert a node as the first child of @p parent */ - C4_ALWAYS_INLINE size_t prepend_child(size_t parent) { return insert_child(parent, NONE); } - /** create and insert a node as the last child of @p parent */ - C4_ALWAYS_INLINE size_t append_child(size_t parent) { return insert_child(parent, _p(parent)->m_last_child); } - -public: - - #if defined(__clang__) - # pragma clang diagnostic push - # pragma clang diagnostic ignored "-Wnull-dereference" - #elif defined(__GNUC__) - # pragma GCC diagnostic push - # if __GNUC__ >= 6 - # pragma GCC diagnostic ignored "-Wnull-dereference" - # endif - #endif - - //! create and insert a new sibling of n. insert after "after" - C4_ALWAYS_INLINE size_t insert_sibling(size_t node, size_t after) - { - return insert_child(_p(node)->m_parent, after); - } - /** create and insert a node as the first node of @p parent */ - C4_ALWAYS_INLINE size_t prepend_sibling(size_t node) { return prepend_child(_p(node)->m_parent); } - C4_ALWAYS_INLINE size_t append_sibling(size_t node) { return append_child(_p(node)->m_parent); } - -public: - - /** remove an entire branch at once: ie remove the children and the node itself */ - inline void remove(size_t node) - { - remove_children(node); - _release(node); - } - - /** remove all the node's children, but keep the node itself */ - void remove_children(size_t node); - - /** change the @p type of the node to one of MAP, SEQ or VAL. @p - * type must have one and only one of MAP,SEQ,VAL; @p type may - * possibly have KEY, but if it does, then the @p node must also - * have KEY. Changing to the same type is a no-op. Otherwise, - * changing to a different type will initialize the node with an - * empty value of the desired type: changing to VAL will - * initialize with a null scalar (~), changing to MAP will - * initialize with an empty map ({}), and changing to SEQ will - * initialize with an empty seq ([]). */ - bool change_type(size_t node, NodeType type); - - bool change_type(size_t node, type_bits type) - { - return change_type(node, (NodeType)type); - } - - #if defined(__clang__) - # pragma clang diagnostic pop - #elif defined(__GNUC__) - # pragma GCC diagnostic pop - #endif - -public: - - /** change the node's position in the parent */ - void move(size_t node, size_t after); - - /** change the node's parent and position */ - void move(size_t node, size_t new_parent, size_t after); - - /** change the node's parent and position to a different tree - * @return the index of the new node in the destination tree */ - size_t move(Tree * src, size_t node, size_t new_parent, size_t after); - - /** ensure the first node is a stream. Eg, change this tree - * - * DOCMAP - * MAP - * KEYVAL - * KEYVAL - * SEQ - * VAL - * - * to - * - * STREAM - * DOCMAP - * MAP - * KEYVAL - * KEYVAL - * SEQ - * VAL - * - * If the root is already a stream, this is a no-op. - */ - void set_root_as_stream(); - -public: - - /** recursively duplicate a node from this tree into a new parent, - * placing it after one of its children - * @return the index of the copy */ - size_t duplicate(size_t node, size_t new_parent, size_t after); - /** recursively duplicate a node from a different tree into a new parent, - * placing it after one of its children - * @return the index of the copy */ - size_t duplicate(Tree const* src, size_t node, size_t new_parent, size_t after); - - /** recursively duplicate the node's children (but not the node) - * @return the index of the last duplicated child */ - size_t duplicate_children(size_t node, size_t parent, size_t after); - /** recursively duplicate the node's children (but not the node), where - * the node is from a different tree - * @return the index of the last duplicated child */ - size_t duplicate_children(Tree const* src, size_t node, size_t parent, size_t after); - - void duplicate_contents(size_t node, size_t where); - void duplicate_contents(Tree const* src, size_t node, size_t where); - - /** duplicate the node's children (but not the node) in a new parent, but - * omit repetitions where a duplicated node has the same key (in maps) or - * value (in seqs). If one of the duplicated children has the same key - * (in maps) or value (in seqs) as one of the parent's children, the one - * that is placed closest to the end will prevail. */ - size_t duplicate_children_no_rep(size_t node, size_t parent, size_t after); - size_t duplicate_children_no_rep(Tree const* src, size_t node, size_t parent, size_t after); - -public: - - void merge_with(Tree const* src, size_t src_node=NONE, size_t dst_root=NONE); - - /** @} */ - -public: - - /** @name internal string arena */ - /** @{ */ - - /** get the current size of the tree's internal arena */ - RYML_DEPRECATED("use arena_size() instead") size_t arena_pos() const { return m_arena_pos; } - /** get the current size of the tree's internal arena */ - inline size_t arena_size() const { return m_arena_pos; } - /** get the current capacity of the tree's internal arena */ - inline size_t arena_capacity() const { return m_arena.len; } - /** get the current slack of the tree's internal arena */ - inline size_t arena_slack() const { RYML_ASSERT(m_arena.len >= m_arena_pos); return m_arena.len - m_arena_pos; } - - /** get the current arena */ - substr arena() const { return m_arena.first(m_arena_pos); } - - /** return true if the given substring is part of the tree's string arena */ - bool in_arena(csubstr s) const - { - return m_arena.is_super(s); - } - - /** serialize the given floating-point variable to the tree's - * arena, growing it as needed to accomodate the serialization. - * - * @note Growing the arena may cause relocation of the entire - * existing arena, and thus change the contents of individual - * nodes, and thus cost O(numnodes)+O(arenasize). To avoid this - * cost, ensure that the arena is reserved to an appropriate size - * using .reserve_arena() - * - * @see alloc_arena() */ - template - typename std::enable_if::value, csubstr>::type - to_arena(T const& C4_RESTRICT a) - { - substr rem(m_arena.sub(m_arena_pos)); - size_t num = to_chars_float(rem, a); - if(num > rem.len) - { - rem = _grow_arena(num); - num = to_chars_float(rem, a); - RYML_ASSERT(num <= rem.len); - } - rem = _request_span(num); - return rem; - } - - /** serialize the given non-floating-point variable to the tree's - * arena, growing it as needed to accomodate the serialization. - * - * @note Growing the arena may cause relocation of the entire - * existing arena, and thus change the contents of individual - * nodes, and thus cost O(numnodes)+O(arenasize). To avoid this - * cost, ensure that the arena is reserved to an appropriate size - * using .reserve_arena() - * - * @see alloc_arena() */ - template - typename std::enable_if::value, csubstr>::type - to_arena(T const& C4_RESTRICT a) - { - substr rem(m_arena.sub(m_arena_pos)); - size_t num = to_chars(rem, a); - if(num > rem.len) - { - rem = _grow_arena(num); - num = to_chars(rem, a); - RYML_ASSERT(num <= rem.len); - } - rem = _request_span(num); - return rem; - } - - /** serialize the given csubstr to the tree's arena, growing the - * arena as needed to accomodate the serialization. - * - * @note Growing the arena may cause relocation of the entire - * existing arena, and thus change the contents of individual - * nodes, and thus cost O(numnodes)+O(arenasize). To avoid this - * cost, ensure that the arena is reserved to an appropriate size - * using .reserve_arena() - * - * @see alloc_arena() */ - csubstr to_arena(csubstr a) - { - if(a.len > 0) - { - substr rem(m_arena.sub(m_arena_pos)); - size_t num = to_chars(rem, a); - if(num > rem.len) - { - rem = _grow_arena(num); - num = to_chars(rem, a); - RYML_ASSERT(num <= rem.len); - } - return _request_span(num); - } - else - { - if(a.str == nullptr) - { - return csubstr{}; - } - else if(m_arena.str == nullptr) - { - // Arena is empty and we want to store a non-null - // zero-length string. - // Even though the string has zero length, we need - // some "memory" to store a non-nullptr string - _grow_arena(1); - } - return _request_span(0); - } - } - C4_ALWAYS_INLINE csubstr to_arena(const char *s) - { - return to_arena(to_csubstr(s)); - } - C4_ALWAYS_INLINE csubstr to_arena(std::nullptr_t) - { - return csubstr{}; - } - - /** copy the given substr to the tree's arena, growing it by the - * required size - * - * @note Growing the arena may cause relocation of the entire - * existing arena, and thus change the contents of individual - * nodes, and thus cost O(numnodes)+O(arenasize). To avoid this - * cost, ensure that the arena is reserved to an appropriate size - * using .reserve_arena() - * - * @see alloc_arena() */ - substr copy_to_arena(csubstr s) - { - substr cp = alloc_arena(s.len); - RYML_ASSERT(cp.len == s.len); - RYML_ASSERT(!s.overlaps(cp)); - #if (!defined(__clang__)) && (defined(__GNUC__) && __GNUC__ >= 10) - C4_SUPPRESS_WARNING_GCC_PUSH - C4_SUPPRESS_WARNING_GCC("-Wstringop-overflow=") // no need for terminating \0 - C4_SUPPRESS_WARNING_GCC( "-Wrestrict") // there's an assert to ensure no violation of restrict behavior - #endif - if(s.len) - memcpy(cp.str, s.str, s.len); - #if (!defined(__clang__)) && (defined(__GNUC__) && __GNUC__ >= 10) - C4_SUPPRESS_WARNING_GCC_POP - #endif - return cp; - } - - /** grow the tree's string arena by the given size and return a substr - * of the added portion - * - * @note Growing the arena may cause relocation of the entire - * existing arena, and thus change the contents of individual - * nodes, and thus cost O(numnodes)+O(arenasize). To avoid this - * cost, ensure that the arena is reserved to an appropriate size - * using .reserve_arena(). - * - * @see reserve_arena() */ - substr alloc_arena(size_t sz) - { - if(sz > arena_slack()) - _grow_arena(sz - arena_slack()); - substr s = _request_span(sz); - return s; - } - - /** ensure the tree's internal string arena is at least the given capacity - * @note This operation has a potential complexity of O(numNodes)+O(arenasize). - * Growing the arena may cause relocation of the entire - * existing arena, and thus change the contents of individual nodes. */ - void reserve_arena(size_t arena_cap) - { - if(arena_cap > m_arena.len) - { - substr buf; - buf.str = (char*) m_callbacks.m_allocate(arena_cap, m_arena.str, m_callbacks.m_user_data); - buf.len = arena_cap; - if(m_arena.str) - { - RYML_ASSERT(m_arena.len >= 0); - _relocate(buf); // does a memcpy and changes nodes using the arena - m_callbacks.m_free(m_arena.str, m_arena.len, m_callbacks.m_user_data); - } - m_arena = buf; - } - } - - /** @} */ - -private: - - substr _grow_arena(size_t more) - { - size_t cap = m_arena.len + more; - cap = cap < 2 * m_arena.len ? 2 * m_arena.len : cap; - cap = cap < 64 ? 64 : cap; - reserve_arena(cap); - return m_arena.sub(m_arena_pos); - } - - substr _request_span(size_t sz) - { - substr s; - s = m_arena.sub(m_arena_pos, sz); - m_arena_pos += sz; - return s; - } - - substr _relocated(csubstr s, substr next_arena) const - { - RYML_ASSERT(m_arena.is_super(s)); - RYML_ASSERT(m_arena.sub(0, m_arena_pos).is_super(s)); - auto pos = (s.str - m_arena.str); - substr r(next_arena.str + pos, s.len); - RYML_ASSERT(r.str - next_arena.str == pos); - RYML_ASSERT(next_arena.sub(0, m_arena_pos).is_super(r)); - return r; - } - -public: - - /** @name lookup */ - /** @{ */ - - struct lookup_result - { - size_t target; - size_t closest; - size_t path_pos; - csubstr path; - - inline operator bool() const { return target != NONE; } - - lookup_result() : target(NONE), closest(NONE), path_pos(0), path() {} - lookup_result(csubstr path_, size_t start) : target(NONE), closest(start), path_pos(0), path(path_) {} - - /** get the part ot the input path that was resolved */ - csubstr resolved() const; - /** get the part ot the input path that was unresolved */ - csubstr unresolved() const; - }; - - /** for example foo.bar[0].baz */ - lookup_result lookup_path(csubstr path, size_t start=NONE) const; - - /** defaulted lookup: lookup @p path; if the lookup fails, recursively modify - * the tree so that the corresponding lookup_path() would return the - * default value. - * @see lookup_path() */ - size_t lookup_path_or_modify(csubstr default_value, csubstr path, size_t start=NONE); - - /** defaulted lookup: lookup @p path; if the lookup fails, recursively modify - * the tree so that the corresponding lookup_path() would return the - * branch @p src_node (from the tree @p src). - * @see lookup_path() */ - size_t lookup_path_or_modify(Tree const *src, size_t src_node, csubstr path, size_t start=NONE); - - /** @} */ - -private: - - struct _lookup_path_token - { - csubstr value; - NodeType type; - _lookup_path_token() : value(), type() {} - _lookup_path_token(csubstr v, NodeType t) : value(v), type(t) {} - inline operator bool() const { return type != NOTYPE; } - bool is_index() const { return value.begins_with('[') && value.ends_with(']'); } - }; - - size_t _lookup_path_or_create(csubstr path, size_t start); - - void _lookup_path (lookup_result *r) const; - void _lookup_path_modify(lookup_result *r); - - size_t _next_node (lookup_result *r, _lookup_path_token *parent) const; - size_t _next_node_modify(lookup_result *r, _lookup_path_token *parent); - - void _advance(lookup_result *r, size_t more) const; - - _lookup_path_token _next_token(lookup_result *r, _lookup_path_token const& parent) const; - -private: - - void _clear(); - void _free(); - void _copy(Tree const& that); - void _move(Tree & that); - - void _relocate(substr next_arena); - -public: - - #if ! RYML_USE_ASSERT - C4_ALWAYS_INLINE void _check_next_flags(size_t, type_bits) {} - #else - void _check_next_flags(size_t node, type_bits f) - { - auto n = _p(node); - type_bits o = n->m_type; // old - C4_UNUSED(o); - if(f & MAP) - { - RYML_ASSERT_MSG((f & SEQ) == 0, "cannot mark simultaneously as map and seq"); - RYML_ASSERT_MSG((f & VAL) == 0, "cannot mark simultaneously as map and val"); - RYML_ASSERT_MSG((o & SEQ) == 0, "cannot turn a seq into a map; clear first"); - RYML_ASSERT_MSG((o & VAL) == 0, "cannot turn a val into a map; clear first"); - } - else if(f & SEQ) - { - RYML_ASSERT_MSG((f & MAP) == 0, "cannot mark simultaneously as seq and map"); - RYML_ASSERT_MSG((f & VAL) == 0, "cannot mark simultaneously as seq and val"); - RYML_ASSERT_MSG((o & MAP) == 0, "cannot turn a map into a seq; clear first"); - RYML_ASSERT_MSG((o & VAL) == 0, "cannot turn a val into a seq; clear first"); - } - if(f & KEY) - { - RYML_ASSERT(!is_root(node)); - auto pid = parent(node); C4_UNUSED(pid); - RYML_ASSERT(is_map(pid)); - } - if((f & VAL) && !is_root(node)) - { - auto pid = parent(node); C4_UNUSED(pid); - RYML_ASSERT(is_map(pid) || is_seq(pid)); - } - } - #endif - - inline void _set_flags(size_t node, NodeType_e f) { _check_next_flags(node, f); _p(node)->m_type = f; } - inline void _set_flags(size_t node, type_bits f) { _check_next_flags(node, f); _p(node)->m_type = f; } - - inline void _add_flags(size_t node, NodeType_e f) { NodeData *d = _p(node); type_bits fb = f | d->m_type; _check_next_flags(node, fb); d->m_type = (NodeType_e) fb; } - inline void _add_flags(size_t node, type_bits f) { NodeData *d = _p(node); f |= d->m_type; _check_next_flags(node, f); d->m_type = f; } - - inline void _rem_flags(size_t node, NodeType_e f) { NodeData *d = _p(node); type_bits fb = d->m_type & ~f; _check_next_flags(node, fb); d->m_type = (NodeType_e) fb; } - inline void _rem_flags(size_t node, type_bits f) { NodeData *d = _p(node); f = d->m_type & ~f; _check_next_flags(node, f); d->m_type = f; } - - void _set_key(size_t node, csubstr key, type_bits more_flags=0) - { - _p(node)->m_key.scalar = key; - _add_flags(node, KEY|more_flags); - } - void _set_key(size_t node, NodeScalar const& key, type_bits more_flags=0) - { - _p(node)->m_key = key; - _add_flags(node, KEY|more_flags); - } - - void _set_val(size_t node, csubstr val, type_bits more_flags=0) - { - RYML_ASSERT(num_children(node) == 0); - RYML_ASSERT(!is_seq(node) && !is_map(node)); - _p(node)->m_val.scalar = val; - _add_flags(node, VAL|more_flags); - } - void _set_val(size_t node, NodeScalar const& val, type_bits more_flags=0) - { - RYML_ASSERT(num_children(node) == 0); - RYML_ASSERT( ! is_container(node)); - _p(node)->m_val = val; - _add_flags(node, VAL|more_flags); - } - - void _set(size_t node, NodeInit const& i) - { - RYML_ASSERT(i._check()); - NodeData *n = _p(node); - RYML_ASSERT(n->m_key.scalar.empty() || i.key.scalar.empty() || i.key.scalar == n->m_key.scalar); - _add_flags(node, i.type); - if(n->m_key.scalar.empty()) - { - if( ! i.key.scalar.empty()) - { - _set_key(node, i.key.scalar); - } - } - n->m_key.tag = i.key.tag; - n->m_val = i.val; - } - - void _set_parent_as_container_if_needed(size_t in) - { - NodeData const* n = _p(in); - size_t ip = parent(in); - if(ip != NONE) - { - if( ! (is_seq(ip) || is_map(ip))) - { - if((in == first_child(ip)) && (in == last_child(ip))) - { - if( ! n->m_key.empty() || has_key(in)) - { - _add_flags(ip, MAP); - } - else - { - _add_flags(ip, SEQ); - } - } - } - } - } - - void _seq2map(size_t node) - { - RYML_ASSERT(is_seq(node)); - for(size_t i = first_child(node); i != NONE; i = next_sibling(i)) - { - NodeData *C4_RESTRICT ch = _p(i); - if(ch->m_type.is_keyval()) - continue; - ch->m_type.add(KEY); - ch->m_key = ch->m_val; - } - auto *C4_RESTRICT n = _p(node); - n->m_type.rem(SEQ); - n->m_type.add(MAP); - } - - size_t _do_reorder(size_t *node, size_t count); - - void _swap(size_t n_, size_t m_); - void _swap_props(size_t n_, size_t m_); - void _swap_hierarchy(size_t n_, size_t m_); - void _copy_hierarchy(size_t dst_, size_t src_); - - inline void _copy_props(size_t dst_, size_t src_) - { - _copy_props(dst_, this, src_); - } - - inline void _copy_props_wo_key(size_t dst_, size_t src_) - { - _copy_props_wo_key(dst_, this, src_); - } - - void _copy_props(size_t dst_, Tree const* that_tree, size_t src_) - { - auto & C4_RESTRICT dst = *_p(dst_); - auto const& C4_RESTRICT src = *that_tree->_p(src_); - dst.m_type = src.m_type; - dst.m_key = src.m_key; - dst.m_val = src.m_val; - } - - void _copy_props_wo_key(size_t dst_, Tree const* that_tree, size_t src_) - { - auto & C4_RESTRICT dst = *_p(dst_); - auto const& C4_RESTRICT src = *that_tree->_p(src_); - dst.m_type = (src.m_type & ~_KEYMASK) | (dst.m_type & _KEYMASK); - dst.m_val = src.m_val; - } - - inline void _clear_type(size_t node) - { - _p(node)->m_type = NOTYPE; - } - - inline void _clear(size_t node) - { - auto *C4_RESTRICT n = _p(node); - n->m_type = NOTYPE; - n->m_key.clear(); - n->m_val.clear(); - n->m_parent = NONE; - n->m_first_child = NONE; - n->m_last_child = NONE; - } - - inline void _clear_key(size_t node) - { - _p(node)->m_key.clear(); - _rem_flags(node, KEY); - } - - inline void _clear_val(size_t node) - { - _p(node)->m_val.clear(); - _rem_flags(node, VAL); - } - -private: - - void _clear_range(size_t first, size_t num); - - size_t _claim(); - void _claim_root(); - void _release(size_t node); - void _free_list_add(size_t node); - void _free_list_rem(size_t node); - - void _set_hierarchy(size_t node, size_t parent, size_t after_sibling); - void _rem_hierarchy(size_t node); - -public: - - // members are exposed, but you should NOT access them directly - - NodeData * m_buf; - size_t m_cap; - - size_t m_size; - - size_t m_free_head; - size_t m_free_tail; - - substr m_arena; - size_t m_arena_pos; - - Callbacks m_callbacks; - - TagDirective m_tag_directives[RYML_MAX_TAG_DIRECTIVES]; - -}; - -} // namespace yml -} // namespace c4 - - -C4_SUPPRESS_WARNING_MSVC_POP -C4_SUPPRESS_WARNING_GCC_CLANG_POP - - -#endif /* _C4_YML_TREE_HPP_ */ diff --git a/thirdparty/ryml/src/c4/yml/writer.hpp b/thirdparty/ryml/src/c4/yml/writer.hpp deleted file mode 100644 index 29e32d47b..000000000 --- a/thirdparty/ryml/src/c4/yml/writer.hpp +++ /dev/null @@ -1,229 +0,0 @@ -#ifndef _C4_YML_WRITER_HPP_ -#define _C4_YML_WRITER_HPP_ - -#ifndef _C4_YML_COMMON_HPP_ -#include "./common.hpp" -#endif - -#include -#include // fwrite(), fputc() -#include // memcpy() - - -namespace c4 { -namespace yml { - - -/** Repeat-Character: a character to be written a number of times. */ -struct RepC -{ - char c; - size_t num_times; -}; -inline RepC indent_to(size_t num_levels) -{ - return {' ', size_t(2) * num_levels}; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -/** A writer that outputs to a file. Defaults to stdout. */ -struct WriterFile -{ - FILE * m_file; - size_t m_pos; - - WriterFile(FILE *f = nullptr) : m_file(f ? f : stdout), m_pos(0) {} - - inline substr _get(bool /*error_on_excess*/) - { - substr sp; - sp.str = nullptr; - sp.len = m_pos; - return sp; - } - - template - inline void _do_write(const char (&a)[N]) - { - fwrite(a, sizeof(char), N - 1, m_file); - m_pos += N - 1; - } - - inline void _do_write(csubstr sp) - { - #if defined(__clang__) - # pragma clang diagnostic push - # pragma GCC diagnostic ignored "-Wsign-conversion" - #elif defined(__GNUC__) - # pragma GCC diagnostic push - # pragma GCC diagnostic ignored "-Wsign-conversion" - #endif - if(sp.empty()) return; - fwrite(sp.str, sizeof(csubstr::char_type), sp.len, m_file); - m_pos += sp.len; - #if defined(__clang__) - # pragma clang diagnostic pop - #elif defined(__GNUC__) - # pragma GCC diagnostic pop - #endif - } - - inline void _do_write(const char c) - { - fputc(c, m_file); - ++m_pos; - } - - inline void _do_write(RepC const rc) - { - for(size_t i = 0; i < rc.num_times; ++i) - { - fputc(rc.c, m_file); - } - m_pos += rc.num_times; - } -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -/** A writer that outputs to an STL-like ostream. */ -template -struct WriterOStream -{ - OStream& m_stream; - size_t m_pos; - - WriterOStream(OStream &s) : m_stream(s), m_pos(0) {} - - inline substr _get(bool /*error_on_excess*/) - { - substr sp; - sp.str = nullptr; - sp.len = m_pos; - return sp; - } - - template - inline void _do_write(const char (&a)[N]) - { - m_stream.write(a, N - 1); - m_pos += N - 1; - } - - inline void _do_write(csubstr sp) - { - #if defined(__clang__) - # pragma clang diagnostic push - # pragma GCC diagnostic ignored "-Wsign-conversion" - #elif defined(__GNUC__) - # pragma GCC diagnostic push - # pragma GCC diagnostic ignored "-Wsign-conversion" - #endif - if(sp.empty()) return; - m_stream.write(sp.str, sp.len); - m_pos += sp.len; - #if defined(__clang__) - # pragma clang diagnostic pop - #elif defined(__GNUC__) - # pragma GCC diagnostic pop - #endif - } - - inline void _do_write(const char c) - { - m_stream.put(c); - ++m_pos; - } - - inline void _do_write(RepC const rc) - { - for(size_t i = 0; i < rc.num_times; ++i) - { - m_stream.put(rc.c); - } - m_pos += rc.num_times; - } -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -/** a writer to a substr */ -struct WriterBuf -{ - substr m_buf; - size_t m_pos; - - WriterBuf(substr sp) : m_buf(sp), m_pos(0) {} - - inline substr _get(bool error_on_excess) - { - if(m_pos <= m_buf.len) - { - return m_buf.first(m_pos); - } - if(error_on_excess) - { - c4::yml::error("not enough space in the given buffer"); - } - substr sp; - sp.str = nullptr; - sp.len = m_pos; - return sp; - } - - template - inline void _do_write(const char (&a)[N]) - { - RYML_ASSERT( ! m_buf.overlaps(a)); - if(m_pos + N-1 <= m_buf.len) - { - memcpy(&(m_buf[m_pos]), a, N-1); - } - m_pos += N-1; - } - - inline void _do_write(csubstr sp) - { - if(sp.empty()) return; - RYML_ASSERT( ! sp.overlaps(m_buf)); - if(m_pos + sp.len <= m_buf.len) - { - memcpy(&(m_buf[m_pos]), sp.str, sp.len); - } - m_pos += sp.len; - } - - inline void _do_write(const char c) - { - if(m_pos + 1 <= m_buf.len) - { - m_buf[m_pos] = c; - } - ++m_pos; - } - - inline void _do_write(RepC const rc) - { - if(m_pos + rc.num_times <= m_buf.len) - { - for(size_t i = 0; i < rc.num_times; ++i) - { - m_buf[m_pos + i] = rc.c; - } - } - m_pos += rc.num_times; - } -}; - - -} // namespace yml -} // namespace c4 - -#endif /* _C4_YML_WRITER_HPP_ */ diff --git a/thirdparty/ryml/src/c4/yml/yml.hpp b/thirdparty/ryml/src/c4/yml/yml.hpp deleted file mode 100644 index 36f78fe82..000000000 --- a/thirdparty/ryml/src/c4/yml/yml.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _C4_YML_YML_HPP_ -#define _C4_YML_YML_HPP_ - -#include "c4/yml/tree.hpp" -#include "c4/yml/node.hpp" -#include "c4/yml/emit.hpp" -#include "c4/yml/parse.hpp" -#include "c4/yml/preprocess.hpp" - -#endif // _C4_YML_YML_HPP_ diff --git a/thirdparty/ryml/src/ryml-gdbtypes.py b/thirdparty/ryml/src/ryml-gdbtypes.py deleted file mode 100644 index 2625a6ccd..000000000 --- a/thirdparty/ryml/src/ryml-gdbtypes.py +++ /dev/null @@ -1,391 +0,0 @@ -# To make this file known to Qt Creator using: -# Tools > Options > Debugger > Locals & Expressions > Extra Debugging Helpers -# Any contents here will be picked up by GDB, LLDB, and CDB based -# debugging in Qt Creator automatically. - - -# Example to display a simple type -# template struct MapNode -# { -# U key; -# V data; -# } -# -# def qdump__MapNode(d, value): -# d.putValue("This is the value column contents") -# d.putExpandable() -# if d.isExpanded(): -# with Children(d): -# # Compact simple case. -# d.putSubItem("key", value["key"]) -# # Same effect, with more customization possibilities. -# with SubItem(d, "data") -# d.putItem("data", value["data"]) - -# Check http://doc.qt.io/qtcreator/creator-debugging-helpers.html -# for more details or look at qttypes.py, stdtypes.py, boosttypes.py -# for more complex examples. - -# to try parsing: -# env PYTHONPATH=/usr/share/qtcreator/debugger/ python src/ryml-gdbtypes.py - - -import dumper -#from dumper import Dumper, Value, Children, SubItem -#from dumper import SubItem, Children -from dumper import * - -import sys -import os - - -# ----------------------------------------------------------------------------- -# ----------------------------------------------------------------------------- -# ----------------------------------------------------------------------------- - -# QtCreator makes it really hard to figure out problems in this code. -# So here are some debugging utilities. - - -# FIXME. this decorator is not working; find out why. -def dbglog(func): - """a decorator that logs entry and exit of functions""" - if not _DBG: - return func - def func_wrapper(*args, **kwargs): - _dbg_enter(func.__name__) - ret = func(*args, **kwargs) - _dbg_exit(func.__name__) - return ret - return func_wrapper - - -_DBG = False -_dbg_log = None -_dbg_stack = 0 -def _dbg(*args, **kwargs): - global _dbg_log, _dbg_stack - if not _DBG: - return - if _dbg_log is None: - filename = os.path.join(os.path.dirname(__file__), "dbg.txt") - _dbg_log = open(filename, "w") - kwargs['file'] = _dbg_log - kwargs['flush'] = True - print(" " * _dbg_stack, *args, **kwargs) - - -def _dbg_enter(name): - global _dbg_stack - _dbg(name, "- enter") - _dbg_stack += 1 - - -def _dbg_exit(name): - global _dbg_stack - _dbg_stack -= 1 - _dbg(name, "- exit!") - - - -# ----------------------------------------------------------------------------- -# ----------------------------------------------------------------------------- -# ----------------------------------------------------------------------------- - - -NPOS = 18446744073709551615 -MAX_SUBSTR_LEN_DISPLAY = 80 -MAX_SUBSTR_LEN_EXPAND = 1000 - - -def get_str_value(d, value, limit=0): - # adapted from dumper.py::Dumper::putCharArrayValue() - m_str = value["str"].pointer() - m_len = value["len"].integer() - if m_len == NPOS: - _dbg("getstr... 1", m_len) - m_str = "!!!!!!!!!!" - m_len = len(m_str) - return m_str, m_len - if limit == 0: - limit = d.displayStringLimit - elided, shown = d.computeLimit(m_len, limit) - mem = bytes(d.readRawMemory(m_str, shown)) - mem = mem.decode('utf8') - return mem, m_len - - -def __display_csubstr(d, value, limit=0): - m_str, m_len = get_str_value(d, value) - safe_len = min(m_len, MAX_SUBSTR_LEN_DISPLAY) - disp = m_str[0:safe_len] - # ensure the string escapes characters like \n\r\t etc - disp = disp.encode('unicode_escape').decode('utf8') - # WATCHOUT. quotes in the string will make qtcreator hang!!! - disp = disp.replace('"', '\\"') - disp = disp.replace('\'', '\\') - if m_len <= MAX_SUBSTR_LEN_DISPLAY: - d.putValue(f"[{m_len}] '{disp}'") - else: - d.putValue(f"[{m_len}] '{disp}'...") - return m_str, m_len - - -def qdump__c4__csubstr(d, value): - m_str, m_len = __display_csubstr(d, value) - d.putExpandable() - if d.isExpanded(): - with Children(d): - safe_len = min(m_len, MAX_SUBSTR_LEN_EXPAND) - for i in range(safe_len): - ct = d.createType('char') - d.putSubItem(safe_len, d.createValue(value["str"].pointer() + i, ct)) - d.putSubItem("len", value["len"]) - d.putPtrItem("str", value["str"].pointer()) - - -def qdump__c4__substr(d, value): - qdump__c4__csubstr(d, value) - - -def qdump__c4__basic_substring(d, value): - qdump__c4__csubstr(d, value) - - -def qdump__c4__yml__NodeScalar(d, value): - alen = value["anchor"]["len"].integer() - tlen = value["tag" ]["len"].integer() - m_str, m_len = get_str_value(d, value["scalar"]) - if alen == 0 and tlen == 0: - d.putValue(f'\'{m_str}\'') - elif alen == 0 and tlen > 0: - d.putValue(f'\'{m_str}\' [Ta]') - elif alen > 0 and tlen == 0: - d.putValue(f'\'{m_str}\' [tA]') - elif alen > 0 and tlen > 0: - d.putValue(f'\'{m_str}\' [TA]') - d.putExpandable() - if d.isExpanded(): - with Children(d): - d.putSubItem("[scalar]", value["scalar"]) - if tlen > 0: - d.putSubItem("[tag]", value["tag"]) - if alen > 0: - d.putSubItem("[anchor or ref]", value["anchor"]) - - -def _format_enum_value(int_value, enum_map): - str_value = enum_map.get(int_value, None) - display = f'{int_value}' if str_value is None else f'{str_value} ({int_value})' - return display - - -def _format_bitmask_value(int_value, enum_map): - str_value = enum_map.get(int_value, None) - if str_value: - return f'{str_value} ({int_value})' - else: - out = "" - orig = int_value - # do in reverse to get compound flags first - for k, v in reversed(enum_map.items()): - if (k != 0): - if (int_value & k) == k: - if len(out) > 0: - out += '|' - out += v - int_value &= ~k - else: - if len(out) == 0 and int_value == 0: - return v - if out == "": - return f'{int_value}' - return f"{out} ({orig})" - - -def _c4bit(*ints): - ret = 0 - for i in ints: - ret |= 1 << i - return ret - - -node_types = { - 0: "NOTYPE", - _c4bit(0): "VAL" , - _c4bit(1): "KEY" , - _c4bit(2): "MAP" , - _c4bit(3): "SEQ" , - _c4bit(4): "DOC" , - _c4bit(5,3): "STREAM", - _c4bit(6): "KEYREF" , - _c4bit(7): "VALREF" , - _c4bit(8): "KEYANCH" , - _c4bit(9): "VALANCH" , - _c4bit(10): "KEYTAG" , - _c4bit(11): "VALTAG" , - _c4bit(12): "VALQUO" , - _c4bit(13): "KEYQUO" , - _c4bit(1,0): "KEYVAL", - _c4bit(1,3): "KEYSEQ", - _c4bit(1,2): "KEYMAP", - _c4bit(4,2): "DOCMAP", - _c4bit(4,3): "DOCSEQ", - _c4bit(4,0): "DOCVAL", - # - _c4bit(14): "STYLE_FLOW_SL", - _c4bit(15): "STYLE_FLOW_ML", - _c4bit(16): "STYLE_BLOCK", - # - _c4bit(17): "KEY_LITERAL", - _c4bit(18): "VAL_LITERAL", - _c4bit(19): "KEY_FOLDED", - _c4bit(20): "VAL_FOLDED", - _c4bit(21): "KEY_SQUO", - _c4bit(22): "VAL_SQUO", - _c4bit(23): "KEY_DQUO", - _c4bit(24): "VAL_DQUO", - _c4bit(25): "KEY_PLAIN", - _c4bit(26): "VAL_PLAIN", -} -node_types_rev = {v: k for k, v in node_types.items()} - - -def _node_type_has_all(node_type_value, type_name): - exp = node_types_rev[type_name] - return (node_type_value & exp) == exp - - -def _node_type_has_any(node_type_value, type_name): - exp = node_types_rev[type_name] - return (node_type_value & exp) != 0 - - -def qdump__c4__yml__NodeType_e(d, value): - v = _format_bitmask_value(value.integer(), node_types) - d.putValue(v) - - -def qdump__c4__yml__NodeType(d, value): - qdump__c4__yml__NodeType_e(d, value["type"]) - - -def qdump__c4__yml__NodeData(d, value): - d.putValue("wtf") - ty = _format_bitmask_value(value.integer(), node_types) - t = value["m_type"]["type"].integer() - k = value["m_key"]["scalar"] - v = value["m_val"]["scalar"] - sk, lk = get_str_value(d, k) - sv, lv = get_str_value(d, v) - if _node_type_has_all(t, "KEYVAL"): - d.putValue(f"'{sk}': '{sv}' {ty}") - elif _node_type_has_any(t, "KEY"): - d.putValue(f"'{sk}': {ty}") - elif _node_type_has_any(t, "VAL"): - d.putValue(f"'{sv}' {ty}") - else: - d.putValue(f"{ty}") - d.putExpandable() - if d.isExpanded(): - with Children(d): - d.putSubItem("m_type", value["m_type"]) - # key - if _node_type_has_any(t, "KEY"): - d.putSubItem("m_key", value["m_key"]) - if _node_type_has_any(t, "KEYREF"): - with SubItem(d, "m_key.ref"): - s_, _ = get_str_value(d, value["m_key"]["anchor"]) - d.putValue(f"'{s_}'") - if _node_type_has_any(t, "KEYANCH"): - with SubItem(d, "m_key.anchor"): - s_, _ = get_str_value(d, value["m_key"]["anchor"]) - d.putValue(f"'{s_}'") - if _node_type_has_any(t, "KEYTAG"): - with SubItem(d, "m_key.tag"): - s_, _ = get_str_value(d, value["m_key"]["tag"]) - d.putValue(f"'{s_}'") - # val - if _node_type_has_any(t, "VAL"): - d.putSubItem("m_val", value["m_val"]) - if _node_type_has_any(t, "VALREF"): - with SubItem(d, "m_val.ref"): - s_, _ = get_str_value(d, value["m_val"]["anchor"]) - d.putValue(f"'{s_}'") - if _node_type_has_any(t, "VALANCH"): - with SubItem(d, "m_val.anchor"): - s_, _ = get_str_value(d, value["m_val"]["anchor"]) - d.putValue(f"'{s_}'") - if _node_type_has_any(t, "VALTAG"): - with SubItem(d, "m_val.tag"): - s_, _ = get_str_value(d, value["m_val"]["tag"]) - d.putValue(f"'{s_}'") - # hierarchy - _dump_node_index(d, "m_parent", value) - _dump_node_index(d, "m_first_child", value) - _dump_node_index(d, "m_last_child", value) - _dump_node_index(d, "m_next_sibling", value) - _dump_node_index(d, "m_prev_sibling", value) - - -def _dump_node_index(d, name, value): - if int(value[name].integer()) == NPOS: - pass - #with SubItem(d, name): - # d.putValue("-") - else: - d.putSubItem(name, value[name]) - - -# c4::yml::Tree -def qdump__c4__yml__Tree(d, value): - m_size = value["m_size"].integer() - m_cap = value["m_cap"].integer() - d.putExpandable() - if d.isExpanded(): - #d.putArrayData(value["m_buf"], m_size, value["m_buf"].dereference()) - with Children(d): - with SubItem(d, f"[nodes]"): - d.putItemCount(m_size) - d.putArrayData(value["m_buf"].pointer(), m_size, value["m_buf"].type.dereference()) - d.putPtrItem("m_buf", value["m_buf"].pointer()) - d.putIntItem("m_size", value["m_size"]) - d.putIntItem("m_cap (capacity)", value["m_cap"]) - d.putIntItem("[slack]", m_cap - m_size) - d.putIntItem("m_free_head", value["m_free_head"]) - d.putIntItem("m_free_tail", value["m_free_tail"]) - d.putSubItem("m_arena", value["m_arena"]) - - -def qdump__c4__yml__detail__stack(d, value): - T = value.type[0] - N = value.type[0] - m_size = value["m_size"].integer() - m_capacity = value["m_capacity"].integer() - d.putItemCount(m_size) - if d.isExpanded(): - with Children(d): - with SubItem(d, f"[nodes]"): - d.putItemCount(m_size) - d.putArrayData(value["m_stack"].pointer(), m_size, T) - d.putIntItem("m_size", value["m_size"]) - d.putIntItem("m_capacity", value["m_capacity"]) - #d.putIntItem("[small capacity]", N) - d.putIntItem("[is large]", value["m_buf"].address() == value["m_stack"].pointer()) - d.putPtrItem("m_stack", value["m_stack"].pointer()) - d.putPtrItem("m_buf", value["m_buf"].address()) - - -def qdump__c4__yml__detail__ReferenceResolver__refdata(d, value): - node = value["node"].integer() - ty = _format_bitmask_value(value["type"].integer(), node_types) - d.putValue(f'{node} {ty}') - d.putExpandable() - if d.isExpanded(): - with Children(d): - d.putSubItem("type", value["type"]) - d.putSubItem("node", value["node"]) - _dump_node_index(d, "prev_anchor", value) - _dump_node_index(d, "target", value) - _dump_node_index(d, "parent_ref", value) - _dump_node_index(d, "parent_ref_sibling", value) diff --git a/thirdparty/ryml/src/ryml.hpp b/thirdparty/ryml/src/ryml.hpp deleted file mode 100644 index c2b3e74b2..000000000 --- a/thirdparty/ryml/src/ryml.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef _RYML_HPP_ -#define _RYML_HPP_ - -#include "c4/yml/yml.hpp" - -namespace ryml { -using namespace c4::yml; -using namespace c4; -} - -#endif /* _RYML_HPP_ */ diff --git a/thirdparty/ryml/src/ryml.natvis b/thirdparty/ryml/src/ryml.natvis deleted file mode 100644 index 5e43b1a5c..000000000 --- a/thirdparty/ryml/src/ryml.natvis +++ /dev/null @@ -1,194 +0,0 @@ - - - - - - - - {scalar.str,[scalar.len]} - {scalar.str,[scalar.len]} [T] - {scalar.str,[scalar.len]} [A] - {scalar.str,[scalar.len]} [T][A] - - scalar - tag - anchor - - - - - {type} - - - - c4::yml::VAL - c4::yml::KEY - c4::yml::MAP - c4::yml::SEQ - c4::yml::DOC - c4::yml::STREAM - c4::yml::KEYREF - c4::yml::VALREF - c4::yml::KEYANCH - c4::yml::VALANCH - c4::yml::KEYTAG - c4::yml::VALTAG - c4::yml::VALQUO - c4::yml::KEYQUO - - - - - - - [KEYVAL] {m_key.scalar.str,[m_key.scalar.len]}: {m_val.scalar.str,[m_val.scalar.len]} - [KEYSEQ] {m_key.scalar.str,[m_key.scalar.len]} - [KEYMAP] {m_key.scalar.str,[m_key.scalar.len]} - [DOCSEQ] - [DOCMAP] - [VAL] {m_val.scalar.str,[m_val.scalar.len]} - [KEY] {m_key.scalar.str,[m_key.scalar.len]} - [SEQ] - [MAP] - [DOC] - [STREAM] - [NOTYPE] - - m_type - m_key - m_val - c4::yml::KEYQUO - c4::yml::VALQUO - m_key.anchor - m_val.anchor - m_key.anchor - m_val.anchor - m_parent - m_first_child - m_last_child - m_prev_sibling - m_next_sibling - - - - - sz={m_size}, cap={m_cap} - - m_size - m_cap - - - - m_cap - m_buf - - - - m_free_head - m_arena - - - - - {value} ({type}) - - value - type - - - - - {path} -- target={target} closest={closest} - - target - closest - path_pos - path - - {path.str,[path_pos]} - - - {path.str+path_pos,[path.len-path_pos]} - - - - - - (void) - [INDEX SEED for] {*(m_tree->m_buf + m_id)} - [NAMED SEED for] {*(m_tree->m_buf + m_id)} - {*(m_tree->m_buf + m_id)} - - m_id - *(m_tree->m_buf + m_id) - m_tree - - - - - - - - buf + curr - curr = (buf + curr)->m_next_sibling - - - - - - - - - - #refs={refs.m_size} #nodes={t->m_size} - - - - - - - t->m_buf + (refs.m_stack + curr)->node - curr = curr+1 - - - - - - - - - refs.m_size - refs.m_stack - - - - t - - - - - sz={m_size} cap={m_capacity} - - m_size - m_capacity - m_buf == m_stack - - - - m_size - m_stack - - - - - - - diff --git a/thirdparty/ryml/src/ryml_std.hpp b/thirdparty/ryml/src/ryml_std.hpp deleted file mode 100644 index 5e81439ac..000000000 --- a/thirdparty/ryml/src/ryml_std.hpp +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _RYML_STD_HPP_ -#define _RYML_STD_HPP_ - -#include "./c4/yml/std/std.hpp" - -#endif /* _RYML_STD_HPP_ */ diff --git a/thirdparty/ryml/tbump.toml b/thirdparty/ryml/tbump.toml deleted file mode 100644 index a14130303..000000000 --- a/thirdparty/ryml/tbump.toml +++ /dev/null @@ -1,56 +0,0 @@ -# https://github.com/TankerHQ/tbump -# https://hackernoon.com/lets-automate-version-number-updates-not-a91q3x7n - -# Uncomment this if your project is hosted on GitHub: -github_url = "https://github.com/biojppm/rapidyaml/" - -[version] -current = "0.5.0" - -# Example of a semver regexp. -# Make sure this matches current_version before -# using tbump -regex = ''' - (?P\d+) - \. - (?P\d+) - \. - (?P\d+) - (-(?P[a-z]+)(?P\d+))? - ''' - -[git] -message_template = "chg: pkg: version {new_version}" -tag_template = "v{new_version}" - -# For each file to patch, add a [[file]] config section containing -# the path of the file, relative to the tbump.toml location. -[[file]] -src = "CMakeLists.txt" -search = "c4_project\\(VERSION {current_version}" -[[file]] -src = "test/test_install/CMakeLists.txt" -search = "c4_project\\(VERSION {current_version}" -[[file]] -src = "test/test_singleheader/CMakeLists.txt" -search = "c4_project\\(VERSION {current_version}" - -# You can specify a list of commands to -# run after the files have been patched -# and before the git commit is made - -# [[before_commit]] -# name = "check changelog" -# cmd = "grep -q {new_version} Changelog.rst" - -# TODO: add version header, containing commit hash -# TODO: consolidate changelog from the git logs: -# https://pypi.org/project/gitchangelog/ -# https://blogs.sap.com/2018/06/22/generating-release-notes-from-git-commit-messages-using-basic-shell-commands-gitgrep/ -# https://medium.com/better-programming/create-your-own-changelog-generator-with-git-aefda291ea93 - -# Or run some commands after the git tag and the branch -# have been pushed: -# [[after_push]] -# name = "publish" -# cmd = "./publish.sh" diff --git a/thirdparty/ryml/test/callbacks_tester.hpp b/thirdparty/ryml/test/callbacks_tester.hpp deleted file mode 100644 index 5286e0c34..000000000 --- a/thirdparty/ryml/test/callbacks_tester.hpp +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef C4_TEST_CALLBACKS_TESTER_HPP_ -#define C4_TEST_CALLBACKS_TESTER_HPP_ - -#ifndef RYML_SINGLE_HEADER -#include "c4/yml/common.hpp" -#endif -#include -#include - -namespace c4 { -namespace yml { - -struct CallbacksTester -{ - std::vector memory_pool; - const char *id; - size_t num_allocs, alloc_size; - size_t num_deallocs, dealloc_size; - - CallbacksTester(const char *id_="notset", size_t sz=10u * 1024u) // 10KB - : memory_pool(sz) - , id(id_) - , num_allocs() - , alloc_size() - , num_deallocs() - , dealloc_size() - { - } - - // checking - ~CallbacksTester() - { - check(); - } - - void check() - { - std::cout << "size: alloc=" << alloc_size << " dealloc=" << dealloc_size << std::endl; - std::cout << "count: #allocs=" << num_allocs << " #deallocs=" << num_deallocs << std::endl; - RYML_CHECK(num_allocs == num_deallocs); - RYML_CHECK(alloc_size == dealloc_size); - } - - Callbacks callbacks() const - { - Callbacks cb = get_callbacks(); - cb.m_user_data = (void*) this; - cb.m_allocate = [](size_t len, void *, void *data){ return ((CallbacksTester*) data)->allocate(len); }; - cb.m_free = [](void *mem, size_t len, void *data){ return ((CallbacksTester*) data)->free(mem, len); }; - return cb; - } - - void *allocate(size_t len) - { - std::cout << "alloc[" << num_allocs << "]=" << len << "B\n"; - void *ptr = &memory_pool[alloc_size]; - alloc_size += len; - ++num_allocs; - RYML_CHECK(alloc_size < memory_pool.size()); - return ptr; - } - - void free(void *mem, size_t len) - { - RYML_CHECK((char*)mem >= &memory_pool.front() && (char*)mem < &memory_pool.back()); - RYML_CHECK((char*)mem+len >= &memory_pool.front() && (char*)mem+len <= &memory_pool.back()); - std::cout << "free[" << num_deallocs << "]=" << len << "B\n"; - dealloc_size += len; - ++num_deallocs; - // no need to free here - } -}; - -} // namespace yml -} // namespace c4 - -#endif /* C4_TEST_CALLBACKS_TESTER_HPP_ */ diff --git a/thirdparty/ryml/test/test_basic.cpp b/thirdparty/ryml/test/test_basic.cpp deleted file mode 100644 index 7a10c073b..000000000 --- a/thirdparty/ryml/test/test_basic.cpp +++ /dev/null @@ -1,304 +0,0 @@ -#ifndef RYML_SINGLE_HEADER -#include "c4/yml/std/std.hpp" -#include "c4/yml/parse.hpp" -#include "c4/yml/emit.hpp" -#include -#include -#include -#endif - -#include "./test_case.hpp" - -#include - -#if defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable: 4389) // signed/unsigned mismatch -#elif defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdollar-in-identifier-extension" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -#endif - -namespace c4 { -namespace yml { - -TEST(general, parsing) -{ - auto tree = parse_in_arena("{foo: 1}"); - - char cmpbuf[128] = {0}; - substr cmp(cmpbuf); - size_t ret; - - ret = cat(cmp, tree["foo"].val()); - EXPECT_EQ(cmp.first(ret), "1"); - - ret = cat(cmp, tree["foo"].key()); - EXPECT_EQ(cmp.first(ret), "foo"); -} - -TEST(general, emitting) -{ - std::string cmpbuf; - - Tree tree; - auto r = tree.rootref(); - - r |= MAP; // this is needed to make the root a map - - r["foo"] = "1"; // ryml works only with strings. - // Note that the tree will be __pointing__ at the - // strings "foo" and "1" used here. You need - // to make sure they have at least the same - // lifetime as the tree. - - auto s = r["seq"]; // does not change the tree until s is written to. - s |= SEQ; - r["seq"].append_child() = "bar0"; // value of this child is now __pointing__ at "bar0" - r["seq"].append_child() = "bar1"; - r["seq"].append_child() = "bar2"; - - //print_tree(tree); - - // emit to stdout (can also emit to FILE* or ryml::span) - emitrs_yaml(tree, &cmpbuf); - const char* exp = R"(foo: 1 -seq: - - bar0 - - bar1 - - bar2 -)"; - EXPECT_EQ(cmpbuf, exp); - - // serializing: using operator<< instead of operator= - // will make the tree serialize the value into a char - // arena inside the tree. This arena can be reserved at will. - int ch3 = 33, ch4 = 44; - s.append_child() << ch3; - s.append_child() << ch4; - - { - std::string tmp = "child5"; - s.append_child() << tmp; // requires #include - // now tmp can go safely out of scope, as it was - // serialized to the tree's internal string arena - // Note the include highlighted above is required so that ryml - // knows how to turn an std::string into a c4::csubstr/c4::substr. - } - - emitrs_yaml(tree, &cmpbuf); - exp = R"(foo: 1 -seq: - - bar0 - - bar1 - - bar2 - - 33 - - 44 - - child5 -)"; - EXPECT_EQ(cmpbuf, exp); - - // to serialize keys: - int k=66; - r.append_child() << key(k) << 7; - - emitrs_yaml(tree, &cmpbuf); - exp = R"(foo: 1 -seq: - - bar0 - - bar1 - - bar2 - - 33 - - 44 - - child5 -66: 7 -)"; - EXPECT_EQ(cmpbuf, exp); -} - -TEST(general, map_to_root) -{ - std::string cmpbuf; const char *exp; - std::map m({{"bar", 2}, {"foo", 1}}); - Tree t; - t.rootref() << m; - - emitrs_yaml(t, &cmpbuf); - exp = R"(bar: 2 -foo: 1 -)"; - EXPECT_EQ(cmpbuf, exp); - - t["foo"] << 10; - t["bar"] << 20; - - m.clear(); - t.rootref() >> m; - - EXPECT_EQ(m["foo"], 10); - EXPECT_EQ(m["bar"], 20); -} - -TEST(general, print_tree) -{ - const char yaml[] = R"( -a: - b: bval - c: - d: - - e - - d - - f: fval - g: gval - h: - - - x: a - y: b - - - z: c - u: -)"; - Tree t = parse_in_arena(yaml); - print_tree(t); // to make sure this is covered too -} - -TEST(general, numbers) -{ - const char yaml[] = R"(- -1 -- -1.0 -- +1.0 -- 1e-2 -- 1e+2 -)"; - Tree t = parse_in_arena(yaml); - auto s = emitrs_yaml(t); - EXPECT_EQ(s, std::string(yaml)); -} - -// github issue 29: https://github.com/biojppm/rapidyaml/issues/29 -TEST(general, newlines_on_maps_nested_in_seqs) -{ - const char yaml[] = R"(enemy: -- actors: - - {name: Enemy_Bokoblin_Junior, value: 4.0} - - {name: Enemy_Bokoblin_Middle, value: 16.0} - - {name: Enemy_Bokoblin_Senior, value: 32.0} - - {name: Enemy_Bokoblin_Dark, value: 48.0} - species: BokoblinSeries -)"; - std::string expected = R"(enemy: - - actors: - - name: Enemy_Bokoblin_Junior - value: 4.0 - - name: Enemy_Bokoblin_Middle - value: 16.0 - - name: Enemy_Bokoblin_Senior - value: 32.0 - - name: Enemy_Bokoblin_Dark - value: 48.0 - species: BokoblinSeries -)"; - Tree t = parse_in_arena(yaml); - auto s = emitrs_yaml(t); - EXPECT_EQ(expected, s); -} - - -TEST(general, test_suite_RZT7) -{ - csubstr yaml = R"( ---- -Time: 2001-11-23 15:01:42 -5 -User: ed -Warning: - This is an error message - for the log file ---- -Time: 2001-11-23 15:02:31 -5 -User: ed -Warning: - A slightly different error - message. ---- -Date: 2001-11-23 15:03:17 -5 -User: ed -Fatal: - Unknown variable "bar" -Stack: - - file: TopClass.py - line: 23 - code: | - x = MoreObject("345\n") - - file: MoreClass.py - line: 58 - code: |- - foo = bar -)"; - test_check_emit_check(yaml, [](Tree const &t){ - ASSERT_TRUE(t.rootref().is_stream()); - ConstNodeRef doc0 = t.rootref()[0]; - EXPECT_EQ(doc0["Time"].val(), csubstr("2001-11-23 15:01:42 -5")); - EXPECT_EQ(doc0["User"].val(), csubstr("ed")); - EXPECT_EQ(doc0["Warning"].val(), csubstr("This is an error message for the log file")); - ConstNodeRef doc1 = t.rootref()[1]; - EXPECT_EQ(doc1["Time"].val(), csubstr("2001-11-23 15:02:31 -5")); - EXPECT_EQ(doc1["User"].val(), csubstr("ed")); - EXPECT_EQ(doc1["Warning"].val(), csubstr("A slightly different error message.")); - ConstNodeRef doc2 = t.rootref()[2]; - EXPECT_EQ(doc2["Date"].val(), csubstr("2001-11-23 15:03:17 -5")); - EXPECT_EQ(doc2["User"].val(), csubstr("ed")); - EXPECT_EQ(doc2["Fatal"].val(), csubstr("Unknown variable \"bar\"")); - EXPECT_EQ(doc2["Stack"][0]["file"].val(), csubstr("TopClass.py")); - EXPECT_EQ(doc2["Stack"][0]["line"].val(), csubstr("23")); - EXPECT_EQ(doc2["Stack"][0]["code"].val(), csubstr("x = MoreObject(\"345\\n\")\n")); - EXPECT_EQ(doc2["Stack"][1]["file"].val(), csubstr("MoreClass.py")); - EXPECT_EQ(doc2["Stack"][1]["line"].val(), csubstr("58")); - EXPECT_EQ(doc2["Stack"][1]["code"].val(), csubstr("foo = bar")); - }); -} - - -TEST(general, github_issue_124) -{ - // All these inputs are basically the same. - // However, the comment was found to confuse the parser in #124. - csubstr yaml[] = { - "a:\n - b\nc: d", - "a:\n - b\n\n# ignore me:\nc: d", - "a:\n - b\n\n # ignore me:\nc: d", - "a:\n - b\n\n # ignore me:\nc: d", - "a:\n - b\n\n#:\nc: d", // also try with just a ':' in the comment - "a:\n - b\n\n# :\nc: d", - "a:\n - b\n\n#\nc: d", // also try with empty comment - }; - for(csubstr inp : yaml) - { - SCOPED_TRACE(inp); - Tree t = parse_in_arena(inp); - std::string s = emitrs_yaml(t); - // The re-emitted output should not contain the comment. - EXPECT_EQ(c4::to_csubstr(s), "a:\n - b\nc: d\n"); - } -} - - - -//------------------------------------------- -// this is needed to use the test case library -Case const* get_case(csubstr /*name*/) -{ - return nullptr; -} - -} // namespace yml -} // namespace c4 - -#if defined(_MSC_VER) -# pragma warning(pop) -#elif defined(__clang__) -# pragma clang diagnostic pop -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#endif diff --git a/thirdparty/ryml/test/test_block_folded.cpp b/thirdparty/ryml/test/test_block_folded.cpp deleted file mode 100644 index 9d579c5a1..000000000 --- a/thirdparty/ryml/test/test_block_folded.cpp +++ /dev/null @@ -1,1574 +0,0 @@ -#include "./test_group.hpp" - -namespace c4 { -namespace yml { - -TEST(block_folded, basic) -{ - { - Tree t = parse_in_arena(R"(> -hello -there - -got it - - -really -)"); - EXPECT_EQ(t.rootref().val(), csubstr("hello there\ngot it\n\nreally\n")); - } -} - -TEST(block_folded, empty_block) -{ - { - Tree t = parse_in_arena(R"(- > -)"); - EXPECT_EQ(t[0].val(), csubstr("")); - } - { - Tree t = parse_in_arena(R"(- >- -)"); - EXPECT_EQ(t[0].val(), csubstr("")); - } - { - Tree t = parse_in_arena(R"(- >+ -)"); - EXPECT_EQ(t[0].val(), csubstr("")); - } - { - Tree t = parse_in_arena(R"( -- > - -- >- - -- >+ - -)"); - EXPECT_FALSE(t.empty()); - EXPECT_EQ(t[0].val(), csubstr("")); - EXPECT_EQ(t[1].val(), csubstr("")); - EXPECT_EQ(t[2].val(), csubstr("\n")); - } - { - Tree t = parse_in_arena(R"( -- > - -- >- - -- >+ - -)"); - EXPECT_FALSE(t.empty()); - EXPECT_EQ(t[0].val(), csubstr("")); - EXPECT_EQ(t[1].val(), csubstr("")); - EXPECT_EQ(t[2].val(), csubstr("\n")); - } - { - Tree t = parse_in_arena(R"( -- > -- >- -- >+ -)"); - EXPECT_FALSE(t.empty()); - EXPECT_EQ(t[0].val(), csubstr("")); - EXPECT_EQ(t[1].val(), csubstr("")); - EXPECT_EQ(t[2].val(), csubstr("")); - } -} - -TEST(block_folded, empty_block0) -{ - Tree t = parse_in_arena(R"(- > -)"); - EXPECT_EQ(t[0].val(), csubstr("")); - t = parse_in_arena(R"(- >- -)"); - EXPECT_EQ(t[0].val(), csubstr("")); - t = parse_in_arena(R"(- >+ -)"); - EXPECT_EQ(t[0].val(), csubstr("")); -} - -TEST(block_folded, empty_block1) -{ - const Tree t = parse_in_arena(R"( -- >- - a -- >- - -- >- - -- >- - - - -- >- - - - -)"); - EXPECT_EQ(t[0].val(), csubstr("a")); - EXPECT_EQ(t[1].val(), csubstr("")); - EXPECT_EQ(t[2].val(), csubstr("")); - EXPECT_EQ(t[3].val(), csubstr("")); - EXPECT_EQ(t[4].val(), csubstr("")); -} - -TEST(block_folded, empty_block_as_container_member) -{ - // this was ok - test_check_emit_check(R"( -map: - a: "" - b: '' - d: | - c: > - e: -)", [](Tree const &t){ - EXPECT_TRUE(t["map"].has_key()); - EXPECT_TRUE(t["map"].is_map()); - EXPECT_EQ(t["map"].num_children(), 5u); - for(const auto &child : t["map"].children()) - { - EXPECT_EQ(child.val(), ""); - if(child.key() != "e") - { - EXPECT_TRUE(child.type().is_val_quoted()); - EXPECT_FALSE(child.val_is_null()); - } - } - }); - // this was ok - test_check_emit_check(R"( -map: - a: "" - b: '' - d: | - c: > -)", [](Tree const &t){ - EXPECT_TRUE(t["map"].has_key()); - EXPECT_TRUE(t["map"].is_map()); - EXPECT_TRUE(t["map"].is_map()); - EXPECT_EQ(t["map"].num_children(), 4u); - for(const auto &child : t["map"].children()) - { - EXPECT_EQ(child.val(), ""); - EXPECT_TRUE(child.type().is_val_quoted()); - EXPECT_FALSE(child.val_is_null()); - } - }); - // this was not ok! the block literal before next is extended: to - // include the YAML for next! - test_check_emit_check(R"( -map: - a: "" - b: '' - d: | - c: > -next: - a: "" - b: '' - d: | - c: > -)", [](Tree const &t){ - for(const char *name : {"map", "next"}) - { - ASSERT_TRUE(t.rootref().has_child(to_csubstr(name))) << "name=" << name; - ConstNodeRef node = t[to_csubstr(name)]; - EXPECT_TRUE(node.has_key()); - EXPECT_TRUE(node.is_map()); - EXPECT_TRUE(node.is_map()); - ASSERT_EQ(node.num_children(), 4u); - for(const auto &child : node.children()) - { - EXPECT_EQ(child.val(), ""); - EXPECT_TRUE(child.type().is_val_quoted()); - EXPECT_FALSE(child.val_is_null()); - } - } - }); - test_check_emit_check(R"( -seq: - - "" - - '' - - | - - > -next: - - "" - - '' - - | - - > -)", [](Tree const &t){ - for(const char *name : {"seq", "next"}) - { - ASSERT_TRUE(t.rootref().has_child(to_csubstr(name))) << "name=" << name; - ConstNodeRef node = t[to_csubstr(name)]; - EXPECT_TRUE(node.has_key()); - EXPECT_TRUE(node.is_seq()); - ASSERT_EQ(node.num_children(), 4u); - for(const auto &child : node.children()) - { - EXPECT_EQ(child.val(), ""); - EXPECT_TRUE(child.type().is_val_quoted()); - EXPECT_FALSE(child.val_is_null()); - } - } - }); -} - -TEST(block_folded, issue152_not_indented) -{ - const Tree t = parse_in_arena(R"( -ok: - - | - exec pg_isready -U "dog" -d "dbname=dog" -h 127.0.0.1 -p 5432 - - parses - yes -ok_parses: yes -err: - - | - exec pg_isready -U "dog" -d "dbname=dog" -h 127.0.0.1 -p 5432 -err_parses: no -err2: - - > - exec pg_isready -U "dog" -d "dbname=dog" -h 127.0.0.1 -p 5432 -err2_parses: no -err3: - - >- - exec pg_isready -U "dog" -d "dbname=dog" -h 127.0.0.1 -p 5432 -err3_parses: no -)"); - EXPECT_EQ(t["ok" ][0].val(), csubstr("exec pg_isready -U \"dog\" -d \"dbname=dog\" -h 127.0.0.1 -p 5432\n")); - EXPECT_EQ(t["err" ][0].val(), csubstr("exec pg_isready -U \"dog\" -d \"dbname=dog\" -h 127.0.0.1 -p 5432\n")); - EXPECT_EQ(t["err2"][0].val(), csubstr("exec pg_isready -U \"dog\" -d \"dbname=dog\" -h 127.0.0.1 -p 5432\n")); - EXPECT_EQ(t["err3"][0].val(), csubstr("exec pg_isready -U \"dog\" -d \"dbname=dog\" -h 127.0.0.1 -p 5432")); -} - -TEST(block_folded, issue152_indented_once) -{ - const Tree t = parse_in_arena(R"( -indented_once: - ok: - - | - exec pg_isready -U "dog" -d "dbname=dog" -h 127.0.0.1 -p 5432 - - parses - yes - ok_parses: yes - err: - - | - exec pg_isready -U "dog" -d "dbname=dog" -h 127.0.0.1 -p 5432 - err_parses: no - err2: - - > - exec pg_isready -U "dog" -d "dbname=dog" -h 127.0.0.1 -p 5432 - err2_parses: no - err3: - - >- - exec pg_isready -U "dog" -d "dbname=dog" -h 127.0.0.1 -p 5432 - err3_parses: no -)"); - ConstNodeRef n = t["indented_once"]; - EXPECT_EQ(n["ok" ][0].val(), csubstr("exec pg_isready -U \"dog\" -d \"dbname=dog\" -h 127.0.0.1 -p 5432\n")); - EXPECT_EQ(n["err" ][0].val(), csubstr("exec pg_isready -U \"dog\" -d \"dbname=dog\" -h 127.0.0.1 -p 5432\n")); - EXPECT_EQ(n["err2"][0].val(), csubstr("exec pg_isready -U \"dog\" -d \"dbname=dog\" -h 127.0.0.1 -p 5432\n")); - EXPECT_EQ(n["err3"][0].val(), csubstr("exec pg_isready -U \"dog\" -d \"dbname=dog\" -h 127.0.0.1 -p 5432")); -} - -TEST(block_folded, issue152_indented_twice) -{ - const Tree t = parse_in_arena(R"( -indented_once: - indented_twice: - ok: - - | - exec pg_isready -U "dog" -d "dbname=dog" -h 127.0.0.1 -p 5432 - - parses - yes - ok_parses: yes - err: - - | - exec pg_isready -U "dog" -d "dbname=dog" -h 127.0.0.1 -p 5432 - err_parses: no - err2: - - > - exec pg_isready -U "dog" -d "dbname=dog" -h 127.0.0.1 -p 5432 - err2_parses: no - err3: - - >- - exec pg_isready -U "dog" -d "dbname=dog" -h 127.0.0.1 -p 5432 - err3_parses: no -)"); - ConstNodeRef n = t["indented_once"]["indented_twice"]; - EXPECT_EQ(n["ok" ][0].val(), csubstr("exec pg_isready -U \"dog\" -d \"dbname=dog\" -h 127.0.0.1 -p 5432\n")); - EXPECT_EQ(n["err" ][0].val(), csubstr("exec pg_isready -U \"dog\" -d \"dbname=dog\" -h 127.0.0.1 -p 5432\n")); - EXPECT_EQ(n["err2"][0].val(), csubstr("exec pg_isready -U \"dog\" -d \"dbname=dog\" -h 127.0.0.1 -p 5432\n")); - EXPECT_EQ(n["err3"][0].val(), csubstr("exec pg_isready -U \"dog\" -d \"dbname=dog\" -h 127.0.0.1 -p 5432")); -} - -TEST(block_folded, issue152_indented_thrice) -{ - const Tree t = parse_in_arena(R"( -indented_once: - indented_twice: - indented_thrice: - ok: - - | - exec pg_isready -U "dog" -d "dbname=dog" -h 127.0.0.1 -p 5432 - - parses - yes - ok_parses: yes - err: - - | - exec pg_isready -U "dog" -d "dbname=dog" -h 127.0.0.1 -p 5432 - err_parses: no - err2: - - > - exec pg_isready -U "dog" -d "dbname=dog" -h 127.0.0.1 -p 5432 - err2_parses: no - err3: - - >- - exec pg_isready -U "dog" -d "dbname=dog" -h 127.0.0.1 -p 5432 - err3_parses: no -)"); - ConstNodeRef n = t["indented_once"]["indented_twice"]["indented_thrice"]; - EXPECT_EQ(n["ok" ][0].val(), csubstr("exec pg_isready -U \"dog\" -d \"dbname=dog\" -h 127.0.0.1 -p 5432\n")); - EXPECT_EQ(n["err" ][0].val(), csubstr("exec pg_isready -U \"dog\" -d \"dbname=dog\" -h 127.0.0.1 -p 5432\n")); - EXPECT_EQ(n["err2"][0].val(), csubstr("exec pg_isready -U \"dog\" -d \"dbname=dog\" -h 127.0.0.1 -p 5432\n")); - EXPECT_EQ(n["err3"][0].val(), csubstr("exec pg_isready -U \"dog\" -d \"dbname=dog\" -h 127.0.0.1 -p 5432")); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -TEST(block_folded, test_suite_4QFQ) -{ - csubstr yaml = R"( -- |1 - child2 -- |3 - child2 -- ' child2 - -' -)"; - test_check_emit_check(yaml, [](Tree const &t){ - EXPECT_EQ(t[0].val(), csubstr(" child2\n")); - EXPECT_EQ(t[1].val(), csubstr(" child2\n")); - EXPECT_EQ(t[2].val(), csubstr(" child2\n")); - }); -} - -TEST(block_folded, test_suite_4QFQ_pt2) -{ - csubstr yaml = R"(--- -- | - child0 -- > - - - # child1 -- |1 - child2 -- > - child3 ---- -foo: - - | - child0 - - > - - - # child1 - - |2 - child2 - - > - child3 -)"; - test_check_emit_check(yaml, [](Tree const &t){ - ASSERT_TRUE(t.rootref().is_stream()); - ConstNodeRef doc = t.rootref().child(0); - ASSERT_TRUE(doc.is_seq()); - ASSERT_EQ(doc.num_children(), 4u); - EXPECT_EQ(doc[0].val(), csubstr("child0\n")); - EXPECT_EQ(doc[1].val(), csubstr("\n\n# child1\n")); - EXPECT_EQ(doc[2].val(), csubstr(" child2\n")); - EXPECT_EQ(doc[3].val(), csubstr("child3\n")); - doc = t.rootref().child(1); - ASSERT_TRUE(doc.is_map()); - ASSERT_EQ(doc["foo"].num_children(), 4u); - EXPECT_EQ(doc["foo"][0].val(), csubstr("child0\n")); - EXPECT_EQ(doc["foo"][1].val(), csubstr("\n\n# child1\n")); - EXPECT_EQ(doc["foo"][2].val(), csubstr(" child2\n")); - EXPECT_EQ(doc["foo"][3].val(), csubstr("child3\n")); - }); -} - -TEST(block_folded, test_suite_6VJK) -{ - csubstr yaml = R"(- > - Sammy Sosa completed another - fine season with great stats. - - 63 Home Runs - 0.288 Batting Average - - What a year! -- > - Sammy Sosa completed another - fine season with great stats. - 63 Home Runs - 0.288 Batting Average - What a year! -- > - Sammy Sosa completed another - fine season with great stats. - - 63 Home Runs - 0.288 Batting Average - - What a year! -- > - Sammy Sosa completed another - fine season with great stats. - - - 63 Home Runs - 0.288 Batting Average - - - What a year! -- > - Sammy Sosa completed another - fine season with great stats. - - - - 63 Home Runs - 0.288 Batting Average - - - - What a year! -- >- - No folding needed -- > - No folding needed)"; - test_check_emit_check(yaml, [](Tree const &t){ - EXPECT_EQ(t[0].val(), csubstr("Sammy Sosa completed another fine season with great stats.\n63 Home Runs 0.288 Batting Average\nWhat a year!\n")); - EXPECT_EQ(t[1].val(), csubstr("Sammy Sosa completed another fine season with great stats.\n 63 Home Runs\n 0.288 Batting Average\nWhat a year!\n")); - EXPECT_EQ(t[2].val(), csubstr("Sammy Sosa completed another fine season with great stats.\n\n 63 Home Runs\n 0.288 Batting Average\n\nWhat a year!\n")); - EXPECT_EQ(t[3].val(), csubstr("Sammy Sosa completed another fine season with great stats.\n\n\n 63 Home Runs\n 0.288 Batting Average\n\n\nWhat a year!\n")); - EXPECT_EQ(t[4].val(), csubstr("Sammy Sosa completed another fine season with great stats.\n\n\n\n 63 Home Runs\n 0.288 Batting Average\n\n\n\nWhat a year!\n")); - EXPECT_EQ(t[5].val(), csubstr("No folding needed")); - EXPECT_EQ(t[6].val(), csubstr("No folding needed\n")); - }); -} - -TEST(block_folded, test_suite_7T8X) -{ - csubstr yaml = R"(> - - folded - line - - next - line - * bullet - - * list - * lines - - last - line - -# Comment -)"; - Tree t = parse_in_arena(yaml); - EXPECT_EQ(t.rootref().val(), "\nfolded line\nnext line\n * bullet\n\n * list\n * lines\n\nlast line\n"); -} - -TEST(block_folded, test_suite_A6F9) -{ - csubstr yaml = R"( -strip: |- - text -clip: | - text -keep: |+ - text -)"; - test_check_emit_check(yaml, [](Tree const &t){ - EXPECT_EQ(t["strip"].val(), "text"); - EXPECT_EQ(t["clip"].val(), "text\n"); - EXPECT_EQ(t["keep"].val(), "text\n"); - }); -} - -TEST(block_folded, test_suite_B3HG) -{ - csubstr yaml = R"( ---- > - folded - text - - ---- > - folded - text ---- > - folded text -)"; - test_check_emit_check(yaml, [](Tree const &t){ - EXPECT_EQ(t.docref(0).val(), csubstr("folded text\n")); - EXPECT_EQ(t.docref(1).val(), csubstr("folded text\n")); - EXPECT_EQ(t.docref(2).val(), csubstr("folded text\n")); - }); -} - -TEST(block_folded, test_suite_D83L) -{ - csubstr yaml = R"( -- |2- - explicit indent and chomp -- |-2 - chomp and explicit indent -)"; - test_check_emit_check(yaml, [](Tree const &t){ - EXPECT_TRUE(t.rootref().is_seq()); - EXPECT_EQ(t[0].val(), csubstr("explicit indent and chomp")); - EXPECT_EQ(t[1].val(), csubstr("chomp and explicit indent")); - }); -} - -TEST(block_folded, test_suite_DWX9) -{ - csubstr yaml = R"( -| - - - literal - - - text - - # Comment -)"; - test_check_emit_check(yaml, [](Tree const &t){ - EXPECT_EQ(t.rootref().val(), csubstr("\n\nliteral\n \n\ntext\n")); - }); -} - -TEST(block_folded, test_suite_F6MC) -{ - csubstr yaml = R"( -a: >2 - more indented - regular -b: >2 - - - more indented - regular -)"; - test_check_emit_check(yaml, [](Tree const &t){ - EXPECT_EQ(t["a"].val(), csubstr(" more indented\nregular\n")); - EXPECT_EQ(t["b"].val(), csubstr("\n\n more indented\nregular\n")); - }); -} - -TEST(block_folded, test_suite_K858) -{ - csubstr yaml = R"(--- -# strip -- >- - -# clip -- > - -# keep -- |+ - ---- -strip: >- - -clip: > - -keep: |+ - -)"; - test_check_emit_check(yaml, [](Tree const &t){ - ASSERT_EQ(t.docref(0).num_children(), 3u); - EXPECT_EQ(t.docref(0)[0].val(), csubstr{}); - EXPECT_EQ(t.docref(0)[1].val(), csubstr{}); - EXPECT_EQ(t.docref(0)[2].val(), csubstr("\n")); - ASSERT_TRUE(t.docref(1).has_child("strip")); - ASSERT_TRUE(t.docref(1).has_child("keep")); - ASSERT_TRUE(t.docref(1).has_child("clip")); - EXPECT_EQ(t.docref(1)["strip"].val(), csubstr{}); - EXPECT_EQ(t.docref(1)["clip"].val(), csubstr{}); - EXPECT_EQ(t.docref(1)["keep"].val(), csubstr("\n")); - }); -} - - -TEST(block_folded, test_suite_MJS9) -{ - csubstr yaml = R"( -- > - foo - - bar - - baz -)"; - test_check_emit_check(yaml, [](Tree const &t){ - EXPECT_EQ(t[0].val(), csubstr("foo \n\n\t bar\n\nbaz\n")); // "foo \n\n \t bar\n\nbaz\n" - }); -} - -TEST(block_folded, test_suite_P2AD) -{ - csubstr yaml = R"( -- | # Empty header↓ - literal -- >1 # Indentation indicator↓ - folded -- |+ # Chomping indicator↓ - keep - -- >1- # Both indicators↓ - strip -- >-1 # Both indicators↓ - strip -)"; - test_check_emit_check(yaml, [](Tree const &t){ - ASSERT_TRUE(t.rootref().is_seq()); - ASSERT_EQ(t.rootref().num_children(), 5u); - EXPECT_EQ(t[0].val(), csubstr("literal\n")); - EXPECT_EQ(t[1].val(), csubstr(" folded\n")); - EXPECT_EQ(t[2].val(), csubstr("keep\n\n")); - EXPECT_EQ(t[3].val(), csubstr(" strip")); - EXPECT_EQ(t[4].val(), csubstr(" strip")); - }); -} - - -TEST(block_folded, test_suite_R4YG) -{ - csubstr yaml = R"( -- | - detected0 -- > - - - # detected1 -- |1 - explicit2 -- > - - detected3 -)"; - test_check_emit_check(yaml, [](Tree const &t){ - ASSERT_TRUE(t.rootref().is_seq()); - ASSERT_EQ(t.rootref().num_children(), 4u); - EXPECT_EQ(t[0].val(), csubstr("detected0\n")); - EXPECT_EQ(t[1].val(), csubstr("\n\n# detected1\n")); - EXPECT_EQ(t[2].val(), csubstr(" explicit2\n")); - EXPECT_EQ(t[3].val(), csubstr("\t\ndetected3\n")); - }); -} - - -TEST(block_folded, test_suite_T26H) -{ - csubstr yaml = R"( ---- | - - - literal - - - text - - # Comment -)"; - test_check_emit_check(yaml, [](Tree const &t){ - ASSERT_TRUE(t.rootref().is_stream()); - ASSERT_TRUE(t.rootref().first_child().is_doc()); - EXPECT_EQ(t.rootref().first_child().val(), csubstr("\n\nliteral\n \n\ntext\n")); - }); -} - - -TEST(block_folded, test_suite_T5N4) -{ - csubstr yaml = R"( ---- | - literal - text - - -)"; - test_check_emit_check(yaml, [](Tree const &t){ - ASSERT_TRUE(t.rootref().is_stream()); - ASSERT_TRUE(t.rootref().first_child().is_doc()); - EXPECT_EQ(t.rootref().first_child().val(), csubstr("literal\n\ttext\n")); - }); -} - - -TEST(block_folded, test_suite_W4TN) -{ - csubstr yaml = R"( ---- | - %!PS-Adobe-2.0 -... ---- > - %!PS-Adobe-2.0 -... ---- | -%!PS-Adobe-2.0 -... ---- > -%!PS-Adobe-2.0 -... ---- -# Empty -... ---- | - %!PS-Adobe-2.0 ---- > - %!PS-Adobe-2.0 ---- | -%!PS-Adobe-2.0 ---- > -%!PS-Adobe-2.0 ---- -# empty -)"; - test_check_emit_check(yaml, [](Tree const &t){ - ConstNodeRef r = t.rootref(); - ASSERT_TRUE(r.is_stream()); - ASSERT_EQ(r.num_children(), 10u); - ASSERT_TRUE(r.doc(0).is_doc()); - ASSERT_TRUE(r.doc(0).is_val()); - EXPECT_EQ(r.doc(0).val(), csubstr("%!PS-Adobe-2.0\n")); - ASSERT_TRUE(r.doc(1).is_doc()); - ASSERT_TRUE(r.doc(1).is_val()); - EXPECT_EQ(r.doc(1).val(), csubstr("%!PS-Adobe-2.0\n")); - ASSERT_TRUE(r.doc(2).is_doc()); - ASSERT_TRUE(r.doc(2).is_val()); - EXPECT_EQ(r.doc(2).val(), csubstr("%!PS-Adobe-2.0\n")); - ASSERT_TRUE(r.doc(3).is_doc()); - ASSERT_TRUE(r.doc(3).is_val()); - EXPECT_EQ(r.doc(3).val(), csubstr("%!PS-Adobe-2.0\n")); - ASSERT_TRUE(r.doc(4).is_doc()); - ASSERT_TRUE(r.doc(4).is_val()); - EXPECT_EQ(r.doc(4).val(), csubstr{}); - ASSERT_TRUE(r.doc(5).is_doc()); - ASSERT_TRUE(r.doc(5).is_val()); - EXPECT_EQ(r.doc(5).val(), csubstr("%!PS-Adobe-2.0\n")); - ASSERT_TRUE(r.doc(6).is_doc()); - ASSERT_TRUE(r.doc(6).is_val()); - EXPECT_EQ(r.doc(6).val(), csubstr("%!PS-Adobe-2.0\n")); - ASSERT_TRUE(r.doc(7).is_doc()); - ASSERT_TRUE(r.doc(7).is_val()); - EXPECT_EQ(r.doc(7).val(), csubstr("%!PS-Adobe-2.0\n")); - ASSERT_TRUE(r.doc(8).is_doc()); - ASSERT_TRUE(r.doc(8).is_val()); - EXPECT_EQ(r.doc(8).val(), csubstr("%!PS-Adobe-2.0\n")); - ASSERT_TRUE(r.doc(4).is_doc()); - ASSERT_TRUE(r.doc(4).is_val()); - EXPECT_EQ(r.doc(4).val(), csubstr{}); - }); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - - -CASE_GROUP(BLOCK_FOLDED) -{ -// -ADD_CASE_TO_GROUP("indentation requirements", -R"(--- -> -hello -there ---- -> - hello - there ---- -> - hello - there ---- -> -ciao -qua ---- -> - ciao - qua ---- -> - ciao - qua ---- -- > - hello - there -- > - ciao - qua ---- -foo: > - hello - there -bar: > - ciao - qua -)", -N(STREAM, L{ - N(DOCVAL|QV, "hello there\n"), - N(DOCVAL|QV, "hello there\n"), - N(DOCVAL|QV, "hello there\n"), - N(DOCVAL|QV, "ciao qua\n"), - N(DOCVAL|QV, "ciao qua\n"), - N(DOCVAL|QV, "ciao qua\n"), - N(SEQ|DOC, L{N(QV, "hello there\n"), N(QV, "ciao qua\n")}), - N(MAP|DOC, L{N(QV, "foo", "hello there\n"), N(QV, "bar", "ciao qua\n")}), - })); - -ADD_CASE_TO_GROUP("indentation requirements err seq", EXPECT_PARSE_ERROR, -R"(- > -hello -there -- > -ciao -qua -)", -N(L{N(QV, "hello there"), N(QV, "ciao qua\n")})); - -ADD_CASE_TO_GROUP("indentation requirements err map", EXPECT_PARSE_ERROR, -R"(foo: > -hello -there -bar: > -ciao -qua -)", -N(L{N(QV, "foo", "hello there\n"), N(QV, "bar" "ciao qua\n")})); - -ADD_CASE_TO_GROUP("indentation requirements err level", EXPECT_PARSE_ERROR, -R"(--- >2 - hello - there -)", -N(NOTYPE)); - -ADD_CASE_TO_GROUP("foo without space after", -R"(> - foo -)", -N(DOCVAL|QV, "foo\n")); - -ADD_CASE_TO_GROUP("foo with space after", -R"(> - foo - -)", -N(DOCVAL|QV, "foo\n")); - -ADD_CASE_TO_GROUP("simple with indents", -R"(> - foo - - bar -)", -N(DOCVAL|QV, "foo\n \n bar\n")); - - -ADD_CASE_TO_GROUP("7T8X", -R"(- > - - folded - line - - next - line - * bullet - - * list - * lines - - last - line - -# Comment - -##### this is the original scalar: -- > - - folded - line - - next - line - * bullet - - * list - * lines - - last - line - -# Comment - -##### without any indentation -- > - - folded - line - - next - line - * bullet - - * list - * lines - - last - line - -# Comment -)", - L{ - N(QV, "\nfolded line\nnext line\n * bullet\n\n * list\n * lines\n\nlast line\n"), - N(QV, "\nfolded line\nnext line\n * bullet\n\n * list\n * lines\n\nlast line\n"), - N(QV, "\nfolded line\nnext line\n * bullet\n\n * list\n * lines\n\nlast line\n"), - } -); - - -ADD_CASE_TO_GROUP("block folded as seq val, implicit indentation 2", -R"( -- > - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - - -- another val -)", - L{ - N(QV, "Several lines of text, with some \"quotes\" of various 'types', and also a blank line:\nplus another line at the end.\n"), - N("another val") - } -); - -ADD_CASE_TO_GROUP("block folded as map val, implicit indentation 2", -R"( -example: > - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - - -another: val -)", - L{ - N(QV, "example", "Several lines of text, with some \"quotes\" of various 'types', and also a blank line:\nplus another line at the end.\n"), - N("another", "val") - } -); - -ADD_CASE_TO_GROUP("block folded as map val, implicit indentation 2, chomp=keep", -R"( -example: >+ - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - - -another: val -)", - L{ - N(QV, "example", "Several lines of text, with some \"quotes\" of various 'types', and also a blank line:\nplus another line at the end.\n\n\n"), - N("another", "val") - } -); - -ADD_CASE_TO_GROUP("block folded as map val, implicit indentation 2, chomp=strip", -R"( -example: >- - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - - -another: val -)", - L{ - N(QV, "example", "Several lines of text, with some \"quotes\" of various 'types', and also a blank line:\nplus another line at the end."), - N("another", "val") - } -); - -ADD_CASE_TO_GROUP("block folded as map val, explicit indentation 2", -R"( -example: >2 - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - - -another: val -)", - L{ - N(QV, "example", "Several lines of text, with some \"quotes\" of various 'types', and also a blank line:\nplus another line at the end.\n"), - N("another", "val") - } -); - -ADD_CASE_TO_GROUP("block folded as map val, explicit indentation 2, chomp=keep", -R"( -example: >+2 - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - - -example2: >2+ - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - - -)", - L{ - N(QV, "example", "Several lines of text, with some \"quotes\" of various 'types', and also a blank line:\nplus another line at the end.\n\n\n"), - N(QV, "example2", "Several lines of text, with some \"quotes\" of various 'types', and also a blank line:\nplus another line at the end.\n\n\n"), - } -); - -ADD_CASE_TO_GROUP("block folded as map val, explicit indentation 2, chomp=strip", -R"( -example: >-2 - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - - -example2: >2- - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - - -)", - L{ - N(QV, "example", "Several lines of text, with some \"quotes\" of various 'types', and also a blank line:\nplus another line at the end."), - N(QV, "example2", "Several lines of text, with some \"quotes\" of various 'types', and also a blank line:\nplus another line at the end."), - } -); - -ADD_CASE_TO_GROUP("block folded as map val, implicit indentation 3", -R"( -example: > - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - - -another: val -)", - L{ - N(QV, "example", "Several lines of text, with some \"quotes\" of various 'types', and also a blank line:\nplus another line at the end.\n"), - N("another", "val") - } -); - -ADD_CASE_TO_GROUP("block folded as map val, explicit indentation 3", -R"( -example: >3 - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - - -another: val -)", - L{ - N(QV, "example", "Several lines of text, with some \"quotes\" of various 'types', and also a blank line:\nplus another line at the end.\n"), - N("another", "val") - } -); - -ADD_CASE_TO_GROUP("block folded as map val, implicit indentation 4", -R"( -example: > - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - - -another: val -)", - L{ - N(QV, "example", "Several lines of text, with some \"quotes\" of various 'types', and also a blank line:\nplus another line at the end.\n"), - N("another", "val") - } -); - -ADD_CASE_TO_GROUP("block folded as map val, explicit indentation 4", -R"( -example: >4 - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - - -another: val -)", - L{ - N(QV, "example", "Several lines of text, with some \"quotes\" of various 'types', and also a blank line:\nplus another line at the end.\n"), - N("another", "val") - } -); - -ADD_CASE_TO_GROUP("block folded as map val, implicit indentation 9", -R"( -example: > - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - - -another: val -)", - L{ - N(QV, "example", "Several lines of text, with some \"quotes\" of various 'types', and also a blank line:\nplus another line at the end.\n"), - N("another", "val") - } -); - -ADD_CASE_TO_GROUP("block folded as map val, explicit indentation 9", -R"( -example: >9 - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - - -another: val -)", - L{ - N(QV, "example", "Several lines of text, with some \"quotes\" of various 'types', and also a blank line:\nplus another line at the end.\n"), - N("another", "val") - } -); - - -ADD_CASE_TO_GROUP("block folded as map entry", -R"( -data: > - Wrapped text - will be folded - into a single - paragraph - - Blank lines denote - paragraph breaks -)", - N(L{N(KEYVAL|VALQUO, "data", "Wrapped text will be folded into a single paragraph\nBlank lines denote paragraph breaks\n")}) -); - -ADD_CASE_TO_GROUP("block folded, no chomp, no indentation", -R"(example: > - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - -another: text -)", - N(L{ - N(KEYVAL|VALQUO, "example", "Several lines of text, with some \"quotes\" of various 'types', and also a blank line:\nplus another line at the end.\n"), - N("another", "text"), - }) -); - -ADD_CASE_TO_GROUP("block folded with tab and spaces", -R"(> - )", - N(DOCVAL|VALQUO, "\t \n") - ); - - -ADD_CASE_TO_GROUP("block folded with empty docval 1", -R"(>)", - N(DOCVAL|VALQUO, "") - ); - -ADD_CASE_TO_GROUP("block folded with empty docval 2", -R"(> -)", - N(DOCVAL|VALQUO, "") - ); - -ADD_CASE_TO_GROUP("block folded with empty docval 3", -R"(> - )", - N(DOCVAL|VALQUO, "") - ); - -ADD_CASE_TO_GROUP("block folded with empty docval 4", -R"(> - -)", - N(DOCVAL|VALQUO, "") - ); - -ADD_CASE_TO_GROUP("block folded with empty docval 5", -R"(> - -)", - N(DOCVAL|VALQUO, "") - ); - -ADD_CASE_TO_GROUP("block folded with empty docval 8", -R"(> - -)", - N(DOCVAL|VALQUO, "") - ); - -ADD_CASE_TO_GROUP("block folded with empty docval 9", -R"(> - - - -)", - N(DOCVAL|VALQUO, "") - ); - -ADD_CASE_TO_GROUP("block folded with empty docval 10", -R"(> - - - - -)", - N(DOCVAL|VALQUO, "") - ); - -ADD_CASE_TO_GROUP("block folded with empty docval 11", -R"(> - - - - )", - N(DOCVAL|VALQUO, "") - ); - -ADD_CASE_TO_GROUP("block folded with empty docval 12", -R"(> - - - - - - - - - -)", - N(DOCVAL|VALQUO, "") - ); - -ADD_CASE_TO_GROUP("block folded with empty docval 13", -R"(> - - - - - - - -)", - N(DOCVAL|VALQUO, "") - ); - -ADD_CASE_TO_GROUP("block folded with docval no newlines at end 0", -R"(> - asd)", - N(DOCVAL|VALQUO, "asd\n") - ); - -ADD_CASE_TO_GROUP("block folded with docval no newlines at end 1", -R"(> - asd -)", - N(DOCVAL|VALQUO, "asd\n") - ); - -ADD_CASE_TO_GROUP("block folded with docval no newlines at end 2", -R"(> - asd - -)", - N(DOCVAL|VALQUO, "asd\n") - ); - -ADD_CASE_TO_GROUP("block folded with docval no newlines at end 3", -R"(> - asd - )", - N(DOCVAL|VALQUO, "asd\n") - ); - -ADD_CASE_TO_GROUP("block folded with docval no newlines at end 4", -R"(> - asd - - )", - N(DOCVAL|VALQUO, "asd\n") - ); - -ADD_CASE_TO_GROUP("block folded with docval no newlines at end 5", -R"(> - asd - - )", - N(DOCVAL|VALQUO, "asd\n") - ); - -ADD_CASE_TO_GROUP("block folded with docval no newlines at end 5.1", -R"(> - asd - - - - - - )", - N(DOCVAL|VALQUO, "asd\n") - ); - -ADD_CASE_TO_GROUP("block folded with docval no newlines at end 5.2", -R"(> - asd - - - - - - )", - N(DOCVAL|VALQUO, "asd\n") - ); - -ADD_CASE_TO_GROUP("block folded with docval no newlines at end 5.3", -R"(> - asd - - - - - - )", - N(DOCVAL|VALQUO, "asd\n\n\n \n") - ); - -ADD_CASE_TO_GROUP("block folded with docval no newlines at end 6", -R"(> - asd - )", - N(DOCVAL|VALQUO, "asd\n \n") - ); - -ADD_CASE_TO_GROUP("block folded with docval no newlines at end 7", -R"(> - asd - -)", - N(DOCVAL|VALQUO, "asd\n \n") - ); - -ADD_CASE_TO_GROUP("block folded with docval no newlines at end 8", -R"(> - asd - )", - N(DOCVAL|VALQUO, "asd\n \n") - ); - -ADD_CASE_TO_GROUP("block folded with docval no newlines at end 9", -R"(> - asd - -)", - N(DOCVAL|VALQUO, "asd\n \n") - ); - -ADD_CASE_TO_GROUP("block folded with docval no newlines at end 10", -R"(> - asd - )", - N(DOCVAL|VALQUO, "asd\n\t \n") - ); - -ADD_CASE_TO_GROUP("block folded with docval no newlines at end 11", -R"(> - asd - )", - N(DOCVAL|VALQUO, "asd\n \t \n") - ); - -ADD_CASE_TO_GROUP("block folded with docval no newlines at end 12", -R"(> - asd - -)", - N(DOCVAL|VALQUO, "asd\n\t \n") - ); - -ADD_CASE_TO_GROUP("block folded with docval no newlines at end 13", -R"(> - asd - -)", - N(DOCVAL|VALQUO, "asd\n \t \n") - ); - - -ADD_CASE_TO_GROUP("block folded, keep, empty docval trailing 0", -R"(>+)", - N(DOCVAL|VALQUO, "") - ); - -ADD_CASE_TO_GROUP("block folded, keep, empty docval trailing 1", -R"(>+ -)", - N(DOCVAL|VALQUO, "") - ); - -ADD_CASE_TO_GROUP("block folded, keep, empty docval trailing 1.1", -R"(>+ - )", - N(DOCVAL|VALQUO, "") - ); - -ADD_CASE_TO_GROUP("block folded, keep, empty docval trailing 1.2", -R"(>+ - asd)", - N(DOCVAL|VALQUO, "asd") - ); - -ADD_CASE_TO_GROUP("block folded, keep, empty docval trailing 1.3", -R"(>+ - asd -)", - N(DOCVAL|VALQUO, "asd\n") - ); - -ADD_CASE_TO_GROUP("block folded, keep, empty docval trailing 1.4", -R"(>+ - asd - -)", - N(DOCVAL|VALQUO, "asd\n\n") - ); - -ADD_CASE_TO_GROUP("block folded, keep, empty docval trailing 2", -R"(>+ - -)", - N(DOCVAL|VALQUO, "\n") - ); - -ADD_CASE_TO_GROUP("block folded, keep, empty docval trailing 2.1", -R"(>+ - - )", - N(DOCVAL|VALQUO, "\n") - ); - -ADD_CASE_TO_GROUP("block folded, keep, empty docval trailing 3", -R"(>+ - - -)", - N(DOCVAL|VALQUO, "\n\n") - ); - -ADD_CASE_TO_GROUP("block folded, keep, empty docval trailing 4", -R"(>+ - - - -)", - N(DOCVAL|VALQUO, "\n\n\n") - ); - -ADD_CASE_TO_GROUP("block folded, keep, empty docval trailing 5", -R"(>+ - - - - -)", - N(DOCVAL|VALQUO, "\n\n\n\n") - ); - -ADD_CASE_TO_GROUP("block folded, empty block vals in seq 0", -R"(- >+ - -- >+ - )", -N(L{N(QV, "\n"), N(QV, ""),})); - -ADD_CASE_TO_GROUP("block folded, empty block vals in seq 1", -R"(- >+ - -- >+ - -)", -N(L{N(QV, "\n"), N(QV, "\n"),})); - -} - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_block_literal.cpp b/thirdparty/ryml/test/test_block_literal.cpp deleted file mode 100644 index fe8e352be..000000000 --- a/thirdparty/ryml/test/test_block_literal.cpp +++ /dev/null @@ -1,1261 +0,0 @@ -#include "./test_group.hpp" - -namespace c4 { -namespace yml { - -TEST(block_literal, empty_block) -{ - { - Tree t = parse_in_arena(R"(- | -)"); - EXPECT_EQ(t[0].val(), csubstr("")); - } - { - Tree t = parse_in_arena(R"(- |- -)"); - EXPECT_EQ(t[0].val(), csubstr("")); - } - { - Tree t = parse_in_arena(R"(- |+ -)"); - EXPECT_EQ(t[0].val(), csubstr("")); - } - { - Tree t = parse_in_arena(R"(# no indentation: fails! -- | - -- |- - -- |+ - -)"); - EXPECT_FALSE(t.empty()); - EXPECT_EQ(t[0].val(), csubstr("")); - EXPECT_EQ(t[1].val(), csubstr("")); - EXPECT_EQ(t[2].val(), csubstr("\n")); - } - { - Tree t = parse_in_arena(R"( -- | - -- |- - -- |+ - -)"); - EXPECT_FALSE(t.empty()); - EXPECT_EQ(t[0].val(), csubstr("")); - EXPECT_EQ(t[1].val(), csubstr("")); - EXPECT_EQ(t[2].val(), csubstr("\n")); - } - { - Tree t = parse_in_arena(R"( -- | -- |- -- |+ -)"); - EXPECT_FALSE(t.empty()); - EXPECT_EQ(t[0].val(), csubstr("")); - EXPECT_EQ(t[1].val(), csubstr("")); - EXPECT_EQ(t[2].val(), csubstr("")); - } -} - - -TEST(block_literal, empty_block_as_container_member) -{ - // this was ok - test_check_emit_check(R"( -map: - a: "" - b: '' - c: > - d: | - e: -)", [](Tree const &t){ - EXPECT_TRUE(t["map"].has_key()); - EXPECT_TRUE(t["map"].is_map()); - EXPECT_EQ(t["map"].num_children(), 5u); - for(const auto &child : t["map"].children()) - { - EXPECT_EQ(child.val(), ""); - if(child.key() != "e") - { - EXPECT_TRUE(child.type().is_val_quoted()); - EXPECT_FALSE(child.val_is_null()); - } - } - }); - // this was ok - test_check_emit_check(R"( -map: - a: "" - b: '' - c: > - d: | -)", [](Tree const &t){ - EXPECT_TRUE(t["map"].has_key()); - EXPECT_TRUE(t["map"].is_map()); - EXPECT_TRUE(t["map"].is_map()); - EXPECT_EQ(t["map"].num_children(), 4u); - for(const auto &child : t["map"].children()) - { - EXPECT_EQ(child.val(), ""); - EXPECT_TRUE(child.type().is_val_quoted()); - EXPECT_FALSE(child.val_is_null()); - } - }); - // this was not ok! the block literal before next is extended: to - // include the YAML for next! - test_check_emit_check(R"( -map: - a: "" - b: '' - c: > - d: | -next: - a: "" - b: '' - c: > - d: | -)", [](Tree const &t){ - for(const char *name : {"map", "next"}) - { - ASSERT_TRUE(t.rootref().has_child(to_csubstr(name))) << "name=" << name; - ConstNodeRef node = t[to_csubstr(name)]; - EXPECT_TRUE(node.has_key()); - EXPECT_TRUE(node.is_map()); - ASSERT_EQ(node.num_children(), 4u); - for(const auto &child : node.children()) - { - EXPECT_EQ(child.val(), ""); - EXPECT_TRUE(child.type().is_val_quoted()); - EXPECT_FALSE(child.val_is_null()); - } - } - }); - test_check_emit_check(R"( -seq: - - "" - - '' - - > - - | -next: - - "" - - '' - - > - - | -)", [](Tree const &t){ - for(const char *name : {"seq", "next"}) - { - ASSERT_TRUE(t.rootref().has_child(to_csubstr(name))) << "name=" << name; - ConstNodeRef node = t[to_csubstr(name)]; - EXPECT_TRUE(node.has_key()); - EXPECT_TRUE(node.is_seq()); - ASSERT_EQ(node.num_children(), 4u); - for(const auto &child : node.children()) - { - EXPECT_EQ(child.val(), ""); - EXPECT_TRUE(child.type().is_val_quoted()); - EXPECT_FALSE(child.val_is_null()); - } - } - }); -} - - -TEST(block_literal, emit_does_not_add_lines_to_multi_at_end_1) -{ - Tree t = parse_in_arena("[]"); - NodeRef r = t.rootref(); - r.append_child() = "\n\n"; - r.append_child() = "\n\n"; - r.append_child() = "last"; - std::string out = emitrs_yaml(t); - t.clear(); - t = parse_in_arena(to_csubstr(out)); - EXPECT_EQ(t[0].val(), csubstr("\n\n")); - EXPECT_EQ(t[1].val(), csubstr("\n\n")); - EXPECT_EQ(t[2].val(), csubstr("last")); - out = emitrs_yaml(t); - t.clear(); - t = parse_in_arena(to_csubstr(out)); - EXPECT_EQ(t[0].val(), csubstr("\n\n")); - EXPECT_EQ(t[1].val(), csubstr("\n\n")); - EXPECT_EQ(t[2].val(), csubstr("last")); - out = emitrs_yaml(t); - t.clear(); - t = parse_in_arena(to_csubstr(out)); - EXPECT_EQ(t[0].val(), csubstr("\n\n")); - EXPECT_EQ(t[1].val(), csubstr("\n\n")); - EXPECT_EQ(t[2].val(), csubstr("last")); - EXPECT_EQ(csubstr("ab\n\n \n").trimr(" \t\n"), csubstr("ab")); -} - -TEST(block_literal, emit_does_not_add_lines_to_multi_at_end_2) -{ - Tree t = parse_in_arena(R"(--- |+ - ab - - -)"); - EXPECT_EQ(t.docref(0).val(), csubstr("ab\n\n \n")); - std::string expected = R"(--- | - ab - - - -)"; - std::string out = emitrs_yaml(t); - EXPECT_EQ(out, expected); - t = parse_in_arena(to_csubstr(out)); - EXPECT_EQ(t.docref(0).val(), csubstr("ab\n\n \n")); - out = emitrs_yaml(t); - EXPECT_EQ(out, expected); - t = parse_in_arena(to_csubstr(out)); - EXPECT_EQ(t.docref(0).val(), csubstr("ab\n\n \n")); - out = emitrs_yaml(t); - EXPECT_EQ(out, expected); - t = parse_in_arena(to_csubstr(out)); - EXPECT_EQ(t.docref(0).val(), csubstr("ab\n\n \n")); -} - -TEST(block_literal, emit_does_not_add_lines_to_multi_at_end_3) -{ - std::string yaml = R"( -- | - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - - - -- |+ - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - -- last -)"; - std::string expected = R"(- | - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - -- |+ - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - -- last -)"; - Tree t = parse_in_arena(to_csubstr(yaml)); - EXPECT_EQ(t[0].val(), "Several lines of text,\nwith some \"quotes\" of various 'types',\nand also a blank line:\n\nplus another line at the end.\n"); - EXPECT_EQ(t[1].val(), "Several lines of text,\nwith some \"quotes\" of various 'types',\nand also a blank line:\n\nplus another line at the end.\n\n"); - std::string out = emitrs_yaml(t); - EXPECT_EQ(out, expected); - t = parse_in_arena(to_csubstr(out)); - EXPECT_EQ(t[0].val(), "Several lines of text,\nwith some \"quotes\" of various 'types',\nand also a blank line:\n\nplus another line at the end.\n"); - EXPECT_EQ(t[1].val(), "Several lines of text,\nwith some \"quotes\" of various 'types',\nand also a blank line:\n\nplus another line at the end.\n\n"); - out = emitrs_yaml(t); - EXPECT_EQ(out, expected); -} - -TEST(block_literal, carriage_return) -{ - std::string yaml = "with: |\r\n" -" text\r\n" -" lines\r\n" -"without: |\n" -" text\n" -" lines\n"; - Tree t = parse_in_arena(to_csubstr(yaml)); - EXPECT_EQ(t["with"].val(), "text\n \tlines\n"); - EXPECT_EQ(t["without"].val(), "text\n \tlines\n"); - auto emitted = emitrs_yaml(t); - #ifdef RYML_DBG - __c4presc(emitted.data(), emitted.size()); - #endif - Tree r = parse_in_arena(to_csubstr(emitted)); - EXPECT_EQ(t["with"].val(), "text\n \tlines\n"); - EXPECT_EQ(t["without"].val(), "text\n \tlines\n"); -} - -#ifdef JAVAI -TEST(block_literal, errors_on_tab_indents) -{ - Tree tree; - ExpectError::do_check(&tree, [&]{ - parse_in_arena("foo: |4\n this is foo\n now with tab-\n \t \tmust not work\n", &tree); - }); -} -#endif - -TEST(block_literal, test_suite_L24T_00) -{ - // this is double quoted, but will be emitted as a block literal - csubstr yaml = R"(foo: "x\n \n" -)"; - test_check_emit_check(yaml, [](Tree const &t){ - EXPECT_EQ(t["foo"].val(), csubstr("x\n \n")); - }); -} - -TEST(block_literal, error_on_bad_spec) -{ - Tree t; - ExpectError::do_check(&t, [&t]{ - t = parse_in_arena("- |012abc\n must have errors above\n"); - }); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - - -CASE_GROUP(BLOCK_LITERAL) -{ -// -ADD_CASE_TO_GROUP("indentation requirements", -R"(--- -| -hello -there ---- -| - hello - there ---- -| - hello - there ---- -| -ciao -qua ---- -| - ciao - qua ---- -| - ciao - qua ---- -- | - hello - there -- | - ciao - qua ---- -foo: | - hello - there -bar: | - ciao - qua -)", -N(STREAM, L{ - N(DOCVAL|QV, "hello\nthere\n"), - N(DOCVAL|QV, "hello\nthere\n"), - N(DOCVAL|QV, "hello\nthere\n"), - N(DOCVAL|QV, "ciao\nqua\n"), - N(DOCVAL|QV, "ciao\nqua\n"), - N(DOCVAL|QV, "ciao\nqua\n"), - N(SEQ|DOC, L{N(QV, "hello\nthere\n"), N(QV, "ciao\nqua\n")}), - N(MAP|DOC, L{N(QV, "foo", "hello\nthere\n"), N(QV, "bar", "ciao\nqua\n")}), - })); - -ADD_CASE_TO_GROUP("indentation requirements err seq", EXPECT_PARSE_ERROR, -R"(- | -hello -there -- | -ciao -qua -)", -N(L{N(QV, "hello\nthere\n"), N(QV, "ciao\nqua\n")})); - -ADD_CASE_TO_GROUP("indentation requirements err map", EXPECT_PARSE_ERROR, -R"(foo: | -hello -there -bar: | -ciao -qua -)", -N(L{N(QV, "foo", "hello\nthere\n"), N(QV, "bar" "ciao\nqua\n")})); - -ADD_CASE_TO_GROUP("indentation requirements err level", EXPECT_PARSE_ERROR, -R"(--- |2 - hello - there -)", -N(NOTYPE)); - -ADD_CASE_TO_GROUP("empty, specs only 2G84_02", -"--- |1-", -N(STREAM, L{N(DOCVAL|VALQUO, {})})); - -ADD_CASE_TO_GROUP("empty, specs only 2G84_03", -"--- |1+", -N(STREAM, L{N(DOCVAL|VALQUO, {})})); - -ADD_CASE_TO_GROUP("empty, specs only 2G84_xx", -"--- |+", -N(STREAM, L{N(DOCVAL|VALQUO, {})})); - -ADD_CASE_TO_GROUP("empty, specs only 2G84_02_1", -"|1-", -N(DOCVAL|VALQUO, {})); - -ADD_CASE_TO_GROUP("empty, specs only 2G84_03_1", -"|1+", -N(DOCVAL|VALQUO, {})); - -ADD_CASE_TO_GROUP("empty, specs only 2G84_xx_1", -"|+", -N(DOCVAL|VALQUO, {})); - -ADD_CASE_TO_GROUP("block literal as map entry", -R"( -data: | - There once was a short man from Ealing - Who got on a bus to Darjeeling - It said on the door - "Please don't spit on the floor" - So he carefully spat on the ceiling -)", - N(MAP, { - N(KEYVAL|VALQUO, "data", "There once was a short man from Ealing\nWho got on a bus to Darjeeling\n It said on the door\n \"Please don't spit on the floor\"\nSo he carefully spat on the ceiling\n") - }) -); - -ADD_CASE_TO_GROUP("block literal and two scalars", -R"( -example: > - HTML goes into YAML without modification -message: | -
      -

      "Three is always greater than two, - even for large values of two"

      -

      --Author Unknown

      -
      -date: 2007-06-01 -)", - N(MAP, L{ - N(KEYVAL|VALQUO, "example", "HTML goes into YAML without modification\n"), - N(KEYVAL|VALQUO, "message", R"(
      -

      "Three is always greater than two, - even for large values of two"

      -

      --Author Unknown

      -
      -)"), - N("date", "2007-06-01"), - }) -); - -ADD_CASE_TO_GROUP("block literal no chomp, no indentation", -R"(example: | - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - -another: text -)", - N(MAP, L{ - N(KEYVAL|VALQUO, "example", "Several lines of text,\nwith some \"quotes\" of various 'types',\nand also a blank line:\n\nplus another line at the end.\n"), - N("another", "text"), - }) -); - -ADD_CASE_TO_GROUP("block literal as seq val, implicit indentation 2", -R"( -- | - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - - -- another val -)", - L{ - N(QV, "Several lines of text,\nwith some \"quotes\" of various 'types',\nand also a blank line:\n\nplus another line at the end.\n"), - N("another val") - } -); - -ADD_CASE_TO_GROUP("block literal as seq val, implicit indentation 2, chomp=keep", -R"( -- |+ - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - - -- another val -)", - L{ - N(QV, "Several lines of text,\nwith some \"quotes\" of various 'types',\nand also a blank line:\n\nplus another line at the end.\n\n\n"), - N("another val") - } -); - -ADD_CASE_TO_GROUP("block literal as seq val, implicit indentation 2, chomp=strip", -R"( -- |- - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - - -- another val -)", - L{ - N(QV, "Several lines of text,\nwith some \"quotes\" of various 'types',\nand also a blank line:\n\nplus another line at the end."), - N("another val") - } -); - -ADD_CASE_TO_GROUP("block literal as seq val at eof, implicit indentation 2", -R"( -- | - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - - -)", - L{ - N(QV, "Several lines of text,\nwith some \"quotes\" of various 'types',\nand also a blank line:\n\nplus another line at the end.\n"), - } -); - -ADD_CASE_TO_GROUP("block literal as seq val at eof, implicit indentation 4", -R"( -- | - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - - -)", - L{ - N(QV, "Several lines of text,\nwith some \"quotes\" of various 'types',\nand also a blank line:\n\nplus another line at the end.\n"), - } -); - -ADD_CASE_TO_GROUP("block literal as map val, implicit indentation 2", -R"( -example: | - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - - -another: val -)", - L{ - N(QV, "example", "Several lines of text,\nwith some \"quotes\" of various 'types',\nand also a blank line:\n\nplus another line at the end.\n"), - N("another", "val") - } -); - -ADD_CASE_TO_GROUP("block literal as map val, explicit indentation 2", -R"( -example: |2 - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - - -another: val -)", - L{ - N(QV, "example", "Several lines of text,\nwith some \"quotes\" of various 'types',\nand also a blank line:\n\nplus another line at the end.\n"), - N("another", "val") - } -); - -ADD_CASE_TO_GROUP("block literal as map val, explicit indentation 2, chomp=keep", -R"( -example: |+2 - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - - -another: val -)", - L{ - N(QV, "example", "Several lines of text,\nwith some \"quotes\" of various 'types',\nand also a blank line:\n\nplus another line at the end.\n\n\n"), - N("another", "val") - } -); - -ADD_CASE_TO_GROUP("block literal as map val, explicit indentation 2, chomp=strip", -R"( -example: |-2 - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - - -another: val -)", - L{ - N(QV, "example", "Several lines of text,\nwith some \"quotes\" of various 'types',\nand also a blank line:\n\nplus another line at the end."), - N("another", "val") - } -); - -ADD_CASE_TO_GROUP("block literal as map val, implicit indentation 3", -R"( -example: | - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - - -another: val -)", - L{ - N(QV, "example", "Several lines of text,\nwith some \"quotes\" of various 'types',\nand also a blank line:\n\nplus another line at the end.\n"), - N("another", "val") - } -); - -ADD_CASE_TO_GROUP("block literal as map val, explicit indentation 3", -R"( -example: |3 - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - - -another: val -)", - L{ - N(QV, "example", "Several lines of text,\nwith some \"quotes\" of various 'types',\nand also a blank line:\n\nplus another line at the end.\n"), - N("another", "val") - } -); - -ADD_CASE_TO_GROUP("block literal as map val, implicit indentation 4", -R"( -example: | - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - - -another: val -)", - L{ - N(QV, "example", "Several lines of text,\nwith some \"quotes\" of various 'types',\nand also a blank line:\n\nplus another line at the end.\n"), - N("another", "val") - } -); - -ADD_CASE_TO_GROUP("block literal as map val, explicit indentation 4", -R"( -example: |4 - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - - -another: val -)", - L{ - N(QV, "example", "Several lines of text,\nwith some \"quotes\" of various 'types',\nand also a blank line:\n\nplus another line at the end.\n"), - N("another", "val") - } -); - -ADD_CASE_TO_GROUP("block literal as map val at eof, implicit indentation 2", -R"( -example: | - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - - -)", - L{ - N(QV, "example", "Several lines of text,\nwith some \"quotes\" of various 'types',\nand also a blank line:\n\nplus another line at the end.\n"), - } -); - -ADD_CASE_TO_GROUP("block literal as map val at eof, implicit indentation 4", -R"( -example: | - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - - -)", - L{ - N(QV, "example", "Several lines of text,\nwith some \"quotes\" of various 'types',\nand also a blank line:\n\nplus another line at the end.\n"), - } -); - -ADD_CASE_TO_GROUP("block literal as map val, implicit indentation 9", -R"( -example: | - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - - -another: val -)", - L{ - N(QV, "example", "Several lines of text,\nwith some \"quotes\" of various 'types',\nand also a blank line:\n\nplus another line at the end.\n"), - N("another", "val") - } -); - -ADD_CASE_TO_GROUP("block literal as map val, explicit indentation 9", -R"( -example: |9 - Several lines of text, - with some "quotes" of various 'types', - and also a blank line: - - plus another line at the end. - - -another: val -)", - L{ - N(QV, "example", "Several lines of text,\nwith some \"quotes\" of various 'types',\nand also a blank line:\n\nplus another line at the end.\n"), - N("another", "val") - } -); - -ADD_CASE_TO_GROUP("block literal with empty unindented lines, without quotes", - R"(tpl: - src: | - #include <{{hdr.filename}}> - - {{src.gencode}} -)", - L{ - N("tpl", L{N(QV, "src", "#include <{{hdr.filename}}>\n\n{{src.gencode}}\n")}) - } -); - -ADD_CASE_TO_GROUP("block literal with empty unindented lines, with double quotes", - R"(tpl: - src: | - #include "{{hdr.filename}}" - - {{src.gencode}} -)", - L{ - N("tpl", L{N(QV, "src", "#include \"{{hdr.filename}}\"\n\n{{src.gencode}}\n")}) - } -); - -ADD_CASE_TO_GROUP("block literal with empty unindented lines, with single quotes", - R"(tpl: - src: | - #include '{{hdr.filename}}' - - {{src.gencode}} -)", - L{ - N("tpl", L{N(QV, "src", "#include '{{hdr.filename}}'\n\n{{src.gencode}}\n")}) - } -); - -ADD_CASE_TO_GROUP("block literal with same indentation level 0", -R"( -aaa: |2 - xxx -bbb: | - yyy -)", - L{N(QV, "aaa", "xxx\n"), N(QV, "bbb", "yyy\n")} - ); - -ADD_CASE_TO_GROUP("block literal with same indentation level 1", -R"( -- aaa: |2 - xxx - bbb: | - yyy -)", - L{N(L{N(QV, "aaa", "xxx\n"), N(QV, "bbb", "yyy\n")})} - ); - -ADD_CASE_TO_GROUP("block literal with tab and spaces", -R"(| - )", - N(DOCVAL|VALQUO, "\t \n") - ); - - -ADD_CASE_TO_GROUP("block literal with empty docval 1", -R"(|)", - N(DOCVAL|VALQUO, "") - ); - -ADD_CASE_TO_GROUP("block literal with empty docval 2", -R"(| -)", - N(DOCVAL|VALQUO, "") - ); - -ADD_CASE_TO_GROUP("block literal with empty docval 3", -R"(| - )", - N(DOCVAL|VALQUO, "") - ); - -ADD_CASE_TO_GROUP("block literal with empty docval 4", -R"(| - -)", - N(DOCVAL|VALQUO, "") - ); - -ADD_CASE_TO_GROUP("block literal with empty docval 5", -R"(| - -)", - N(DOCVAL|VALQUO, "") - ); - -ADD_CASE_TO_GROUP("block literal with empty docval 8", -R"(| - - -)", - N(DOCVAL|VALQUO, "") - ); - -ADD_CASE_TO_GROUP("block literal with empty docval 9", -R"(| - - - -)", - N(DOCVAL|VALQUO, "") - ); - -ADD_CASE_TO_GROUP("block literal with empty docval 10", -R"(| - - - - -)", - N(DOCVAL|VALQUO, "") - ); - -ADD_CASE_TO_GROUP("block literal with empty docval 11", -R"(| - - - - )", - N(DOCVAL|VALQUO, "") - ); - -ADD_CASE_TO_GROUP("block literal with empty docval 12", -R"(| - - - - - - - - - -)", - N(DOCVAL|VALQUO, "") - ); - -ADD_CASE_TO_GROUP("block literal with empty docval 13", -R"(| - - - - - - - -)", - N(DOCVAL|VALQUO, "") - ); - -ADD_CASE_TO_GROUP("block literal with empty docval 14.0", -R"(- |+ -)", - N(SEQ, L{N(VALQUO, "")}) - ); - -ADD_CASE_TO_GROUP("block literal with empty docval 14.0.1", -R"(- |+ - )", - N(SEQ, L{N(VALQUO, "\n")}) - ); - -ADD_CASE_TO_GROUP("block literal with empty docval 14.0.2", -R"(- |+ - )", - N(SEQ, L{N(VALQUO, "\n")}) - ); - -ADD_CASE_TO_GROUP("block literal with empty docval 14.1", -R"(foo: |+ -)", - N(MAP, L{N(VALQUO, "foo", "")}) - ); - -ADD_CASE_TO_GROUP("block literal with empty docval 14.1.1", -R"(foo: |+ - )", - N(MAP, L{N(VALQUO, "foo", "\n")}) - ); - -ADD_CASE_TO_GROUP("block literal with empty docval 14.1.2", -R"(foo: |+ - )", - N(MAP, L{N(VALQUO, "foo", "\n")}) - ); - -ADD_CASE_TO_GROUP("block literal with empty docval 14.2", -R"(|+ -)", - N(DOCVAL|VALQUO, "") - ); - -ADD_CASE_TO_GROUP("block literal with empty docval 14.2.1", -R"(|+ - )", - N(DOCVAL|VALQUO, "\n") - ); - -ADD_CASE_TO_GROUP("block literal with empty docval 14.2.2", -R"(|+ - )", - N(DOCVAL|VALQUO, "\n") - ); - -ADD_CASE_TO_GROUP("block literal with empty docval 15.0", -R"(- |+ - -)", - N(SEQ, L{N(VALQUO, "\n")}) - ); - -ADD_CASE_TO_GROUP("block literal with empty docval 15.0.1", -R"(- |+ - - )", - N(SEQ, L{N(VALQUO, "\n")}) - ); - -ADD_CASE_TO_GROUP("block literal with empty docval 15.1", -R"(foo: |+ - -)", - N(MAP, L{N(VALQUO, "foo", "\n")}) - ); - -ADD_CASE_TO_GROUP("block literal with empty docval 15.1.1", -R"(foo: |+ - - )", - N(MAP, L{N(VALQUO, "foo", "\n")}) - ); - -ADD_CASE_TO_GROUP("block literal with empty docval 15.2", -R"(|+ - -)", - N(DOCVAL|VALQUO, "\n") - ); - -ADD_CASE_TO_GROUP("block literal with empty docval 15.2.1", -R"(|+ - - )", - N(DOCVAL|VALQUO, "\n") - ); - -ADD_CASE_TO_GROUP("block literal with empty docval 16", -R"(|+ - - -)", - N(DOCVAL|VALQUO, "\n\n") - ); - -ADD_CASE_TO_GROUP("block literal with empty docval 16.1", -R"(foo: |+ - - -)", - N(MAP, L{N(VALQUO, "foo", "\n\n")}) - ); - -ADD_CASE_TO_GROUP("block literal with empty docval 16.2", -R"(- |+ - - -)", - N(SEQ, L{N(VALQUO, "\n\n")}) - ); - -ADD_CASE_TO_GROUP("block literal with empty docval 17", -R"(|+ - - - -)", - N(DOCVAL|VALQUO, "\n\n\n") - ); - -ADD_CASE_TO_GROUP("block literal with empty docval 17.1", -R"(foo: |+ - - - -)", - N(MAP, L{N(VALQUO, "foo", "\n\n\n")}) - ); - -ADD_CASE_TO_GROUP("block literal with empty docval 17.2", -R"(- |+ - - - -)", - N(SEQ, L{N(VALQUO, "\n\n\n")}) - ); - -ADD_CASE_TO_GROUP("block literal with docval no newlines at end 0", -R"(| - asd)", - N(DOCVAL|VALQUO, "asd\n") - ); - -ADD_CASE_TO_GROUP("block literal with docval no newlines at end 1", -R"(| - asd -)", - N(DOCVAL|VALQUO, "asd\n") - ); - -ADD_CASE_TO_GROUP("block literal with docval no newlines at end 1.1", -R"(| - asd - )", - N(DOCVAL|VALQUO, "asd\n") - ); - -ADD_CASE_TO_GROUP("block literal with docval no newlines at end 1.2", -R"(|+ - asd - )", - N(DOCVAL|VALQUO, "asd\n") - ); - -ADD_CASE_TO_GROUP("block literal with docval no newlines at end 2", -R"(| - asd - -)", - N(DOCVAL|VALQUO, "asd\n") - ); - -ADD_CASE_TO_GROUP("block literal with docval no newlines at end 3", -R"(| - asd - )", - N(DOCVAL|VALQUO, "asd\n") - ); - -ADD_CASE_TO_GROUP("block literal with docval no newlines at end 4", -R"(| - asd - - )", - N(DOCVAL|VALQUO, "asd\n") - ); - -ADD_CASE_TO_GROUP("block literal with docval no newlines at end 5", -R"(| - asd - - )", - N(DOCVAL|VALQUO, "asd\n") - ); - -ADD_CASE_TO_GROUP("block literal with docval no newlines at end 5.1", -R"(| - asd - - - - - - )", - N(DOCVAL|VALQUO, "asd\n") - ); - -ADD_CASE_TO_GROUP("block literal with docval no newlines at end 5.2", -R"(| - asd - - - - - - )", - N(DOCVAL|VALQUO, "asd\n") - ); - -ADD_CASE_TO_GROUP("block literal with docval no newlines at end 5.3", -R"(| - asd - - - - - - )", - N(DOCVAL|VALQUO, "asd\n\n\n \n") - ); - -ADD_CASE_TO_GROUP("block literal with docval no newlines at end 6", -R"(| - asd - )", - N(DOCVAL|VALQUO, "asd\n \n") - ); - -ADD_CASE_TO_GROUP("block literal with docval no newlines at end 7", -R"(| - asd - -)", - N(DOCVAL|VALQUO, "asd\n \n") - ); - -ADD_CASE_TO_GROUP("block literal with docval no newlines at end 8", -R"(| - asd - )", - N(DOCVAL|VALQUO, "asd\n \n") - ); - -ADD_CASE_TO_GROUP("block literal with docval no newlines at end 9", -R"(| - asd - -)", - N(DOCVAL|VALQUO, "asd\n \n") - ); - -ADD_CASE_TO_GROUP("block literal with docval no newlines at end 10", -R"(| - asd - )", - N(DOCVAL|VALQUO, "asd\n\t \n") - ); - -ADD_CASE_TO_GROUP("block literal with docval no newlines at end 11", -R"(| - asd - )", - N(DOCVAL|VALQUO, "asd\n \t \n") - ); - -ADD_CASE_TO_GROUP("block literal with docval no newlines at end 12", -R"(| - asd - -)", - N(DOCVAL|VALQUO, "asd\n\t \n") - ); - -ADD_CASE_TO_GROUP("block literal with docval no newlines at end 13", -R"(| - asd - -)", - N(DOCVAL|VALQUO, "asd\n \t \n") - ); - -ADD_CASE_TO_GROUP("block literal, empty block vals in seq 0", -R"(- |+ - -- |+ - )", -N(L{N(QV, "\n"), N(QV, "\n"),})); - -ADD_CASE_TO_GROUP("block literal, empty block vals in seq 1", -R"(- |+ - -- |+ - -)", -N(L{N(QV, "\n"), N(QV, "\n"),})); - -} - - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_callbacks.cpp b/thirdparty/ryml/test/test_callbacks.cpp deleted file mode 100644 index 6f4bbf0ed..000000000 --- a/thirdparty/ryml/test/test_callbacks.cpp +++ /dev/null @@ -1,356 +0,0 @@ -#include "./test_case.hpp" -#ifndef RYML_SINGLE_HEADER -#include "c4/yml/common.hpp" -#endif -#include - - -namespace c4 { -namespace yml { - -static_assert(std::is_same::type, size_t>::value, "invalid type"); -static_assert(std::is_same::type, size_t>::value, "invalid type"); -static_assert(size_t(c4::yml::npos) == ((size_t)-1), "invalid value"); // some debuggers show the wrong value... -static_assert(size_t(c4::yml::NONE) == ((size_t)-1), "invalid value"); // some debuggers show the wrong value... - -std::string stored_msg; -Location stored_location; -void * stored_mem; -size_t stored_length; - -void test_error_impl(const char* msg, size_t length, Location loc, void * /*user_data*/) -{ - stored_msg = std::string(msg, length); - stored_location = loc; -} - -void* test_allocate_impl(size_t length, void * /*hint*/, void * /*user_data*/) -{ - void *mem = ::malloc(length); - stored_length = length; - stored_mem = mem; - if(mem == nullptr) - { - const char msg[] = "could not allocate memory"; - test_error_impl(msg, sizeof(msg)-1, {}, nullptr); - } - return mem; -} - -void test_free_impl(void *mem, size_t length, void * /*user_data*/) -{ - stored_mem = mem; - stored_length = length; - ::free(mem); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - - -TEST(Callbacks, ctor) -{ - { - Callbacks cb; - EXPECT_NE(cb.m_allocate, &test_allocate_impl); - EXPECT_NE(cb.m_free, &test_free_impl); - EXPECT_NE(cb.m_error, &test_error_impl); - #ifndef RYML_NO_DEFAULT_CALLBACKS - EXPECT_EQ(cb.m_user_data, nullptr); - EXPECT_NE(cb.m_allocate, nullptr); - EXPECT_NE(cb.m_free, nullptr); - EXPECT_NE(cb.m_error, nullptr); - #else - EXPECT_EQ(cb.m_user_data, nullptr); - EXPECT_EQ(cb.m_allocate, nullptr); - EXPECT_EQ(cb.m_free, nullptr); - EXPECT_EQ(cb.m_error, nullptr); - #endif - } - { - Callbacks cb((void*)0xff, nullptr, nullptr, nullptr); - EXPECT_NE(cb.m_allocate, &test_allocate_impl); - EXPECT_NE(cb.m_free, &test_free_impl); - EXPECT_NE(cb.m_error, &test_error_impl); - #ifndef RYML_NO_DEFAULT_CALLBACKS - EXPECT_EQ(cb.m_user_data, (void*)0xff); - EXPECT_NE(cb.m_allocate, nullptr); - EXPECT_NE(cb.m_free, nullptr); - EXPECT_NE(cb.m_error, nullptr); - #else - EXPECT_EQ(cb.m_user_data, (void*)0xff); - EXPECT_EQ(cb.m_allocate, nullptr); - EXPECT_EQ(cb.m_free, nullptr); - EXPECT_EQ(cb.m_error, nullptr); - #endif - } - { - Callbacks cb((void*)0xff, &test_allocate_impl, nullptr, nullptr); - #ifndef RYML_NO_DEFAULT_CALLBACKS - EXPECT_EQ(cb.m_user_data, (void*)0xff); - EXPECT_EQ(cb.m_allocate, &test_allocate_impl); - EXPECT_NE(cb.m_free, nullptr); - EXPECT_NE(cb.m_error, nullptr); - #else - EXPECT_EQ(cb.m_user_data, (void*)0xff); - EXPECT_EQ(cb.m_allocate, nullptr); - EXPECT_EQ(cb.m_free, nullptr); - EXPECT_EQ(cb.m_error, nullptr); - #endif - } - { - Callbacks cb((void*)0xff, nullptr, &test_free_impl, nullptr); - #ifndef RYML_NO_DEFAULT_CALLBACKS - EXPECT_EQ(cb.m_user_data, (void*)0xff); - EXPECT_NE(cb.m_allocate, nullptr); - EXPECT_EQ(cb.m_free, &test_free_impl); - EXPECT_NE(cb.m_error, nullptr); - #else - EXPECT_EQ(cb.m_user_data, (void*)0xff); - EXPECT_EQ(cb.m_allocate, nullptr); - EXPECT_EQ(cb.m_free, &test_free_impl); - EXPECT_EQ(cb.m_error, nullptr); - #endif - } - { - Callbacks cb((void*)0xff, nullptr, nullptr, &test_error_impl); - #ifndef RYML_NO_DEFAULT_CALLBACKS - EXPECT_EQ(cb.m_user_data, (void*)0xff); - EXPECT_NE(cb.m_allocate, nullptr); - EXPECT_NE(cb.m_free, nullptr); - EXPECT_EQ(cb.m_error, &test_error_impl); - #else - EXPECT_EQ(cb.m_user_data, (void*)0xff); - EXPECT_EQ(cb.m_allocate, nullptr); - EXPECT_EQ(cb.m_free, nullptr); - EXPECT_EQ(cb.m_error, test_error_impl); - #endif - } -} - -TEST(Callbacks, get) -{ - Callbacks cb = get_callbacks(); - EXPECT_NE(cb.m_allocate, &test_allocate_impl); - EXPECT_NE(cb.m_free, &test_free_impl); - EXPECT_NE(cb.m_error, &test_error_impl); - #ifndef RYML_NO_DEFAULT_CALLBACKS - EXPECT_EQ(cb.m_user_data, nullptr); - EXPECT_NE(cb.m_allocate, nullptr); - EXPECT_NE(cb.m_free, nullptr); - EXPECT_NE(cb.m_error, nullptr); - #else - EXPECT_EQ(cb.m_user_data, nullptr); - EXPECT_EQ(cb.m_allocate, nullptr); - EXPECT_EQ(cb.m_free, nullptr); - EXPECT_EQ(cb.m_error, nullptr); - #endif -} - -TEST(Callbacks, set) -{ - Callbacks before = get_callbacks(); - Callbacks cb((void*)0xff, &test_allocate_impl, &test_free_impl, &test_error_impl); - - set_callbacks(cb); - Callbacks after = get_callbacks(); - EXPECT_EQ(cb.m_user_data, after.m_user_data); - EXPECT_EQ(cb.m_allocate, after.m_allocate); - EXPECT_EQ(cb.m_free, after.m_free); - EXPECT_EQ(cb.m_error, after.m_error); - - set_callbacks(before); - after = get_callbacks(); - EXPECT_EQ(before.m_user_data, after.m_user_data); - EXPECT_EQ(before.m_allocate, after.m_allocate); - EXPECT_EQ(before.m_free, after.m_free); - EXPECT_EQ(before.m_error, after.m_error); - - set_callbacks(cb); - after = get_callbacks(); - EXPECT_EQ(cb.m_user_data, after.m_user_data); - EXPECT_EQ(cb.m_allocate, after.m_allocate); - EXPECT_EQ(cb.m_free, after.m_free); - EXPECT_EQ(cb.m_error, after.m_error); -} - -TEST(Callbacks, reset) -{ - Callbacks before = get_callbacks(); - Callbacks cb((void*)0xff, &test_allocate_impl, &test_free_impl, &test_error_impl); - - set_callbacks(cb); - Callbacks after = get_callbacks(); - EXPECT_EQ(cb.m_user_data, after.m_user_data); - EXPECT_EQ(cb.m_allocate, after.m_allocate); - EXPECT_EQ(cb.m_free, after.m_free); - EXPECT_EQ(cb.m_error, after.m_error); - - reset_callbacks(); - EXPECT_EQ(before.m_user_data, after.m_user_data); - EXPECT_EQ(before.m_allocate, after.m_allocate); - EXPECT_EQ(before.m_free, after.m_free); - EXPECT_EQ(before.m_error, after.m_error); -} - -TEST(Callbacks, eq) -{ - Callbacks before = get_callbacks(); - Callbacks bf2 = get_callbacks(); - Callbacks cb((void*)0xff, &test_allocate_impl, &test_free_impl, &test_error_impl); - - EXPECT_EQ(bf2, before); - EXPECT_TRUE(bf2 == before); - EXPECT_FALSE(!(bf2 == before)); - EXPECT_TRUE(!(cb == before)); -} - -TEST(Callbacks, ne) -{ - Callbacks before = get_callbacks(); - Callbacks bf2 = get_callbacks(); - Callbacks cb((void*)0xff, &test_allocate_impl, &test_free_impl, &test_error_impl); - - EXPECT_NE(cb, before); - EXPECT_TRUE(cb != before); - EXPECT_TRUE(!(bf2 != before)); - EXPECT_FALSE(!(cb != before)); -} - -TEST(Callbacks, cmp_user_data) -{ - Callbacks before = get_callbacks(); - Callbacks cp = before; - EXPECT_EQ(cp, before); - cp.m_user_data = (void*)(((char*)before.m_user_data) + 100u); - EXPECT_NE(cp, before); -} - -TEST(Callbacks, cmp_allocate) -{ - Callbacks before = get_callbacks(); - Callbacks cp = before; - EXPECT_NE(cp.m_allocate, nullptr); - EXPECT_EQ(cp, before); - cp.m_allocate = nullptr; - EXPECT_NE(cp, before); -} - -TEST(Callbacks, cmp_free) -{ - Callbacks before = get_callbacks(); - Callbacks cp = before; - EXPECT_NE(cp.m_free, nullptr); - EXPECT_EQ(cp, before); - cp.m_free = nullptr; - EXPECT_NE(cp, before); -} - -TEST(Callbacks, cmp_error) -{ - Callbacks before = get_callbacks(); - Callbacks cp = before; - EXPECT_NE(cp.m_error, nullptr); - EXPECT_EQ(cp, before); - cp.m_error = nullptr; - EXPECT_NE(cp, before); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -TEST(allocate_and_free, basic) -{ - EXPECT_NE(get_callbacks().m_allocate, &test_allocate_impl); - EXPECT_NE(get_callbacks().m_error, &test_error_impl); - Callbacks cb(nullptr, &test_allocate_impl, &test_free_impl, nullptr); - set_callbacks(cb); - void *mem = get_callbacks().m_allocate(32, /*hint*/0, get_callbacks().m_user_data); - EXPECT_EQ(stored_mem, mem); - EXPECT_EQ(stored_length, 32u); - stored_mem = nullptr; - stored_length = 0; - get_callbacks().m_free(mem, 32u, get_callbacks().m_user_data); - EXPECT_EQ(stored_mem, mem); - EXPECT_EQ(stored_length, 32u); -} - -TEST(error, basic) -{ - EXPECT_NE(get_callbacks().m_error, &test_error_impl); - Callbacks cb(nullptr, nullptr, nullptr, &test_error_impl); - set_callbacks(cb); - // message - EXPECT_EQ(get_callbacks().m_error, &test_error_impl); - c4::yml::error("some message 123"); // calls test_error_impl, which sets stored_msg and stored_location - EXPECT_EQ(stored_msg, "some message 123"); - EXPECT_EQ(stored_location.name, ""); - EXPECT_EQ(stored_location.offset, 0u); - EXPECT_EQ(stored_location.line, 0u); - EXPECT_EQ(stored_location.col, 0u); - // location - c4::yml::error("some message 456", Location("file.yml", 433u, 123u, 4u)); - EXPECT_EQ(stored_msg, "some message 456"); - EXPECT_EQ(stored_location.name, "file.yml"); - EXPECT_EQ(stored_location.offset, 433u); - EXPECT_EQ(stored_location.line, 123u); - EXPECT_EQ(stored_location.col, 4u); - reset_callbacks(); - EXPECT_NE(get_callbacks().m_error, &test_error_impl); -} - -TEST(RYML_CHECK, basic) -{ - EXPECT_NE(get_callbacks().m_error, &test_error_impl); - Callbacks cb(nullptr, nullptr, nullptr, &test_error_impl); - set_callbacks(cb); - size_t the_line = __LINE__; RYML_CHECK(false); // keep both statements in the same line - EXPECT_EQ(stored_msg, "check failed: false"); - EXPECT_EQ(stored_location.name, __FILE__); - EXPECT_EQ(stored_location.offset, 0u); - EXPECT_EQ(stored_location.line, the_line); - EXPECT_EQ(stored_location.col, 0u); - reset_callbacks(); - EXPECT_NE(get_callbacks().m_error, &test_error_impl); -} - - -TEST(RYML_ASSERT, basic) -{ - EXPECT_NE(get_callbacks().m_error, &test_error_impl); - Callbacks cb(nullptr, nullptr, nullptr, &test_error_impl); - set_callbacks(cb); - stored_msg = ""; - stored_location = {}; - size_t the_line = __LINE__; RYML_ASSERT(false); // keep both statements in the same line - #if RYML_USE_ASSERT - EXPECT_EQ(stored_msg, "check failed: false"); - EXPECT_EQ(stored_location.name, __FILE__); - EXPECT_EQ(stored_location.offset, 0u); - EXPECT_EQ(stored_location.line, the_line); - EXPECT_EQ(stored_location.col, 0u); - #else - C4_UNUSED(the_line); - EXPECT_EQ(stored_msg, ""); - EXPECT_EQ(stored_location.name, nullptr); - EXPECT_EQ(stored_location.offset, 0u); - EXPECT_EQ(stored_location.line, 0u); - EXPECT_EQ(stored_location.col, 0u); - #endif - reset_callbacks(); - EXPECT_NE(get_callbacks().m_error, &test_error_impl); -} - - -// FIXME this is here merely to avoid a linker error -Case const* get_case(csubstr) -{ - return nullptr; -} - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_case.cpp b/thirdparty/ryml/test/test_case.cpp deleted file mode 100644 index a850d242b..000000000 --- a/thirdparty/ryml/test/test_case.cpp +++ /dev/null @@ -1,898 +0,0 @@ -#include "./test_case.hpp" -#ifndef RYML_SINGLE_HEADER -#include "c4/yml/common.hpp" -#include "c4/format.hpp" -#include "c4/span.hpp" -#include "c4/yml/std/std.hpp" -#include "c4/yml/detail/print.hpp" -#include "c4/yml/detail/checks.hpp" -#endif - -#include - -#if defined(_MSC_VER) -# pragma warning(push) -#elif defined(__clang__) -# pragma clang diagnostic push -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wuseless-cast" -# if __GNUC__ >= 6 -# pragma GCC diagnostic ignored "-Wnull-dereference" -# endif -#endif - -namespace c4 { -namespace yml { - - -size_t _num_leaves(Tree const& t, size_t node) -{ - size_t count = 0; - for(size_t ch = t.first_child(node); ch != NONE; ch = t.next_sibling(ch)) - count += _num_leaves(t, ch); - return count; -} - - -void test_compare(Tree const& actual, Tree const& expected) -{ - ASSERT_EQ(actual.empty(), expected.empty()); - if(actual.empty() || expected.empty()) - return; - EXPECT_EQ(actual.size(), expected.size()); - EXPECT_EQ(_num_leaves(actual, actual.root_id()), _num_leaves(expected, expected.root_id())); - test_compare(actual, actual.root_id(), expected, expected.root_id(), 0); -} - - -void test_compare(Tree const& actual, size_t node_actual, - Tree const& expected, size_t node_expected, - size_t level) -{ - #define _MORE_INFO "actual=" << node_actual << " vs expected=" << node_expected - - ASSERT_NE(node_actual, (size_t)NONE); - ASSERT_NE(node_expected, (size_t)NONE); - ASSERT_LT(node_actual, actual.capacity()); - ASSERT_LT(node_expected, expected.capacity()); - - EXPECT_EQ((type_bits)(actual.type(node_actual)&_TYMASK), (type_bits)(expected.type(node_expected)&_TYMASK)) << _MORE_INFO; - - EXPECT_EQ(actual.has_key(node_actual), expected.has_key(node_expected)) << _MORE_INFO; - if(actual.has_key(node_actual) && expected.has_key(node_expected)) - { - EXPECT_EQ(actual.key(node_actual), expected.key(node_expected)) << _MORE_INFO; - } - - EXPECT_EQ(actual.has_val(node_actual), expected.has_val(node_expected)) << _MORE_INFO; - if(actual.has_val(node_actual) && expected.has_val(node_expected)) - { - EXPECT_EQ(actual.val(node_actual), expected.val(node_expected)) << _MORE_INFO; - } - - EXPECT_EQ(actual.has_key_tag(node_actual), expected.has_key_tag(node_expected)) << _MORE_INFO; - if(actual.has_key_tag(node_actual) && expected.has_key_tag(node_expected)) - { - EXPECT_EQ(actual.key_tag(node_actual), expected.key_tag(node_expected)) << _MORE_INFO; - } - - EXPECT_EQ(actual.has_val_tag(node_actual), expected.has_val_tag(node_expected)) << _MORE_INFO; - if(actual.has_val_tag(node_actual) && expected.has_val_tag(node_expected)) - { - auto filtered = [](csubstr tag) { - if(tag.begins_with("!')) - return tag.offs(3, 1); - return tag; - }; - csubstr actual_tag = filtered(actual.val_tag(node_actual)); - csubstr expected_tag = filtered(actual.val_tag(node_expected)); - EXPECT_EQ(actual_tag, expected_tag) << _MORE_INFO; - } - - EXPECT_EQ(actual.has_key_anchor(node_actual), expected.has_key_anchor(node_expected)) << _MORE_INFO; - if(actual.has_key_anchor(node_actual) && expected.has_key_anchor(node_expected)) - { - EXPECT_EQ(actual.key_anchor(node_actual), expected.key_anchor(node_expected)) << _MORE_INFO; - } - - EXPECT_EQ(actual.has_val_anchor(node_actual), expected.has_val_anchor(node_expected)) << _MORE_INFO; - if(actual.has_val_anchor(node_actual) && expected.has_val_anchor(node_expected)) - { - EXPECT_EQ(actual.val_anchor(node_actual), expected.val_anchor(node_expected)) << _MORE_INFO; - } - - EXPECT_EQ(actual.num_children(node_actual), expected.num_children(node_expected)) << _MORE_INFO; - for(size_t ia = actual.first_child(node_actual), ib = expected.first_child(node_expected); - ia != NONE && ib != NONE; - ia = actual.next_sibling(ia), ib = expected.next_sibling(ib)) - { - test_compare(actual, ia, expected, ib, level+1); - } - - #undef _MORE_INFO -} - -void test_arena_not_shared(Tree const& a, Tree const& b) -{ - for(NodeData const* n = a.m_buf, *e = a.m_buf + a.m_cap; n != e; ++n) - { - EXPECT_FALSE(b.in_arena(n->m_key.scalar)) << n - a.m_buf; - EXPECT_FALSE(b.in_arena(n->m_key.tag )) << n - a.m_buf; - EXPECT_FALSE(b.in_arena(n->m_key.anchor)) << n - a.m_buf; - EXPECT_FALSE(b.in_arena(n->m_val.scalar)) << n - a.m_buf; - EXPECT_FALSE(b.in_arena(n->m_val.tag )) << n - a.m_buf; - EXPECT_FALSE(b.in_arena(n->m_val.anchor)) << n - a.m_buf; - } - for(NodeData const* n = b.m_buf, *e = b.m_buf + b.m_cap; n != e; ++n) - { - EXPECT_FALSE(a.in_arena(n->m_key.scalar)) << n - b.m_buf; - EXPECT_FALSE(a.in_arena(n->m_key.tag )) << n - b.m_buf; - EXPECT_FALSE(a.in_arena(n->m_key.anchor)) << n - b.m_buf; - EXPECT_FALSE(a.in_arena(n->m_val.scalar)) << n - b.m_buf; - EXPECT_FALSE(a.in_arena(n->m_val.tag )) << n - b.m_buf; - EXPECT_FALSE(a.in_arena(n->m_val.anchor)) << n - b.m_buf; - } - for(TagDirective const& td : a.m_tag_directives) - { - EXPECT_FALSE(b.in_arena(td.handle)); - EXPECT_FALSE(b.in_arena(td.prefix)); - } - for(TagDirective const& td : b.m_tag_directives) - { - EXPECT_FALSE(a.in_arena(td.handle)); - EXPECT_FALSE(a.in_arena(td.prefix)); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -// ensure coverage of the default callback report -#ifndef RYML_NO_DEFAULT_CALLBACKS -extern void report_error_impl(const char* msg, size_t len, Location loc, FILE *file); -#endif - -std::string format_error(const char* msg, size_t len, Location loc) -{ - // ensure coverage of the default callback report - #ifndef RYML_NO_DEFAULT_CALLBACKS - report_error_impl(msg, len, loc, nullptr); - #endif - if(!loc) return msg; - std::string out; - if(!loc.name.empty()) c4::formatrs(append, &out, "{}:", loc.name); - c4::formatrs(append, &out, "{}:{}:", loc.line, loc.col); - if(loc.offset) c4::formatrs(append, &out, " (@{}B):", loc.offset); - c4::formatrs(append, &out, "{}:", csubstr(msg, len)); - return out; -} - -struct ExpectedError : public std::runtime_error -{ - Location error_location; - ExpectedError(const char* msg, size_t len, Location loc) - : std::runtime_error(format_error(msg, len, loc)) - , error_location(loc) - { - } -}; - - -//----------------------------------------------------------------------------- - -ExpectError::ExpectError(Tree *tree, Location loc) - : m_got_an_error(false) - , m_tree(tree) - , m_glob_prev(get_callbacks()) - , m_tree_prev(tree ? tree->callbacks() : Callbacks{}) - , expected_location(loc) -{ - auto err = [](const char* msg, size_t len, Location errloc, void *this_) { - ((ExpectError*)this_)->m_got_an_error = true; - throw ExpectedError(msg, len, errloc); - }; - #ifdef RYML_NO_DEFAULT_CALLBACKS - c4::yml::Callbacks tcb((void*)this, nullptr, nullptr, err); - c4::yml::Callbacks gcb((void*)this, nullptr, nullptr, err); - #else - c4::yml::Callbacks tcb((void*)this, tree ? m_tree_prev.m_allocate : nullptr, tree ? m_tree_prev.m_free : nullptr, err); - c4::yml::Callbacks gcb((void*)this, m_glob_prev.m_allocate, m_glob_prev.m_free, err); - #endif - if(tree) - tree->callbacks(tcb); - set_callbacks(gcb); -} - -ExpectError::~ExpectError() -{ - if(m_tree) - m_tree->callbacks(m_tree_prev); - set_callbacks(m_tree_prev); -} - -void ExpectError::do_check(Tree *tree, std::function fn, Location expected_location) -{ - auto context = ExpectError(tree, expected_location); - try - { - fn(); - } - catch(ExpectedError const& e) - { - #if defined(RYML_DBG) - std::cout << "---------------\n"; - std::cout << "got an expected error:\n" << e.what() << "\n"; - std::cout << "---------------\n"; - #endif - if(context.expected_location) - { - EXPECT_EQ(static_cast(context.expected_location), - static_cast(e.error_location)); - EXPECT_EQ(e.error_location.line, context.expected_location.line); - EXPECT_EQ(e.error_location.col, context.expected_location.col); - if(context.expected_location.offset) - { - EXPECT_EQ(e.error_location.offset, context.expected_location.offset); - } - } - }; - EXPECT_TRUE(context.m_got_an_error); -} - -void ExpectError::check_assertion(Tree *tree, std::function fn, Location expected_location) -{ - #if RYML_USE_ASSERT - ExpectError::do_check(tree, fn, expected_location); - #else - C4_UNUSED(tree); - C4_UNUSED(fn); - C4_UNUSED(expected_location); - #endif -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -using N = CaseNode; -using L = CaseNode::iseqmap; - -TEST(CaseNode, setting_up) -{ - L tl1 = {DOC, DOC}; - L tl2 = {(DOC), (DOC)}; - - ASSERT_EQ(tl1.size(), tl2.size()); - N const& d1 = *tl1.begin(); - N const& d2 = *(tl1.begin() + 1); - ASSERT_EQ(d1.reccount(), d2.reccount()); - ASSERT_EQ((type_bits)d1.type, (type_bits)DOC); - ASSERT_EQ((type_bits)d2.type, (type_bits)DOC); - - N n1(tl1); - N n2(tl2); - ASSERT_EQ(n1.reccount(), n2.reccount()); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -NodeType_e CaseNode::_guess() const -{ - NodeType t; - C4_ASSERT(!val.empty() != !children.empty() || (val.empty() && children.empty())); - if(children.empty()) - { - C4_ASSERT(parent); - if(key.empty()) - { - t = VAL; - } - else - { - t = KEYVAL; - } - } - else - { - NodeType_e has_key = key.empty() ? NOTYPE : KEY; - auto const& ch = children.front(); - if(ch.key.empty()) - { - t = (has_key|SEQ); - } - else - { - t = (has_key|MAP); - } - } - if( ! key_tag.empty()) - { - C4_ASSERT( ! key.empty()); - t.add(KEYTAG); - } - if( ! val_tag.empty()) - { - C4_ASSERT( ! val.empty() || ! children.empty()); - t.add(VALTAG); - } - if( ! key_anchor.str.empty()) - { - t.add(key_anchor.type); - } - if( ! val_anchor.str.empty()) - { - t.add(val_anchor.type); - } - return t; -} - - -//----------------------------------------------------------------------------- -void CaseNode::compare_child(yml::ConstNodeRef const& n, size_t pos) const -{ - EXPECT_TRUE(pos < n.num_children()); - EXPECT_TRUE(pos < children.size()); - - if(pos >= n.num_children() || pos >= children.size()) return; - - ASSERT_GT(n.num_children(), pos); - auto const& expectedch = children[pos]; - - if(type & MAP) - { - auto actualch = n.find_child(expectedch.key); - if(actualch != nullptr) - { - // there may be duplicate keys. - if(actualch.id() != n[pos].id()) - actualch = n[pos]; - //EXPECT_EQ(fch, n[ch.key]); - EXPECT_EQ(actualch.get(), n[pos].get()); - //EXPECT_EQ(n[pos], n[ch.key]); - EXPECT_EQ(n[expectedch.key].key(), expectedch.key); - } - else - { - printf("error: node should have child %.*s: ", (int)expectedch.key.len, expectedch.key.str); - print_path(n); - printf("\n"); - print_node(n); - GTEST_FAIL(); - } - } - - if(type & SEQ) - { - EXPECT_FALSE(n[pos].has_key()); - EXPECT_EQ(n[pos].get()->m_key.scalar, children[pos].key); - auto actualch = n.child(pos); - EXPECT_EQ(actualch.get(), n[pos].get()); - } - - if(expectedch.type & KEY) - { - auto actualfch = n[pos]; - EXPECT_TRUE(actualfch.has_key()) << "id=" << actualfch.id(); - if(actualfch.has_key()) - { - EXPECT_EQ(actualfch.key(), expectedch.key) << "id=" << actualfch.id(); - } - - if( ! expectedch.key_tag.empty()) - { - EXPECT_TRUE(actualfch.has_key_tag()) << "id=" << actualfch.id(); - if(actualfch.has_key_tag()) - { - EXPECT_EQ(actualfch.key_tag(), expectedch.key_tag) << "id=" << actualfch.id(); - } - } - } - - if(expectedch.type & VAL) - { - auto actualch = n[pos]; - EXPECT_TRUE(actualch.has_val()) << "id=" << actualch.id(); - if(actualch.has_val()) - { - EXPECT_EQ(actualch.val(), expectedch.val) << "id=" << actualch.id(); - } - - if( ! expectedch.val_tag.empty()) - { - EXPECT_TRUE(actualch.has_val_tag()) << "id=" << actualch.id(); - if(actualch.has_val_tag()) - { - EXPECT_EQ(actualch.val_tag(), expectedch.val_tag) << "id=" << actualch.id(); - } - } - } -} - -void CaseNode::compare(yml::ConstNodeRef const& actual, bool ignore_quote) const -{ - if(ignore_quote) - { - const auto actual_type = actual.get()->m_type & ~(VALQUO | KEYQUO); - const auto expected_type = type & ~(VALQUO | KEYQUO); - EXPECT_EQ(expected_type, actual_type) << "id=" << actual.id(); - } - else - { - EXPECT_EQ((int)actual.get()->m_type, (int)type) << "id=" << actual.id(); // the type() method masks the type, and thus tag flags are omitted on its return value - } - - EXPECT_EQ(actual.num_children(), children.size()) << "id=" << actual.id(); - - if(actual.has_key()) - { - EXPECT_EQ(actual.key(), key) << "id=" << actual.id(); - } - - if(actual.has_val()) - { - EXPECT_EQ(actual.val(), val) << "id=" << actual.id(); - } - - // check that the children are in the same order - { - EXPECT_EQ(children.size(), actual.num_children()) << "id=" << actual.id(); - - size_t ic = 0; - for(auto const &expectedch : children) - { - SCOPED_TRACE("comparing: iteration based on the ref children"); - (void)expectedch; // unused - compare_child(actual, ic++); - } - - ic = 0; - for(auto const actualch : actual.children()) - { - SCOPED_TRACE("comparing: iteration based on the yml::Node children"); - (void)actualch; // unused - compare_child(actual, ic++); - } - - if(actual.first_child() != nullptr) - { - ic = 0; - for(auto const ch : actual.first_child().siblings()) - { - SCOPED_TRACE("comparing: iteration based on the yml::Node siblings"); - (void)ch; // unused - compare_child(actual, ic++); - } - } - } - - for(size_t i = 0, ei = actual.num_children(), j = 0, ej = children.size(); i < ei && j < ej; ++i, ++j) - { - children[j].compare(actual[i], ignore_quote); - } -} - -void CaseNode::recreate(yml::NodeRef *n) const -{ - C4_ASSERT( ! n->has_children()); - auto *nd = n->get(); - nd->m_type = type|key_anchor.type|val_anchor.type; - nd->m_key.scalar = key; - nd->m_key.tag = (key_tag); - nd->m_key.anchor = key_anchor.str; - nd->m_val.scalar = val; - nd->m_val.tag = (val_tag); - nd->m_val.anchor = val_anchor.str; - auto &tree = *n->tree(); - size_t nid = n->id(); // don't use node from now on - for(auto const& ch : children) - { - size_t id = tree.append_child(nid); - NodeRef chn(n->tree(), id); - ch.recreate(&chn); - } -} - - -//----------------------------------------------------------------------------- - -void print_path(ConstNodeRef const& n) -{ - size_t len = 0; - char buf[1024]; - ConstNodeRef p = n; - while(p != nullptr) - { - if(p.has_key()) - { - len += 1 + p.key().len; - } - else - { - int ret = snprintf(buf, sizeof(buf), "/%zd", p.has_parent() ? p.parent().child_pos(p) : 0); - RYML_ASSERT(ret >= 0); - len += static_cast(ret); - } - p = p.parent(); - }; - C4_ASSERT(len < sizeof(buf)); - size_t pos = len; - p = n; - while(p.valid() && p != nullptr) - { - if(p.has_key()) - { - size_t tl = p.key().len; - int ret = snprintf(buf + pos - tl, tl, "%.*s", (int)tl, p.key().str); - RYML_ASSERT(ret >= 0); - pos -= static_cast(ret); - } - else if(p.has_parent()) - { - pos = p.parent().child_pos(p); - int ret = snprintf(buf, 0, "/%zd", pos); - RYML_ASSERT(ret >= 0); - size_t tl = static_cast(ret); - RYML_ASSERT(pos >= tl); - ret = snprintf(buf + static_cast(pos - tl), tl, "/%zd", pos); - RYML_ASSERT(ret >= 0); - pos -= static_cast(ret); - } - p = p.parent(); - }; - printf("%.*s", (int)len, buf); -} - - - -void print_node(CaseNode const& p, int level) -{ - printf("%*s%p", (2*level), "", (void*)&p); - if( ! p.parent) - { - printf(" [ROOT]"); - } - printf(" %s:", NodeType::type_str(p.type)); - if(p.has_key()) - { - if(p.has_key_anchor()) - { - csubstr ka = p.key_anchor.str; - printf(" &%.*s", (int)ka.len, ka.str); - } - if(p.key_tag.empty()) - { - csubstr v = p.key; - printf(" '%.*s'", (int)v.len, v.str); - } - else - { - csubstr vt = p.key_tag; - csubstr v = p.key; - printf(" '%.*s %.*s'", (int)vt.len, vt.str, (int)v.len, v.str); - } - } - if(p.has_val()) - { - if(p.val_tag.empty()) - { - csubstr v = p.val; - printf(" '%.*s'", (int)v.len, v.str); - } - else - { - csubstr vt = p.val_tag; - csubstr v = p.val; - printf(" '%.*s %.*s'", (int)vt.len, vt.str, (int)v.len, v.str); - } - } - else - { - if( ! p.val_tag.empty()) - { - csubstr vt = p.val_tag; - printf(" %.*s", (int)vt.len, vt.str); - } - } - if(p.has_val_anchor()) - { - auto &a = p.val_anchor.str; - printf(" valanchor='&%.*s'", (int)a.len, a.str); - } - printf(" (%zd sibs)", p.parent ? p.parent->children.size() : 0); - if(p.is_container()) - { - printf(" %zd children:", p.children.size()); - } - printf("\n"); -} - - -void print_tree(ConstNodeRef const& p, int level) -{ - print_node(p, level); - for(ConstNodeRef ch : p.children()) - { - print_tree(ch, level+1); - } -} - -void print_tree(CaseNode const& p, int level) -{ - print_node(p, level); - for(auto const& ch : p.children) - print_tree(ch, level+1); -} - -void print_tree(CaseNode const& t) -{ - printf("--------------------------------------\n"); - print_tree(t, 0); - printf("#nodes: %zd\n", t.reccount()); - printf("--------------------------------------\n"); -} - -void test_invariants(ConstNodeRef const& n) -{ - #define _MORE_INFO << "id=" << n.id() - - if(n.is_root()) - { - EXPECT_FALSE(n.has_other_siblings()) _MORE_INFO; - } - // keys or vals cannot be root - if(n.has_key() || n.is_val() || n.is_keyval()) - { - EXPECT_TRUE(!n.is_root() || (n.is_doc() && !n.has_key())) _MORE_INFO; - } - // vals cannot be containers - if( ! n.empty() && ! n.is_doc()) - { - EXPECT_NE(n.has_val(), n.is_container()) _MORE_INFO; - } - if(n.has_children()) - { - EXPECT_TRUE(n.is_container()) _MORE_INFO; - EXPECT_FALSE(n.is_val()) _MORE_INFO; - } - // check parent & sibling reciprocity - for(ConstNodeRef s : n.siblings()) - { - EXPECT_TRUE(n.has_sibling(s)) _MORE_INFO; - EXPECT_TRUE(s.has_sibling(n)) _MORE_INFO; - EXPECT_EQ(s.parent().get(), n.parent().get()) _MORE_INFO; - } - if(n.parent() != nullptr) - { - EXPECT_EQ(n.parent().num_children() > 1, n.has_other_siblings()) _MORE_INFO; - EXPECT_TRUE(n.parent().has_child(n)) _MORE_INFO; - EXPECT_EQ(n.parent().num_children(), n.num_siblings()) _MORE_INFO; - // doc parent must be a seq and a stream - if(n.is_doc()) - { - EXPECT_TRUE(n.parent().is_seq()) _MORE_INFO; - EXPECT_TRUE(n.parent().is_stream()) _MORE_INFO; - } - } - else - { - EXPECT_TRUE(n.is_root()) _MORE_INFO; - } - if(n.is_seq()) - { - EXPECT_TRUE(n.is_container()) _MORE_INFO; - EXPECT_FALSE(n.is_map()) _MORE_INFO; - for(ConstNodeRef ch : n.children()) - { - EXPECT_FALSE(ch.is_keyval()) _MORE_INFO; - EXPECT_FALSE(ch.has_key()) _MORE_INFO; - } - } - if(n.is_map()) - { - EXPECT_TRUE(n.is_container()) _MORE_INFO; - EXPECT_FALSE(n.is_seq()) _MORE_INFO; - for(ConstNodeRef ch : n.children()) - { - EXPECT_TRUE(ch.has_key()) _MORE_INFO; - } - } - if(n.has_key_anchor()) - { - EXPECT_FALSE(n.key_anchor().empty()) _MORE_INFO; - EXPECT_FALSE(n.is_key_ref()) _MORE_INFO; - } - if(n.has_val_anchor()) - { - EXPECT_FALSE(n.val_anchor().empty()) _MORE_INFO; - EXPECT_FALSE(n.is_val_ref()) _MORE_INFO; - } - if(n.is_key_ref()) - { - EXPECT_FALSE(n.key_ref().empty()) _MORE_INFO; - EXPECT_FALSE(n.has_key_anchor()) _MORE_INFO; - } - if(n.is_val_ref()) - { - EXPECT_FALSE(n.val_ref().empty()) _MORE_INFO; - EXPECT_FALSE(n.has_val_anchor()) _MORE_INFO; - } - // ... add more tests here - - // now recurse into the children - for(ConstNodeRef ch : n.children()) - { - test_invariants(ch); - } - - #undef _MORE_INFO -} - -size_t test_tree_invariants(ConstNodeRef const& n) -{ - auto parent = n.parent(); - - if(n.get()->m_prev_sibling == NONE) - { - if(parent != nullptr) - { - EXPECT_EQ(parent.first_child().get(), n.get()); - EXPECT_EQ(parent.first_child().id(), n.id()); - } - } - - if(n.get()->m_next_sibling == NONE) - { - if(parent != nullptr) - { - EXPECT_EQ(parent.last_child().get(), n.get()); - EXPECT_EQ(parent.last_child().id(), n.id()); - } - } - - if(parent == nullptr) - { - EXPECT_TRUE(n.is_root()); - EXPECT_EQ(n.prev_sibling().get(), nullptr); - EXPECT_EQ(n.next_sibling().get(), nullptr); - } - - size_t count = 1, num = 0; - for(ConstNodeRef ch : n.children()) - { - EXPECT_NE(ch.id(), n.id()); - count += test_tree_invariants(ch); - ++num; - } - - EXPECT_EQ(num, n.num_children()); - - return count; -} - -void test_invariants(Tree const& t) -{ - - ASSERT_LE(t.size(), t.capacity()); - EXPECT_EQ(t.size() + t.slack(), t.capacity()); - - ASSERT_LE(t.arena_size(), t.arena_capacity()); - ASSERT_LE(t.arena_slack(), t.arena_capacity()); - EXPECT_EQ(t.arena_size() + t.arena_slack(), t.arena_capacity()); - - if(t.empty()) - return; - - size_t count = test_tree_invariants(t.rootref()); - EXPECT_EQ(count, t.size()); - - check_invariants(t); - test_invariants(t.rootref()); - - if(!testing::UnitTest::GetInstance()->current_test_info()->result()->Passed()) - { - print_tree(t); - } - - return; -#if 0 == 1 - for(size_t i = 0; i < t.m_size; ++i) - { - auto n = t.get(i); - if(n->m_prev_sibling == NONE) - { - EXPECT_TRUE(i == t.m_head || i == t.m_free_head); - } - if(n->m_next_sibling == NONE) - { - EXPECT_TRUE(i == t.m_tail || i == t.m_free_tail); - } - } - - std::vector touched(t.capacity()); - - for(size_t i = t.m_head; i != NONE; i = t.get(i)->m_next_sibling) - touched[i] = true; - - size_t size = 0; - for(bool v : touched) - size += v; - - EXPECT_EQ(size, t.size()); - - touched.clear(); - touched.resize(t.capacity()); - - for(size_t i = t.m_free_head; i != NONE; i = t.get(i)->m_next_sibling) - { - touched[i] = true; - } - - size_t slack = 0; - for(auto v : touched) - { - slack += v; - } - - EXPECT_EQ(slack, t.slack()); - EXPECT_EQ(size+slack, t.capacity()); - - // there are more checks to be done -#endif -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -CaseData* get_data(csubstr name) -{ - static std::map m; - - auto it = m.find(name); - CaseData *cd; - if(it == m.end()) - { - cd = &m[name]; - Case const* c = get_case(name); - RYML_CHECK(c->src.find("\n\r") == csubstr::npos); - { - std::string tmp; - replace_all("\r", "", c->src, &tmp); - cd->unix_style.src_buf.assign(tmp.begin(), tmp.end()); - cd->unix_style.src = to_substr(cd->unix_style.src_buf); - cd->unix_style_json.src_buf.assign(tmp.begin(), tmp.end()); - cd->unix_style_json.src = to_substr(cd->unix_style.src_buf); - } - { - std::string tmp; - replace_all("\n", "\r\n", cd->unix_style.src, &tmp); - cd->windows_style.src_buf.assign(tmp.begin(), tmp.end()); - cd->windows_style.src = to_substr(cd->windows_style.src_buf); - cd->windows_style_json.src_buf.assign(tmp.begin(), tmp.end()); - cd->windows_style_json.src = to_substr(cd->windows_style.src_buf); - } - } - else - { - cd = &it->second; - } - return cd; -} - -} // namespace yml -} // namespace c4 - -#if defined(_MSC_VER) -# pragma warning(pop) -#elif defined(__clang__) -# pragma clang diagnostic pop -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#endif diff --git a/thirdparty/ryml/test/test_case.hpp b/thirdparty/ryml/test/test_case.hpp deleted file mode 100644 index 7ddc0a96d..000000000 --- a/thirdparty/ryml/test/test_case.hpp +++ /dev/null @@ -1,533 +0,0 @@ -#ifndef _TEST_CASE_HPP_ -#define _TEST_CASE_HPP_ - -#ifdef RYML_SINGLE_HEADER -#include -#else -#include "c4/std/vector.hpp" -#include "c4/std/string.hpp" -#include "c4/format.hpp" -#include -#include -#endif - -#include -#include - -#ifdef __GNUC__ -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wtype-limits" -#endif - -#if defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable: 4296/*expression is always 'boolean_value'*/) -# pragma warning(disable: 4389/*'==': signed/unsigned mismatch*/) -# if C4_MSVC_VERSION != C4_MSVC_VERSION_2017 -# pragma warning(disable: 4800/*'int': forcing value to bool 'true' or 'false' (performance warning)*/) -# endif -#endif - -#ifdef RYML_DBG -# include -#endif - -namespace c4 { - -inline void PrintTo(substr s, ::std::ostream* os) { os->write(s.str, (std::streamsize)s.len); } -inline void PrintTo(csubstr s, ::std::ostream* os) { os->write(s.str, (std::streamsize)s.len); } - -namespace yml { - -inline void PrintTo(NodeType ty, ::std::ostream* os) -{ - *os << ty.type_str(); -} -inline void PrintTo(NodeType_e ty, ::std::ostream* os) -{ - *os << NodeType::type_str(ty); -} - -inline void PrintTo(Callbacks const& cb, ::std::ostream* os) -{ -#ifdef __GNUC__ -#define RYML_GNUC_EXTENSION __extension__ -#else -#define RYML_GNUC_EXTENSION -#endif - *os << '{' - << "userdata." << (void*)cb.m_user_data << ',' - << "allocate." << RYML_GNUC_EXTENSION (void*)cb.m_allocate << ',' - << "free." << RYML_GNUC_EXTENSION (void*)cb.m_free << ',' - << "error." << RYML_GNUC_EXTENSION (void*)cb.m_error << '}'; -#undef RYML_GNUC_EXTENSION -} - -struct Case; -struct CaseNode; -struct CaseData; - -Case const* get_case(csubstr name); -CaseData* get_data(csubstr name); - -void test_compare(Tree const& actual, Tree const& expected); -void test_compare(Tree const& actual, size_t node_actual, - Tree const& expected, size_t node_expected, - size_t level=0); - -void test_arena_not_shared(Tree const& a, Tree const& b); - -void test_invariants(Tree const& t); -void test_invariants(ConstNodeRef const& n); - -void print_node(CaseNode const& t, int level=0); -void print_tree(CaseNode const& p, int level=0); -void print_path(ConstNodeRef const& p); - - - -template -void test_check_emit_check(Tree const& t, CheckFn check_fn) -{ - #ifdef RYML_DBG - print_tree(t); - #endif - { - SCOPED_TRACE("original yaml"); - test_invariants(t); - check_fn(t); - } - auto emit_and_parse = [&check_fn](Tree const& tp, const char* identifier){ - SCOPED_TRACE(identifier); - std::string emitted = emitrs_yaml(tp); - #ifdef RYML_DBG - printf("~~~%s~~~\n%.*s", identifier, (int)emitted.size(), emitted.data()); - #endif - Tree cp = parse_in_arena(to_csubstr(emitted)); - #ifdef RYML_DBG - print_tree(cp); - #endif - test_invariants(cp); - check_fn(cp); - return cp; - }; - Tree cp = emit_and_parse(t, "emitted 1"); - cp = emit_and_parse(cp, "emitted 2"); - cp = emit_and_parse(cp, "emitted 3"); -} - -template -void test_check_emit_check(csubstr yaml, CheckFn check_fn) -{ - Tree t = parse_in_arena(yaml); - test_check_emit_check(t, check_fn); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - - -inline c4::substr replace_all(c4::csubstr pattern, c4::csubstr repl, c4::csubstr subject, std::string *dst) -{ - RYML_CHECK(!subject.overlaps(to_csubstr(*dst))); - size_t ret = subject.replace_all(to_substr(*dst), pattern, repl); - if(ret != dst->size()) - { - dst->resize(ret); - ret = subject.replace_all(to_substr(*dst), pattern, repl); - } - RYML_CHECK(ret == dst->size()); - return c4::to_substr(*dst); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -struct ExpectError -{ - bool m_got_an_error; - Tree *m_tree; - c4::yml::Callbacks m_glob_prev; - c4::yml::Callbacks m_tree_prev; - Location expected_location; - - ExpectError(Location loc={}) : ExpectError(nullptr, loc) {} - ExpectError(Tree *tree, Location loc={}); - ~ExpectError(); - - static void do_check( std::function fn, Location expected={}) { do_check(nullptr, fn, expected); } - static void do_check(Tree *tree, std::function fn, Location expected={}); - static void check_assertion( std::function fn, Location expected={}) { check_assertion(nullptr, fn, expected); } - static void check_assertion(Tree *tree, std::function fn, Location expected={}); -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -struct TaggedScalar -{ - csubstr tag; - csubstr scalar; - template - TaggedScalar(const char (&t)[N], const char (&s)[M]) : tag(t), scalar(s) {} - template - TaggedScalar(const char (&t)[N], std::nullptr_t) : tag(t), scalar() {} -}; - -struct AnchorRef -{ - NodeType_e type; - csubstr str; - AnchorRef() : type(NOTYPE), str() {} - AnchorRef(NodeType_e t) : type(t), str() {} - AnchorRef(NodeType_e t, csubstr v) : type(t), str(v) {} -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -/** a node class against which ryml structures are tested. Uses initializer - * lists to facilitate minimal specification. */ -struct CaseNode -{ -public: - - using seqmap = std::vector; - using iseqmap = std::initializer_list; - - struct TaggedList - { - csubstr tag; - iseqmap ilist; - template TaggedList(const char (&t)[N], iseqmap l) : tag(t), ilist(l) {} - }; - -public: - - NodeType type; - csubstr key, key_tag; AnchorRef key_anchor; - csubstr val, val_tag; AnchorRef val_anchor; - seqmap children; - CaseNode * parent; - -public: - - CaseNode(CaseNode && that) noexcept { _move(std::move(that)); } - CaseNode(CaseNode const& that) noexcept { _copy(that); } - - CaseNode& operator= (CaseNode && that) noexcept { _move(std::move(that)); return *this; } - CaseNode& operator= (CaseNode const& that) noexcept { _copy(that); return *this; } - - ~CaseNode() = default; - -public: - - // brace yourself: what you are about to see is ... crazy. - - CaseNode() : CaseNode(NOTYPE) {} - CaseNode(NodeType_e t) : type(t), key(), key_tag(), key_anchor(), val(), val_tag(), val_anchor(), children(), parent(nullptr) { _set_parent(); } - - // val - template explicit CaseNode(const char (&v)[N] ) : type((VAL )), key(), key_tag(), key_anchor(), val(v ), val_tag( ), val_anchor(), children(), parent(nullptr) { _set_parent(); } - explicit CaseNode(TaggedScalar const& v) : type((VAL|VALTAG)), key(), key_tag(), key_anchor(), val(v.scalar), val_tag(v.tag), val_anchor(), children(), parent(nullptr) { _set_parent(); } - explicit CaseNode(std::nullptr_t ) : type((VAL )), key(), key_tag(), key_anchor(), val( ), val_tag( ), val_anchor(), children(), parent(nullptr) { _set_parent(); } - // val, with anchor/ref - template explicit CaseNode(const char (&v)[N] , AnchorRef const& arv) : type((arv.type|VAL )), key(), key_tag(), key_anchor(), val(v ), val_tag( ), val_anchor(arv), children(), parent(nullptr) { _set_parent(); } - explicit CaseNode(TaggedScalar const& v, AnchorRef const& arv) : type((arv.type|VAL|VALTAG)), key(), key_tag(), key_anchor(), val(v.scalar), val_tag(v.tag), val_anchor(arv), children(), parent(nullptr) { _set_parent(); } - explicit CaseNode(std::nullptr_t , AnchorRef const& arv) : type((arv.type|VAL )), key(), key_tag(), key_anchor(), val( ), val_tag( ), val_anchor(arv), children(), parent(nullptr) { _set_parent(); } - explicit CaseNode( AnchorRef const& arv) : type((arv.type|VAL )), key(), key_tag(), key_anchor(), val(arv.str ), val_tag( ), val_anchor(arv), children(), parent(nullptr) { _set_parent(); RYML_ASSERT(arv.type == VALREF); } - - - // val, explicit type - template explicit CaseNode(NodeType t, const char (&v)[N] ) : type((VAL|t )), key(), key_tag(), key_anchor(), val(v ), val_tag( ), val_anchor(), children(), parent(nullptr) { _set_parent(); } - explicit CaseNode(NodeType t, TaggedScalar const& v) : type((VAL|VALTAG|t)), key(), key_tag(), key_anchor(), val(v.scalar), val_tag(v.tag), val_anchor(), children(), parent(nullptr) { _set_parent(); } - explicit CaseNode(NodeType t, std::nullptr_t ) : type((VAL |t)), key(), key_tag(), key_anchor(), val( ), val_tag( ), val_anchor(), children(), parent(nullptr) { _set_parent(); } - // val, explicit type, with val anchor/ref - template explicit CaseNode(NodeType t, const char (&v)[N] , AnchorRef const& arv) : type((arv.type|VAL|t )), key(), key_tag(), key_anchor(), val(v ), val_tag( ), val_anchor(arv), children(), parent(nullptr) { _set_parent(); } - explicit CaseNode(NodeType t, TaggedScalar const& v, AnchorRef const& arv) : type((arv.type|VAL|VALTAG|t)), key(), key_tag(), key_anchor(), val(v.scalar), val_tag(v.tag), val_anchor(arv), children(), parent(nullptr) { _set_parent(); } - explicit CaseNode(NodeType t, std::nullptr_t , AnchorRef const& arv) : type((arv.type|VAL |t)), key(), key_tag(), key_anchor(), val( ), val_tag( ), val_anchor(arv), children(), parent(nullptr) { _set_parent(); } - - - // keyval - template explicit CaseNode(const char (&k)[N] , const char (&v)[M] ) : type((KEYVAL )), key(k ), key_tag( ), key_anchor( ), val(v ), val_tag( ), val_anchor( ), children(), parent(nullptr) { _set_parent(); } - template explicit CaseNode(std::nullptr_t , const char (&v)[M] ) : type((KEYVAL )), key( ), key_tag( ), key_anchor( ), val(v ), val_tag( ), val_anchor( ), children(), parent(nullptr) { _set_parent(); } - template explicit CaseNode(const char (&k)[N] , std::nullptr_t ) : type((KEYVAL )), key(k ), key_tag( ), key_anchor( ), val( ), val_tag( ), val_anchor( ), children(), parent(nullptr) { _set_parent(); } - template explicit CaseNode(const char (&k)[N] , TaggedScalar const& v) : type((KEYVAL|VALTAG )), key(k ), key_tag( ), key_anchor( ), val(v.scalar), val_tag(v.tag), val_anchor( ), children(), parent(nullptr) { _set_parent(); } - template explicit CaseNode(TaggedScalar const& k, const char (&v)[M] ) : type((KEYVAL|KEYTAG )), key(k.scalar), key_tag(k.tag), key_anchor( ), val(v ), val_tag( ), val_anchor( ), children(), parent(nullptr) { _set_parent(); } - explicit CaseNode(TaggedScalar const& k, TaggedScalar const& v) : type((KEYVAL|KEYTAG|VALTAG )), key(k.scalar), key_tag(k.tag), key_anchor( ), val(v.scalar), val_tag(v.tag), val_anchor( ), children(), parent(nullptr) { _set_parent(); } - explicit CaseNode(std::nullptr_t , TaggedScalar const& v) : type((KEYVAL |VALTAG )), key( ), key_tag( ), key_anchor( ), val(v.scalar), val_tag(v.tag), val_anchor( ), children(), parent(nullptr) { _set_parent(); } - explicit CaseNode(TaggedScalar const& k, std::nullptr_t ) : type((KEYVAL|KEYTAG )), key(k.scalar), key_tag(k.tag), key_anchor( ), val( ), val_tag( ), val_anchor( ), children(), parent(nullptr) { _set_parent(); } - explicit CaseNode(std::nullptr_t , std::nullptr_t ) : type((KEYVAL )), key( ), key_tag( ), key_anchor( ), val( ), val_tag( ), val_anchor( ), children(), parent(nullptr) { _set_parent(); } - explicit CaseNode(AnchorRef const& ark, AnchorRef const& arv) : type((KEYVAL|ark.type|arv.type)), key(ark.str ), key_tag( ), key_anchor(ark), val(arv.str ), val_tag( ), val_anchor(arv), children(), parent(nullptr) { _set_parent(); RYML_ASSERT(ark.type == KEYREF); RYML_ASSERT(arv.type == VALREF); } - // keyval, with val anchor/ref - template explicit CaseNode(const char (&k)[N] , const char (&v)[M] , AnchorRef const& arv) : type((arv.type|KEYVAL )), key(k ), key_tag( ), key_anchor(), val(v ), val_tag( ), val_anchor(arv), children(), parent(nullptr) { _set_parent(); } - template explicit CaseNode(const char (&k)[N] , TaggedScalar const& v, AnchorRef const& arv) : type((arv.type|KEYVAL|VALTAG )), key(k ), key_tag( ), key_anchor(), val(v.scalar), val_tag(v.tag), val_anchor(arv), children(), parent(nullptr) { _set_parent(); } - template explicit CaseNode(TaggedScalar const& k, const char (&v)[M] , AnchorRef const& arv) : type((arv.type|KEYVAL|KEYTAG )), key(k.scalar), key_tag(k.tag), key_anchor(), val(v ), val_tag( ), val_anchor(arv), children(), parent(nullptr) { _set_parent(); } - explicit CaseNode(TaggedScalar const& k, TaggedScalar const& v, AnchorRef const& arv) : type((arv.type|KEYVAL|KEYTAG|VALTAG)), key(k.scalar), key_tag(k.tag), key_anchor(), val(v.scalar), val_tag(v.tag), val_anchor(arv), children(), parent(nullptr) { _set_parent(); } - // keyval, with key anchor/ref - template explicit CaseNode(const char (&k)[N] , AnchorRef const& ark, const char (&v)[M] ) : type((ark.type|KEYVAL )), key(k ), key_tag( ), key_anchor(ark), val(v ), val_tag( ), val_anchor(), children(), parent(nullptr) { _set_parent(); } - template explicit CaseNode(const char (&k)[N] , AnchorRef const& ark, TaggedScalar const& v) : type((ark.type|KEYVAL|VALTAG )), key(k ), key_tag( ), key_anchor(ark), val(v.scalar), val_tag(v.tag), val_anchor(), children(), parent(nullptr) { _set_parent(); } - template explicit CaseNode(TaggedScalar const& k, AnchorRef const& ark, const char (&v)[M] ) : type((ark.type|KEYVAL|KEYTAG )), key(k.scalar), key_tag(k.tag), key_anchor(ark), val(v ), val_tag( ), val_anchor(), children(), parent(nullptr) { _set_parent(); } - explicit CaseNode(TaggedScalar const& k, AnchorRef const& ark, TaggedScalar const& v) : type((ark.type|KEYVAL|KEYTAG|VALTAG)), key(k.scalar), key_tag(k.tag), key_anchor(ark), val(v.scalar), val_tag(v.tag), val_anchor(), children(), parent(nullptr) { _set_parent(); } - // keyval, with key anchor/ref + val anchor/ref - template explicit CaseNode(const char (&k)[N] , AnchorRef const& ark, const char (&v)[M] , AnchorRef const& arv) : type((ark.type|arv.type|KEYVAL )), key(k ), key_tag( ), key_anchor(ark), val(v ), val_tag( ), val_anchor(arv), children(), parent(nullptr) { _set_parent(); } - template explicit CaseNode(const char (&k)[N] , AnchorRef const& ark, TaggedScalar const& v, AnchorRef const& arv) : type((ark.type|arv.type|KEYVAL|VALTAG )), key(k ), key_tag( ), key_anchor(ark), val(v.scalar), val_tag(v.tag), val_anchor(arv), children(), parent(nullptr) { _set_parent(); } - template explicit CaseNode(TaggedScalar const& k, AnchorRef const& ark, const char (&v)[M] , AnchorRef const& arv) : type((ark.type|arv.type|KEYVAL|KEYTAG )), key(k.scalar), key_tag(k.tag), key_anchor(ark), val(v ), val_tag( ), val_anchor(arv), children(), parent(nullptr) { _set_parent(); } - explicit CaseNode(TaggedScalar const& k, AnchorRef const& ark, TaggedScalar const& v, AnchorRef const& arv) : type((ark.type|arv.type|KEYVAL|KEYTAG|VALTAG)), key(k.scalar), key_tag(k.tag), key_anchor(ark), val(v.scalar), val_tag(v.tag), val_anchor(arv), children(), parent(nullptr) { _set_parent(); } - - - // keyval, explicit type - template explicit CaseNode(NodeType t, const char (&k)[N] , const char (&v)[M] ) : type((KEYVAL|t )), key(k ), key_tag( ), key_anchor(), val(v ), val_tag( ), val_anchor(), children(), parent(nullptr) { _set_parent(); } - template explicit CaseNode(NodeType t, const char (&k)[N] , std::nullptr_t ) : type((KEYVAL|t )), key(k ), key_tag( ), key_anchor(), val( ), val_tag( ), val_anchor(), children(), parent(nullptr) { _set_parent(); } - template explicit CaseNode(NodeType t, std::nullptr_t , const char (&v)[M] ) : type((KEYVAL|t )), key( ), key_tag( ), key_anchor(), val(v ), val_tag( ), val_anchor(), children(), parent(nullptr) { _set_parent(); } - template explicit CaseNode(NodeType t, const char (&k)[N] , TaggedScalar const& v) : type((KEYVAL|VALTAG|t )), key(k ), key_tag( ), key_anchor(), val(v.scalar), val_tag(v.tag), val_anchor(), children(), parent(nullptr) { _set_parent(); } - template explicit CaseNode(NodeType t, TaggedScalar const& k, const char (&v)[M] ) : type((KEYVAL|KEYTAG|t )), key(k.scalar), key_tag(k.tag), key_anchor(), val(v ), val_tag( ), val_anchor(), children(), parent(nullptr) { _set_parent(); } - explicit CaseNode(NodeType t, TaggedScalar const& k, TaggedScalar const& v) : type((KEYVAL|KEYTAG|VALTAG|t)), key(k.scalar), key_tag(k.tag), key_anchor(), val(v.scalar), val_tag(v.tag), val_anchor(), children(), parent(nullptr) { _set_parent(); } - explicit CaseNode(NodeType t, TaggedScalar const& k, std::nullptr_t ) : type((KEYVAL|KEYTAG |t)), key(k.scalar), key_tag(k.tag), key_anchor(), val( ), val_tag( ), val_anchor(), children(), parent(nullptr) { _set_parent(); } - explicit CaseNode(NodeType t, std::nullptr_t , TaggedScalar const& v) : type((KEYVAL |VALTAG|t)), key( ), key_tag( ), key_anchor(), val(v.scalar), val_tag(v.tag), val_anchor(), children(), parent(nullptr) { _set_parent(); } - explicit CaseNode(NodeType t, std::nullptr_t , std::nullptr_t ) : type((KEYVAL |t)), key( ), key_tag( ), key_anchor(), val( ), val_tag( ), val_anchor(), children(), parent(nullptr) { _set_parent(); } - // keyval, explicit type, with val anchor/ref - template explicit CaseNode(NodeType t, const char (&k)[N] , const char (&v)[M] , AnchorRef const& arv) : type((arv.type|KEYVAL|t )), key(k ), key_tag( ), key_anchor(), val(v ), val_tag( ), val_anchor(arv), children(), parent(nullptr) { _set_parent(); } - template explicit CaseNode(NodeType t, const char (&k)[N] , TaggedScalar const& v, AnchorRef const& arv) : type((arv.type|KEYVAL|VALTAG|t )), key(k ), key_tag( ), key_anchor(), val(v.scalar), val_tag(v.tag), val_anchor(arv), children(), parent(nullptr) { _set_parent(); } - template explicit CaseNode(NodeType t, TaggedScalar const& k, const char (&v)[M] , AnchorRef const& arv) : type((arv.type|KEYVAL|KEYTAG|t )), key(k.scalar), key_tag(k.tag), key_anchor(), val(v ), val_tag( ), val_anchor(arv), children(), parent(nullptr) { _set_parent(); } - explicit CaseNode(NodeType t, TaggedScalar const& k, TaggedScalar const& v, AnchorRef const& arv) : type((arv.type|KEYVAL|KEYTAG|VALTAG|t)), key(k.scalar), key_tag(k.tag), key_anchor(), val(v.scalar), val_tag(v.tag), val_anchor(arv), children(), parent(nullptr) { _set_parent(); } - // keyval, explicit type, with key anchor/ref - template explicit CaseNode(NodeType t, const char (&k)[N] , AnchorRef const& ark, const char (&v)[M] ) : type((ark.type|KEYVAL|t )), key(k ), key_tag( ), key_anchor(ark), val(v ), val_tag( ), val_anchor(), children(), parent(nullptr) { _set_parent(); } - template explicit CaseNode(NodeType t, const char (&k)[N] , AnchorRef const& ark, TaggedScalar const& v) : type((ark.type|KEYVAL|VALTAG|t )), key(k ), key_tag( ), key_anchor(ark), val(v.scalar), val_tag(v.tag), val_anchor(), children(), parent(nullptr) { _set_parent(); } - template explicit CaseNode(NodeType t, TaggedScalar const& k, AnchorRef const& ark, const char (&v)[M] ) : type((ark.type|KEYVAL|KEYTAG|t )), key(k.scalar), key_tag(k.tag), key_anchor(ark), val(v ), val_tag( ), val_anchor(), children(), parent(nullptr) { _set_parent(); } - explicit CaseNode(NodeType t, TaggedScalar const& k, AnchorRef const& ark, TaggedScalar const& v) : type((ark.type|KEYVAL|KEYTAG|VALTAG|t)), key(k.scalar), key_tag(k.tag), key_anchor(ark), val(v.scalar), val_tag(v.tag), val_anchor(), children(), parent(nullptr) { _set_parent(); } - // keyval, explicit type, with key anchor/ref + val anchor/ref - template explicit CaseNode(NodeType t, const char (&k)[N] , AnchorRef const& ark, const char (&v)[M] , AnchorRef const& arv) : type((ark.type|arv.type|KEYVAL|t )), key(k ), key_tag( ), key_anchor(ark), val(v ), val_tag( ), val_anchor(arv), children(), parent(nullptr) { _set_parent(); } - template explicit CaseNode(NodeType t, const char (&k)[N] , AnchorRef const& ark, TaggedScalar const& v, AnchorRef const& arv) : type((ark.type|arv.type|KEYVAL|VALTAG|t )), key(k ), key_tag( ), key_anchor(ark), val(v.scalar), val_tag(v.tag), val_anchor(arv), children(), parent(nullptr) { _set_parent(); } - template explicit CaseNode(NodeType t, TaggedScalar const& k, AnchorRef const& ark, const char (&v)[M] , AnchorRef const& arv) : type((ark.type|arv.type|KEYVAL|KEYTAG|t )), key(k.scalar), key_tag(k.tag), key_anchor(ark), val(v ), val_tag( ), val_anchor(arv), children(), parent(nullptr) { _set_parent(); } - explicit CaseNode(NodeType t, TaggedScalar const& k, AnchorRef const& ark, TaggedScalar const& v, AnchorRef const& arv) : type((ark.type|arv.type|KEYVAL|KEYTAG|VALTAG|t)), key(k.scalar), key_tag(k.tag), key_anchor(ark), val(v.scalar), val_tag(v.tag), val_anchor(arv), children(), parent(nullptr) { _set_parent(); } - - - // container - template explicit CaseNode(const char (&k)[N] , iseqmap s) : type(), key(k ), key_tag( ), key_anchor(), val(), val_tag( ), val_anchor(), children(s ), parent(nullptr) { _set_parent(); type = _guess(); } - template explicit CaseNode(const char (&k)[N] , TaggedList s) : type(), key(k ), key_tag( ), key_anchor(), val(), val_tag(s.tag), val_anchor(), children(s.ilist), parent(nullptr) { _set_parent(); type = _guess(); } - explicit CaseNode(TaggedScalar const& k, iseqmap s) : type(), key(k.scalar), key_tag(k.tag), key_anchor(), val(), val_tag( ), val_anchor(), children(s ), parent(nullptr) { _set_parent(); type = _guess(); } - explicit CaseNode(TaggedScalar const& k, TaggedList s) : type(), key(k.scalar), key_tag(k.tag), key_anchor(), val(), val_tag(s.tag), val_anchor(), children(s.ilist), parent(nullptr) { _set_parent(); type = _guess(); } - explicit CaseNode( iseqmap m) : CaseNode("", m) {} - explicit CaseNode( TaggedList m) : CaseNode("", m) {} - // container, with val anchor/ref - template explicit CaseNode(const char (&k)[N] , iseqmap s, AnchorRef const& arv) : type(), key(k ), key_tag( ), key_anchor(), val(), val_tag( ), val_anchor(arv), children(s ), parent(nullptr) { _set_parent(); type = _guess(); } - template explicit CaseNode(const char (&k)[N] , TaggedList s, AnchorRef const& arv) : type(), key(k ), key_tag( ), key_anchor(), val(), val_tag(s.tag), val_anchor(arv), children(s.ilist), parent(nullptr) { _set_parent(); type = _guess(); } - explicit CaseNode(TaggedScalar const& k, iseqmap s, AnchorRef const& arv) : type(), key(k.scalar), key_tag(k.tag), key_anchor(), val(), val_tag( ), val_anchor(arv), children(s ), parent(nullptr) { _set_parent(); type = _guess(); } - explicit CaseNode(TaggedScalar const& k, TaggedList s, AnchorRef const& arv) : type(), key(k.scalar), key_tag(k.tag), key_anchor(), val(), val_tag(s.tag), val_anchor(arv), children(s.ilist), parent(nullptr) { _set_parent(); type = _guess(); } - explicit CaseNode( iseqmap m, AnchorRef const& arv) : CaseNode("", m, arv) {} - explicit CaseNode( TaggedList m, AnchorRef const& arv) : CaseNode("", m, arv) {} - // container, with key anchor/ref - template explicit CaseNode(const char (&k)[N] , AnchorRef const& ark, iseqmap s) : type(), key(k ), key_tag( ), key_anchor(ark), val(), val_tag( ), val_anchor(), children(s ), parent(nullptr) { _set_parent(); type = _guess(); } - template explicit CaseNode(const char (&k)[N] , AnchorRef const& ark, TaggedList s) : type(), key(k ), key_tag( ), key_anchor(ark), val(), val_tag(s.tag), val_anchor(), children(s.ilist), parent(nullptr) { _set_parent(); type = _guess(); } - explicit CaseNode(TaggedScalar const& k, AnchorRef const& ark, iseqmap s) : type(), key(k.scalar), key_tag(k.tag), key_anchor(ark), val(), val_tag( ), val_anchor(), children(s ), parent(nullptr) { _set_parent(); type = _guess(); } - explicit CaseNode(TaggedScalar const& k, AnchorRef const& ark, TaggedList s) : type(), key(k.scalar), key_tag(k.tag), key_anchor(ark), val(), val_tag(s.tag), val_anchor(), children(s.ilist), parent(nullptr) { _set_parent(); type = _guess(); } - // container, with key anchor/ref + val anchor/ref - template explicit CaseNode(const char (&k)[N] , AnchorRef const& ark, iseqmap s, AnchorRef const& arv) : type(), key(k ), key_tag( ), key_anchor(ark), val(), val_tag( ), val_anchor(arv), children(s ), parent(nullptr) { _set_parent(); type = _guess(); } - template explicit CaseNode(const char (&k)[N] , AnchorRef const& ark, TaggedList s, AnchorRef const& arv) : type(), key(k ), key_tag( ), key_anchor(ark), val(), val_tag(s.tag), val_anchor(arv), children(s.ilist), parent(nullptr) { _set_parent(); type = _guess(); } - explicit CaseNode(TaggedScalar const& k, AnchorRef const& ark, iseqmap s, AnchorRef const& arv) : type(), key(k.scalar), key_tag(k.tag), key_anchor(ark), val(), val_tag( ), val_anchor(arv), children(s ), parent(nullptr) { _set_parent(); type = _guess(); } - explicit CaseNode(TaggedScalar const& k, AnchorRef const& ark, TaggedList s, AnchorRef const& arv) : type(), key(k.scalar), key_tag(k.tag), key_anchor(ark), val(), val_tag(s.tag), val_anchor(arv), children(s.ilist), parent(nullptr) { _set_parent(); type = _guess(); } - - - // container, explicit type - template explicit CaseNode(NodeType t, const char (&k)[N] , iseqmap s) : type((t )), key(k ), key_tag( ), key_anchor(), val(), val_tag( ), val_anchor(), children(s ), parent(nullptr) { _set_parent(); } - template explicit CaseNode(NodeType t, const char (&k)[N] , TaggedList s) : type((t|VALTAG)), key(k ), key_tag( ), key_anchor(), val(), val_tag(s.tag), val_anchor(), children(s.ilist), parent(nullptr) { _set_parent(); } - explicit CaseNode(NodeType t, TaggedScalar const& k, iseqmap s) : type((t|KEYTAG)), key(k.scalar), key_tag(k.tag), key_anchor(), val(), val_tag( ), val_anchor(), children(s ), parent(nullptr) { _set_parent(); } - explicit CaseNode(NodeType t, iseqmap s) : type((t )), key( ), key_tag( ), key_anchor(), val(), val_tag( ), val_anchor(), children(s ), parent(nullptr) { _set_parent(); } - explicit CaseNode(NodeType t, TaggedList s) : type((t|VALTAG)), key( ), key_tag( ), key_anchor(), val(), val_tag(s.tag), val_anchor(), children(s.ilist), parent(nullptr) { _set_parent(); } - // container, explicit type, with val anchor/ref - template explicit CaseNode(NodeType t, const char (&k)[N] , iseqmap s, AnchorRef const& arv) : type((t |VALANCH)), key(k ), key_tag( ), key_anchor(), val(), val_tag( ), val_anchor(arv), children(s ), parent(nullptr) { _set_parent(); } - template explicit CaseNode(NodeType t, const char (&k)[N] , TaggedList s, AnchorRef const& arv) : type((t|VALTAG|VALANCH)), key(k ), key_tag( ), key_anchor(), val(), val_tag(s.tag), val_anchor(arv), children(s.ilist), parent(nullptr) { _set_parent(); } - explicit CaseNode(NodeType t, TaggedScalar const& k, iseqmap s, AnchorRef const& arv) : type((t|KEYTAG|VALANCH)), key(k.scalar), key_tag(k.tag), key_anchor(), val(), val_tag( ), val_anchor(arv), children(s ), parent(nullptr) { _set_parent(); } - explicit CaseNode(NodeType t, iseqmap s, AnchorRef const& arv) : type((t |VALANCH)), key( ), key_tag( ), key_anchor(), val(), val_tag( ), val_anchor(arv), children(s ), parent(nullptr) { _set_parent(); } - explicit CaseNode(NodeType t, TaggedList s, AnchorRef const& arv) : type((t|VALTAG|VALANCH)), key( ), key_tag( ), key_anchor(), val(), val_tag(s.tag), val_anchor(arv), children(s.ilist), parent(nullptr) { _set_parent(); } - // container, explicit type, with key anchor/ref - template explicit CaseNode(NodeType t, const char (&k)[N] , AnchorRef const& ark, iseqmap s) : type((t |KEYANCH)), key(k ), key_tag( ), key_anchor(ark), val(), val_tag( ), val_anchor(), children(s ), parent(nullptr) { _set_parent(); } - template explicit CaseNode(NodeType t, const char (&k)[N] , AnchorRef const& ark, TaggedList s) : type((t|VALTAG|KEYANCH)), key(k ), key_tag( ), key_anchor(ark), val(), val_tag(s.tag), val_anchor(), children(s.ilist), parent(nullptr) { _set_parent(); } - explicit CaseNode(NodeType t, TaggedScalar const& k, AnchorRef const& ark, iseqmap s) : type((t|KEYTAG|KEYANCH)), key(k.scalar), key_tag(k.tag), key_anchor(ark), val(), val_tag( ), val_anchor(), children(s ), parent(nullptr) { _set_parent(); } - // container, explicit type, with key anchor/ref + val anchor/ref - template explicit CaseNode(NodeType t, const char (&k)[N] , AnchorRef const& ark, iseqmap s, AnchorRef const& arv) : type((t |KEYANCH|VALANCH)), key(k ), key_tag( ), key_anchor(ark), val(), val_tag( ), val_anchor(arv), children(s ), parent(nullptr) { _set_parent(); } - template explicit CaseNode(NodeType t, const char (&k)[N] , AnchorRef const& ark, TaggedList s, AnchorRef const& arv) : type((t|VALTAG|KEYANCH|VALANCH)), key(k ), key_tag( ), key_anchor(ark), val(), val_tag(s.tag), val_anchor(arv), children(s.ilist), parent(nullptr) { _set_parent(); } - explicit CaseNode(NodeType t, TaggedScalar const& k, AnchorRef const& ark, iseqmap s, AnchorRef const& arv) : type((t|KEYTAG|KEYANCH|VALANCH)), key(k.scalar), key_tag(k.tag), key_anchor(ark), val(), val_tag( ), val_anchor(arv), children(s ), parent(nullptr) { _set_parent(); } - - -public: - - void _move(CaseNode&& that) - { - type = that.type; - key = that.key; - key_tag = that.key_tag; - key_anchor = that.key_anchor; - val = that.val; - val_tag = that.val_tag; - val_anchor = that.val_anchor; - children = std::move(that.children); - parent = nullptr; - _set_parent(); - } - void _copy(CaseNode const& that) - { - type = that.type; - key = that.key; - key_tag = that.key_tag; - key_anchor = that.key_anchor; - val = that.val; - val_tag = that.val_tag; - val_anchor = that.val_anchor; - children = that.children; - parent = nullptr; - _set_parent(); - } - - void _set_parent() - { - for(auto &ch : children) - { - ch.parent = this; - } - } - - NodeType_e _guess() const; - - bool is_root() const { return parent; } - bool is_doc() const { return type & DOC; } - bool is_map() const { return type & MAP; } - bool is_seq() const { return type & SEQ; } - bool has_val() const { return type & VAL; } - bool has_key() const { return type & KEY; } - bool is_container() const { return type & (SEQ|MAP); } - bool has_key_anchor() const { return type & KEYANCH; } - bool has_val_anchor() const { return type & VALANCH; } - -public: - - CaseNode const& operator[] (size_t i) const - { - C4_ASSERT(i >= 0 && i < children.size()); - return children[i]; - } - - CaseNode const& operator[] (csubstr const& name) const - { - auto ch = lookup(name); - C4_ASSERT(ch != nullptr); - return *ch; - } - - CaseNode const* lookup(csubstr const& name) const - { - C4_ASSERT( ! children.empty()); - for(auto const& ch : children) - if(ch.key == name) - return &ch; - return nullptr; - } - -public: - - void compare(yml::ConstNodeRef const& n, bool ignore_quote=false) const; - void compare_child(yml::ConstNodeRef const& n, size_t pos) const; - - size_t reccount() const - { - size_t c = 1; - for(auto const& ch : children) - c += ch.reccount(); - return c; - } - - void recreate(yml::NodeRef *n) const; - -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -typedef enum { - EXPECT_PARSE_ERROR = (1<<0), - RESOLVE_REFS = (1<<1), - JSON_ALSO = (1<<2), // TODO: make it the opposite: opt-out instead of opt-in -} TestCaseFlags_e; - - -struct Case -{ - std::string filelinebuf; - csubstr fileline; - csubstr name; - csubstr src; - CaseNode root; - TestCaseFlags_e flags; - Location expected_location; - - //! create a standard test case: name, source and expected CaseNode structure - template Case(csubstr file, int line, const char *name_, const char *src_, Args&& ...args) : filelinebuf(catrs(file, ':', line)), fileline(to_csubstr(filelinebuf)), name(to_csubstr(name_)), src(to_csubstr(src_)), root(std::forward(args)...), flags(), expected_location() {} - //! create a test case with explicit flags: name, source flags, and expected CaseNode structure - template Case(csubstr file, int line, const char *name_, int f_, const char *src_, Args&& ...args) : filelinebuf(catrs(file, ':', line)), fileline(to_csubstr(filelinebuf)), name(to_csubstr(name_)), src(to_csubstr(src_)), root(std::forward(args)...), flags((TestCaseFlags_e)f_), expected_location() {} - //! create a test case with an error on an expected location - Case(csubstr file, int line, const char *name_, int f_, const char *src_, LineCol loc) : filelinebuf(catrs(file, ':', line)), fileline(to_csubstr(filelinebuf)), name(to_csubstr(name_)), src(to_csubstr(src_)), root(), flags((TestCaseFlags_e)f_), expected_location(name, loc.line, loc.col) {} -}; - -//----------------------------------------------------------------------------- - -// a persistent data store to avoid repeating operations on every test -struct CaseDataLineEndings -{ - std::vector src_buf; - substr src; - - Tree parsed_tree; - - size_t numbytes_stdout; - size_t numbytes_stdout_json; - - std::string emit_buf; - csubstr emitted_yml; - - std::string emitjson_buf; - csubstr emitted_json; - - std::string parse_buf; - substr parsed_yml; - - std::string parse_buf_json; - substr parsed_json; - - Tree emitted_tree; - Tree emitted_tree_json; - - Tree recreated; -}; - - -struct CaseData -{ - CaseDataLineEndings unix_style; - CaseDataLineEndings unix_style_json; - CaseDataLineEndings windows_style; - CaseDataLineEndings windows_style_json; -}; - - -} // namespace yml -} // namespace c4 - -#if defined(_MSC_VER) -# pragma warning(pop) -#endif - -#ifdef __GNUC__ -# pragma GCC diagnostic pop -#endif - -#endif /* _TEST_CASE_HPP_ */ diff --git a/thirdparty/ryml/test/test_double_quoted.cpp b/thirdparty/ryml/test/test_double_quoted.cpp deleted file mode 100644 index 6c3915873..000000000 --- a/thirdparty/ryml/test/test_double_quoted.cpp +++ /dev/null @@ -1,610 +0,0 @@ -#include "./test_group.hpp" - -namespace c4 { -namespace yml { - -TEST(double_quoted, escaped_chars) -{ - csubstr yaml = R"("\\\"\n\r\t\ \/\ \0\b\f\a\v\e\_\N\L\P")"; - // build the string like this because some of the characters are - // filtered out under the double quotes - std::string expected; - expected += '\\'; - expected += '"'; - expected += '\n'; - expected += '\r'; - expected += '\t'; - expected += '\t'; - expected += '/'; - expected += ' '; - expected += '\0'; - expected += '\b'; - expected += '\f'; - expected += '\a'; - expected += '\v'; - expected += INT8_C(0x1b); // \e - // - // wrap explicitly to avoid overflow - expected += _RYML_CHCONST(-0x3e, 0xc2); // \_ (1) - expected += _RYML_CHCONST(-0x60, 0xa0); // \_ (2) - // - expected += _RYML_CHCONST(-0x3e, 0xc2); // \N (1) - expected += _RYML_CHCONST(-0x7b, 0x85); // \N (2) - // - expected += _RYML_CHCONST(-0x1e, 0xe2); // \L (1) - expected += _RYML_CHCONST(-0x80, 0x80); // \L (2) - expected += _RYML_CHCONST(-0x58, 0xa8); // \L (3) - // - expected += _RYML_CHCONST(-0x1e, 0xe2); // \P (1) - expected += _RYML_CHCONST(-0x80, 0x80); // \P (2) - expected += _RYML_CHCONST(-0x57, 0xa9); // \P (3) - // - Tree t = parse_in_arena(yaml); - csubstr v = t.rootref().val(); - std::string actual = {v.str, v.len}; - EXPECT_EQ(actual, expected); -} - -TEST(double_quoted, test_suite_3RLN) -{ - csubstr yaml = R"(--- -"1 leading - \ttab" ---- -"2 leading - \ tab" ---- -"3 leading - tab" ---- -"4 leading - \t tab" ---- -"5 leading - \ tab" ---- -"6 leading - tab" -)"; - test_check_emit_check(yaml, [](Tree const &t){ - EXPECT_EQ(t.docref(0).val(), "1 leading \ttab"); - EXPECT_EQ(t.docref(1).val(), "2 leading \ttab"); - EXPECT_EQ(t.docref(2).val(), "3 leading tab"); - EXPECT_EQ(t.docref(3).val(), "4 leading \t tab"); - EXPECT_EQ(t.docref(4).val(), "5 leading \t tab"); - EXPECT_EQ(t.docref(5).val(), "6 leading tab"); - }); -} - -TEST(double_quoted, test_suite_5GBF) -{ - csubstr yaml = R"( -Folding: - "Empty line - - as a line feed" -Folding2: - "Empty line - - as a line feed" -Folding3: - "Empty line - - as a line feed" -)"; - test_check_emit_check(yaml, [](Tree const &t){ - ASSERT_TRUE(t.rootref().is_map()); - EXPECT_EQ(t["Folding"].val(), csubstr("Empty line\nas a line feed")); - EXPECT_EQ(t["Folding2"].val(), csubstr("Empty line\nas a line feed")); - EXPECT_EQ(t["Folding3"].val(), csubstr("Empty line\nas a line feed")); - }); -} - -TEST(double_quoted, test_suite_6SLA) -{ - csubstr yaml = R"( -"foo\nbar:baz\tx \\$%^&*()x": 23 -'x\ny:z\tx $%^&*()x': 24 -)"; - test_check_emit_check(yaml, [](Tree const &t){ - ASSERT_TRUE(t.rootref().is_map()); - ASSERT_TRUE(t.rootref().has_child("foo\nbar:baz\tx \\$%^&*()x")); - ASSERT_TRUE(t.rootref().has_child("x\\ny:z\\tx $%^&*()x")); - ASSERT_EQ(t["foo\nbar:baz\tx \\$%^&*()x"].val(), csubstr("23")); - ASSERT_EQ(t["x\\ny:z\\tx $%^&*()x"].val(), csubstr("24")); - }); -} - -TEST(double_quoted, test_suite_6WPF) -{ - csubstr yaml = R"( -" - foo - - bar - - baz -" -)"; - test_check_emit_check(yaml, [](Tree const &t){ - ASSERT_TRUE(t.rootref().is_val()); - EXPECT_EQ(t.rootref().val(), csubstr(" foo\nbar\nbaz ")); - }); -} - -TEST(double_quoted, test_suite_9TFX) -{ - csubstr yaml = R"( -" 1st non-empty - - 2nd non-empty - 3rd non-empty " -)"; - test_check_emit_check(yaml, [](Tree const &t){ - ASSERT_TRUE(t.rootref().is_val()); - EXPECT_EQ(t.rootref().val(), csubstr(" 1st non-empty\n2nd non-empty 3rd non-empty ")); - }); -} - -TEST(double_quoted, test_suite_G4RS) -{ - csubstr yaml = R"(--- -unicode: "\u263A\u2705\U0001D11E" -control: "\b1998\t1999\t2000\n" -#hex esc: "\x0d\x0a is \r\n" -#--- -#- "\x0d\x0a is \r\n" -#--- -#{hex esc: "\x0d\x0a is \r\n"} -#--- -#["\x0d\x0a is \r\n"] -)"; - test_check_emit_check(yaml, [](Tree const &t){ - EXPECT_EQ(t.docref(0)["unicode"].val(), csubstr(R"(☺✅𝄞)")); - EXPECT_EQ(t.docref(0)["control"].val(), csubstr("\b1998\t1999\t2000\n")); - //EXPECT_EQ(t.docref(0)["hex esc"].val(), csubstr("\r\n is \r\n")); TODO - //EXPECT_EQ(t.docref(1)[0].val(), csubstr("\r\n is \r\n")); - //EXPECT_EQ(t.docref(2)[0].val(), csubstr("\r\n is \r\n")); - //EXPECT_EQ(t.docref(3)[0].val(), csubstr("\r\n is \r\n")); - }); -} - -TEST(double_quoted, test_suite_KSS4) -{ - csubstr yaml = R"( ---- -"quoted -string" ---- "quoted -string" ---- -- "quoted - string" ---- -- "quoted -string" ---- -"quoted - string": "quoted - string" ---- -"quoted -string": "quoted -string" -)"; - test_check_emit_check(yaml, [](Tree const &t){ - EXPECT_EQ(t.docref(0).val(), "quoted string"); - EXPECT_EQ(t.docref(1).val(), "quoted string"); - EXPECT_EQ(t.docref(2)[0].val(), "quoted string"); - EXPECT_EQ(t.docref(3)[0].val(), "quoted string"); - EXPECT_EQ(t.docref(4)["quoted string"].val(), "quoted string"); - EXPECT_EQ(t.docref(5)["quoted string"].val(), "quoted string"); - }); -} - -TEST(double_quoted, test_suite_NAT4) -{ - csubstr yaml = R"( -a: ' - ' -b: ' - ' -c: " - " -d: " - " -e: ' - - ' -f: " - - " -g: ' - - - ' -h: " - - - " -)"; - test_check_emit_check(yaml, [](Tree const &t){ - EXPECT_EQ(t["a"].val(), csubstr(" ")); - EXPECT_EQ(t["b"].val(), csubstr(" ")); - EXPECT_EQ(t["c"].val(), csubstr(" ")); - EXPECT_EQ(t["d"].val(), csubstr(" ")); - EXPECT_EQ(t["e"].val(), csubstr("\n")); - EXPECT_EQ(t["f"].val(), csubstr("\n")); - EXPECT_EQ(t["g"].val(), csubstr("\n\n")); - EXPECT_EQ(t["h"].val(), csubstr("\n\n")); - }); -} - -TEST(double_quoted, test_suite_NP9H) -{ - csubstr yaml = R"( -"folded -to a space, - -to a line feed, or \ - \ non-content" -)"; - test_check_emit_check(yaml, [](Tree const &t){ - ASSERT_TRUE(t.rootref().is_val()); - EXPECT_EQ(t.rootref().val(), csubstr("folded to a space,\nto a line feed, or \t \tnon-content")); - }); -} - -TEST(double_quoted, test_suite_Q8AD) -{ - csubstr yaml = R"( -"folded -to a space, - -to a line feed, or \ - \ non-content" -)"; - test_check_emit_check(yaml, [](Tree const &t){ - ASSERT_TRUE(t.rootref().is_val()); - EXPECT_EQ(t.rootref().val(), csubstr("folded to a space,\nto a line feed, or \t \tnon-content")); - }); -} - -TEST(double_quoted, test_suite_R4YG) -{ - csubstr yaml = R"( -- " - -detected - -" - -)"; - test_check_emit_check(yaml, [](Tree const &t){ - EXPECT_EQ(t[0].val(), csubstr("\t\ndetected\n")); - }); -} - - -//----------------------------------------------------------------------------- - -void verify_error_is_reported(csubstr case_name, csubstr yaml, Location loc={}) -{ - SCOPED_TRACE(case_name); - SCOPED_TRACE(yaml); - Tree tree; - ExpectError::do_check(&tree, [&](){ - parse_in_arena(yaml, &tree); - }, loc); -} - -TEST(double_quoted, error_on_unmatched_quotes) -{ - verify_error_is_reported("map block", R"(foo: "' -bar: "")"); - verify_error_is_reported("seq block", R"(- "' -- "")"); - verify_error_is_reported("map flow", R"({foo: "', bar: ""})"); - verify_error_is_reported("seq flow", R"(["', ""])"); -} - -TEST(double_quoted, error_on_unmatched_quotes_with_escapes) -{ - verify_error_is_reported("map block", R"(foo: "\"' -bar: "")"); - verify_error_is_reported("seq block", R"(- "\"' -- "")"); - verify_error_is_reported("map flow", R"({foo: "\"', bar: ""})"); - verify_error_is_reported("seq flow", R"(["\"', ""])"); -} - -TEST(double_quoted, error_on_unmatched_quotes_at_end) -{ - verify_error_is_reported("map block", R"(foo: "" -bar: "')"); - verify_error_is_reported("seq block", R"(- "" -- "')"); - verify_error_is_reported("map flow", R"({foo: "", bar: "'})"); - verify_error_is_reported("seq flow", R"(["", "'])"); -} - -TEST(double_quoted, error_on_unmatched_quotes_at_end_with_escapes) -{ - verify_error_is_reported("map block", R"(foo: "" -bar: "\"')"); - verify_error_is_reported("seq block", R"(- "" -- "\"')"); - verify_error_is_reported("map flow", R"({foo: "", bar: "\"'})"); - verify_error_is_reported("seq flow", R"(["", "\"'])"); -} - -TEST(double_quoted, error_on_unclosed_quotes) -{ - verify_error_is_reported("map block", R"(foo: ", -bar: what)"); - verify_error_is_reported("seq block", R"(- " -- what)"); - verify_error_is_reported("map flow", R"({foo: ", bar: what})"); - verify_error_is_reported("seq flow", R"([", what])"); -} - -TEST(double_quoted, error_on_unclosed_quotes_with_escapes) -{ - verify_error_is_reported("map block", R"(foo: "\", -bar: what)"); - verify_error_is_reported("seq block", R"(- "\" -- what)"); - verify_error_is_reported("map flow", R"({foo: "\", bar: what})"); - verify_error_is_reported("seq flow", R"(["\", what])"); -} - -TEST(double_quoted, error_on_unclosed_quotes_at_end) -{ - verify_error_is_reported("map block", R"(foo: what -bar: ")"); - verify_error_is_reported("seq block", R"(- what -- ")"); - verify_error_is_reported("map flow", R"({foo: what, bar: "})"); - verify_error_is_reported("seq flow", R"([what, "])"); -} - -TEST(double_quoted, error_on_unclosed_quotes_at_end_with_escapes) -{ - verify_error_is_reported("map block", R"(foo: what -bar: "\")"); - verify_error_is_reported("seq block", R"(- what -- "\")"); - verify_error_is_reported("map flow", R"({foo: what, bar: "\"})"); - verify_error_is_reported("seq flow", R"([what, "\"])"); -} - -TEST(double_quoted, error_on_bad_utf_codepoints) -{ - verify_error_is_reported("incomplete \\x 0", R"(foo: "\x")"); - verify_error_is_reported("incomplete \\x 1", R"(foo: "\x1")"); - verify_error_is_reported("bad value \\x" , R"(foo: "\xko")"); - verify_error_is_reported("incomplete \\u 0", R"(foo: "\u")"); - verify_error_is_reported("incomplete \\u 1", R"(foo: "\u1")"); - verify_error_is_reported("incomplete \\u 2", R"(foo: "\u12")"); - verify_error_is_reported("incomplete \\u 3", R"(foo: "\u123")"); - verify_error_is_reported("bad value \\u" , R"(foo: "\ukoko")"); - verify_error_is_reported("incomplete \\U 0", R"(foo: "\U")"); - verify_error_is_reported("incomplete \\U 1", R"(foo: "\U1")"); - verify_error_is_reported("incomplete \\U 2", R"(foo: "\U12")"); - verify_error_is_reported("incomplete \\U 3", R"(foo: "\U123")"); - verify_error_is_reported("incomplete \\U 4", R"(foo: "\U1234")"); - verify_error_is_reported("incomplete \\U 5", R"(foo: "\U12345")"); - verify_error_is_reported("incomplete \\U 6", R"(foo: "\U123456")"); - verify_error_is_reported("incomplete \\U 7", R"(foo: "\U1234567")"); - verify_error_is_reported("bad value \\U" , R"(foo: "\Ukokokoko")"); -} - -TEST(double_quoted, github253) -{ - { - Tree tree; - NodeRef root = tree.rootref(); - root |= MAP; - root["t"] = "t't\\nt"; - root["t"] |= _WIP_VAL_DQUO; - std::string s = emitrs_yaml(tree); - Tree tree2 = parse_in_arena(to_csubstr(s)); - EXPECT_EQ(tree2["t"].val(), tree["t"].val()); - } - { - Tree tree; - NodeRef root = tree.rootref(); - root |= MAP; - root["t"] = "t't\\nt"; - root["t"] |= _WIP_VAL_SQUO; - std::string s = emitrs_yaml(tree); - Tree tree2 = parse_in_arena(to_csubstr(s)); - EXPECT_EQ(tree2["t"].val(), tree["t"].val()); - } - { - Tree tree; - NodeRef root = tree.rootref(); - root |= MAP; - root["s"] = "t\rt"; - root["s"] |= _WIP_VAL_DQUO; - std::string s = emitrs_yaml(tree); - EXPECT_EQ(s, "s: \"t\\rt\"\n"); - Tree tree2 = parse_in_arena(to_csubstr(s)); - EXPECT_EQ(tree2["s"].val(), tree["s"].val()); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -CASE_GROUP(DOUBLE_QUOTED) -{ - -ADD_CASE_TO_GROUP("dquoted, only text", -R"("Some text without any quotes." -)", - N(DOCVAL | VALQUO, "Some text without any quotes.") -); - -ADD_CASE_TO_GROUP("dquoted, with single quotes", -R"("Some text 'with single quotes'")", - N(DOCVAL|VALQUO, "Some text 'with single quotes'") -); - -ADD_CASE_TO_GROUP("dquoted, with double quotes", -R"("Some \"text\" \"with double quotes\"")", - N(DOCVAL|VALQUO, "Some \"text\" \"with double quotes\"") -); - -ADD_CASE_TO_GROUP("dquoted, with single and double quotes", -R"("Some text 'with single quotes' \"and double quotes\".")", - N(DOCVAL|VALQUO, "Some text 'with single quotes' \"and double quotes\".") -); - -ADD_CASE_TO_GROUP("dquoted, with escapes", -R"("Some text with escapes \\n \\r \\t")", - N(DOCVAL|VALQUO, "Some text with escapes \\n \\r \\t") -); - -ADD_CASE_TO_GROUP("dquoted, with newline", -R"("Some text with\nnewline")", - N(DOCVAL|VALQUO, "Some text with\nnewline") -); - -ADD_CASE_TO_GROUP("dquoted, with tabs", -R"("\tSome\ttext\twith\ttabs\t")", - N(DOCVAL|VALQUO, "\tSome\ttext\twith\ttabs\t") -); - -ADD_CASE_TO_GROUP("dquoted, with tabs 4ZYM", -R"(plain: text - lines -quoted: "text - lines" -block: | - text - lines -)", - L{N("plain", "text lines"), - N(KEYVAL|VALQUO, "quoted", "text lines"), - N(KEYVAL|VALQUO,"block", "text\n \tlines\n")} -); - -ADD_CASE_TO_GROUP("dquoted, with tabs 7A4E", -R"(" 1st non-empty - - 2nd non-empty - 3rd non-empty ")", - N(DOCVAL|VALQUO, " 1st non-empty\n2nd non-empty 3rd non-empty ") -); - -ADD_CASE_TO_GROUP("dquoted, with tabs TL85", -R"(" - foo - - bar - - baz -")", N(DOCVAL|VALQUO, " foo\nbar\nbaz ")); - -ADD_CASE_TO_GROUP("dquoted, all", -R"("Several lines of text, -containing 'single quotes' and \"double quotes\". \ -Escapes (like \\n) work.\nIn addition, -newlines can be esc\ -aped to prevent them from being converted to a space. - -Newlines can also be added by leaving a blank line. - Leading whitespace on lines is ignored." -)", - N(DOCVAL|VALQUO, "Several lines of text, containing 'single quotes' and \"double quotes\". Escapes (like \\n) work.\nIn addition, newlines can be escaped to prevent them from being converted to a space.\nNewlines can also be added by leaving a blank line. Leading whitespace on lines is ignored.") -); - -ADD_CASE_TO_GROUP("dquoted, empty", -R"("")", - N(DOCVAL|VALQUO, "") -); - -ADD_CASE_TO_GROUP("dquoted, blank", -R"( -- "" -- " " -- " " -- " " -- " " -)", - L{N(QV, ""), N(QV, " "), N(QV, " "), N(QV, " "), N(QV, " ")} -); - -ADD_CASE_TO_GROUP("dquoted, numbers", // these should not be quoted when emitting -R"( -- -1 -- -1.0 -- +1.0 -- 1e-2 -- 1e+2 -)", - L{N("-1"), N("-1.0"), N("+1.0"), N("1e-2"), N("1e+2")} -); - -ADD_CASE_TO_GROUP("dquoted, trailing space", -R"('a aaaa ')", - N(DOCVAL|VALQUO, "a aaaa ") -); - -ADD_CASE_TO_GROUP("dquoted, leading space", -R"(' a aaaa')", - N(DOCVAL|VALQUO, " a aaaa") -); - -ADD_CASE_TO_GROUP("dquoted, trailing and leading space", -R"(' 012345 ')", - N(DOCVAL|VALQUO, " 012345 ") -); - -ADD_CASE_TO_GROUP("dquoted, 1 dquote", -R"("\"")", - N(DOCVAL|VALQUO, "\"") -); - -ADD_CASE_TO_GROUP("dquoted, 2 dquotes", -R"("\"\"")", - N(DOCVAL|VALQUO, "\"\"") -); - -ADD_CASE_TO_GROUP("dquoted, 3 dquotes", -R"("\"\"\"")", - N(DOCVAL|VALQUO, "\"\"\"") -); - -ADD_CASE_TO_GROUP("dquoted, 4 dquotes", -R"("\"\"\"\"")", - N(DOCVAL|VALQUO, "\"\"\"\"") -); - -ADD_CASE_TO_GROUP("dquoted, 5 dquotes", -R"("\"\"\"\"\"")", - N(DOCVAL|VALQUO, "\"\"\"\"\"") -); - -ADD_CASE_TO_GROUP("dquoted, example 2", -R"("This is a key\nthat has multiple lines\n": and this is its value -)", - L{N(QK, "This is a key\nthat has multiple lines\n", "and this is its value")} -); - -ADD_CASE_TO_GROUP("dquoted, example 2.1", -R"("This is a key - -that has multiple lines - -": and this is its value -)", - L{N(QK, "This is a key\nthat has multiple lines\n", "and this is its value")} -); -} - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_emit.cpp b/thirdparty/ryml/test/test_emit.cpp deleted file mode 100644 index 3166dfaed..000000000 --- a/thirdparty/ryml/test/test_emit.cpp +++ /dev/null @@ -1,491 +0,0 @@ -#ifndef RYML_SINGLE_HEADER -#include "c4/yml/std/std.hpp" -#include "c4/yml/parse.hpp" -#include "c4/yml/emit.hpp" -#include -#include -#include -#endif -#include - -#include "./test_case.hpp" - -#include - -namespace c4 { -namespace yml { - -template -std::string emit2file(Emit &&fn) -{ - C4_SUPPRESS_WARNING_MSVC_WITH_PUSH(4996) // fopen unsafe - std::string filename = fs::tmpnam(); - FILE *f = fopen(filename.c_str(), "wb"); - C4_CHECK(f != nullptr); - fn(f); - fflush(f); - fclose(f); - std::string result = fs::file_get_contents(filename.c_str()); - fs::rmfile(filename.c_str()); - return result; - C4_SUPPRESS_WARNING_MSVC_POP -} - -template -std::string emit2stream(Emit &&fn) -{ - std::ostringstream ss; - fn(ss); - return ss.str(); -} - -template -std::string emit2buf(Emit &&fn) -{ - std::string buf; - buf.resize(2048); - substr out = fn(to_substr(buf)); - if(out.len > buf.size()) - { - buf.resize(out.len); - out = fn(to_substr(buf)); - } - buf.resize(out.len); - return buf; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -TEST(as_json, basic) -{ - Tree et; - { - as_json j(et); - EXPECT_EQ(j.tree, &et); - } - Tree t = parse_in_arena("[foo, bar]"); - { - as_json j(t); - EXPECT_EQ(j.tree, &t); - EXPECT_EQ(j.node, t.root_id()); - } - { - as_json j(t, 2u); - EXPECT_EQ(j.tree, &t); - EXPECT_EQ(j.node, 2u); - } - { - as_json j(t[0]); - EXPECT_EQ(j.tree, &t); - EXPECT_EQ(j.node, 1u); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -template -void test_emits(Tree const& t, size_t id, std::string const& expected, std::string const& expected_json) -{ - EXPECT_EQ(emit2buf([&](substr buf){ return emit_yaml(t, id, buf); }), expected); - EXPECT_EQ(emit2buf([&](substr buf){ return emit_json(t, id, buf); }), expected_json); - EXPECT_EQ(emit2file([&](FILE *f){ return emit_yaml(t, id, f); }), expected); - EXPECT_EQ(emit2file([&](FILE *f){ return emit_json(t, id, f); }), expected_json); - EXPECT_EQ(emitrs_yaml(t, id), expected); - EXPECT_EQ(emitrs_json(t, id), expected_json); -} - -template -void test_emits(Tree const& t, std::string const& expected, std::string const& expected_json) -{ - EXPECT_EQ(emit2buf([&](substr buf){ return emit_yaml(t, buf); }), expected); - EXPECT_EQ(emit2buf([&](substr buf){ return emit_json(t, buf); }), expected_json); - EXPECT_EQ(emit2file([&](FILE *f){ return emit_yaml(t, f); }), expected); - EXPECT_EQ(emit2file([&](FILE *f){ return emit_json(t, f); }), expected_json); - EXPECT_EQ(emit2stream([&](std::ostream& s){ s << t; }), expected); - EXPECT_EQ(emit2stream([&](std::ostream& s){ s << as_json(t); }), expected_json); - EXPECT_EQ(emitrs_yaml(t), expected); - EXPECT_EQ(emitrs_json(t), expected_json); -} - -template -void test_emits(ConstNodeRef t, std::string const& expected, std::string const& expected_json) -{ - EXPECT_EQ(emit2buf([&](substr buf){ return emit_yaml(t, buf); }), expected); - EXPECT_EQ(emit2buf([&](substr buf){ return emit_json(t, buf); }), expected_json); - EXPECT_EQ(emit2file([&](FILE *f){ return emit_yaml(t, f); }), expected); - EXPECT_EQ(emit2file([&](FILE *f){ return emit_json(t, f); }), expected_json); - EXPECT_EQ(emit2stream([&](std::ostream& s){ s << t; }), expected); - EXPECT_EQ(emit2stream([&](std::ostream& s){ s << as_json(t); }), expected_json); - EXPECT_EQ(emitrs_yaml(t), expected); - EXPECT_EQ(emitrs_json(t), expected_json); -} - - -TEST(emit, empty_tree) -{ - const Tree t; // must be const! - std::string expected = R"()"; - test_emits(t, expected, expected); -} - -TEST(emit, existing_tree) -{ - const Tree t = parse_in_arena("[foo, bar]"); - std::string expected = "- foo\n- bar\n"; - std::string expected_json = R"(["foo","bar"])"; - test_emits(t, expected, expected_json); -} - -TEST(emit, existing_seq_node) -{ - Tree nct = parse_in_arena("[foo, bar, [nested, seq], {nested: map}]"); - Tree const& t = nct; - { - std::string expected = "- foo\n- bar\n- - nested\n - seq\n- nested: map\n"; - std::string expected_json = R"(["foo","bar",["nested","seq"],{"nested": "map"}])"; - { - SCOPED_TRACE("rootref"); - test_emits(t.crootref(), expected, expected_json); - } - { - SCOPED_TRACE("t"); - test_emits(t, expected, expected_json); - } - { - SCOPED_TRACE("t, id"); - test_emits(t, t.root_id(), expected, expected_json); - } - } - { - ConstNodeRef n = t[0]; - std::string expected = "foo\n"; - std::string expected_json = "\"foo\""; - { - SCOPED_TRACE("noderef"); - test_emits(n, expected, expected_json); - } - { - SCOPED_TRACE("t, id"); - test_emits(t, n.id(), expected, expected_json); - } - nct._add_flags(n.id(), _WIP_STYLE_FLOW_SL); - expected = "foo"; - { - SCOPED_TRACE("t, id"); - test_emits(n, expected, expected_json); - } - { - SCOPED_TRACE("t, id"); - test_emits(t, n.id(), expected, expected_json); - } - } - { - ConstNodeRef n = t[1]; - std::string expected = "bar\n"; - std::string expected_json = "\"bar\""; - { - SCOPED_TRACE("noderef"); - test_emits(n, expected, expected_json); - } - { - SCOPED_TRACE("t, id"); - test_emits(t, n.id(), expected, expected_json); - } - nct._add_flags(n.id(), _WIP_STYLE_FLOW_SL); - expected = "bar"; - { - SCOPED_TRACE("t, id"); - test_emits(n, expected, expected_json); - } - { - SCOPED_TRACE("t, id"); - test_emits(t, n.id(), expected, expected_json); - } - - } - { - ConstNodeRef n = t[2]; - std::string expected = "- nested\n- seq\n"; - std::string expected_json = "[\"nested\",\"seq\"]"; - { - SCOPED_TRACE("noderef"); - test_emits(n, expected, expected_json); - } - { - SCOPED_TRACE("t, id"); - test_emits(t, n.id(), expected, expected_json); - } - expected = "[nested,seq]"; - nct._add_flags(n.id(), _WIP_STYLE_FLOW_SL); - { - SCOPED_TRACE("t, id"); - test_emits(n, expected, expected_json); - } - { - SCOPED_TRACE("t, id"); - test_emits(t, n.id(), expected, expected_json); - } - } - { - ConstNodeRef n = t[3]; - std::string expected = "nested: map\n"; - std::string expected_json = "{\"nested\": \"map\"}"; - { - SCOPED_TRACE("noderef"); - test_emits(n, expected, expected_json); - } - { - SCOPED_TRACE("t, id"); - test_emits(t, n.id(), expected, expected_json); - } - expected = "{nested: map}"; - nct._add_flags(n.id(), _WIP_STYLE_FLOW_SL); - { - SCOPED_TRACE("t, id"); - test_emits(n, expected, expected_json); - } - { - SCOPED_TRACE("t, id"); - test_emits(t, n.id(), expected, expected_json); - } - } -} - -TEST(emit, existing_map_node) -{ - Tree nct = parse_in_arena("{0: foo, 1: bar, 2: [nested, seq], 3: {nested: map}}"); - Tree const& t = nct; - { - std::string expected = "0: foo\n1: bar\n2:\n - nested\n - seq\n3:\n nested: map\n"; - std::string expected_json = R"({"0": "foo","1": "bar","2": ["nested","seq"],"3": {"nested": "map"}})"; - { - SCOPED_TRACE("rootref"); - test_emits(t.rootref(), expected, expected_json); - } - { - SCOPED_TRACE("t"); - test_emits(t, expected, expected_json); - } - { - SCOPED_TRACE("t, id"); - test_emits(t, t.root_id(), expected, expected_json); - } - } - { - ConstNodeRef n = t[0]; - std::string expected = "0: foo\n"; - std::string expected_json = "\"0\": \"foo\""; - { - SCOPED_TRACE("noderef"); - test_emits(n, expected, expected_json); - } - { - SCOPED_TRACE("t, id"); - test_emits(t, n.id(), expected, expected_json); - } - expected = "0: foo"; - nct._add_flags(n.id(), _WIP_STYLE_FLOW_SL); - { - SCOPED_TRACE("t, id"); - test_emits(n, expected, expected_json); - } - { - SCOPED_TRACE("t, id"); - test_emits(t, n.id(), expected, expected_json); - } - } - { - ConstNodeRef n = t[1]; - std::string expected = "1: bar\n"; - std::string expected_json = "\"1\": \"bar\""; - { - SCOPED_TRACE("noderef"); - test_emits(n, expected, expected_json); - } - { - SCOPED_TRACE("t, id"); - test_emits(t, n.id(), expected, expected_json); - } - expected = "1: bar"; - nct._add_flags(n.id(), _WIP_STYLE_FLOW_SL); - { - SCOPED_TRACE("t, id"); - test_emits(n, expected, expected_json); - } - { - SCOPED_TRACE("t, id"); - test_emits(t, n.id(), expected, expected_json); - } - } - { - ConstNodeRef n = t[2]; - std::string expected = "2:\n - nested\n - seq\n"; - std::string expected_json = "\"2\": [\"nested\",\"seq\"]"; - { - SCOPED_TRACE("noderef"); - test_emits(n, expected, expected_json); - } - { - SCOPED_TRACE("t, id"); - test_emits(t, n.id(), expected, expected_json); - } - expected = "2: [nested,seq]"; - nct._add_flags(n.id(), _WIP_STYLE_FLOW_SL); - { - SCOPED_TRACE("t, id"); - test_emits(n, expected, expected_json); - } - { - SCOPED_TRACE("t, id"); - test_emits(t, n.id(), expected, expected_json); - } - } - { - ConstNodeRef n = t[3]; - std::string expected = "3:\n nested: map\n"; - std::string expected_json = "\"3\": {\"nested\": \"map\"}"; - { - SCOPED_TRACE("noderef"); - test_emits(n, expected, expected_json); - } - { - SCOPED_TRACE("t, id"); - test_emits(t, n.id(), expected, expected_json); - } - expected = "3: {nested: map}"; - nct._add_flags(n.id(), _WIP_STYLE_FLOW_SL); - { - SCOPED_TRACE("t, id"); - test_emits(n, expected, expected_json); - } - { - SCOPED_TRACE("t, id"); - test_emits(t, n.id(), expected, expected_json); - } - } -} - -TEST(emit, percent_is_quoted) -{ - Tree ti = parse_in_arena("{}"); - ASSERT_TRUE(ti.rootref().is_map()); - ti["%ROOT"] = "%VAL"; - ti["%ROOT2"] |= SEQ; - ti["%ROOT2"][0] = "%VAL"; - ti["%ROOT2"][1] = "%VAL"; - std::string yaml = emitrs_yaml(ti); - test_check_emit_check(to_csubstr(yaml), [](Tree const &t){ - ASSERT_TRUE(t.rootref().is_map()); - ASSERT_TRUE(t.rootref().has_child("%ROOT")); - ASSERT_TRUE(t.rootref().has_child("%ROOT2")); - ASSERT_EQ(t["%ROOT2"].num_children(), 2u); - EXPECT_TRUE(t["%ROOT"].is_key_quoted()); - EXPECT_TRUE(t["%ROOT"].is_val_quoted()); - EXPECT_TRUE(t["%ROOT2"].is_key_quoted()); - EXPECT_TRUE(t["%ROOT2"][0].is_val_quoted()); - EXPECT_TRUE(t["%ROOT2"][1].is_val_quoted()); - }); -} - -TEST(emit, at_is_quoted__issue_309) -{ - Tree ti = parse_in_arena("{at: [], backtick: []"); - ti["at"][0] << "@test"; - ti["at"][1] = "@test2"; - ti["at"][2] << "@"; - ti["at"][3] = "@"; - ti["backtick"][0] << "`test"; - ti["backtick"][1] = "`test2"; - ti["backtick"][2] << "`"; - ti["backtick"][3] = "`"; - std::string yaml = emitrs_yaml(ti); - test_check_emit_check(to_csubstr(yaml), [](Tree const &t){ - ASSERT_TRUE(t.rootref().is_map()); - ASSERT_TRUE(t.rootref().has_child("at")); - ASSERT_TRUE(t.rootref().has_child("backtick")); - ASSERT_EQ(t["at"].num_children(), 4u); - ASSERT_EQ(t["backtick"].num_children(), 4u); - EXPECT_EQ(t["at"][0].val(), "@test"); - EXPECT_EQ(t["at"][1].val(), "@test2"); - EXPECT_EQ(t["at"][2].val(), "@"); - EXPECT_EQ(t["at"][3].val(), "@"); - EXPECT_TRUE(t["at"][0].is_val_quoted()); - EXPECT_TRUE(t["at"][1].is_val_quoted()); - EXPECT_TRUE(t["at"][2].is_val_quoted()); - EXPECT_TRUE(t["at"][3].is_val_quoted()); - EXPECT_EQ(t["backtick"][0].val(), "`test"); - EXPECT_EQ(t["backtick"][1].val(), "`test2"); - EXPECT_EQ(t["backtick"][2].val(), "`"); - EXPECT_EQ(t["backtick"][3].val(), "`"); - EXPECT_TRUE(t["backtick"][0].is_val_quoted()); - EXPECT_TRUE(t["backtick"][1].is_val_quoted()); - EXPECT_TRUE(t["backtick"][2].is_val_quoted()); - EXPECT_TRUE(t["backtick"][3].is_val_quoted()); - }); -} - -TEST(emit, at_is_quoted_only_in_the_beggining__issue_320) -{ - Tree ti = parse_in_arena("{at: [], backtick: []"); - ti["at"].append_child() << "@test"; - ti["at"].append_child() << "t@est"; - ti["at"].append_child() << "test@"; - ti["at"].append_child() = "@test2"; - ti["at"].append_child() = "t@est2"; - ti["at"].append_child() = "test2@"; - ti["backtick"].append_child() << "`test"; - ti["backtick"].append_child() << "t`est"; - ti["backtick"].append_child() << "test`"; - ti["backtick"].append_child() = "`test2"; - ti["backtick"].append_child() = "t`est2"; - ti["backtick"].append_child() = "test2`"; - std::string yaml = emitrs_yaml(ti); - test_check_emit_check(to_csubstr(yaml), [](Tree const &t){ - ASSERT_TRUE(t.rootref().is_map()); - ASSERT_TRUE(t.rootref().has_child("at")); - ASSERT_TRUE(t.rootref().has_child("backtick")); - ASSERT_EQ(t["at"].num_children(), 6u); - ASSERT_EQ(t["backtick"].num_children(), 6u); - EXPECT_EQ(t["at"][0].val(), "@test"); - EXPECT_EQ(t["at"][1].val(), "t@est"); - EXPECT_EQ(t["at"][2].val(), "test@"); - EXPECT_EQ(t["at"][3].val(), "@test2"); - EXPECT_EQ(t["at"][4].val(), "t@est2"); - EXPECT_EQ(t["at"][5].val(), "test2@"); - EXPECT_TRUE( t["at"][0].is_val_quoted()); - EXPECT_TRUE( ! t["at"][1].is_val_quoted()); - EXPECT_TRUE( ! t["at"][2].is_val_quoted()); - EXPECT_TRUE( t["at"][3].is_val_quoted()); - EXPECT_TRUE( ! t["at"][4].is_val_quoted()); - EXPECT_TRUE( ! t["at"][5].is_val_quoted()); - EXPECT_EQ(t["backtick"][0].val(), "`test"); - EXPECT_EQ(t["backtick"][1].val(), "t`est"); - EXPECT_EQ(t["backtick"][2].val(), "test`"); - EXPECT_EQ(t["backtick"][3].val(), "`test2"); - EXPECT_EQ(t["backtick"][4].val(), "t`est2"); - EXPECT_EQ(t["backtick"][5].val(), "test2`"); - EXPECT_TRUE( t["backtick"][0].is_val_quoted()); - EXPECT_TRUE( ! t["backtick"][1].is_val_quoted()); - EXPECT_TRUE( ! t["backtick"][2].is_val_quoted()); - EXPECT_TRUE( t["backtick"][3].is_val_quoted()); - EXPECT_TRUE( ! t["backtick"][4].is_val_quoted()); - EXPECT_TRUE( ! t["backtick"][5].is_val_quoted()); - }); -} - - -//------------------------------------------- -// this is needed to use the test case library -Case const* get_case(csubstr /*name*/) -{ - return nullptr; -} - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_empty_file.cpp b/thirdparty/ryml/test/test_empty_file.cpp deleted file mode 100644 index 38e66fbaf..000000000 --- a/thirdparty/ryml/test/test_empty_file.cpp +++ /dev/null @@ -1,79 +0,0 @@ -#include "./test_group.hpp" - -namespace c4 { -namespace yml { - - -CASE_GROUP(EMPTY_FILE) -{ - -ADD_CASE_TO_GROUP("empty0-nochars", -"", -NOTYPE); - - -ADD_CASE_TO_GROUP("empty0-multiline", R"( - - -)", NOTYPE); - - -ADD_CASE_TO_GROUP("empty0-multiline with spaces", R"( - - - - - - -)", NOTYPE); - - -ADD_CASE_TO_GROUP("empty0-multiline with spaces and tabs", R"( - - - - - - - -)", NOTYPE); - - -ADD_CASE_TO_GROUP("empty0-multiline-with-comments 0", R"( -# well hello sir, I see you are fine -# very fine thank you -# send my very best wishes -)", NOTYPE); - -ADD_CASE_TO_GROUP("empty0-multiline-with-comments 1", R"( - - - -# well hello sir, I see you are fine -# very fine thank you -# send my very best wishes - - - -)", NOTYPE); - -ADD_CASE_TO_GROUP("empty0-multiline-with-comments 2", R"( - - - - -# well hello sir, I see you are fine -# very fine thank you -# send my very best wishes - - - - - - -)", NOTYPE); - -} - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_empty_map.cpp b/thirdparty/ryml/test/test_empty_map.cpp deleted file mode 100644 index 44d818cc6..000000000 --- a/thirdparty/ryml/test/test_empty_map.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include "./test_group.hpp" - -namespace c4 { -namespace yml { - - -CASE_GROUP(EMPTY_MAP) -{ - -ADD_CASE_TO_GROUP("empty map, explicit", -"{}", - MAP -); - - -ADD_CASE_TO_GROUP("empty map, explicit, whitespace", -" {}", - MAP -); - - -ADD_CASE_TO_GROUP("empty map, multiline", -R"({ - -} -)", - MAP -); - - -ADD_CASE_TO_GROUP("empty map, multilines", -R"({ -# ksjdfkjhsdfkjhsdfkjh - - -} -)", - MAP - ); -} - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_empty_scalar.cpp b/thirdparty/ryml/test/test_empty_scalar.cpp deleted file mode 100644 index 52147569c..000000000 --- a/thirdparty/ryml/test/test_empty_scalar.cpp +++ /dev/null @@ -1,353 +0,0 @@ -#include "./test_group.hpp" -#include - -namespace c4 { -namespace yml { - -// See also: -// https://github.com/biojppm/rapidyaml/issues/263 -// https://github.com/biojppm/rapidyaml/pull/264 - -C4_SUPPRESS_WARNING_GCC_WITH_PUSH("-Wuseless-cast") - -constexpr const NodeType_e DQV = (NodeType_e)(DOC | QV); - -TEST(empty_scalar, parse_zero_length_strings) -{ - char inp[] = R"( -seq: - - "" - - '' - - > - - | -map: - a: "" - b: '' - c: > - d: | -)"; - const Tree tr = parse_in_place(inp); - EXPECT_TRUE(tr["seq"].has_key()); - EXPECT_TRUE(tr["map"].has_key()); - EXPECT_TRUE(tr["seq"].is_seq()); - EXPECT_TRUE(tr["map"].is_map()); - for(const char *name : {"seq", "map"}) - { - ConstNodeRef node = tr[to_csubstr(name)]; - ASSERT_EQ(node.num_children(), 4); - for(const auto &child : node.children()) - { - EXPECT_TRUE(child.is_val_quoted()); - EXPECT_EQ(child.val().len, 0u); - EXPECT_NE(child.val().str, nullptr); - EXPECT_NE(child.val(), nullptr); - EXPECT_EQ(child.val(), ""); - EXPECT_FALSE(child.val_is_null()); - } - } -} - -TEST(empty_scalar, flow_seq) -{ - test_check_emit_check("['', '']", [&](Tree const &t){ - ASSERT_TRUE(t.rootref().has_children()); - for(ConstNodeRef ch : t.rootref().children()) - { - EXPECT_TRUE(ch.is_val_quoted()); - EXPECT_FALSE(ch.val_is_null()); - EXPECT_EQ(ch.val().len, 0); - EXPECT_NE(ch.val().str, nullptr); - EXPECT_NE(ch.val(), nullptr); - } - }); - test_check_emit_check("[ , ]", [&](Tree const &t){ - ASSERT_TRUE(t.rootref().has_children()); - for(ConstNodeRef ch : t.rootref().children()) - { - EXPECT_FALSE(ch.is_val_quoted()); - EXPECT_TRUE(ch.val_is_null()); - EXPECT_EQ(ch.val().len, 0); - EXPECT_EQ(ch.val().str, nullptr); - EXPECT_EQ(ch.val(), nullptr); - } - }); -} - -TEST(empty_scalar, parse_empty_strings) -{ - char inp[] = R"( -# use multiple empty entries to ensure the parser -# correctly deals with the several cases -seq: - - - - - - - - -map: - a: - b: - c: - d: -)"; - const Tree tr = parse_in_place(inp); - for(const char *name : {"seq", "map"}) - { - ConstNodeRef node = tr[to_csubstr(name)]; - ASSERT_EQ(node.num_children(), 4); - for(const auto &child : node.children()) - { - EXPECT_FALSE(child.type().is_val_quoted()); - EXPECT_EQ(child.val(), ""); - EXPECT_EQ(child.val(), nullptr); - EXPECT_EQ(child.val().str, nullptr); - EXPECT_EQ(child.val().len, 0u); - EXPECT_TRUE(child.val_is_null()); - } - } -} - -TEST(empty_scalar, std_string) -{ - std::string stdstr; - csubstr stdss = to_csubstr(stdstr); - csubstr nullss; - EXPECT_NE(stdss, nullptr); - EXPECT_NE(stdss.str, nullptr); - EXPECT_EQ(stdss.len, 0u); - EXPECT_EQ(nullss, nullptr); - EXPECT_EQ(nullss.str, nullptr); - EXPECT_EQ(nullss.len, 0u); - Tree tree = parse_in_arena("{ser: {}, eq: {}}"); - tree["ser"]["stdstr"] << stdss; - tree["ser"]["nullss"] << nullss; - tree["eq"]["stdstr"] = stdss; - tree["eq"]["nullss"] = nullss; - EXPECT_EQ(emitrs_yaml(tree), - "ser:\n" - " stdstr: ''\n" - " nullss: \n" - "eq:\n" - " stdstr: ''\n" - " nullss: \n" - ); -} - -TEST(empty_scalar, to_arena) -{ - Tree tr; - { - const char *val = ""; - size_t num = to_chars(substr{}, val); - ASSERT_EQ(num, 0u); - char buf_[10]; - csubstr serialized = to_chars_sub(buf_, val); - EXPECT_EQ(serialized.len, 0); - EXPECT_NE(serialized.str, nullptr); - EXPECT_NE(serialized, nullptr); - csubstr r = tr.to_arena(""); - EXPECT_EQ(r.len, 0u); - EXPECT_NE(r.str, nullptr); - EXPECT_NE(r, nullptr); - } - { - const char *val = nullptr; - size_t num = to_chars(substr{}, val); - ASSERT_EQ(num, 0u); - char buf_[10]; - csubstr serialized = to_chars_sub(buf_, val); - EXPECT_EQ(serialized.len, 0); - EXPECT_NE(serialized.str, nullptr); - EXPECT_NE(serialized, nullptr); - csubstr r = tr.to_arena(""); - EXPECT_EQ(r.len, 0u); - EXPECT_NE(r.str, nullptr); - EXPECT_NE(r, nullptr); - r = tr.to_arena(val); - EXPECT_EQ(r.len, 0u); - EXPECT_EQ(r.str, nullptr); - EXPECT_EQ(r, nullptr); - } - { - std::nullptr_t val = nullptr; - size_t num = to_chars(substr{}, val); - ASSERT_EQ(num, 0u); - csubstr r = tr.to_arena(val); - EXPECT_EQ(r.len, 0u); - EXPECT_EQ(r.str, nullptr); - EXPECT_EQ(r, nullptr); - } -} - -TEST(empty_scalar, gcc_error) -{ - Tree tr; - csubstr nullstr = {}; - ASSERT_EQ(nullstr.str, nullptr); - ASSERT_EQ(nullstr.len, 0); - std::cout << "\nserializing with empty arena...\n"; - csubstr result = tr.to_arena(nullstr); - EXPECT_EQ(result.str, nullptr); // fails! - EXPECT_EQ(result.len, 0); - std::cout << "\nserializing with nonempty arena...\n"; - result = tr.to_arena(nullstr); - EXPECT_EQ(result.str, nullptr); // fails! - EXPECT_EQ(result.len, 0); -} - -TEST(empty_scalar, build_zero_length_string) -{ - Tree tr; - NodeRef root = tr.rootref(); - root |= MAP; - auto addseq = [&root](csubstr name) { NodeRef n = root[name]; n |= SEQ; return n; }; - - // try both with nonnull-zero-length and null-zero-length - std::string stdstr; - csubstr stdss = to_csubstr(stdstr); - csubstr empty = csubstr("nonempty").first(0); - csubstr nullss = {}; - - // these are the conditions we wish to cover: - ASSERT_TRUE(stdss.str != nullptr); - ASSERT_TRUE(stdss.len == 0u); - ASSERT_TRUE(empty.str != nullptr); - ASSERT_TRUE(empty.len == 0u); - ASSERT_TRUE(nullss.str == nullptr); - ASSERT_TRUE(nullss.len == 0u); - - // = and << must have exactly the same behavior where nullity is - // regarded - - { - NodeRef quoted = addseq("quoted"); - {NodeRef r = quoted.append_child(); r = "" ; r.set_type(r.type() | VALQUO);} - {NodeRef r = quoted.append_child(); r << "" ; r.set_type(r.type() | VALQUO);} - {NodeRef r = quoted.append_child(); r = empty ; r.set_type(r.type() | VALQUO);} - {NodeRef r = quoted.append_child(); r << empty ; r.set_type(r.type() | VALQUO);} - {NodeRef r = quoted.append_child(); r = stdss ; r.set_type(r.type() | VALQUO);} - {NodeRef r = quoted.append_child(); r << stdss ; r.set_type(r.type() | VALQUO);} - } - { - NodeRef quoted_null = addseq("quoted_null"); - {NodeRef r = quoted_null.append_child(); r = nullss ; r.set_type(r.type() | VALQUO);} - {NodeRef r = quoted_null.append_child(); r << nullss ; r.set_type(r.type() | VALQUO);} - {NodeRef r = quoted_null.append_child(); r = nullptr ; r.set_type(r.type() | VALQUO);} - {NodeRef r = quoted_null.append_child(); r << nullptr; r.set_type(r.type() | VALQUO);} - } - { - NodeRef non_quoted = addseq("nonquoted"); - non_quoted.append_child() = ""; - non_quoted.append_child() << ""; - non_quoted.append_child() = empty; - non_quoted.append_child() << empty; - non_quoted.append_child() = stdss; - non_quoted.append_child() << stdss; - } - { - NodeRef non_quoted_null = addseq("nonquoted_null"); - non_quoted_null.append_child() = nullss; - non_quoted_null.append_child() << nullss; - non_quoted_null.append_child() = nullptr; - non_quoted_null.append_child() << nullptr; - } - - // quoted cases will never be null, regardless of the - // incoming scalar - auto test_quoted_empty = [](ConstNodeRef node){ - SCOPED_TRACE(node.key()); - ASSERT_TRUE(node.has_children()); - { - size_t pos = 0; - for(ConstNodeRef child : node.cchildren()) - { - EXPECT_TRUE(child.is_val_quoted()) << "pos=" << pos; - EXPECT_EQ(child.val().len, 0u) << "pos=" << pos; - EXPECT_NE(child.val().str, nullptr) << "pos=" << pos; - EXPECT_NE(child.val(), nullptr) << "pos=" << pos; - EXPECT_EQ(child.val(), "") << "pos=" << pos; - EXPECT_FALSE(child.val_is_null()) << "pos=" << pos; - pos++; - } - } - }; - auto test_quoted_null = [](ConstNodeRef node){ - SCOPED_TRACE(node.key()); - ASSERT_TRUE(node.has_children()); - size_t pos = 0; - for(ConstNodeRef child : node.cchildren()) - { - EXPECT_TRUE(child.is_val_quoted()) << "pos=" << pos; - EXPECT_FALSE(child.val_is_null()) << "pos=" << pos; // because it's quoted - EXPECT_EQ(child.val().len, 0u) << "pos=" << pos; - EXPECT_EQ(child.val().str, nullptr) << "pos=" << pos; - EXPECT_EQ(child.val(), nullptr) << "pos=" << pos; - EXPECT_EQ(child.val(), "") << "pos=" << pos; - pos++; - } - }; - // ... but according to the incoming scalar, non quoted cases may - // or may not be null - auto test_non_quoted_empty = [](ConstNodeRef node){ - SCOPED_TRACE(node.key()); - ASSERT_TRUE(node.has_children()); - size_t pos = 0; - for(ConstNodeRef child : node.cchildren()) - { - EXPECT_TRUE(child.is_val()) << "pos=" << pos; - EXPECT_FALSE(child.val_is_null()) << "pos=" << pos; // because it's quoted - EXPECT_EQ(child.val(), "") << "pos=" << pos; - EXPECT_NE(child.val(), nullptr) << "pos=" << pos; - EXPECT_EQ(child.val().len, 0u) << "pos=" << pos; - EXPECT_NE(child.val().str, nullptr) << "pos=" << pos; - ++pos; - } - }; - auto test_non_quoted_null = [](ConstNodeRef node){ - SCOPED_TRACE(node.key()); - ASSERT_TRUE(node.has_children()); - size_t pos = 0; - for(ConstNodeRef child : node.cchildren()) - { - EXPECT_TRUE(child.is_val()) << "pos=" << pos; - EXPECT_EQ(child.val(), "") << "pos=" << pos; - EXPECT_EQ(child.val(), nullptr) << "pos=" << pos; - EXPECT_EQ(child.val().len, 0u) << "pos=" << pos; - EXPECT_EQ(child.val().str, nullptr) << "pos=" << pos; - EXPECT_TRUE(child.val_is_null()) << "pos=" << pos; - ++pos; - } - }; - - { - SCOPED_TRACE("input tree"); - test_quoted_empty(tr["quoted"]); - // in the built tree, the values will be quoted and null - test_quoted_null(tr["quoted_null"]); - test_non_quoted_empty(tr["nonquoted"]); - test_non_quoted_null(tr["nonquoted_null"]); - } - - std::string yaml = emitrs_yaml(tr); - std::cout << yaml; - test_check_emit_check(to_csubstr(yaml), [&](Tree const &t){ - SCOPED_TRACE("output tree"); - test_quoted_empty(t["quoted"]); - // after a roundtrip, they will be nonnull, because the quotes win. - test_quoted_empty(t["quoted_null"]); - test_non_quoted_empty(t["nonquoted"]); - test_non_quoted_null(t["nonquoted_null"]); - }); -} - -CASE_GROUP(EMPTY_SCALAR) -{ -ADD_CASE_TO_GROUP("empty scalar, single quoted", - "''", - N(DQV, "") -); -} - -} // namespace yml -} // namespace c4 - -C4_SUPPRESS_WARNING_GCC_POP diff --git a/thirdparty/ryml/test/test_empty_seq.cpp b/thirdparty/ryml/test/test_empty_seq.cpp deleted file mode 100644 index 2b8bcab7b..000000000 --- a/thirdparty/ryml/test/test_empty_seq.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "./test_group.hpp" - -namespace c4 { -namespace yml { - -CASE_GROUP(EMPTY_SEQ) -{ - -ADD_CASE_TO_GROUP("empty seq, explicit", -"[]", - SEQ -); - - -ADD_CASE_TO_GROUP("empty seq, explicit, whitespace", -" []", - SEQ -); - - -ADD_CASE_TO_GROUP("empty seq, multiline", -R"([ -] -)", - SEQ -); - -ADD_CASE_TO_GROUP("empty seq, multilines", -R"([ -# ksjdfkjhsdfkjhsdfkjh - - -] -)", - SEQ -); -} - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_explicit_key.cpp b/thirdparty/ryml/test/test_explicit_key.cpp deleted file mode 100644 index a9aefd59e..000000000 --- a/thirdparty/ryml/test/test_explicit_key.cpp +++ /dev/null @@ -1,419 +0,0 @@ -#include "./test_group.hpp" - -namespace c4 { -namespace yml { - - -TEST(explicit_key, test_suite_5WE3) -{ - csubstr yaml = R"( -? explicit key # Empty value -? | - block key -: - one # Explicit compact - - two # block value -)"; - test_check_emit_check(yaml, [](Tree const &t){ - ASSERT_TRUE(t.rootref().is_map()); - ASSERT_NE(t.find_child(t.root_id(), "explicit key"), (size_t)NONE); - ASSERT_NE(t.find_child(t.root_id(), "block key\n"), (size_t)NONE); - EXPECT_EQ(t["explicit key"].val(), csubstr{}); - EXPECT_TRUE(t["block key\n"].is_seq()); - EXPECT_EQ(t["block key\n"][0], csubstr("one")); - EXPECT_EQ(t["block key\n"][1], csubstr("two")); - }); -} - - -TEST(explicit_key, test_suite_DFF7_v1) -{ - csubstr yaml = R"( -{ -? explicit: entry, -implicit: entry, -? -} -)"; - test_check_emit_check(yaml, [](Tree const &t){ - ASSERT_TRUE(t.rootref().is_map()); - ASSERT_EQ(t.rootref().num_children(), 3u); - ASSERT_TRUE(t.rootref().has_child("explicit")); - EXPECT_EQ(t["explicit"].val(), csubstr("entry")); - ASSERT_TRUE(t.rootref().has_child("implicit")); - EXPECT_EQ(t["explicit"].val(), csubstr("entry")); - ASSERT_TRUE(t.rootref().has_child(csubstr{})); - EXPECT_EQ(t[csubstr{}].val(), csubstr{}); - }); -} - -TEST(explicit_key, test_suite_DFF7_v2) -{ - csubstr yaml = R"( -{ -? - key on next line -: - val on next line -, -? - # no key -: - val on next line -} -)"; - test_check_emit_check(yaml, [](Tree const &t){ - ASSERT_TRUE(t.rootref().is_map()); - ASSERT_EQ(t.rootref().num_children(), 2u); - ASSERT_TRUE(t.rootref().has_child("key on next line")); - EXPECT_EQ(t[0].key(), "key on next line"); - EXPECT_EQ(t[0].val(), "val on next line"); - EXPECT_EQ(t[1].key(), csubstr{}); - EXPECT_EQ(t[1].val(), "val on next line"); - }); -} - - -TEST(explicit_key, test_suite_FRK4) -{ - csubstr yaml = R"( -{ - ? foo :, - : bar, -} -)"; - test_check_emit_check(yaml, [](Tree const &t){ - ASSERT_TRUE(t.rootref().is_map()); - ASSERT_TRUE(t.rootref().has_child("foo")); - EXPECT_EQ(t["foo"].val(), csubstr{}); - ASSERT_TRUE(t.rootref().has_child(csubstr{})); - EXPECT_EQ(t[csubstr{}].val(), csubstr("bar")); - }); -} - - -TEST(explicit_key, test_suite_M2N8) -{ - csubstr yaml = R"( -- ? : x -- ? : -- ? : -)"; - test_check_emit_check(yaml, [](Tree const &t){ - ASSERT_TRUE(t.rootref().is_seq()); - ASSERT_EQ(t.rootref().num_children(), 3u); - ASSERT_EQ(t[0].num_children(), 1u); - EXPECT_EQ(t[0][0].key(), csubstr{}); - EXPECT_EQ(t[0][0].val(), "x"); - ASSERT_EQ(t[1].num_children(), 1u); - EXPECT_EQ(t[1][0].key(), csubstr{}); - EXPECT_EQ(t[1][0].val(), csubstr{}); - ASSERT_EQ(t[2].num_children(), 1u); - EXPECT_EQ(t[2][0].key(), csubstr{}); - EXPECT_EQ(t[2][0].val(), csubstr{}); - }); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - - -CASE_GROUP(EXPLICIT_KEY) -{ -// -ADD_CASE_TO_GROUP("explicit key, last value missing", -R"( -? a -? b -? ---- !!set # test that we do not add any last item -? a -? b ---- !!set # test that we do add the last item -? a -? b -? -... -)", -N(STREAM, L{ - N(DOCMAP, L{ - N(KEYVAL, "a", {}), - N(KEYVAL, "b", {}), - N(KEYVAL, "", {}) - }), - N(DOCMAP, TL("!!set", L{ - N(KEYVAL, "a", {}), - N(KEYVAL, "b", {}), - })), - N(DOCMAP, TL("!!set", L{ - N(KEYVAL, "a", {}), - N(KEYVAL, "b", {}), - N(KEYVAL, "", {}) - })), - }) -); - -ADD_CASE_TO_GROUP("explicit key, ambiguity 2EBW", -R"( -a!"#$%&'()*+,-./09:;<=>?@AZ[\]^_`az{|}~: safe -?foo: safe question mark -:foo: safe colon --foo: safe dash -this is#not: a comment -)", -L{ - N("a!\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~", "safe"), - N("?foo", "safe question mark"), - N(":foo", "safe colon"), - N("-foo", "safe dash"), - N("this is#not", "a comment"), -}); - -ADD_CASE_TO_GROUP("explicit key, ambiguity 2EBW, expl", -R"({ - a!"#$%&'()*+-./09:;<=>?@AZ[\]^_`az{|~: safe, - ?foo: safe question mark, - :foo: safe colon, - -foo: safe dash, - this is#not: a comment, -})", -L{ - N("a!\"#$%&'()*+-./09:;<=>?@AZ[\\]^_`az{|~", "safe"), - N("?foo", "safe question mark"), - N(":foo", "safe colon"), - N("-foo", "safe dash"), - N("this is#not", "a comment"), -}); - -ADD_CASE_TO_GROUP("explicit key, ambiguity 2EBW, impl seq", -R"( -- a!"#$%&'()*+,-./09:;<=>?@AZ[\]^_`az{|}~ -- ?foo -- :foo -- -foo -- this is#not:a comment -)", -L{ - N("a!\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~"), - N("?foo"), - N(":foo"), - N("-foo"), - N("this is#not:a comment"), -}); - -ADD_CASE_TO_GROUP("explicit key, ambiguity 2EBW, expl seq", -R"([ - a!"#$%&'()*+-./09:;<=>?@AZ[\^_`az{|}~, - ?foo, - :foo, - -foo, - this is#not:a comment, -])", -L{ - N("a!\"#$%&'()*+-./09:;<=>?@AZ[\\^_`az{|}~"), - N("?foo"), - N(":foo"), - N("-foo"), - N("this is#not:a comment"), -}); - -ADD_CASE_TO_GROUP("explicit key with line break in between", -R"( -? an explicit key -: its value -)", - L{N("an explicit key", "its value")} -); - -ADD_CASE_TO_GROUP("explicit key 2nd, inside explicit map", -R"( -{ - a simple key: a value, - ? an explicit key: another value, -} -)", - L{ - N("a simple key", "a value"), - N("an explicit key", "another value"), - } -); - -ADD_CASE_TO_GROUP("explicit key 1st, inside explicit map", -R"( -{ - ? an explicit key: another value, - a simple key: a value, -} -)", - L{ - N("an explicit key", "another value"), - N("a simple key", "a value"), - } -); - -ADD_CASE_TO_GROUP("explicit key 2nd", -R"( -a simple key: a value -? an explicit key: another value -)", - L{ - N("a simple key", "a value"), - N("an explicit key", "another value"), - } -); - -ADD_CASE_TO_GROUP("explicit key 1st", -R"( -? an explicit key: another value -a simple key: a value -)", - L{ - N("an explicit key", "another value"), - N("a simple key", "a value"), - } -); - -ADD_CASE_TO_GROUP("explicit key nested in a map, 1st", -R"( -map: - ? an explicit key: another value - a simple key: a value -? an explicit key deindented: its value -)", - L{ - N("map", L{ - N("an explicit key", "another value"), - N("a simple key", "a value"), - }), - N("an explicit key deindented", "its value") - } -); - -ADD_CASE_TO_GROUP("explicit key nested in a seq, 1st", -R"( -- ? an explicit key: another value - a simple key: a value -- ? another explicit key: its value -)", - L{ - N(L{ - N("an explicit key", "another value"), - N("a simple key", "a value"), - }), - N(L{N("another explicit key", "its value")}) - } -); - -ADD_CASE_TO_GROUP("explicit block key, literal, clip", -R"(? | - This is a key - that has multiple lines - -: and this is its value -)", - L{ - N(QK, "This is a key\nthat has multiple lines\n", "and this is its value") - } -); - -ADD_CASE_TO_GROUP("explicit block key, literal, keep", -R"(? |+ - This is a key - that has multiple lines - -: and this is its value -)", - L{ - N(QK, "This is a key\nthat has multiple lines\n\n", "and this is its value") - } -); - -ADD_CASE_TO_GROUP("explicit block key, literal, strip", -R"(? |- - This is a key - that has multiple lines - -: and this is its value -)", - L{ - N(QK, "This is a key\nthat has multiple lines", "and this is its value") - } -); - -ADD_CASE_TO_GROUP("explicit block key, folded, clip", -R"(? > - This is a key - that has multiple lines - -: and this is its value -)", - L{ - N(QK, "This is a key that has multiple lines\n", "and this is its value") - } -); - -ADD_CASE_TO_GROUP("explicit block key, folded, keep", -R"(? >+ - This is a key - that has multiple lines - -: and this is its value -)", - L{ - N(QK, "This is a key that has multiple lines\n\n", "and this is its value") - } -); - -ADD_CASE_TO_GROUP("explicit block key, folded, strip", -R"(? >- - This is a key - that has multiple lines - -: and this is its value -)", - L{ - N(QK, "This is a key that has multiple lines", "and this is its value") - } -); - -ADD_CASE_TO_GROUP("explicit key, missing val 7W2P", -R"( -? a -? b -c: -? d -e: -)", -N(MAP, L{ - N(KEYVAL, "a", {}), - N(KEYVAL, "b", {}), - N(KEYVAL, "c", {}), - N(KEYVAL, "d", {}), - N(KEYVAL, "e", {}), - }) -); - -ADD_CASE_TO_GROUP("explicit key, missing val ZWK4", -R"( -a: 1 -? b -&anchor c: 3 -? d -!!str e: 4 -? f -)", -N(MAP, L{ - N("a", "1"), - N(KEYVAL, "b", {}), - N("c", AR(KEYANCH, "anchor"), "3"), - N(KEYVAL, "d", {}), - N(TS("!!str", "e"), "4"), - N(KEYVAL, "f", {}), - }) -); - -} - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_generic_map.cpp b/thirdparty/ryml/test/test_generic_map.cpp deleted file mode 100644 index 273c05cb4..000000000 --- a/thirdparty/ryml/test/test_generic_map.cpp +++ /dev/null @@ -1,89 +0,0 @@ -#include "./test_group.hpp" - -namespace c4 { -namespace yml { - - -CASE_GROUP(GENERIC_MAP) -{ - -ADD_CASE_TO_GROUP("generic map", -R"( -a simple key: a value # The KEY token is produced here. -? a complex key -: another value -a mapping: - key 1: value 1 - key 2: value 2 -a sequence: - - item 1 - - item 2 -)", - L{ - N("a simple key", "a value"), - N("a complex key", "another value"), - N("a mapping", L{N("key 1", "value 1"), N("key 2", "value 2")}), - N("a sequence", L{N("item 1"), N("item 2")}), - } -); - - -ADD_CASE_TO_GROUP("seq nested in map", -R"( -items: - - part_no: A4786 - descrip: Water Bucket (Filled) - price: 1.47 - quantity: 4 - - part_no: E1628 - descrip: High Heeled "Ruby" Slippers - size: 8 - price: 133.7 - quantity: 1 -)", -L{ - N{"items", L{ - N{L{N{"part_no", "A4786"}, - N{"descrip", "Water Bucket (Filled)"}, - N{"price", "1.47"}, - N{"quantity", "4"},}}, - N{L{N{"part_no", "E1628"}, - N{"descrip", "High Heeled \"Ruby\" Slippers"}, - N{"size", "8"}, - N{"price", "133.7"}, - N{"quantity", "1"},}}}}, - } -); - -ADD_CASE_TO_GROUP("seq nested in map, v2", -R"( -items: - - - part_no: A4786 - descrip: Water Bucket (Filled) - price: 1.47 - quantity: 4 - - - part_no: E1628 - descrip: High Heeled "Ruby" Slippers - size: 8 - price: 133.7 - quantity: 1 -)", -L{ - N{"items", L{ - N{L{N{"part_no", "A4786"}, - N{"descrip", "Water Bucket (Filled)"}, - N{"price", "1.47"}, - N{"quantity", "4"},}}, - N{L{N{"part_no", "E1628"}, - N{"descrip", "High Heeled \"Ruby\" Slippers"}, - N{"size", "8"}, - N{"price", "133.7"}, - N{"quantity", "1"},}}}}, - } -); -} - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_generic_seq.cpp b/thirdparty/ryml/test/test_generic_seq.cpp deleted file mode 100644 index 45f9c1d3e..000000000 --- a/thirdparty/ryml/test/test_generic_seq.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include "./test_group.hpp" - -namespace c4 { -namespace yml { - -CASE_GROUP(GENERIC_SEQ) -{ - -ADD_CASE_TO_GROUP("generic seq v0", -R"( -- item 1 -- item 2 -- - item 3.1 - - item 3.2 -- key 1: value 1 - key 2: value 2 -)", - L{ - N("item 1"), - N("item 2"), - N(L{N("item 3.1"), N("item 3.2")}), - N(L{N("key 1", "value 1"), N("key 2", "value 2")}) - } -); - -ADD_CASE_TO_GROUP("generic seq v1", -R"( -- item 1 -- item 2 -- - - item 3.1 - - item 3.2 -- - key 1: value 1 - key 2: value 2 -)", - L{ - N("item 1"), - N("item 2"), - N(L{N("item 3.1"), N("item 3.2")}), - N(L{N("key 1", "value 1"), N("key 2", "value 2")}) - } -); -} - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_github_issues.cpp b/thirdparty/ryml/test/test_github_issues.cpp deleted file mode 100644 index 3c12307fc..000000000 --- a/thirdparty/ryml/test/test_github_issues.cpp +++ /dev/null @@ -1,590 +0,0 @@ -#include "./test_group.hpp" - -namespace c4 { -namespace yml { - -TEST(github, 268) -{ - Tree tree = parse_in_arena(R"( - list: - - &bar bar - map: - node: *bar - )"); - tree.resolve(); - auto root = tree.rootref(); - ASSERT_TRUE(root["map"].is_map()); - ASSERT_TRUE(root["map"].has_child("node")); - ASSERT_EQ(root["map"]["node"], "bar"); -} - -TEST(github, 277) -{ - Tree tree = parse_in_arena(R"( - A: &A - V: 3 - W: 4 - B: - <<: *A - V: 5 - X: 6 - )"); - const char *keys[] = {"V", "W", "X"}; - const char *vals[] = {"5", "4", "6"}; - tree.resolve(); - auto root = tree.rootref(); - ASSERT_TRUE(root["B"].is_map()); - size_t num_childs = root["B"].num_children(); - size_t child = 0; - ASSERT_EQ(num_childs, 3); - for (const auto node : root["B"].children()) - { - EXPECT_EQ(node.key(), csubstr(keys[child], 1)); - EXPECT_EQ(node.val(), csubstr(vals[child], 1)); - child++; - } - // test whether the tree is corrupted - test_invariants(tree); - child = num_childs; - for (size_t n = tree.last_child(root["B"].id()); n != NONE; n = tree.prev_sibling(n)) - { - ASSERT_NE(child, 0); - EXPECT_EQ(tree.key(n), csubstr(keys[child - 1], 1)); - child--; - } -} - - -TEST(github, 78) -{ - Tree t = parse_in_arena("{foo: 1, bar: [2, 3]}"); - EXPECT_EQ(t["foo"].val(), "1"); - EXPECT_EQ(t["bar"][0].val(), "2"); - EXPECT_EQ(t["bar"][1].val(), "3"); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -TEST(github, 60) -{ - Tree tree = parse_in_arena(R"( - traits: - roleBonuses: - - bonus: 5 - bonusText: - de: Bonus auf die Virusstärke von Relikt- - und Datenanalysatoren - en: bonus to Relic and Data - Analyzer virus strength - fr: de bonus à la puissance du virus des analyseurs - de reliques et des analyseurs de données - ja: 遺物アナライザーデータアナライザーのウイルス強度が増加 - ru: повышается степень опасности вирусов, применяемых в комплексах - анализа данных и комплексах анализа - артефактов - zh: 遗迹分析仪数据分析仪病毒强度加成 - importance: 1 - unitID: 139 -)"); - auto root = tree.rootref(); - ASSERT_TRUE(root.is_map()); - ASSERT_TRUE(root.has_child("traits")); - auto rb = root["traits"]["roleBonuses"][0]; - ASSERT_TRUE(rb.valid()); - EXPECT_EQ(rb["bonus"].val(), "5"); - auto txt = rb["bonusText"]; - ASSERT_TRUE(txt.valid()); - ASSERT_TRUE(txt.is_map()); - EXPECT_TRUE(txt.has_child("de")); - EXPECT_TRUE(txt.has_child("en")); - EXPECT_TRUE(txt.has_child("fr")); - EXPECT_TRUE(txt.has_child("ja")); - EXPECT_TRUE(txt.has_child("ru")); - EXPECT_TRUE(txt.has_child("zh")); - EXPECT_EQ(txt["de"].val(), "Bonus auf die Virusstärke von Relikt- und Datenanalysatoren"); - EXPECT_EQ(txt["en"].val(), "bonus to Relic and Data Analyzer virus strength"); - EXPECT_EQ(txt["fr"].val(), "de bonus à la puissance du virus des analyseurs de reliques et des analyseurs de données"); - EXPECT_EQ(txt["ja"].val(), "遺物アナライザーデータアナライザーのウイルス強度が増加"); - EXPECT_EQ(txt["ru"].val(), "повышается степень опасности вирусов, применяемых в комплексах анализа данных и комплексах анализа артефактов"); - EXPECT_EQ(txt["zh"].val(), "遗迹分析仪数据分析仪病毒强度加成"); - - - tree = parse_in_arena(R"(208: - basePrice: 3000.0 - description: - de: Ursprünglich als Rakete für den Fangschuss entworfen, um einem beschädigten - Schiff den Todesstoß zu geben, hat die Inferno Heavy Missile seither eine - Reihe technischer Upgrades durchlaufen. Die neueste Version hat eine leichtere - Sprengladung als das Original, aber stark verbesserte Lenksysteme. - en: Originally designed as a 'finisher' - the killing blow to a crippled ship - - the Inferno heavy missile has since gone through various technological - upgrades. The latest version has a lighter payload than the original, - but much improved guidance systems. - fr: Conçu à l'origine pour donner le coup de grâce, le missile lourd Inferno - a depuis subi de nombreuses améliorations techniques. La dernière version - emporte une charge utile réduite par rapport à l'originale, mais est dotée - de systèmes de guidage améliorés. - ja: 元々「フィニッシャー」―大破した船にとどめを刺す兵器として設計されたインフェルノヘビーミサイルは、以来各種の技術改良を経てきた。現行型は初期型より軽い弾頭を採用しているが、それを補って余りある優れた誘導システムを持つ。 - ru: Тяжелая ракета Inferno изначально была спроектирована как «оружие последнего - удара» для уничтожения подбитых кораблей. С тех пор было выпущено несколько - ее модификаций. В последней модификации используется заряд меньшей мощности, - но более совершенная система наведения. - zh: 炼狱重型导弹历经多种技术改良,原本被设计为给予落魄敌舰最后一击的“终结者”角色。相比原型,最新版导弹载荷较轻,但装配了大幅改进的制导系统。 - graphicID: 20048 - groupID: 385 - iconID: 188 - marketGroupID: 924 - mass: 1000.0 - name: - de: Inferno Heavy Missile - en: Inferno Heavy Missile - fr: Missile lourd Inferno - ja: インフェルノヘビーミサイル - ru: Inferno Heavy Missile - zh: 炼狱重型导弹 - portionSize: 100 - published: true - radius: 300.0 - volume: 0.03 -)"); - root = tree.rootref()["208"]; - EXPECT_EQ(root["description"]["ja"].val(), "元々「フィニッシャー」―大破した船にとどめを刺す兵器として設計されたインフェルノヘビーミサイルは、以来各種の技術改良を経てきた。現行型は初期型より軽い弾頭を採用しているが、それを補って余りある優れた誘導システムを持つ。"); - EXPECT_EQ(root["name"]["ja"].val(), "インフェルノヘビーミサイル"); - EXPECT_EQ(root["name"]["zh"].val(), "炼狱重型导弹"); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -TEST(github, 31) -{ - Tree tree; - NodeRef r = tree.rootref(); - r |= MAP; - - auto meas = r["meas"]; - meas |= MAP; - - auto plist = meas["createParameterList"]; - plist |= SEQ; - - { - auto lumi = plist.append_child(); - lumi << "Lumi"; - EXPECT_TRUE(lumi.is_val()); - } - - { - auto lumi = plist.append_child(); - lumi |= MAP; - lumi["value"] << 1; - lumi["relErr"] << 0.1; - EXPECT_TRUE(lumi.is_map()); - } - - { - ExpectError::check_assertion(&tree, [&](){ - auto lumi = plist.append_child(); - lumi << "Lumi"; - lumi |= MAP; - }); - } - - { - ExpectError::check_assertion(&tree, [&](){ - auto lumi = plist.append_child(); - lumi << "Lumi"; - lumi |= SEQ; - }); - } - - { - ExpectError::check_assertion(&tree, [&](){ - auto lumi = plist.append_child(); - lumi |= MAP; - lumi << "Lumi"; - }); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -CASE_GROUP(GITHUB_ISSUES) -{ - -ADD_CASE_TO_GROUP("github3-problem1", -R"( -translation: [-2, -2, 5])", -L{N("translation", L{N("-2"), N("-2"), N("5")})} -); - -// these must work without quotes -ADD_CASE_TO_GROUP("github3-problem2-ex1", -R"( -audio resource: -)", -L{N(KEYVAL, "audio resource", /*"~"*/{})} -); -ADD_CASE_TO_GROUP("github3-problem2-ex2", -R"( -audio resource: -more: - example: y -)", -L{N(KEYVAL, "audio resource", /*"~"*/{}), N("more", L{N("example", "y")})} -); - -ADD_CASE_TO_GROUP("github3-problem3", -R"(component: - type: perspective camera component - some_data: {} # this was working - data: - {} # but this was not working -)", -L{N("component", L{ - N("type", "perspective camera component"), - N(KEYMAP, "some_data", L{}), - N(KEYMAP, "data", L{}) - } -)} -); - -/* THIS IS CAUSING VS TO CRASH OUT OF HEAP SPACE -ADD_CASE_TO_GROUP("github3", -R"( -universe: - objects: - object: - uuid: A7AB039C0EF3A74480A1B398247039A7 - components: - - component: - type: name component - data: - object name: Root Node - - component: - type: transform component - data: - translation: [-2, -2, 5] - rotation: [0, 0, 0, 1] - scaling: [1, 1, 1] - - component: - type: perspective camera component - data: - {} - - component: - type: mesh component - data: - mesh resource: TODO - - component: - type: lua script component - data: - {} - - component: - type: audio component - data: - audio resource: '' - type: 0 - current sample: 184102 - spatialized: true - children: - - object: - uuid: E1C364A925D649408E83C8EEF5179A87 - components: - - component: - type: name component - data: - object name: Prepend - children: - [] - - object: - uuid: 377DBA885AF4CD42B8A56BB3471F60E5 - components: - - component: - type: name component - data: - object name: pivot - children: - [] - - object: - uuid: 6DD1835797DADB4F95232CE7E9DE41BA - components: - - component: - type: name component - data: - object name: Append - children: - [] -)", - L{N("universe", L{ - N("objects", L{ - N("object", L{ - N("uuid", "A7AB039C0EF3A74480A1B398247039A7"), - N("components", L{ - N(L{N("component", L{N("type", "name component"), N("data", L{N("object name", "Root Node")}), }), }), - N(L{N("component", L{N("type", "transform component"), N("data", L{N("translation", L{N("-2"), N("-2"), N("5")}), N("rotation", L{N("0"), N("0"), N("0"), N("1")}), N("scaling", L{N("1"), N("1"), N("1")}),}), }), }), - N(L{N("component", L{N("type", "perspective camera component"), N(KEYMAP, "data", L{}), }), }), - N(L{N("component", L{N("type", "mesh component"), N("data", L{N("mesh resource", "TODO")}), }), }), - N(L{N("component", L{N("type", "lua script component"), N(KEYMAP, "data", L{}), }), }), - N(L{N("component", L{N("type", "audio component"), N("data", L{N("audio resource", ""), N("type", "0"), N("current sample", "184102"), N("spatialized", "true"), }), }), }), // component - }), // components - N("children", L{ - N(L{N("object", L{ - N("uuid", "E1C364A925D649408E83C8EEF5179A87"), - N("components", L{N(L{N("component", L{N("type", "name component"), N("data", L{N("object name", "Prepend")}), }), }), }), - N(KEYSEQ, "children", L{}), - }), }), // object - N(L{N("object", L{ - N("uuid", "377DBA885AF4CD42B8A56BB3471F60E5"), - N("components", L{N(L{N("component", L{N("type", "name component"), N("data", L{N("object name", "pivot")}), }), }), }), - N(KEYSEQ, "children", L{}), - }), }), // object - N(L{N("object", L{ - N("uuid", "6DD1835797DADB4F95232CE7E9DE41BA"), - N("components", L{N(L{N("component", L{N("type", "name component"), N("data", L{N("object name", "Append")}), }), }), }), - N(KEYSEQ, "children", L{}), - }), }), // object - }), // children - }), // object - }) // objects - }) // universe - } -); -*/ - -ADD_CASE_TO_GROUP("github6-problem1", -R"( -- UQxRibHKEDI: - - 0.mp4 - - 1.mp4 - - 2.mp4 - - 3.mp4 -- DcYsg8VFdC0: - - 0.mp4 - - 1.mp4 - - 2.mp4 - - 3.mp4 -- Yt3ymqZXzLY: - - 0.mp4 - - 1.mp4 - - 2.mp4 - - 3.mp4 -)", -L{ -N(L{N("UQxRibHKEDI", L{N("0.mp4"), N("1.mp4"), N("2.mp4"), N("3.mp4")})}), -N(L{N("DcYsg8VFdC0", L{N("0.mp4"), N("1.mp4"), N("2.mp4"), N("3.mp4")})}), -N(L{N("Yt3ymqZXzLY", L{N("0.mp4"), N("1.mp4"), N("2.mp4"), N("3.mp4")})}), -} -); - -ADD_CASE_TO_GROUP("github6", -R"(videos: -- UQxRibHKEDI: - - 0.mp4 - - 1.mp4 - - 2.mp4 - - 3.mp4 -- DcYsg8VFdC0: - - 0.mp4 - - 1.mp4 - - 2.mp4 - - 3.mp4 -- Yt3ymqZXzLY: - - 0.mp4 - - 1.mp4 - - 2.mp4 - - 3.mp4 -)", -L{N("videos", L{ -N(L{N("UQxRibHKEDI", L{N("0.mp4"), N("1.mp4"), N("2.mp4"), N("3.mp4")})}), -N(L{N("DcYsg8VFdC0", L{N("0.mp4"), N("1.mp4"), N("2.mp4"), N("3.mp4")})}), -N(L{N("Yt3ymqZXzLY", L{N("0.mp4"), N("1.mp4"), N("2.mp4"), N("3.mp4")})}), -})} -); - -ADD_CASE_TO_GROUP("github34/ex1", -R"( -# correct: -MessageID1: 'MapRegion_HyrulePrairie' -MessageID2: "MapRegion_HyrulePrairie" -MessageID3: 'MapRegion_HyrulePrairie' -MessageID4: "MapRegion_HyrulePrairie" -# incorrect: uninitialised memory? -MessageID5: 'MapRegion_HyrulePrairie' -MessageID6: "MapRegion_HyrulePrairie" -MessageID7: 'MapRegion_HyrulePrairie' -MessageID8: "MapRegion_HyrulePrairie" -MessageID9: 'MapRegion_HyrulePrairie' -MessageID0: "MapRegion_HyrulePrairie" -)", -L{ - N(QV, "MessageID1", "MapRegion_HyrulePrairie"), - N(QV, "MessageID2", "MapRegion_HyrulePrairie"), - N(QV, "MessageID3", "MapRegion_HyrulePrairie"), - N(QV, "MessageID4", "MapRegion_HyrulePrairie"), - N(QV, "MessageID5", "MapRegion_HyrulePrairie"), - N(QV, "MessageID6", "MapRegion_HyrulePrairie"), - N(QV, "MessageID7", "MapRegion_HyrulePrairie"), - N(QV, "MessageID8", "MapRegion_HyrulePrairie"), - N(QV, "MessageID9", "MapRegion_HyrulePrairie"), - N(QV, "MessageID0", "MapRegion_HyrulePrairie"), -} -); - -ADD_CASE_TO_GROUP("github34/ex2", -R"( -# correct: -- MessageID1: 'MapRegion_HyrulePrairie' -- MessageID2: "MapRegion_HyrulePrairie" -- MessageID3: 'MapRegion_HyrulePrairie' -- MessageID4: "MapRegion_HyrulePrairie" -# incorrect: uninitialised memory? -- MessageID5: 'MapRegion_HyrulePrairie' -- MessageID6: "MapRegion_HyrulePrairie" -- MessageID7: 'MapRegion_HyrulePrairie' -- MessageID8: "MapRegion_HyrulePrairie" -- MessageID9: 'MapRegion_HyrulePrairie' -- MessageID0: "MapRegion_HyrulePrairie" -)", -L{ - N(L{N(QV, "MessageID1", "MapRegion_HyrulePrairie")}), - N(L{N(QV, "MessageID2", "MapRegion_HyrulePrairie")}), - N(L{N(QV, "MessageID3", "MapRegion_HyrulePrairie")}), - N(L{N(QV, "MessageID4", "MapRegion_HyrulePrairie")}), - N(L{N(QV, "MessageID5", "MapRegion_HyrulePrairie")}), - N(L{N(QV, "MessageID6", "MapRegion_HyrulePrairie")}), - N(L{N(QV, "MessageID7", "MapRegion_HyrulePrairie")}), - N(L{N(QV, "MessageID8", "MapRegion_HyrulePrairie")}), - N(L{N(QV, "MessageID9", "MapRegion_HyrulePrairie")}), - N(L{N(QV, "MessageID0", "MapRegion_HyrulePrairie")}), -} -); - -ADD_CASE_TO_GROUP("github34", -R"( -# incorrect: uninitialised memory? -- MessageID1: 'MapRegion_HyrulePrairie' -- MessageID2: "MapRegion_HyrulePrairie" - -# incorrect: uninitialised memory? -- MessageID3: 'MapRegion_HyrulePrairie ' -- MessageID4: "MapRegion_HyrulePrairie " - -# incorrect: for some reason the ' is included in the string -- MessageID5: 'MapRegion_HyrulePrairie ' -- MessageID6: 'MapRegion_HyrulePrairie ' -- MessageID7: "MapRegion_HyrulePrairie " -- MessageID8: "MapRegion_HyrulePrairie " - -# incorrect: same issue -- MessageID9: 'MapRegion_HyrulePrairie ' -- MessageID10: "MapRegion_HyrulePrairie " - -# incorrect: still has the trailing quote -- MessageID11: 'MapRegion_HyrulePrairie' -- MessageID12: "MapRegion_HyrulePrairie" - -# the string is parsed correctly in this case -- key1: true1 - MessageID1: 'MapRegion_HyrulePrairie1 ' -- key2: true2 - MessageID2: "MapRegion_HyrulePrairie2 " -)", -L{ - N(L{N(QV, "MessageID1", "MapRegion_HyrulePrairie")}), - N(L{N(QV, "MessageID2", "MapRegion_HyrulePrairie")}), - N(L{N(QV, "MessageID3", "MapRegion_HyrulePrairie ")}), - N(L{N(QV, "MessageID4", "MapRegion_HyrulePrairie ")}), - N(L{N(QV, "MessageID5", "MapRegion_HyrulePrairie ")}), - N(L{N(QV, "MessageID6", "MapRegion_HyrulePrairie ")}), - N(L{N(QV, "MessageID7", "MapRegion_HyrulePrairie ")}), - N(L{N(QV, "MessageID8", "MapRegion_HyrulePrairie ")}), - N(L{N(QV, "MessageID9", "MapRegion_HyrulePrairie ")}), - N(L{N(QV, "MessageID10", "MapRegion_HyrulePrairie ")}), - N(L{N(QV, "MessageID11", "MapRegion_HyrulePrairie")}), - N(L{N(QV, "MessageID12", "MapRegion_HyrulePrairie")}), - N(L{N("key1", "true1"), N(QV, "MessageID1", "MapRegion_HyrulePrairie1 ")}), - N(L{N("key2", "true2"), N(QV, "MessageID2", "MapRegion_HyrulePrairie2 ")}), -} -); - -ADD_CASE_TO_GROUP("github35/expected_error11", EXPECT_PARSE_ERROR, -R"( -# *segfault* // not anymore! -- key1: true1 - MessageID1: 'MapRegion_HyrulePrairie1 ' -)", - LineCol(4, 1) -); - -ADD_CASE_TO_GROUP("github35/expected_error12", EXPECT_PARSE_ERROR, -R"( -# *segfault* // not anymore! -- key2: true2 - MessageID2: "MapRegion_HyrulePrairie2 " -)", - LineCol(4, 1) -); - -ADD_CASE_TO_GROUP("github35/expected_error21", EXPECT_PARSE_ERROR, -R"( -# *segfault* // not anymore! -- key1: true1 - MessageID1: 'MapRegion_HyrulePrairie1 ' -)", - LineCol(4, 15) -); - -ADD_CASE_TO_GROUP("github35/expected_error22", EXPECT_PARSE_ERROR, -R"( -# *segfault* // not anymore! -- key2: true2 - MessageID2: "MapRegion_HyrulePrairie2 " -)", - LineCol(4, 15) -); - -ADD_CASE_TO_GROUP("github128/1", RESOLVE_REFS | EXPECT_PARSE_ERROR, "a: *invalid"); -ADD_CASE_TO_GROUP("github128/2", RESOLVE_REFS/* | HAS_PARSE_ERROR*/, "*", N(DOCVAL, "*")); - -ADD_CASE_TO_GROUP("github129", RESOLVE_REFS, R"( -ref: &ref ref_val -a: *ref # resolve the reference -b: '*ref' # don't resolve, it's just a string -c: "*ref" # don't resolve, it's just a string -d: > # don't resolve, it's just a string - *ref -e: >- # don't resolve, it's just a string - *ref -f: >+ # don't resolve, it's just a string - *ref -g: | # don't resolve, it's just a string - *ref -h: |- # don't resolve, it's just a string - *ref -i: |+ # don't resolve, it's just a string - *ref -)", L{ - N("ref", "ref_val"), - N("a", "ref_val"), // this should be resolved - N(QV, "b", "*ref"), // this should not be resolved (just a string) - N(QV, "c", "*ref"), // this should not be resolved (just a string) - N(QV, "d", "*ref\n"), // this should not be resolved (just a string) - N(QV, "e", "*ref"), // this should not be resolved (just a string) - N(QV, "f", "*ref\n"), // this should not be resolved (just a string) - N(QV, "g", "*ref\n"), // this should not be resolved (just a string) - N(QV, "h", "*ref"), // this should not be resolved (just a string) - N(QV, "i", "*ref\n"), // this should not be resolved (just a string) - } -); -} - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_group.cpp b/thirdparty/ryml/test/test_group.cpp deleted file mode 100644 index 77ef5fa23..000000000 --- a/thirdparty/ryml/test/test_group.cpp +++ /dev/null @@ -1,732 +0,0 @@ -#ifndef RYML_SINGLE_HEADER -#include "c4/yml/detail/print.hpp" -#endif -#include "test_group.hpp" -#include "test_case.hpp" -#include -#include -#include - -#define RYML_NFO (RYML_DBG || 0) - -//----------------------------------------------------------------------------- -namespace c4 { -namespace yml { - -void YmlTestCase::_test_parse_using_ryml(CaseDataLineEndings *cd) -{ - #ifdef RYML_NFO - std::cout << "---------------\n"; - std::cout << c->src; - std::cout << "---------------\n"; - #endif - - if(c->flags & EXPECT_PARSE_ERROR) - { - auto flags = c->flags; - ExpectError::do_check(&cd->parsed_tree, [this, cd, flags](){ - parse_in_place(c->fileline, cd->src, &cd->parsed_tree); - if(flags & RESOLVE_REFS) - cd->parsed_tree.resolve(); - #ifdef RYML_DBG - // if this point was reached, then it means that the expected - // error failed to occur. So print debugging info. - std::cout << "failed to catch expected error while parsing.\nPARSED TREE:\n"; - print_tree(cd->parsed_tree); - #endif - }, c->expected_location); - return; - } - - cd->parsed_tree.clear(); - parse_in_place(c->fileline, cd->src, &cd->parsed_tree); - - #ifdef RYML_NFO - std::cout << "REF TREE:\n"; - print_tree(c->root); - std::cout << "PARSED TREE:\n"; - print_tree(cd->parsed_tree); - #endif - - { - SCOPED_TRACE("checking tree invariants of unresolved parsed tree"); - test_invariants(cd->parsed_tree); - } - { - SCOPED_TRACE("checking node invariants of unresolved parsed tree"); - test_invariants(cd->parsed_tree.rootref()); - } - - if(c->flags & RESOLVE_REFS) - { - cd->parsed_tree.resolve(); - #ifdef RYML_NFO - std::cout << "resolved tree!!!\n"; - print_tree(cd->parsed_tree); - #endif - { - SCOPED_TRACE("checking tree invariants of resolved parsed tree"); - test_invariants(cd->parsed_tree); - } - { - SCOPED_TRACE("checking node invariants of resolved parsed tree"); - test_invariants(cd->parsed_tree.rootref()); - } - } - - { - SCOPED_TRACE("comparing parsed tree to ref tree"); - EXPECT_GE(cd->parsed_tree.capacity(), c->root.reccount()); - EXPECT_EQ(cd->parsed_tree.size(), c->root.reccount()); - c->root.compare(cd->parsed_tree.rootref()); - } - - if(c->flags & RESOLVE_REFS) - { - cd->parsed_tree.reorder(); - #ifdef RYML_NFO - std::cout << "reordered tree!!!\n"; - print_tree(cd->parsed_tree); - #endif - { - SCOPED_TRACE("checking tree invariants of reordered parsed tree after resolving"); - test_invariants(cd->parsed_tree); - } - { - SCOPED_TRACE("checking node invariants of reordered parsed tree after resolving"); - test_invariants(cd->parsed_tree.rootref()); - } - - { - SCOPED_TRACE("comparing parsed tree to ref tree"); - EXPECT_GE(cd->parsed_tree.capacity(), c->root.reccount()); - EXPECT_EQ(cd->parsed_tree.size(), c->root.reccount()); - c->root.compare(cd->parsed_tree.rootref()); - } - } -} - - -//----------------------------------------------------------------------------- -void YmlTestCase::_test_emit_yml_stdout(CaseDataLineEndings *cd) -{ - if(c->flags & EXPECT_PARSE_ERROR) - return; - _ensure_parse(cd); - _ensure_emit(cd); - cd->numbytes_stdout = emit_yaml(cd->parsed_tree); - EXPECT_EQ(cd->numbytes_stdout, cd->emitted_yml.size()); -} - -//----------------------------------------------------------------------------- -void YmlTestCase::_test_emit_json_stdout(CaseDataLineEndings *cd) -{ - if(!(c->flags & JSON_ALSO)) - return; - if(c->flags & EXPECT_PARSE_ERROR) - return; - _ensure_parse(cd); - _ensure_emit_json(cd); - cd->numbytes_stdout_json = emit_json(cd->parsed_tree); - EXPECT_EQ(cd->numbytes_stdout_json, cd->emitted_json.size()); -} - -//----------------------------------------------------------------------------- -void YmlTestCase::_test_emit_yml_cout(CaseDataLineEndings *cd) -{ - if(c->flags & EXPECT_PARSE_ERROR) - return; - _ensure_parse(cd); - _ensure_emit(cd); - std::cout << cd->parsed_tree; - std::cout << cd->parsed_tree.rootref(); -} - -//----------------------------------------------------------------------------- -void YmlTestCase::_test_emit_json_cout(CaseDataLineEndings *cd) -{ - if(!(c->flags & JSON_ALSO)) - return; - if(c->flags & EXPECT_PARSE_ERROR) - return; - _ensure_parse(cd); - _ensure_emit_json(cd); - std::cout << as_json(cd->parsed_tree); - std::cout << as_json(cd->parsed_tree.rootref()); -} - - -//----------------------------------------------------------------------------- -void YmlTestCase::_test_emit_yml_stringstream(CaseDataLineEndings *cd) -{ - if(c->flags & EXPECT_PARSE_ERROR) - return; - _ensure_parse(cd); - _ensure_emit(cd); - { - std::stringstream ss; - ss << cd->parsed_tree; - std::string actual = ss.str(); - EXPECT_EQ(actual, cd->emit_buf); - } - { - std::stringstream ss; - ss << cd->parsed_tree.rootref(); - std::string actual = ss.str(); - EXPECT_EQ(actual, cd->emit_buf); - } -} - -//----------------------------------------------------------------------------- -void YmlTestCase::_test_emit_json_stringstream(CaseDataLineEndings *cd) -{ - if(!(c->flags & JSON_ALSO)) - return; - if(c->flags & EXPECT_PARSE_ERROR) - return; - _ensure_parse(cd); - _ensure_emit_json(cd); - { - std::stringstream ss; - ss << as_json(cd->parsed_tree); - std::string actual = ss.str(); - EXPECT_EQ(actual, cd->emitjson_buf); - } - { - std::stringstream ss; - ss << as_json(cd->parsed_tree.rootref()); - std::string actual = ss.str(); - EXPECT_EQ(actual, cd->emitjson_buf); - } -} - -//----------------------------------------------------------------------------- -void YmlTestCase::_test_emit_yml_ofstream(CaseDataLineEndings *cd) -{ - if(c->flags & EXPECT_PARSE_ERROR) - return; - _ensure_parse(cd); - _ensure_emit(cd); - { - auto fn = fs::tmpnam(); - { - std::ofstream f(fn, std::ios::binary); - f << cd->parsed_tree; - } - auto actual = fs::file_get_contents(fn.c_str()); - EXPECT_EQ(actual, cd->emit_buf); - fs::rmfile(fn.c_str()); - } - { - auto fn = fs::tmpnam(); - { - std::ofstream f(fn, std::ios::binary); - f << cd->parsed_tree.rootref(); - } - auto actual = fs::file_get_contents(fn.c_str()); - EXPECT_EQ(actual, cd->emit_buf); - fs::rmfile(fn.c_str()); - } -} - -//----------------------------------------------------------------------------- -void YmlTestCase::_test_emit_json_ofstream(CaseDataLineEndings *cd) -{ - if(!(c->flags & JSON_ALSO)) - return; - if(c->flags & EXPECT_PARSE_ERROR) - return; - _ensure_parse(cd); - _ensure_emit_json(cd); - { - auto fn = fs::tmpnam(); - { - std::ofstream f(fn, std::ios::binary); - f << as_json(cd->parsed_tree); - } - auto actual = fs::file_get_contents(fn.c_str()); - EXPECT_EQ(actual, cd->emitjson_buf); - fs::rmfile(fn.c_str()); - } - { - auto fn = fs::tmpnam(); - { - std::ofstream f(fn, std::ios::binary); - f << as_json(cd->parsed_tree.rootref()); - } - auto actual = fs::file_get_contents(fn.c_str()); - EXPECT_EQ(actual, cd->emitjson_buf); - fs::rmfile(fn.c_str()); - } -} - -//----------------------------------------------------------------------------- -void YmlTestCase::_test_emit_yml_string(CaseDataLineEndings *cd) -{ - if(c->flags & EXPECT_PARSE_ERROR) - return; - _ensure_parse(cd); - _ensure_emit(cd); - auto em = emitrs_yaml(cd->parsed_tree, &cd->emit_buf); - EXPECT_EQ(em.len, cd->emit_buf.size()); - EXPECT_EQ(em.len, cd->numbytes_stdout); - #ifdef RYML_NFO - std::cout << em; - #endif -} - -//----------------------------------------------------------------------------- -void YmlTestCase::_test_emit_json_string(CaseDataLineEndings *cd) -{ - if(!(c->flags & JSON_ALSO)) - return; - if(c->flags & EXPECT_PARSE_ERROR) - return; - _ensure_parse(cd); - _ensure_emit_json(cd); - auto em = emitrs_json(cd->parsed_tree, &cd->emit_buf); - EXPECT_EQ(em.len, cd->emitjson_buf.size()); - EXPECT_EQ(em.len, cd->numbytes_stdout_json); - #ifdef RYML_NFO - std::cout << em; - #endif -} - -//----------------------------------------------------------------------------- -void YmlTestCase::_test_emitrs(CaseDataLineEndings *cd) -{ - if(c->flags & EXPECT_PARSE_ERROR) - return; - _ensure_parse(cd); - using vtype = std::vector; - using stype = std::string; - vtype vv, v = emitrs_yaml(cd->parsed_tree); - stype ss, s = emitrs_yaml(cd->parsed_tree); - EXPECT_EQ(to_csubstr(v), to_csubstr(s)); - csubstr svv = emitrs_yaml(cd->parsed_tree, &vv); - csubstr sss = emitrs_yaml(cd->parsed_tree, &ss); - EXPECT_EQ(svv, sss); -} - -//----------------------------------------------------------------------------- -void YmlTestCase::_test_emitrs_json(CaseDataLineEndings *cd) -{ - if(!(c->flags & JSON_ALSO)) - return; - if(c->flags & EXPECT_PARSE_ERROR) - return; - _ensure_parse(cd); - using vtype = std::vector; - using stype = std::string; - vtype vv, v = emitrs_json(cd->parsed_tree); - stype ss, s = emitrs_json(cd->parsed_tree); - EXPECT_EQ(to_csubstr(v), to_csubstr(s)); - csubstr svv = emitrs_json(cd->parsed_tree, &vv); - csubstr sss = emitrs_json(cd->parsed_tree, &ss); - EXPECT_EQ(svv, sss); -} - -//----------------------------------------------------------------------------- -void YmlTestCase::_test_emitrs_cfile(CaseDataLineEndings *cd) -{ - if(c->flags & EXPECT_PARSE_ERROR) - return; - _ensure_parse(cd); - auto s = emitrs_yaml(cd->parsed_tree); - std::string r; - { - c4::fs::ScopedTmpFile f; - emit_yaml(cd->parsed_tree, f.m_file); - fflush(f.m_file); - r = f.contents(); - } - EXPECT_EQ(s, r); -} - -//----------------------------------------------------------------------------- -void YmlTestCase::_test_emitrs_json_cfile(CaseDataLineEndings *cd) -{ - if(!(c->flags & JSON_ALSO)) - return; - if(c->flags & EXPECT_PARSE_ERROR) - return; - _ensure_parse(cd); - auto s = emitrs_json(cd->parsed_tree); - std::string r; - { - c4::fs::ScopedTmpFile f; - emit_json(cd->parsed_tree, f.m_file); - fflush(f.m_file); - r = f.contents(); - } - EXPECT_EQ(s, r); -} - - -//----------------------------------------------------------------------------- -void YmlTestCase::_test_complete_round_trip(CaseDataLineEndings *cd) -{ - if(c->flags & EXPECT_PARSE_ERROR) - return; - _ensure_parse(cd); - _ensure_emit(cd); - { - SCOPED_TRACE("parsing emitted yml"); - cd->parse_buf = cd->emit_buf; - cd->parsed_yml = to_substr(cd->parse_buf); - parse_in_place(c->fileline, cd->parsed_yml, &cd->emitted_tree); - } - #ifdef RYML_NFO - std::cout << "~~~~~~~~~~~~~~ src yml:\n"; - _c4presc(cd->src); - std::cout << "~~~~~~~~~~~~~~ parsed tree:\n"; - print_tree(cd->parsed_tree); - std::cout << "~~~~~~~~~~~~~~ emitted yml:\n"; - _c4presc(cd->emitted_yml); - std::cout << "~~~~~~~~~~~~~~ emitted tree:\n"; - print_tree(cd->emitted_tree); - std::cout << "~~~~~~~~~~~~~~\n"; - #endif - { - SCOPED_TRACE("checking node invariants of emitted tree"); - test_invariants(cd->parsed_tree.rootref()); - } - { - SCOPED_TRACE("checking node invariants of emitted tree"); - test_invariants(cd->emitted_tree.rootref()); - } - { - SCOPED_TRACE("comparing emitted and parsed tree"); - test_compare(cd->emitted_tree, cd->parsed_tree); - } - { - SCOPED_TRACE("checking tree invariants of emitted tree"); - test_invariants(cd->emitted_tree); - } - { - SCOPED_TRACE("comparing parsed tree to ref tree"); - EXPECT_GE(cd->parsed_tree.capacity(), c->root.reccount()); - EXPECT_EQ(cd->parsed_tree.size(), c->root.reccount()); - c->root.compare(cd->parsed_tree.rootref()); - } - { - SCOPED_TRACE("comparing emitted tree to ref tree"); - EXPECT_GE(cd->emitted_tree.capacity(), c->root.reccount()); - EXPECT_EQ(cd->emitted_tree.size(), c->root.reccount()); - // in this case, we can ignore whether scalars are quoted. - // Because it can happen that a scalar was quoted in the - // original file, but the re-emitted data does not quote the - // scalars. - c->root.compare(cd->emitted_tree.rootref(), true); - } -} - - -//----------------------------------------------------------------------------- -void YmlTestCase::_test_complete_round_trip_json(CaseDataLineEndings *cd) -{ - if(!(c->flags & JSON_ALSO)) - return; - if(c->flags & EXPECT_PARSE_ERROR) - return; - _ensure_parse(cd); - _ensure_emit_json(cd); - { - SCOPED_TRACE("parsing emitted json"); - cd->parse_buf_json = cd->emitjson_buf; - cd->parsed_json = to_substr(cd->parse_buf_json); - parse_in_place(c->fileline, cd->parsed_json, &cd->emitted_tree_json); - } - #ifdef RYML_NFO - std::cout << "~~~~~~~~~~~~~~ src yml:\n"; - _c4presc(cd->src); - std::cout << "~~~~~~~~~~~~~~ parsed tree:\n"; - print_tree(cd->parsed_tree); - std::cout << "~~~~~~~~~~~~~~ emitted json:\n"; - _c4presc(cd->emitted_json); - std::cout << "~~~~~~~~~~~~~~ emitted json tree:\n"; - print_tree(cd->emitted_tree_json); - std::cout << "~~~~~~~~~~~~~~\n"; - #endif - { - SCOPED_TRACE("checking node invariants of emitted tree"); - test_invariants(cd->parsed_tree.rootref()); - } - { - SCOPED_TRACE("checking node invariants of emitted json tree"); - test_invariants(cd->emitted_tree_json.rootref()); - } - { - SCOPED_TRACE("comparing emitted json and parsed tree"); - test_compare(cd->emitted_tree_json, cd->parsed_tree); - } - { - SCOPED_TRACE("checking tree invariants of emitted json tree"); - test_invariants(cd->emitted_tree_json); - } - { - SCOPED_TRACE("comparing parsed tree to ref tree"); - EXPECT_GE(cd->parsed_tree.capacity(), c->root.reccount()); - EXPECT_EQ(cd->parsed_tree.size(), c->root.reccount()); - c->root.compare(cd->parsed_tree.rootref()); - } - { - SCOPED_TRACE("comparing emitted tree to ref tree"); - EXPECT_GE(cd->emitted_tree_json.capacity(), c->root.reccount()); - EXPECT_EQ(cd->emitted_tree_json.size(), c->root.reccount()); - // in this case, we can ignore whether scalars are quoted. - // Because it can happen that a scalar was quoted in the - // original file, but the re-emitted data does not quote the - // scalars. - c->root.compare(cd->emitted_tree_json.rootref(), true); - } -} - -//----------------------------------------------------------------------------- -void YmlTestCase::_test_recreate_from_ref(CaseDataLineEndings *cd) -{ - if(c->flags & EXPECT_PARSE_ERROR) - return; - if(cd->parsed_tree.empty()) - parse_in_place(c->fileline, cd->src, &cd->parsed_tree); - if(cd->emit_buf.empty()) - cd->emitted_yml = emitrs_yaml(cd->parsed_tree, &cd->emit_buf); - { - SCOPED_TRACE("recreating a new tree from the ref tree"); - cd->recreated.reserve(cd->parsed_tree.size()); - NodeRef r = cd->recreated.rootref(); - c->root.recreate(&r); - } - #ifdef RYML_NFO - std::cout << "REF TREE:\n"; - print_tree(c->root); - std::cout << "RECREATED TREE:\n"; - print_tree(cd->recreated); - #endif - { - SCOPED_TRACE("checking node invariants of recreated tree"); - test_invariants(cd->recreated.rootref()); - } - { - SCOPED_TRACE("checking tree invariants of recreated tree"); - test_invariants(cd->recreated); - } - { - SCOPED_TRACE("comparing recreated tree to ref tree"); - c->root.compare(cd->recreated.rootref()); - } -} - -//----------------------------------------------------------------------------- -TEST_P(YmlTestCase, parse_unix) -{ - SCOPED_TRACE("unix style"); - _test_parse_using_ryml(&d->unix_style); -} - -TEST_P(YmlTestCase, parse_windows) -{ - SCOPED_TRACE("windows style"); - _test_parse_using_ryml(&d->windows_style); -} - -//----------------------------------------------------------------------------- -TEST_P(YmlTestCase, emit_yml_unix_stdout) -{ - SCOPED_TRACE("unix style"); - _test_emit_yml_stdout(&d->unix_style); -} -TEST_P(YmlTestCase, emit_json_unix_stdout) -{ - SCOPED_TRACE("unix style json"); - _test_emit_json_stdout(&d->unix_style_json); -} - -TEST_P(YmlTestCase, emit_yml_windows_stdout) -{ - SCOPED_TRACE("windows style"); - _test_emit_yml_stdout(&d->windows_style); -} -TEST_P(YmlTestCase, emit_json_windows_stdout) -{ - SCOPED_TRACE("windows style json"); - _test_emit_json_stdout(&d->windows_style_json); -} - -//----------------------------------------------------------------------------- -TEST_P(YmlTestCase, emit_yml_unix_cout) -{ - SCOPED_TRACE("unix style"); - _test_emit_yml_cout(&d->unix_style); -} -TEST_P(YmlTestCase, emit_json_unix_cout) -{ - SCOPED_TRACE("unix style json"); - _test_emit_json_cout(&d->unix_style_json); -} - -TEST_P(YmlTestCase, emit_yml_windows_cout) -{ - SCOPED_TRACE("windows style"); - _test_emit_yml_cout(&d->windows_style); -} -TEST_P(YmlTestCase, emit_json_windows_cout) -{ - SCOPED_TRACE("windows style json"); - _test_emit_json_cout(&d->windows_style_json); -} - -//----------------------------------------------------------------------------- -TEST_P(YmlTestCase, emit_yml_unix_stringstream) -{ - SCOPED_TRACE("unix style"); - _test_emit_yml_stringstream(&d->unix_style); -} -TEST_P(YmlTestCase, emit_json_unix_stringstream) -{ - SCOPED_TRACE("unix style json"); - _test_emit_json_stringstream(&d->unix_style_json); -} - -TEST_P(YmlTestCase, emit_yml_windows_stringstream) -{ - SCOPED_TRACE("windows style"); - _test_emit_yml_stringstream(&d->windows_style); -} -TEST_P(YmlTestCase, emit_json_windows_stringstream) -{ - SCOPED_TRACE("windows style json"); - _test_emit_json_stringstream(&d->windows_style_json); -} - -//----------------------------------------------------------------------------- -TEST_P(YmlTestCase, emit_yml_unix_ofstream) -{ - SCOPED_TRACE("unix style"); - _test_emit_yml_ofstream(&d->unix_style); -} -TEST_P(YmlTestCase, emit_json_unix_ofstream) -{ - SCOPED_TRACE("unix style json"); - _test_emit_json_ofstream(&d->unix_style_json); -} - -TEST_P(YmlTestCase, emit_yml_windows_ofstream) -{ - SCOPED_TRACE("windows style"); - _test_emit_yml_ofstream(&d->windows_style); -} -TEST_P(YmlTestCase, emit_json_windows_ofstream) -{ - SCOPED_TRACE("windows style json"); - _test_emit_json_ofstream(&d->windows_style_json); -} - -//----------------------------------------------------------------------------- -TEST_P(YmlTestCase, emit_yml_unix_string) -{ - SCOPED_TRACE("unix style"); - _test_emit_yml_string(&d->unix_style); -} -TEST_P(YmlTestCase, emit_json_unix_string) -{ - SCOPED_TRACE("unix style json"); - _test_emit_json_string(&d->unix_style_json); -} - -TEST_P(YmlTestCase, emit_yml_windows_string) -{ - SCOPED_TRACE("windows style"); - _test_emit_yml_string(&d->windows_style); -} -TEST_P(YmlTestCase, emit_json_windows_string) -{ - SCOPED_TRACE("windows style json"); - _test_emit_json_string(&d->windows_style_json); -} - -//----------------------------------------------------------------------------- -TEST_P(YmlTestCase, unix_emitrs) -{ - SCOPED_TRACE("unix style"); - _test_emitrs(&d->unix_style); -} -TEST_P(YmlTestCase, unix_emitrs_json) -{ - SCOPED_TRACE("unix style json"); - _test_emitrs_json(&d->unix_style_json); -} - -TEST_P(YmlTestCase, windows_emitrs) -{ - SCOPED_TRACE("windows style"); - _test_emitrs(&d->windows_style); -} -TEST_P(YmlTestCase, windows_emitrs_json) -{ - SCOPED_TRACE("windows style json"); - _test_emitrs_json(&d->windows_style_json); -} - -//----------------------------------------------------------------------------- -TEST_P(YmlTestCase, unix_emitrs_cfile) -{ - SCOPED_TRACE("unix style"); - _test_emitrs_cfile(&d->unix_style); -} -TEST_P(YmlTestCase, unix_emitrs_json_cfile) -{ - SCOPED_TRACE("unix style json"); - _test_emitrs_json_cfile(&d->unix_style_json); -} - -TEST_P(YmlTestCase, windows_emitrs_cfile) -{ - SCOPED_TRACE("windows style"); - _test_emitrs_cfile(&d->windows_style); -} -TEST_P(YmlTestCase, windows_emitrs_json_cfile) -{ - SCOPED_TRACE("windows style json"); - _test_emitrs_json_cfile(&d->windows_style_json); -} - -//----------------------------------------------------------------------------- -TEST_P(YmlTestCase, complete_unix_round_trip) -{ - SCOPED_TRACE("unix style"); - _test_complete_round_trip(&d->unix_style); -} -TEST_P(YmlTestCase, complete_unix_round_trip_json) -{ - SCOPED_TRACE("unix style json"); - _test_complete_round_trip_json(&d->unix_style_json); -} - -TEST_P(YmlTestCase, complete_windows_round_trip) -{ - SCOPED_TRACE("windows style"); - _test_complete_round_trip(&d->windows_style); -} -TEST_P(YmlTestCase, complete_windows_round_trip_json) -{ - SCOPED_TRACE("windows style json"); - _test_complete_round_trip_json(&d->windows_style_json); -} - -//----------------------------------------------------------------------------- -TEST_P(YmlTestCase, unix_recreate_from_ref) -{ - SCOPED_TRACE("unix style"); - _test_recreate_from_ref(&d->unix_style); -} - -TEST_P(YmlTestCase, windows_recreate_from_ref) -{ - SCOPED_TRACE("windows style"); - _test_recreate_from_ref(&d->windows_style); -} - - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_group.hpp b/thirdparty/ryml/test/test_group.hpp deleted file mode 100644 index f661ec9b5..000000000 --- a/thirdparty/ryml/test/test_group.hpp +++ /dev/null @@ -1,210 +0,0 @@ -#pragma once -#ifndef C4_RYML_TEST_GROUP_HPP_ -#define C4_RYML_TEST_GROUP_HPP_ - -#include "./test_case.hpp" -#include "c4/span.hpp" -#include - -#if defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable: 4068/*unknown pragma*/) -#elif defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wunknown-pragmas" -//# pragma GCC diagnostic ignored "-Wpragma-system-header-outside-header" -#endif - - -namespace c4 { -namespace yml { - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// a fixture for running the tests -struct YmlTestCase : public ::testing::TestWithParam -{ - csubstr const name; - Case const* c; - CaseData * d; - - YmlTestCase() : name(to_csubstr(GetParam())) - { - c = get_case(name); - d = get_data(name); - } - - void SetUp() override - { - // Code here will be called immediately after the constructor (right - // before each test). - std::cout << "-------------------------------------------\n"; - std::cout << "running test case '" << name << "'\n"; - std::cout << "-------------------------------------------\n"; - } - - void _test_parse_using_ryml(CaseDataLineEndings *cd); - - void _test_emit_yml_stdout(CaseDataLineEndings *cd); - void _test_emit_json_stdout(CaseDataLineEndings *cd); - - void _test_emit_yml_cout(CaseDataLineEndings *cd); - void _test_emit_json_cout(CaseDataLineEndings *cd); - - void _test_emit_yml_stringstream(CaseDataLineEndings *cd); - void _test_emit_json_stringstream(CaseDataLineEndings *cd); - - void _test_emit_yml_ofstream(CaseDataLineEndings *cd); - void _test_emit_json_ofstream(CaseDataLineEndings *cd); - - void _test_emit_yml_string(CaseDataLineEndings *cd); - void _test_emit_json_string(CaseDataLineEndings *cd); - - void _test_emitrs(CaseDataLineEndings *cd); - void _test_emitrs_json(CaseDataLineEndings *cd); - - void _test_emitrs_cfile(CaseDataLineEndings *cd); - void _test_emitrs_json_cfile(CaseDataLineEndings *cd); - - void _test_complete_round_trip(CaseDataLineEndings *cd); - void _test_complete_round_trip_json(CaseDataLineEndings *cd); - - void _test_recreate_from_ref(CaseDataLineEndings *cd); - - void _ensure_parse(CaseDataLineEndings *cd) - { - if(cd->parsed_tree.empty()) - parse_in_place(c->fileline, cd->src, &cd->parsed_tree); - } - void _ensure_emit(CaseDataLineEndings *cd) - { - _ensure_parse(cd); - if(cd->emit_buf.empty()) - { - cd->emitted_yml = emitrs_yaml(cd->parsed_tree, &cd->emit_buf); - ASSERT_EQ(cd->emitted_yml.size(), cd->emit_buf.size()); - if(cd->emitted_yml.size()) - { - ASSERT_EQ(cd->emitted_yml.data(), cd->emit_buf.data()); - } - } - } - void _ensure_emit_json(CaseDataLineEndings *cd) - { - _ensure_parse(cd); - if(cd->emitjson_buf.empty()) - { - cd->emitted_json = emitrs_json(cd->parsed_tree, &cd->emitjson_buf); - ASSERT_EQ(cd->emitted_json.size(), cd->emitjson_buf.size()); - if(cd->emitted_json.size()) - { - ASSERT_EQ(cd->emitted_json.data(), cd->emitjson_buf.data()); - } - } - } -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// facilities for declaring test data - -using N = CaseNode; -using L = CaseNode::iseqmap; -using TS = TaggedScalar; -using TL = CaseNode::TaggedList; -using AR = AnchorRef; - -constexpr const NodeType_e QK = (NodeType_e)(VAL | KEYQUO); -constexpr const NodeType_e QV = (NodeType_e)(VAL | VALQUO); -constexpr const NodeType_e QKV = (NodeType_e)(VAL | KEYQUO | VALQUO); - -#ifdef __GNUC__ -#if __GNUC__ == 4 && __GNUC_MINOR__ >= 8 -struct CaseAdder { - std::vector *group_cases; - const csubstr file; - const int line; - - template - void operator ()(Args... parameters) const { - group_cases->emplace_back(csubstr(file), line, parameters...); - } -}; - -/* all arguments are to the constructor of Case */ -#define ADD_CASE_TO_GROUP CaseAdder{group_cases__, csubstr(__FILE__), __LINE__+1} -#endif -#endif - -#ifndef ADD_CASE_TO_GROUP -#define ADD_CASE_TO_GROUP(...) \ - group_cases__->emplace_back(csubstr(__FILE__), __LINE__+1, __VA_ARGS__) -#endif - -#define CASE_GROUP(group_name) \ - \ -/* fwd declaration to fill the container with cases */ \ -void add_cases_##group_name(std::vector *group_cases); \ - \ -/* container with the cases */ \ -std::vector const& get_cases_##group_name() \ -{ \ - static std::vector cases_##group_name; \ - if(cases_##group_name.empty()) \ - add_cases_##group_name(&cases_##group_name); \ - return cases_##group_name; \ -} \ - \ -/* container with the case names */ \ -std::vector const& get_case_names_##group_name() \ -{ \ - static std::vector case_names_##group_name; \ - if(case_names_##group_name.empty()) \ - { \ - for(auto const& c : get_cases_##group_name()) \ - case_names_##group_name.emplace_back(c.name); \ - /* check repetitions */ \ - std::vector cp = case_names_##group_name; \ - std::sort(cp.begin(), cp.end()); \ - for(size_t i = 0; i+1 < cp.size(); ++i) \ - if(cp[i] == cp[i+1]) \ - C4_ERROR("duplicate case name: '%.*s'", _c4prsp(cp[i])); \ - } \ - return case_names_##group_name; \ -} \ - \ -INSTANTIATE_TEST_SUITE_P(group_name, YmlTestCase, ::testing::ValuesIn(get_case_names_##group_name())); \ -GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(YmlTestCase); \ - \ -/* used by the fixture to obtain a case by name */ \ -Case const* get_case(csubstr name) \ -{ \ - for(Case const& c : get_cases_##group_name()) \ - if(c.name == name) \ - return &c; \ - C4_ERROR("case not found: '%.*s'", _c4prsp(name)); \ - return nullptr; \ -} \ - \ -/* finally, define the cases by calling ADD_CASE_TO_GROUP() */ \ -void add_cases_##group_name(std::vector *group_cases__) - - -} // namespace yml -} // namespace c4 - -#if defined(_MSC_VER) -# pragma warning(pop) -#elif defined(__clang__) -# pragma clang diagnostic pop -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#endif - -#endif // C4_RYML_TEST_GROUP_HPP_ diff --git a/thirdparty/ryml/test/test_indentation.cpp b/thirdparty/ryml/test/test_indentation.cpp deleted file mode 100644 index 46b6f9bff..000000000 --- a/thirdparty/ryml/test/test_indentation.cpp +++ /dev/null @@ -1,340 +0,0 @@ -#include "./test_group.hpp" - -namespace c4 { -namespace yml { - -CASE_GROUP(INDENTATION) -{ - -ADD_CASE_TO_GROUP("indented doc", R"( - # this is an indented doc - --- - - foo - - bar - - baz -)", -N(STREAM, L{N(DOCSEQ, L{N("foo"), N("bar"), N("baz")})}) -); - -ADD_CASE_TO_GROUP("4 chars", -R"( -key: - value -another_key: - sub_key0: - - val0 - - val1 - sub_key1: - - val2 - - val3 - sub_key2: - - val4 - - val5 -)", -L{ - N("key", "value"), - N("another_key", L{ - N("sub_key0", L{N("val0"), N("val1")}), - N("sub_key1", L{N("val2"), N("val3")}), - N("sub_key2", L{N("val4"), N("val5")}), - }) -}); - -ADD_CASE_TO_GROUP("2 chars + 4 chars, ex0", -R"( -key: - value -another_key: - sub_key0: - - val0 - - val1 - sub_key1: - - val2 - - val3 - sub_key2: - - val4 - - val5 -)", -L{ - N("key", "value"), - N("another_key", L{ - N("sub_key0", L{N("val0"), N("val1")}), - N("sub_key1", L{N("val2"), N("val3")}), - N("sub_key2", L{N("val4"), N("val5")}), - }) -}); - -ADD_CASE_TO_GROUP("2 chars + 4 chars, ex1", -R"( -key: - value -another_key: - sub_key0: - - val0 - - val1 - sub_key1: - - val2 - - val3 - sub_key2: - - val4 - - val5 -)", -L{ - N("key", "value"), - N("another_key", L{ - N("sub_key0", L{N("val0"), N("val1")}), - N("sub_key1", L{N("val2"), N("val3")}), - N("sub_key2", L{N("val4"), N("val5")}), - }) -}); - -ADD_CASE_TO_GROUP("2 chars + 4 chars, ex2", -R"( -key: - value -another_key: - sub_key0: - - val0 - - val1 - sub_key1: - - val2 - - val3 - sub_key2: - - val4 - - val5 -)", -L{ - N("key", "value"), - N("another_key", L{ - N("sub_key0", L{N("val0"), N("val1")}), - N("sub_key1", L{N("val2"), N("val3")}), - N("sub_key2", L{N("val4"), N("val5")}), - }) -}); - -ADD_CASE_TO_GROUP("non-indented blank lines", -R"( -matrix: - - include: # next line is blank - - - env01 - - env02 - - env03 - - env04 # next line has one space - - - env11 - - env12 - - env13 - - env14 # next line has two spaces - - - env21 - - env22 - - env23 - - env24 # next line has three spaces - - - env31 - - env32 - - env33 - - env34 # next line has four spaces - - - env41 - - env42 - - env43 - - env44 # next line has five spaces - - - env51 - - env52 - - env53 - - env54 # next line has six spaces - - - env61 - - env62 - - env63 - - env64 # next line has five spaces -)", -L{N("matrix", L{ - N("include", L{ - N("env01"), N("env02"), N("env03"), N("env04"), - N("env11"), N("env12"), N("env13"), N("env14"), - N("env21"), N("env22"), N("env23"), N("env24"), - N("env31"), N("env32"), N("env33"), N("env34"), - N("env41"), N("env42"), N("env43"), N("env44"), - N("env51"), N("env52"), N("env53"), N("env54"), - N("env61"), N("env62"), N("env63"), N("env64"), - } - )}) -}); - -ADD_CASE_TO_GROUP("unnecessary indentation", -R"( -skip_commits: - files: - - a - - b - - c - - d - - e - - f - more_files: - - a - - b - even_more_files: - - a - - b -more_skip: - files: - - a - - b - - c - - d - - e - - f - more_files: - - a - - b -)", -L{ - N("skip_commits", L{ - N("files", L{N("a"), N("b"), N("c"), N("d"), N("e"), N("f"),}), - N("more_files", L{N("a"), N("b"),}), - N("even_more_files", L{N("a"), N("b"),}), - }), - N("more_skip", L{ - N("files", L{N("a"), N("b"), N("c"), N("d"), N("e"), N("f"),}), - N("more_files", L{N("a"), N("b"),}), - }) -}); - - -ADD_CASE_TO_GROUP("blank lines indented, 1 - at same scope", -R"( -skip_commits: - files: - - a # next line has 22 spaces (aligns with -) - - - b # next line has 23 spaces (aligns with #) - - - c # next line has 3 spaces - - - d -)", -L{ - N("skip_commits", L{ - N("files", L{N("a"), N("b"), N("c"), N("d"),}), - }), -}); - -ADD_CASE_TO_GROUP("indentation at start", -R"( - foo: - - a - - b - bar: - - c - - d -)", -L{ - N("foo", L{N("a"), N("b"),}), - N("bar", L{N("c"), N("d"),}), -}); - -ADD_CASE_TO_GROUP("unaligned comments", -R"( - stand2sit: - map: mirror - dat: - - a - - b -# - - b1 - # - - b2 - # - # - # - - b3 - # - # - # - - b4 - # - # - c - #- d - - b5 - #- d2 - #- d3 - #- d4 - - b6 - #- d41 - # - - b61 - # - # - - b62 - # - # - # - - b63 - # - - b64 - # - - b65 - # - # - # - - b66 - # - # - # - # - #- d41 - #- d5 - #- d6 - #- d7 - - b7 - #- d8 - # - # - # - - b8 - # - # - # - - b9 - # - # - - b10 - # -# - - e - - f - - g -)", -L{ - N("stand2sit", L{ - N("map", "mirror"), - N("dat", L{N("a"), N("b"), N("b1"), N("b2"), N("b3"), N("b4"), N("b5"), N("b6"), N("b61"), N("b62"), N("b63"), N("b64"), N("b65"), N("b66"), N("b7"), N("b8"), N("b9"), N("b10"), N("e"), N("f"), N("g")}), - }), -}); - -ADD_CASE_TO_GROUP("issue83", -R"( -e: - - f -g: h -a: - - b - -c: d -)", -L{ -N("e", L{N("f")}), -N("g", "h"), -N("a", L{N("b")}), -N("c", "d"), -}); -} - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_json.cpp b/thirdparty/ryml/test/test_json.cpp deleted file mode 100644 index 8be31b794..000000000 --- a/thirdparty/ryml/test/test_json.cpp +++ /dev/null @@ -1,516 +0,0 @@ -#ifndef RYML_SINGLE_HEADER -#include "c4/yml/std/std.hpp" -#include "c4/yml/parse.hpp" -#include "c4/yml/emit.hpp" -#include -#include -#include -#endif - -#include "./test_case.hpp" - -#include - -namespace foo { - -template -struct vec2 -{ - T x, y; -}; -template -struct vec3 -{ - T x, y, z; -}; -template -struct vec4 -{ - T x, y, z, w; -}; - -template size_t to_chars(c4::substr buf, vec2 v) { return c4::format(buf, "({},{})", v.x, v.y); } -template size_t to_chars(c4::substr buf, vec3 v) { return c4::format(buf, "({},{},{})", v.x, v.y, v.z); } -template size_t to_chars(c4::substr buf, vec4 v) { return c4::format(buf, "({},{},{},{})", v.x, v.y, v.z, v.w); } - -template bool from_chars(c4::csubstr buf, vec2 *v) { size_t ret = c4::unformat(buf, "({},{})", v->x, v->y); return ret != c4::yml::npos; } -template bool from_chars(c4::csubstr buf, vec3 *v) { size_t ret = c4::unformat(buf, "({},{},{})", v->x, v->y, v->z); return ret != c4::yml::npos; } -template bool from_chars(c4::csubstr buf, vec4 *v) { size_t ret = c4::unformat(buf, "({},{},{},{})", v->x, v->y, v->z, v->w); return ret != c4::yml::npos; } - -TEST(serialize, type_as_str) -{ - c4::yml::Tree t; - - auto r = t.rootref(); - r |= c4::yml::MAP; - - vec2 v2in{10, 11}; - vec2 v2out; - r["v2"] << v2in; - r["v2"] >> v2out; - EXPECT_EQ(v2in.x, v2out.x); - EXPECT_EQ(v2in.y, v2out.y); - - vec3 v3in{100, 101, 102}; - vec3 v3out; - r["v3"] << v3in; - r["v3"] >> v3out; - EXPECT_EQ(v3in.x, v3out.x); - EXPECT_EQ(v3in.y, v3out.y); - EXPECT_EQ(v3in.z, v3out.z); - - vec4 v4in{1000, 1001, 1002, 1003}; - vec4 v4out; - r["v4"] << v4in; - r["v4"] >> v4out; - EXPECT_EQ(v4in.x, v4out.x); - EXPECT_EQ(v4in.y, v4out.y); - EXPECT_EQ(v4in.z, v4out.z); - EXPECT_EQ(v4in.w, v4out.w); - - char buf[256]; - c4::csubstr interm = c4::yml::emit_json(t, buf); - EXPECT_EQ(interm, R"_({"v2": "(10,11)","v3": "(100,101,102)","v4": "(1000,1001,1002,1003)"})_"); -} -} // namespace foo - -namespace c4 { -namespace yml { - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -TEST(general, emitting) -{ - std::string cmpbuf; - std::string cmpbuf2; - - Tree tree; - auto r = tree.rootref(); - - r |= MAP; // this is needed to make the root a map - - r["foo"] = "1"; // ryml works only with strings. - // Note that the tree will be __pointing__ at the - // strings "foo" and "1" used here. You need - // to make sure they have at least the same - // lifetime as the tree. - - auto s = r["seq"]; // does not change the tree until s is written to. - s |= SEQ; - r["seq"].append_child() = "bar0"; // value of this child is now __pointing__ at "bar0" - r["seq"].append_child() = "bar1"; - r["seq"].append_child() = "bar2"; - - //print_tree(tree); - - // emit to stdout (can also emit to FILE* or ryml::span) - emitrs_json(tree, &cmpbuf); - EXPECT_EQ(cmpbuf, R"({"foo": 1,"seq": ["bar0","bar1","bar2"]})"); - - // serializing: using operator<< instead of operator= - // will make the tree serialize the value into a char - // arena inside the tree. This arena can be reserved at will. - int ch3 = 33, ch4 = 44; - s.append_child() << ch3; - s.append_child() << ch4; - - { - std::string tmp = "child5"; - s.append_child() << tmp; - // now tmp can go safely out of scope, as it was - // serialized to the tree's internal string arena - } - - emitrs_json(tree, &cmpbuf); - EXPECT_EQ(cmpbuf, R"({"foo": 1,"seq": ["bar0","bar1","bar2",33,44,"child5"]})"); - - // to serialize keys: - int k = 66; - r.append_child() << key(k) << 7; - emitrs_json(tree, &cmpbuf); - EXPECT_EQ(cmpbuf, R"({"foo": 1,"seq": ["bar0","bar1","bar2",33,44,"child5"],"66": 7})"); -} - -TEST(general, map_to_root) -{ - std::string cmpbuf; const char *exp; - std::map m({{"bar", 2}, {"foo", 1}}); - Tree t; - t.rootref() << m; - - emitrs_json(t, &cmpbuf); - exp = "{\"bar\": 2,\"foo\": 1}"; - EXPECT_EQ(cmpbuf, exp); - - t["foo"] << 10; - t["bar"] << 20; - - m.clear(); - t.rootref() >> m; - - EXPECT_EQ(m["foo"], 10); - EXPECT_EQ(m["bar"], 20); -} - -TEST(general, json_stream_operator) -{ - std::map out, m({{"bar", 2}, {"foo", 1}, {"foobar_barfoo:barfoo_foobar", 1001}, {"asdfjkl;", 42}, {"00000000000000000000000000000000000000000000000000000000000000", 1}}); - Tree t; - t.rootref() << m; - std::string str; - { - std::stringstream ss; - ss << as_json(t); - str = ss.str(); - } - Tree res = c4::yml::parse_in_place(to_substr(str)); - EXPECT_EQ(res["foo"].val(), "1"); - EXPECT_EQ(res["bar"].val(), "2"); - EXPECT_EQ(res["foobar_barfoo:barfoo_foobar"].val(), "1001"); - EXPECT_EQ(res["asdfjkl;"].val(), "42"); - EXPECT_EQ(res["00000000000000000000000000000000000000000000000000000000000000"].val(), "1"); - res.rootref() >> out; - EXPECT_EQ(out["foo"], 1); - EXPECT_EQ(out["bar"], 2); - EXPECT_EQ(out["foobar_barfoo:barfoo_foobar"], 1001); - EXPECT_EQ(out["asdfjkl;"], 42); - EXPECT_EQ(out["00000000000000000000000000000000000000000000000000000000000000"], 1); -} - -TEST(emit_json, issue72) -{ - Tree t; - NodeRef r = t.rootref(); - - r |= MAP; - r["1"] = "null"; - r["2"] = "true"; - r["3"] = "false"; - r["null"] = "1"; - r["true"] = "2"; - r["false"] = "3"; - - std::string out; - emitrs_json(t, &out); - - EXPECT_EQ(out, R"({"1": null,"2": true,"3": false,"null": 1,"true": 2,"false": 3})"); -} - - -TEST(emit_json, issue121) -{ - Tree t = parse_in_arena(R"( -string_value: "string" -number_value: "9001" -broken_value: "0.30.2" -)"); - EXPECT_TRUE(t["string_value"].get()->m_type.type & VALQUO); - EXPECT_TRUE(t["number_value"].get()->m_type.type & VALQUO); - EXPECT_TRUE(t["broken_value"].get()->m_type.type & VALQUO); - std::string out; - emitrs_json(t, &out); - EXPECT_EQ(out, R"({"string_value": "string","number_value": "9001","broken_value": "0.30.2"})"); - out.clear(); - emitrs_yaml(t, &out); - EXPECT_EQ(out, R"(string_value: 'string' -number_value: '9001' -broken_value: '0.30.2' -)"); -} - -TEST(emit_json, issue291) -{ - Tree t = parse_in_arena("{}"); - t["james"] = "045"; - auto s = emitrs_json(t); - EXPECT_EQ(s, "{\"james\": \"045\"}"); -} - -TEST(emit_json, issue292) -{ - EXPECT_FALSE(csubstr("0.0.0").is_number()); - EXPECT_FALSE(csubstr("0.0.0").is_integer()); - EXPECT_FALSE(csubstr("0.0.0").is_real()); - EXPECT_FALSE(csubstr("0.1.0").is_number()); - EXPECT_FALSE(csubstr("0.1.0").is_integer()); - EXPECT_FALSE(csubstr("0.1.0").is_real()); - EXPECT_FALSE(csubstr("0.6.1").is_number()); - EXPECT_FALSE(csubstr("0.6.1").is_integer()); - EXPECT_FALSE(csubstr("0.6.1").is_real()); - EXPECT_FALSE(csubstr("1.1.9").is_number()); - EXPECT_FALSE(csubstr("1.1.9").is_integer()); - EXPECT_FALSE(csubstr("1.1.9").is_real()); - EXPECT_FALSE(csubstr("1.2.3").is_number()); - EXPECT_FALSE(csubstr("1.2.3").is_integer()); - EXPECT_FALSE(csubstr("1.2.3").is_real()); - Tree t = parse_in_arena("{}"); - t["james"] = "0.0.0"; - EXPECT_EQ(emitrs_json(t), "{\"james\": \"0.0.0\"}"); - t["james"] = "0.1.0"; - EXPECT_EQ(emitrs_json(t), "{\"james\": \"0.1.0\"}"); - t["james"] = "0.6.1"; - EXPECT_EQ(emitrs_json(t), "{\"james\": \"0.6.1\"}"); - t["james"] = "1.1.9"; - EXPECT_EQ(emitrs_json(t), "{\"james\": \"1.1.9\"}"); - t["james"] = "1.2.3"; - EXPECT_EQ(emitrs_json(t), "{\"james\": \"1.2.3\"}"); -} - -TEST(emit_json, issue297) -{ - char yml_buf[] = R"( -comment: | - abc - def -)"; - Tree t = parse_in_place(yml_buf); - auto s = emitrs_json(t); - EXPECT_EQ(s, "{\"comment\": \"abc\\ndef\\n\"}"); -} - -TEST(emit_json, issue297_escaped_chars) -{ - Tree t = parse_in_arena("{}"); - t["quote"] = "abc\"def"; - t["newline"] = "abc\ndef"; - t["tab"] = "abc\tdef"; - t["carriage"] = "abc\rdef"; - t["backslash"] = "abc\\def"; - t["backspace"] = "abc\bdef"; - t["formfeed"] = "abc\fdef"; - std::string expected = R"({"quote": "abc\"def","newline": "abc\ndef","tab": "abc\tdef","carriage": "abc\rdef","backslash": "abc\\def","backspace": "abc\bdef","formfeed": "abc\fdef"})"; - auto actual = emitrs_json(t); - EXPECT_EQ(actual, expected); -} - -namespace { -std::string k(ConstNodeRef node) { return std::string(node.key().str, node.key().len); } -std::string v(ConstNodeRef node) { return std::string(node.val().str, node.val().len); } -} -TEST(emit_json, issue313_quoted_numbers__1) -{ - EXPECT_TRUE(csubstr("0.99356698989868164").is_number()); // [WEIRD0][0] - EXPECT_TRUE(csubstr("0.99356698989868164").is_real()); // [WEIRD0][0] - EXPECT_FALSE(csubstr("0.99356698989868164").is_integer()); // [WEIRD0][0] - EXPECT_TRUE(csubstr("0.0064908224157989025").is_number()); // [WEIRD2][0] - EXPECT_TRUE(csubstr("0.0064908224157989025").is_real()); // [WEIRD2][0] - EXPECT_FALSE(csubstr("0.0064908224157989025").is_integer()); // [WEIRD2][0] - EXPECT_TRUE(csubstr("0.0064917667768895626").is_number()); // [WEIRD2][1] - EXPECT_TRUE(csubstr("0.0064917667768895626").is_real()); // [WEIRD2][1] - EXPECT_FALSE(csubstr("0.0064917667768895626").is_integer()); // [WEIRD2][1] - EXPECT_TRUE(csubstr("0.0064947893843054771").is_number()); // [WEIRD2][2] - EXPECT_TRUE(csubstr("0.0064947893843054771").is_real()); // [WEIRD2][2] - EXPECT_FALSE(csubstr("0.0064947893843054771").is_integer()); // [WEIRD2][2] - EXPECT_TRUE(csubstr("0.91054189205169678").is_number()); // [WEIRD4][0] - EXPECT_TRUE(csubstr("0.91054189205169678").is_real()); // [WEIRD4][0] - EXPECT_FALSE(csubstr("0.91054189205169678").is_integer()); // [WEIRD4][0] - EXPECT_TRUE(csubstr("0.13215841352939606").is_number()); // [REALLY_WEIRD5][9][0] - EXPECT_TRUE(csubstr("0.13215841352939606").is_real()); // [REALLY_WEIRD5][9][0] - EXPECT_FALSE(csubstr("0.13215841352939606").is_integer()); // [REALLY_WEIRD5][9][0] - Tree t0 = parse_in_arena(R"([ - 0.99356698989868164, - 0.0064908224157989025, - 0.0064917667768895626, - 0.0064947893843054771, - 0.91054189205169678, - 0.13215841352939606, -])"); - std::string yaml = emitrs_json(t0); - test_check_emit_check(to_csubstr(yaml), [&](Tree const &t){ - for(ConstNodeRef number : t.rootref().children()) - { - ASSERT_TRUE(number.is_val()); - EXPECT_FALSE(number.is_val_quoted()) << "tree[" << t.rootref().child_pos(number) << "]=" << v(number); - } - }); -} - - -TEST(emit_json, issue313_quoted_numbers__2) -{ - Tree ti = parse_in_arena(R"({ -WEIRD0: [0.99356698989868164, 1.0605627298355103], -OK1: [0, 0, 0], -WEIRD2: [0.0064908224157989025, 0.0064917667768895626, 0.0064947893843054771], -OK3: [6.6227097511291504, 6.8674740791320801, 7.0403199195861816, 7.5792555809020996, 7.9916787147521973, 8.136042594909668, 8.5505847930908203, 8.701807975769043, 8.926518440246582, 8.9484291076660156, 9.0740194320678711, 9.3788108825683594, 9.406926155090332], -WEIRD4: [0.91054189205169678, 0.98725020885467529, 1.070807933807373], -REALLY_WEIRD5: [ - [1.5158847570419312, 1.6361792087554932], # 0 - [1.0741721391677856, 1.1791903972625732], # 1 - [1.4423576593399048, 1.7063977718353271], # 2 - [1.1791903972625732], # 3 - [1.1493504047393799, 1.1791903972625732], # 4 - [1.1791903972625732, 1.3334760665893555], # 5 - [1.0655292272567749, 1.4933452606201172], # 6 - [1.0712906122207642, 1.1791903972625732], # 7 - [1.1791903972625732, 1.830910325050354], # 8 - [0.13215841352939606, 1.4161584377288818], # 9 - [1.1791903972625732, 1.5179581642150879], # 10 - [1.1791903972625732, 1.2864601612091064], # 11 - [1.1791903972625732, 1.6865267753601074], # 12 - [1.1791903972625732, 1.2192368507385254], # 13 - [1.1130030155181885, 1.5196701288223267], # 14 - [1.0621790885925293, 1.1791903972625732] # 15 -]})"); - std::string yaml = emitrs_json(ti); - test_check_emit_check(to_csubstr(yaml), [](Tree const &t){ - for(ConstNodeRef node : t.rootref().children()) - { - ASSERT_TRUE(node.is_seq()); - ASSERT_TRUE(node.has_key()); - EXPECT_TRUE(node.is_key_quoted()) << "tree[" << k(node) << "]"; - if(node.key() != "REALLY_WEIRD5") - { - for(ConstNodeRef number : node.children()) - { - ASSERT_TRUE(number.is_val()); - EXPECT_FALSE(number.is_val_quoted()) << "tree[" << k(node) << "][" << node.child_pos(number) << "]=" << v(number); - } - } - else - { - for(ConstNodeRef seq : node.children()) - { - ASSERT_TRUE(seq.is_seq()); - for(ConstNodeRef number : seq.children()) - { - ASSERT_TRUE(number.is_val()); - EXPECT_FALSE(number.is_val_quoted()) << "tree[" << k(node) << "][" << node.child_pos(seq) << "][" << seq.child_pos(number) << "]=" << v(number); - } - } - } - } - }); -} - - -#define _test(actual_src, expected_src) \ - { \ - SCOPED_TRACE(__LINE__); \ - csubstr file = __FILE__ ":" C4_XQUOTE(__LINE__); \ - Tree actual = parse_in_arena(file, actual_src); \ - Tree expected = parse_in_arena(file, expected_src); \ - test_compare(actual, expected); \ - } - - -TEST(json, basic) -{ - _test("", ""); - _test("{}", "{}"); - _test(R"("a":"b")", - R"("a": "b")"); - _test(R"('a':'b')", - R"('a': 'b')"); - _test(R"({'a':'b'})", - R"({'a': 'b'})"); - _test(R"({"a":"b"})", - R"({"a": "b"})"); - - _test(R"({"a":{"a":"b"}})", - R"({"a": {"a": "b"}})"); - _test(R"({'a':{'a':'b'}})", - R"({'a': {'a': 'b'}})"); -} - -TEST(json, github142) -{ - _test(R"({"A":"B}"})", - R"({"A": "B}"})"); - _test(R"({"A":"{B"})", - R"({"A": "{B"})"); - _test(R"({"A":"{B}"})", - R"({"A": "{B}"})"); - _test(R"({ "A":"B}" })", - R"({ "A": "B}" })"); - _test(R"({"A":["B]","[C","[D]"]})", - R"({"A": ["B]","[C","[D]"]})"); - //_test(R"({"A":["B\"]","[\"C","\"[D]\""]})", // VS2019 chokes on this. - // R"({"A": ["B\"]","[\"C","\"[D]\""]})"); - - _test(R"({'A':'B}'})", - R"({'A': 'B}'})"); - _test(R"({'A':'{B'})", - R"({'A': '{B'})"); - _test(R"({'A':'{B}'})", - R"({'A': '{B}'})"); - _test(R"({ 'A':'B}' })", - R"({ 'A': 'B}' })"); - _test(R"({'A':['B]','[C','[D]']})", - R"({'A': ['B]','[C','[D]']})"); - _test(R"({'A':['B'']','[''C','''[D]''']})", - R"({'A': ['B'']','[''C','''[D]''']})"); -} - -TEST(json, github52) -{ - _test(R"({"a": "b","c": 42,"d": "e"})", - R"({"a": "b","c": 42,"d": "e"})"); - _test(R"({"aaaa": "bbbb","cccc": 424242,"dddddd": "eeeeeee"})", - R"({"aaaa": "bbbb","cccc": 424242,"dddddd": "eeeeeee"})"); - - _test(R"({"a":"b","c":42,"d":"e"})", - R"({"a": "b","c": 42,"d": "e"})"); - _test(R"({"aaaaa":"bbbbb","ccccc":424242,"ddddd":"eeeee"})", - R"({"aaaaa": "bbbbb","ccccc": 424242,"ddddd": "eeeee"})"); - _test(R"({"a":"b","c":{},"d":"e"})", - R"({"a": "b","c": {},"d": "e"})"); - _test(R"({"aaaaa":"bbbbb","ccccc":{ },"ddddd":"eeeee"})", - R"({"aaaaa": "bbbbb","ccccc": { },"ddddd": "eeeee"})"); - _test(R"({"a":"b","c":true,"d":"e"})", - R"({"a": "b","c": true,"d": "e"})"); - _test(R"({"a":"b","c":false,"d":"e"})", - R"({"a": "b","c": false,"d": "e"})"); - _test(R"({"a":"b","c":true,"d":"e"})", - R"({"a": "b","c": true,"d": "e"})"); - _test(R"({"a":"b","c":null,"d":"e"})", - R"({"a": "b","c": null,"d": "e"})"); - _test(R"({"aaaaa":"bbbbb","ccccc":false,"ddddd":"eeeee"})", - R"({"aaaaa": "bbbbb","ccccc": false,"ddddd": "eeeee"})"); - _test(R"({"a":"b","c":false,"d":"e"})", - R"({"a": "b","c": false,"d": "e"})"); - _test(R"({"aaaaa":"bbbbb","ccccc":true,"ddddd":"eeeee"})", - R"({"aaaaa": "bbbbb","ccccc": true,"ddddd": "eeeee"})"); -} - -TEST(json, nested) -{ - _test(R"({"a":"b","c":{"a":"b","c":{},"d":"e"},"d":"e"})", - R"({"a": "b","c": {"a": "b","c": {},"d": "e"},"d": "e"})"); - _test(R"({"a":"b","c":{"a":"b","c":{"a":"b","c":{},"d":"e"},"d":"e"},"d":"e"})", - R"({"a": "b","c": {"a": "b","c": {"a": "b","c": {},"d": "e"},"d": "e"},"d": "e"})"); - _test(R"({"a":"b","c":{"a":"b","c":{"a":"b","c":{"a":"b","c":{},"d":"e"},"d":"e"},"d":"e"},"d":"e"})", - R"({"a": "b","c": {"a": "b","c": {"a": "b","c": {"a": "b","c": {},"d": "e"},"d": "e"},"d": "e"},"d": "e"})"); - _test(R"({"a":"b","c":{"a":"b","c":{"a":"b","c":{"a":"b","c":{"a":"b","c":{},"d":"e"},"d":"e"},"d":"e"},"d":"e"},"d":"e"})", - R"({"a": "b","c": {"a": "b","c": {"a": "b","c": {"a": "b","c": {"a": "b","c": {},"d": "e"},"d": "e"},"d": "e"},"d": "e"},"d": "e"})"); - - _test(R"({"a":"b","c":["a","c","d","e"],"d":"e"})", - R"({"a": "b","c": ["a","c","d","e"],"d": "e"})"); -} - -TEST(json, nested_end) -{ - _test(R"({"a":"b","d":"e","c":{"a":"b","d":"e","c":{}}})", - R"({"a": "b","d": "e","c": {"a": "b","d": "e","c": {}}})"); - _test(R"({"a":"b","d":"e","c":{"a":"b","d":"e","c":{"a":"b","d":"e","c":{}}}})", - R"({"a": "b","d": "e","c": {"a": "b","d": "e","c": {"a": "b","d": "e","c": {}}}})"); - _test(R"({"a":"b","d":"e","c":{"a":"b","d":"e","c":{"a":"b","d":"e","c":{"a":"b","d":"e","c":{}}}}})", - R"({"a": "b","d": "e","c": {"a": "b","d": "e","c": {"a": "b","d": "e","c": {"a": "b","d": "e","c": {}}}}})"); - _test(R"({"a":"b","d":"e","c":{"a":"b","d":"e","c":{"a":"b","d":"e","c":{"a":"b","d":"e","c":{"a":"b","d":"e","c":{}}}}}})", - R"({"a": "b","d": "e","c": {"a": "b","d": "e","c": {"a": "b","d": "e","c": {"a": "b","d": "e","c": {"a": "b","d": "e","c": {}}}}}})"); -} - -#undef _test - - -//------------------------------------------- -// this is needed to use the test case library -Case const* get_case(csubstr /*name*/) -{ - return nullptr; -} - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_location.cpp b/thirdparty/ryml/test/test_location.cpp deleted file mode 100644 index e05407eeb..000000000 --- a/thirdparty/ryml/test/test_location.cpp +++ /dev/null @@ -1,720 +0,0 @@ -#ifndef RYML_SINGLE_HEADER -#include -#include -#endif -#include "./test_case.hpp" -#include - - -namespace c4 { -namespace yml { - -TEST(locations, default_is_no_location) -{ - { - ParserOptions opts; - EXPECT_EQ(opts.locations(), false); - } - { - Parser parser; - EXPECT_EQ(parser.options().locations(), false); - } - { - Parser parser(ParserOptions{}); - EXPECT_EQ(parser.options().locations(), false); - } - { - Parser parser(ParserOptions().locations(false)); - EXPECT_EQ(parser.options().locations(), false); - } - { - Parser parser(ParserOptions().locations(true)); - EXPECT_EQ(parser.options().locations(), true); - } -} - - -TEST(locations, error_is_triggered_querying_with_locations_disabled) -{ - bool parsed_ok = false; - ExpectError::do_check([&]{ - Parser parser(ParserOptions().locations(false)); - Tree t = parser.parse_in_arena("test", "foo: bar"); - parsed_ok = true; - (void)parser.location(t["foo"]); - }); - EXPECT_TRUE(parsed_ok); -} - - - -#define _checkloc(node, line_, col_, str) \ - { \ - const Location loc = parser.location(node); \ - EXPECT_EQ(loc.name, "myfile.yml"); \ - EXPECT_EQ(loc.line, line_); \ - EXPECT_EQ(loc.col, col_); \ - EXPECT_EQ(t.arena().sub(loc.offset, csubstr(str).len), csubstr(str)); \ - } - -TEST(locations, no_error_is_triggered_querying_with_locations) -{ - Parser parser(ParserOptions().locations(true)); - EXPECT_EQ(parser.options().locations(), true); - Tree t = parser.parse_in_arena("myfile.yml", "foo: bar"); - _checkloc(t["foo"], 0, 0, "foo"); -} - - -TEST(locations, docval) -{ - ParserOptions opts = ParserOptions().locations(true); - Parser parser(opts); - Tree t = parser.parse_in_arena("myfile.yml", "docval"); - _checkloc(t.rootref(), 0u, 0u, "docval"); - t = parser.parse_in_arena("myfile.yml", "\n docval"); - _checkloc(t.rootref(), 1u, 1u, "docval"); - t = parser.parse_in_arena("myfile.yml", "\n\n docval"); - _checkloc(t.rootref(), 2u, 1u, "docval"); -} - -TEST(locations, docval_null) -{ - ParserOptions opts = ParserOptions().locations(true); - Parser parser(opts); - Tree t = parser.parse_in_arena("myfile.yml", "~"); - _checkloc(t.rootref(), 0u, 0u, "~"); - t = parser.parse_in_arena("myfile.yml", ""); - _checkloc(t.rootref(), 0u, 0u, ""); - t = parser.parse_in_arena("myfile.yml", R"(# -# -# -# -# -)"); - _checkloc(t.rootref(), 0u, 0u, ""); -} - -TEST(locations, seq_block) -{ - ParserOptions opts = ParserOptions().locations(true); - Parser parser(opts); - csubstr yaml = R"( -- this -- is -- a -- seq -- - and - - this - - - as - - well - - - # this one works as well - # even with a comment in between - the scalar value is here - - and here's another value - - - - another val - - yet another val -)"; - Tree t = parser.parse_in_arena("myfile.yml", yaml); - ConstNodeRef seq = t.rootref(); - ASSERT_TRUE(seq.is_seq()); - _checkloc(seq , 1u, 0u, "- "); - _checkloc(seq[0] , 1u, 2u, "this"); - _checkloc(seq[1] , 2u, 2u, "is"); - _checkloc(seq[2] , 3u, 2u, "a"); - _checkloc(seq[3] , 4u, 2u, "seq"); - _checkloc(seq[4] , 5u, 2u, "- "); - _checkloc(seq[4][0] , 5u, 4u, "and"); - _checkloc(seq[4][1] , 6u, 4u, "this"); - _checkloc(seq[4][2] , 7u, 4u, "- "); - _checkloc(seq[4][2][0], 7u, 6u, "as"); - _checkloc(seq[4][2][1], 8u, 6u, "well"); - _checkloc(seq[4][3] , 9u, 4u, "- # this one works as well"); - _checkloc(seq[4][3][0], 11u, 6u, "the scalar value is here"); - _checkloc(seq[4][3][1], 12u, 8u, "and here's another value"); - _checkloc(seq[4][3][2], 14u, 6u, "- "); - _checkloc(seq[4][3][2][0], 14u, 8u, "another val"); - _checkloc(seq[4][3][2][1], 15u, 8u, "yet another val"); -} - -TEST(locations, map_block) -{ - ParserOptions opts = ParserOptions().locations(true); - Parser parser(opts); - csubstr yaml = R"( -this: ~ -is: ~ -a: ~ -map: ~ -and: - this: - as: ~ - well: ~ - aswell: # this one works as well - # even with a comment in between - val: here - hah: here -)"; - Tree t = parser.parse_in_arena("myfile.yml", yaml); - ConstNodeRef map = t.rootref(); - ASSERT_TRUE(map.is_map()); - _checkloc(map , 1u, 0u, "this:"); - _checkloc(map["this"] , 1u, 0u, "this:"); - _checkloc(map["is"] , 2u, 0u, "is:"); - _checkloc(map["a"] , 3u, 0u, "a:"); - _checkloc(map["map"] , 4u, 0u, "map:"); - _checkloc(map["and"] , 5u, 0u, "and:"); - _checkloc(map["and"]["this"] , 6u, 2u, "this:"); - _checkloc(map["and"]["this"]["as"] , 7u, 4u, "as:"); - _checkloc(map["and"]["this"]["well"] , 8u, 4u, "well:"); - _checkloc(map["and"]["aswell"] , 9u, 2u, "aswell:"); - _checkloc(map["and"]["aswell"]["val"] , 11u, 4u, "val:"); - _checkloc(map["and"]["aswell"]["hah"] , 12u, 4u, "hah:"); -} - -TEST(locations, seq_block_null) -{ - ParserOptions opts = ParserOptions().locations(true); - Parser parser(opts); - const Tree t = parser.parse_in_arena("myfile.yml", R"(--- -- ~ -- ~ -- notnull -- ~ -- ~ ---- -- ~ -- - ~ -- - - ~ -- - - - ~ -- - - - - ~ -- - - - ~ -- - - ~ -- - ~ -- ~ ---- -- -- -- -- - - - - - - - - - - - - - - - - - - - - - - - - -- -)"); - _checkloc(t.rootref() , 0u, 0u, "---"); - _checkloc(t.docref(0) , 1u, 0u, "- "); - _checkloc(t.docref(0)[0], 1u, 2u, "~"); - _checkloc(t.docref(0)[1], 2u, 2u, "~"); - _checkloc(t.docref(0)[2], 3u, 2u, "notnull"); - _checkloc(t.docref(0)[3], 4u, 2u, "~"); - _checkloc(t.docref(0)[4], 5u, 2u, "~"); - _checkloc(t.docref(1) , 7u, 0u, "- "); - _checkloc(t.docref(1)[0], 7u, 2u, "~"); - _checkloc(t.docref(1)[1], 8u, 2u, "- "); - _checkloc(t.docref(1)[1][0], 8u, 4u, "~"); - _checkloc(t.docref(1)[2], 9u, 2u, "- "); - _checkloc(t.docref(1)[2][0], 9u, 4u, "- "); - _checkloc(t.docref(1)[2][0][0], 9u, 6u, "~"); - _checkloc(t.docref(1)[3], 10u, 2u, "- "); - _checkloc(t.docref(1)[3][0], 10u, 4u, "- "); - _checkloc(t.docref(1)[3][0][0], 10u, 6u, "- "); - _checkloc(t.docref(1)[3][0][0][0], 10u, 8u, "~"); - _checkloc(t.docref(1)[4], 11u, 2u, "- "); - _checkloc(t.docref(1)[4][0], 11u, 4u, "- "); - _checkloc(t.docref(1)[4][0][0], 11u, 6u, "- "); - _checkloc(t.docref(1)[4][0][0][0], 11u, 8u, "- "); - _checkloc(t.docref(1)[4][0][0][0][0], 11u, 10u, "~"); - _checkloc(t.docref(1)[5], 12u, 2u, "- "); - _checkloc(t.docref(1)[5][0], 12u, 4u, "- "); - _checkloc(t.docref(1)[5][0][0], 12u, 6u, "- "); - _checkloc(t.docref(1)[5][0][0][0], 12u, 8u, "~"); - _checkloc(t.docref(1)[6], 13u, 2u, "- "); - _checkloc(t.docref(1)[6][0], 13u, 4u, "- "); - _checkloc(t.docref(1)[6][0][0], 13u, 6u, "~"); - _checkloc(t.docref(1)[7], 14u, 2u, "- "); - _checkloc(t.docref(1)[7][0], 14u, 4u, "~"); - _checkloc(t.docref(1)[8], 15u, 2u, "~"); - _checkloc(t.docref(2) , 17u, 0u, "-"); - _checkloc(t.docref(2)[0], 17u, 0u, "-"); - _checkloc(t.docref(2)[1], 17u, 0u, "-"); - _checkloc(t.docref(2)[2], 21u, 2u, "-"); - _checkloc(t.docref(2)[3], 21u, 2u, "-"); - _checkloc(t.docref(2)[3][0], 21u, 2u, "-"); - _checkloc(t.docref(2)[3][1], 24u, 4u, "-"); - _checkloc(t.docref(2)[3][2], 24u, 4u, "-"); - _checkloc(t.docref(2)[3][2][0], 25u, 6u, "-"); - _checkloc(t.docref(2)[3][2][0][0], 26u, 8u, "-"); - _checkloc(t.docref(2)[3][2][0][0][0], 26u, 8u, "-"); - _checkloc(t.docref(2)[3][2][0][0][1], 26u, 8u, "-"); - _checkloc(t.docref(2)[3][2][1], 25u, 6u, "-"); - _checkloc(t.docref(2)[3][3], 24u, 4u, "-"); // fix: this should be after the previous child - _checkloc(t.docref(2)[3][4], 21u, 2u, "-"); // fix: this should be after the previous child - _checkloc(t.docref(2)[3][5], 21u, 2u, "-"); // fix: this should be after the previous child -} - -TEST(locations, map_block_null) -{ - ParserOptions opts = ParserOptions().locations(true); - Parser parser(opts); - Tree t = parser.parse_in_arena("myfile.yml", R"(--- -~: v ---- -null: v ---- - : v -)"); - _checkloc(t.rootref() , 0u, 0u, "---"); - _checkloc(t.docref(0) , 1u, 0u, ""); - _checkloc(t.docref(0)[0], 1u, 0u, "~"); - _checkloc(t.docref(1) , 3u, 0u, "null"); - _checkloc(t.docref(1)[0], 3u, 0u, "null"); - _checkloc(t.docref(2) , 5u, 1u, ""); - _checkloc(t.docref(2)[0], 5u, 3u, ""); -} - -TEST(locations, empty_seq) -{ - ParserOptions opts = ParserOptions().locations(true); - Parser parser(opts); - Tree t = parser.parse_in_arena("myfile.yml", R"(--- -- [] -- [] -- notnull -- [] -- [] ---- -- [] ---- -[] ---- -key0: [] -key1: [] -key2: notnull -key3: [] -key4: [] ---- -key: [] -)"); - _checkloc(t.rootref() , 0u, 0u, "---"); - _checkloc(t.docref(0) , 1u, 0u, "- "); - _checkloc(t.docref(0)[0], 1u, 2u, "[]"); - _checkloc(t.docref(0)[1], 2u, 2u, "[]"); - _checkloc(t.docref(0)[2], 3u, 2u, "notnull"); - _checkloc(t.docref(0)[3], 4u, 2u, "[]"); - _checkloc(t.docref(0)[4], 5u, 2u, "[]"); - _checkloc(t.docref(1) , 7u, 0u, "- "); - _checkloc(t.docref(1)[0], 7u, 2u, "[]"); - _checkloc(t.docref(2) , 9u, 0u, "[]"); - _checkloc(t.docref(3) , 11u, 0u, "key0"); // WTF - _checkloc(t.docref(3)["key0"], 11u, 0u, "key0"); - _checkloc(t.docref(3)["key1"], 12u, 0u, "key1"); - _checkloc(t.docref(3)["key2"], 13u, 0u, "key2"); - _checkloc(t.docref(3)["key3"], 14u, 0u, "key3"); - _checkloc(t.docref(3)["key4"], 15u, 0u, "key4"); -} - -TEST(locations, empty_map) -{ - ParserOptions opts = ParserOptions().locations(true); - Parser parser(opts); - Tree t = parser.parse_in_arena("myfile.yml", R"(--- -- {} -- {} -- notnull -- {} -- {} ---- -- {} ---- -{} ---- -key0: {} -key1: {} -key2: notnull -key3: {} -key4: {} ---- -key: {} -)"); - _checkloc(t.rootref() , 0u, 0u, "---"); - _checkloc(t.docref(0) , 1u, 0u, "- "); - _checkloc(t.docref(0)[0], 1u, 2u, "{}"); - _checkloc(t.docref(0)[1], 2u, 2u, "{}"); - _checkloc(t.docref(0)[2], 3u, 2u, "notnull"); - _checkloc(t.docref(0)[3], 4u, 2u, "{}"); - _checkloc(t.docref(0)[4], 5u, 2u, "{}"); - _checkloc(t.docref(1) , 7u, 0u, "- "); - _checkloc(t.docref(1)[0], 7u, 2u, "{}"); - _checkloc(t.docref(2) , 9u, 0u, "{}"); - _checkloc(t.docref(3) , 11u, 0u, "key0"); // WTF - _checkloc(t.docref(3)["key0"], 11u, 0u, "key0"); - _checkloc(t.docref(3)["key1"], 12u, 0u, "key1"); - _checkloc(t.docref(3)["key2"], 13u, 0u, "key2"); - _checkloc(t.docref(3)["key3"], 14u, 0u, "key3"); - _checkloc(t.docref(3)["key4"], 15u, 0u, "key4"); -} - - -TEST(locations, seq_flow) -{ - Tree t; - ParserOptions opts = ParserOptions().locations(true); - Parser parser(opts); - csubstr yaml = R"([one,two,three,four,items])"; - parser.parse_in_arena("myfile.yml", yaml, &t); - ConstNodeRef seq = t.rootref(); - ASSERT_TRUE(seq.is_seq()); - _checkloc(seq , 0u, 0u, "["); - _checkloc(seq[0], 0u, 1u, "one"); - _checkloc(seq[1], 0u, 5u, "two"); - _checkloc(seq[2], 0u, 9u, "three"); - _checkloc(seq[3], 0u, 15u, "four"); - _checkloc(seq[4], 0u, 20u, "items"); -} - -TEST(locations, map_flow) -{ - Tree t; - ParserOptions opts = ParserOptions().locations(true); - Parser parser(opts); - csubstr yaml = R"({one: item,two: items,three: items,four: items})"; - parser.parse_in_arena("myfile.yml", yaml, &t); - ConstNodeRef map = t.rootref(); - ASSERT_TRUE(map.is_map()); - _checkloc(map , 0u, 0u, "{"); - _checkloc(map[0], 0u, 1u, "one:"); - _checkloc(map[1], 0u, 11u, "two:"); - _checkloc(map[2], 0u, 22u, "three:"); - _checkloc(map[3], 0u, 35u, "four:"); -} - -TEST(locations, seq_flow_nested) -{ - Tree t; - ParserOptions opts = ParserOptions().locations(true); - Parser parser(opts); - csubstr yaml = R"([ - one, - two, - [woops, there, [ goes, master]], - five, - {wait: is, this: { really: a map? }, nope: [ a seq!, { had: you there, eehh: no. } ]}, - yep, - it, - was -])"; - parser.parse_in_arena("myfile.yml", yaml, &t); - ConstNodeRef seq = t.rootref(); - ASSERT_TRUE(seq.is_seq()); - _checkloc(seq , 0u, 0u, "["); - _checkloc(seq[0] , 1u, 2u, "one"); - _checkloc(seq[1] , 2u, 2u, "two"); - _checkloc(seq[2] , 3u, 2u, "["); - _checkloc(seq[2][0] , 3u, 3u, "woops"); - _checkloc(seq[2][1] , 3u, 14u, "there"); - _checkloc(seq[2][2] , 3u, 24u, "["); - _checkloc(seq[2][2][0] , 3u, 27u, "goes"); - _checkloc(seq[2][2][1] , 3u, 37u, "master"); - _checkloc(seq[3] , 4u, 2u, "five"); - _checkloc(seq[4] , 5u, 2u, "{"); - _checkloc(seq[4]["wait"] , 5u, 3u, "wait"); - _checkloc(seq[4]["this"] , 5u, 15u, "this"); - _checkloc(seq[4]["this"]["really"] , 5u, 27u, "really"); - _checkloc(seq[4]["nope"] , 5u, 47u, "nope"); - _checkloc(seq[4]["nope"][0] , 5u, 56u, "a seq!"); - _checkloc(seq[4]["nope"][1] , 5u, 64u, "{"); - _checkloc(seq[4]["nope"][1]["had"] , 5u, 66u, "had"); - _checkloc(seq[4]["nope"][1]["eehh"], 5u, 83u, "eehh"); - _checkloc(seq[5] , 6u, 2u, "yep"); - _checkloc(seq[6] , 7u, 2u, "it"); - _checkloc(seq[7] , 8u, 2u, "was"); -} - -TEST(locations, grow_array) -{ - ParserOptions opts = ParserOptions().locations(true); - Parser parser(opts); - Tree t = parser.parse_in_arena("myfile.yml", "docval"); - _checkloc(t.rootref(), 0u, 0u, "docval"); - t = parser.parse_in_arena("myfile.yml", "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\ndocval"); - _checkloc(t.rootref(), 47u, 0u, "docval"); -} - -// do a test with a buffer size up to 30 lines to ensure hitting -// the binary search path -TEST(locations, small_array) -{ - Tree t; - ParserOptions opts = ParserOptions().locations(true); - Parser parser(opts); - csubstr yaml = R"(--- -foo: yes -bar: - - 1 - - 2 -baz: - - 1_ - - 2_ - - 3_ -)"; - parser.parse_in_arena("myfile.yml", yaml, &t); - ConstNodeRef stream = t.rootref(); - ConstNodeRef map = t.docref(0); - ASSERT_TRUE(map.is_map()); - ASSERT_TRUE(map.is_doc()); - _checkloc(stream , 0u, 0u, "---"); - _checkloc(map , 1u, 0u, "foo"); - _checkloc(map["foo"] , 1u, 0u, "foo"); - _checkloc(map["bar"] , 2u, 0u, "bar"); - _checkloc(map["bar"][0], 3u, 4u, "1"); - _checkloc(map["bar"][1], 4u, 4u, "2"); - _checkloc(map["baz"] , 5u, 0u, "baz"); - _checkloc(map["baz"][0], 6u, 6u, "1_"); - _checkloc(map["baz"][1], 7u, 6u, "2_"); - _checkloc(map["baz"][2], 8u, 10u, "3_"); -} - -// do a test with a buffer of at least 30 lines to ensure hitting -// the binary search path -TEST(locations, large_array) -{ - Tree t; - ParserOptions opts = ParserOptions().locations(true); - Parser parser(opts); - csubstr yaml = R"(--- -foo1: definitely # 1 -bar1: - - 1 - - 2 -baz1: - - 1_ - - 2_ - - 3_ - - - -foo2: definitely # 12 -bar2: - - 1 - - 2 -baz2: - - 1_ - - 2_ - - 3_ - - - -foo3: definitely # 23 -bar3: - - 1 - - 2 -baz3: - - 1_ - - 2_ - - 3_ - - - -foo4: definitely # 34 -bar4: - - 1 - - 2 -baz4: - - 1_ - - 2_ - - 3_ - - - -foo5: definitely # 45 -bar5: - - 1 - - 2 -baz5: - - 1_ - - 2_ - - 3_ - - - -foo6: definitely # 56 -bar6: - - 1 - - 2 -baz6: - - 1_ - - 2_ - - 3_ -)"; - parser.parse_in_arena("myfile.yml", yaml, &t); - ConstNodeRef map = t.docref(0); - ASSERT_TRUE(map.is_map()); - ASSERT_TRUE(map.is_doc()); - _checkloc(t.rootref() , 0u, 0u, "---"); - _checkloc(map , 1u, 0u, "foo1"); - _checkloc(map["foo1"] , 0u+1u, 0u, "foo1"); - _checkloc(map["bar1"] , 0u+2u, 0u, "bar1"); - _checkloc(map["bar1"][0], 0u+3u, 4u, "1"); - _checkloc(map["bar1"][1], 0u+4u, 4u, "2"); - _checkloc(map["baz1"] , 0u+5u, 0u, "baz"); - _checkloc(map["baz1"][0], 0u+6u, 6u, "1_"); - _checkloc(map["baz1"][1], 0u+7u, 6u, "2_"); - _checkloc(map["baz1"][2], 0u+8u, 10u, "3_"); - // - _checkloc(map["foo2"] , 11u+1u, 0u, "foo2"); - _checkloc(map["bar2"] , 11u+2u, 0u, "bar2"); - _checkloc(map["bar2"][0], 11u+3u, 4u, "1"); - _checkloc(map["bar2"][1], 11u+4u, 4u, "2"); - _checkloc(map["baz2"] , 11u+5u, 0u, "baz2"); - _checkloc(map["baz2"][0], 11u+6u, 6u, "1_"); - _checkloc(map["baz2"][1], 11u+7u, 6u, "2_"); - _checkloc(map["baz2"][2], 11u+8u, 10u, "3_"); - // - _checkloc(map["foo3"] , 22u+1u, 0u, "foo3"); - _checkloc(map["bar3"] , 22u+2u, 0u, "bar3"); - _checkloc(map["bar3"][0], 22u+3u, 4u, "1"); - _checkloc(map["bar3"][1], 22u+4u, 4u, "2"); - _checkloc(map["baz3"] , 22u+5u, 0u, "baz3"); - _checkloc(map["baz3"][0], 22u+6u, 6u, "1_"); - _checkloc(map["baz3"][1], 22u+7u, 6u, "2_"); - _checkloc(map["baz3"][2], 22u+8u, 10u, "3_"); - // - _checkloc(map["foo4"] , 33u+1u, 0u, "foo4"); - _checkloc(map["bar4"] , 33u+2u, 0u, "bar4"); - _checkloc(map["bar4"][0], 33u+3u, 4u, "1"); - _checkloc(map["bar4"][1], 33u+4u, 4u, "2"); - _checkloc(map["baz4"] , 33u+5u, 0u, "baz4"); - _checkloc(map["baz4"][0], 33u+6u, 6u, "1_"); - _checkloc(map["baz4"][1], 33u+7u, 6u, "2_"); - _checkloc(map["baz4"][2], 33u+8u, 10u, "3_"); - // - _checkloc(map["foo5"] , 44u+1u, 0u, "foo5"); - _checkloc(map["bar5"] , 44u+2u, 0u, "bar5"); - _checkloc(map["bar5"][0], 44u+3u, 4u, "1"); - _checkloc(map["bar5"][1], 44u+4u, 4u, "2"); - _checkloc(map["baz5"] , 44u+5u, 0u, "baz5"); - _checkloc(map["baz5"][0], 44u+6u, 6u, "1_"); - _checkloc(map["baz5"][1], 44u+7u, 6u, "2_"); - _checkloc(map["baz5"][2], 44u+8u, 10u, "3_"); - // - _checkloc(map["foo6"] , 55u+1u, 0u, "foo6"); - _checkloc(map["bar6"] , 55u+2u, 0u, "bar6"); - _checkloc(map["bar6"][0], 55u+3u, 4u, "1"); - _checkloc(map["bar6"][1], 55u+4u, 4u, "2"); - _checkloc(map["baz6"] , 55u+5u, 0u, "baz6"); - _checkloc(map["baz6"][0], 55u+6u, 6u, "1_"); - _checkloc(map["baz6"][1], 55u+7u, 6u, "2_"); - _checkloc(map["baz6"][2], 55u+8u, 10u, "3_"); -} - - -TEST(locations, issue260_0) -{ - ParserOptions opts = ParserOptions().locations(true); - Parser parser(opts); - Tree tree = parser.parse_in_arena("source.yml", R"(Body: - - Id: 1 - Name: Apple - Script: | - Line One - Line Two - - Id: 2 - Name: Cat - Script: | - Line One - Line Two - - Id: 3 - Name: Dog - Script: | - Line One - Line Two)"); - EXPECT_EQ(tree["Body"][2]["Name"].val(), "Dog"); - EXPECT_EQ(parser.location(tree["Body"][2]["Name"]).line, 12u); -} - -TEST(locations, issue260_1) -{ - ParserOptions opts = ParserOptions().locations(true); - Parser parser(opts); - Tree tree = parser.parse_in_arena("source.yml", R"(Body: # 0 - - Id: 1 # line 1 - Name: Apple - - Id: 2 # line 3 - Name: Cat - Script: | - Line One - Line Two - - Id: 3 # line 8 - Name: Cat2 - Script: > - Line One - Line Two - - Id: 4 # line 13 - Name: Cat3 - Script: " - Line One - Line Two" - - Id: 5 # line 18 - Name: Cat4 - Script: ' - Line One - Line Two' - - Id: 5 # line 23 - Name: Cat5 - Script: - Line One - Line Two - - Id: 6 # line 28 - Name: Dog - Script: | - Line One - Line Two)"); - EXPECT_EQ(parser.location(tree["Body"][0]).line, 1u); - EXPECT_EQ(parser.location(tree["Body"][1]).line, 3u); - EXPECT_EQ(parser.location(tree["Body"][2]).line, 8u); - EXPECT_EQ(parser.location(tree["Body"][3]).line, 13u); - EXPECT_EQ(parser.location(tree["Body"][4]).line, 18u); - EXPECT_EQ(parser.location(tree["Body"][5]).line, 23u); - EXPECT_EQ(parser.location(tree["Body"][6]).line, 28u); - EXPECT_EQ(parser.location(tree["Body"][0]["Id"]).line, 1u); - EXPECT_EQ(parser.location(tree["Body"][1]["Id"]).line, 3u); - EXPECT_EQ(parser.location(tree["Body"][2]["Id"]).line, 8u); - EXPECT_EQ(parser.location(tree["Body"][3]["Id"]).line, 13u); - EXPECT_EQ(parser.location(tree["Body"][4]["Id"]).line, 18u); - EXPECT_EQ(parser.location(tree["Body"][5]["Id"]).line, 23u); - EXPECT_EQ(parser.location(tree["Body"][6]["Id"]).line, 28u); - EXPECT_EQ(parser.location(tree["Body"][0]["Name"]).line, 1u+1u); - EXPECT_EQ(parser.location(tree["Body"][1]["Name"]).line, 3u+1u); - EXPECT_EQ(parser.location(tree["Body"][2]["Name"]).line, 8u+1u); - EXPECT_EQ(parser.location(tree["Body"][3]["Name"]).line, 13u+1u); - EXPECT_EQ(parser.location(tree["Body"][4]["Name"]).line, 18u+1u); - EXPECT_EQ(parser.location(tree["Body"][5]["Name"]).line, 23u+1u); - EXPECT_EQ(parser.location(tree["Body"][6]["Name"]).line, 28u+1u); -} - - - -// The other test executables are written to contain the declarative-style -// YmlTestCases. This executable does not have any but the build setup -// assumes it does, and links with the test lib, which requires an existing -// get_case() function. So this is here to act as placeholder until (if?) -// proper test cases are added here. This was detected in #47 (thanks -// @cburgard). -Case const* get_case(csubstr) -{ - return nullptr; -} - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_map_of_seq.cpp b/thirdparty/ryml/test/test_map_of_seq.cpp deleted file mode 100644 index fc577223e..000000000 --- a/thirdparty/ryml/test/test_map_of_seq.cpp +++ /dev/null @@ -1,201 +0,0 @@ -#include "./test_group.hpp" - -namespace c4 { -namespace yml { - - -CASE_GROUP(MAP_OF_SEQ) -{ - -ADD_CASE_TO_GROUP("map of empty seqs", -R"({foo: [], bar: [], baz: []})", - L{ - N(KEYSEQ, "foo", L()), - N(KEYSEQ, "bar", L()), - N(KEYSEQ, "baz", L()), - } -); - -ADD_CASE_TO_GROUP("map of seqs, one line", -R"({men: [John Smith, Bill Jones], women: [Mary Smith, Susan Williams]})", - L{ - N("men", L{N{"John Smith"}, N{"Bill Jones"}}), - N("women", L{N{"Mary Smith"}, N{"Susan Williams"}}) - } -); - -ADD_CASE_TO_GROUP("map of seqs", -R"( -men: - - John Smith - - Bill Jones -women: - - Mary Smith - - Susan Williams -)", - L{ - N("men", L{N{"John Smith"}, N{"Bill Jones"}}), - N("women", L{N{"Mary Smith"}, N{"Susan Williams"}}) - } -); - -ADD_CASE_TO_GROUP("map of seqs, not indented", -R"( -men: -- John Smith -- Bill Jones -women: -- Mary Smith -- Susan Williams -)", - L{ - N("men", L{N{"John Smith"}, N{"Bill Jones"}}), - N("women", L{N{"Mary Smith"}, N{"Susan Williams"}}) - } -); - -ADD_CASE_TO_GROUP("map of seqs, not indented, more", -R"( -product: -- sku: BL4438H - quantity: 1 - description: Super Hoop - price: 2392.00 # jumping one level here would be wrong. -tax: 1234.5 # we must jump two levels -product2: - subproduct1: - - sku: BL4438H - quantity: 1 - description: Super Hoop - price: 2392.00 # jumping one level here would be wrong. - subproduct2: - - sku: BL4438H - quantity: 1 - description: Super Hoop - price: 2392.00 # jumping one level here would be wrong. - tax2: 789.10 # we must jump two levels -tax3: 1234.5 -product3: - subproduct1: - - sku: BL4438H - quantity: 1 - description: Super Hoop - price: 2392.00 # jumping one level here would be wrong. - subproduct2: - - sku: BL4438H - quantity: 1 - description: Super Hoop - price: 2392.00 # jumping one level here would be wrong. - # a comment here, will it ruin parsing? - tax2: 789.10 # we must jump two levels -tax4: 1234.5 -product4: - subproduct1: - - sku: BL4438H - quantity: 1 - description: Super Hoop - price: 2392.00 # jumping one level here would be wrong. - subproduct2: - - sku: BL4438H - quantity: 1 - description: Super Hoop - price: 2392.00 # jumping one level here would be wrong. - # what about here? - tax2: 789.10 # we must jump two levels -tax5: 1234.5 -)", -L{ - N("product", L{ - N(L{N("sku", "BL4438H"), N("quantity", "1"), N("description", "Super Hoop"), N("price", "2392.00")}), - }), - N("tax", "1234.5"), - N("product2", L{ - N("subproduct1", L{ - N(L{N("sku", "BL4438H"), N("quantity", "1"), N("description", "Super Hoop"), N("price", "2392.00")}), - }), - N("subproduct2", L{ - N(L{N("sku", "BL4438H"), N("quantity", "1"), N("description", "Super Hoop"), N("price", "2392.00")}), - }), - N("tax2", "789.10"), - }), - N("tax3", "1234.5"), - N("product3", L{ - N("subproduct1", L{ - N(L{N("sku", "BL4438H"), N("quantity", "1"), N("description", "Super Hoop"), N("price", "2392.00")}), - }), - N("subproduct2", L{ - N(L{N("sku", "BL4438H"), N("quantity", "1"), N("description", "Super Hoop"), N("price", "2392.00")}), - }), - N("tax2", "789.10"), - }), - N("tax4", "1234.5"), - N("product4", L{ - N("subproduct1", L{ - N(L{N("sku", "BL4438H"), N("quantity", "1"), N("description", "Super Hoop"), N("price", "2392.00")}), - }), - N("subproduct2", L{ - N(L{N("sku", "BL4438H"), N("quantity", "1"), N("description", "Super Hoop"), N("price", "2392.00")}), - }), - N("tax2", "789.10"), - }), - N("tax5", "1234.5"), -}); - -ADD_CASE_TO_GROUP("map of seqs, next line", -R"( -men: - - - John Smith - - - Bill Jones -women: - - - Mary Smith - - - Susan Williams -)", - L{ - N("men", L{N{"John Smith"}, N{"Bill Jones"}}), - N("women", L{N{"Mary Smith"}, N{"Susan Williams"}}) - } -); - -ADD_CASE_TO_GROUP("map of seqs, next line without space", -R"( -men: - - - John Smith - - - Bill Jones -women: - - - Mary Smith - - - Susan Williams -)", - L{ - N("men", L{N{"John Smith"}, N{"Bill Jones"}}), - N("women", L{N{"Mary Smith"}, N{"Susan Williams"}}) - } -); - -ADD_CASE_TO_GROUP("map of seqs, deal with unk", -R"( -skip_commits: - files: - - a - - b - - c - - d - - e -)", -L{ - N("skip_commits", L{N("files", - L{N("a"), N("b"), N("c"), N("d"), N("e")} - )}), -} -); -} - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_merge.cpp b/thirdparty/ryml/test/test_merge.cpp deleted file mode 100644 index 873412115..000000000 --- a/thirdparty/ryml/test/test_merge.cpp +++ /dev/null @@ -1,225 +0,0 @@ -#ifndef RYML_SINGLE_HEADER -#include -#include -#endif -#include - -#include "./test_case.hpp" - -namespace c4 { -namespace yml { - -// The other test executables are written to contain the declarative-style -// YmlTestCases. This executable does not have any but the build setup -// assumes it does, and links with the test lib, which requires an existing -// get_case() function. So this is here to act as placeholder until (if?) -// proper test cases are added here. This was detected in #47 (thanks -// @cburgard). -Case const* get_case(csubstr) -{ - return nullptr; -} - - -void test_merge(std::initializer_list li, csubstr expected) -{ - Tree loaded, merged, ref; - - parse_in_arena(expected, &ref); - - // make sure the arena in the loaded tree is never resized - size_t arena_dim = 2; - for(csubstr src : li) - { - arena_dim += src.len; - } - loaded.reserve_arena(arena_dim); - - for(csubstr src : li) - { - loaded.clear(); // do not clear the arena of the loaded tree - parse_in_arena(src, &loaded); - merged.merge_with(&loaded); - } - - auto buf_result = emitrs_yaml(merged); - auto buf_expected = emitrs_yaml(ref); - - EXPECT_EQ(buf_result, buf_expected); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -TEST(merge, basic) -{ - test_merge( - { - "{a: 0, b: 1}", - "{a: 1, c: 20}" - }, - "{a: 1, b: 1, c: 20}" - ); -} - -TEST(merge, val_to_seq) -{ - test_merge( - { - "{a: 0, b: 1}", - "{a: [1, 2]}" - }, - "{a: [1, 2], b: 1}" - ); -} - -TEST(merge, seq_to_val) -{ - test_merge( - { - "{a: [1, 2]}", - "{a: 0, b: 1}", - }, - "{a: 0, b: 1}" - ); -} - -TEST(merge, val_to_map) -{ - test_merge( - { - "{a: 0, b: 1}", - "{a: {c: 10, d: 20}}" - }, - "{a: {c: 10, d: 20}, b: 1}" - ); -} - -TEST(merge, map_to_val) -{ - test_merge( - { - "{a: {c: 10, d: 20}}", - "{a: 0, b: 1}", - }, - "{a: 0, b: 1}" - ); -} - -TEST(merge, seq_no_overlap_explicit) -{ - test_merge( - {"[0, 1, 2]", "[3, 4, 5]", "[6, 7, 8]"}, - "[0, 1, 2, 3, 4, 5, 6, 7, 8]" - ); -} - - -TEST(merge, seq_no_overlap_implicit) -{ - test_merge( - {"0, 1, 2", "3, 4, 5", "6, 7, 8"}, - "0, 1, 2, 3, 4, 5, 6, 7, 8" - ); -} - - -TEST(merge, seq_overlap_explicit) -{ - test_merge( - {"[0, 1, 2]", "[1, 2, 3]", "[2, 3, 4]"}, - "[0, 1, 2, 1, 2, 3, 2, 3, 4]" - // or this? "[0, 1, 2, 3, 4]" - ); -} - - -TEST(merge, seq_overlap_implicit) -{ - // now a bit more difficult - test_merge( - {"0, 1, 2", "1, 2, 3", "2, 3, 4"}, - "0, 1, 2, 1, 2, 3, 2, 3, 4" - // or this? "0, 1, 2, 3, 4" - ); -} - - -TEST(merge, map_orthogonal) -{ - test_merge( - {"a: 0", "b: 1", "c: 2"}, - "{a: 0, b: 1, c: 2}" - ); -} - - -TEST(merge, map_overriding) -{ - test_merge( - { - "a: 0", - "{a: 1, b: 1}", - "c: 2" - }, - "{a: 1, b: 1, c: 2}" - ); -} - -TEST(merge, map_overriding_multiple) -{ - test_merge( - { - "a: 0", - "{a: 1, b: 1}", - "c: 2", - "a: 2", - "a: 3", - "c: 4", - "c: 5", - "a: 4", - }, - "{a: 4, b: 1, c: 5}" - ); -} - - -TEST(merge, seq_nested_in_map) -{ - test_merge( - { - "{a: 0, seq: [a, b, c], d: 2}", - "{a: 1, seq: [d, e, f], d: 3, c: 3}" - }, - "{a: 1, seq: [a, b, c, d, e, f], d: 3, c: 3}" - ); -} - - -TEST(merge, seq_nested_in_map_override_with_map) -{ - test_merge( - { - "{a: 0, ovr: [a, b, c], d: 2}", - "{a: 1, ovr: {d: 0, b: 1, c: 2}, d: 3, c: 3}" - }, - "{a: 1, ovr: {d: 0, b: 1, c: 2}, d: 3, c: 3}" - ); -} - - -TEST(merge, seq_nested_in_map_override_with_keyval) -{ - test_merge( - { - "{a: 0, ovr: [a, b, c], d: 2}", - "{a: 1, ovr: foo, d: 3, c: 3}" - }, - "{a: 1, ovr: foo, d: 3, c: 3}" - ); -} - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_nested_mapx2.cpp b/thirdparty/ryml/test/test_nested_mapx2.cpp deleted file mode 100644 index b1856fa08..000000000 --- a/thirdparty/ryml/test/test_nested_mapx2.cpp +++ /dev/null @@ -1,73 +0,0 @@ -#include "./test_group.hpp" - -namespace c4 { -namespace yml { - -CASE_GROUP(NESTED_MAPX2) -{ - -ADD_CASE_TO_GROUP("nested map x2, explicit, same line", -R"({foo: {foo0: 00, bar0: 01, baz0: 02}, bar: {foo1: 10, bar1: 11, baz1: 12}, baz: {foo2: 20, bar2: 21, baz2: 22}})", - L{ - N{"foo", L{N{"foo0", "00"}, N{"bar0", "01"}, N{"baz0", "02"}}}, - N{"bar", L{N{"foo1", "10"}, N{"bar1", "11"}, N{"baz1", "12"}}}, - N{"baz", L{N{"foo2", "20"}, N{"bar2", "21"}, N{"baz2", "22"}}}, - } -); - -ADD_CASE_TO_GROUP("nested map x2, explicit", -R"({ -foo: {foo0: 00, bar0: 01, baz0: 02}, -bar: {foo1: 10, bar1: 11, baz1: 12}, -baz: {foo2: 20, bar2: 21, baz2: 22} -})", - L{ - N{"foo", L{N{"foo0", "00"}, N{"bar0", "01"}, N{"baz0", "02"}}}, - N{"bar", L{N{"foo1", "10"}, N{"bar1", "11"}, N{"baz1", "12"}}}, - N{"baz", L{N{"foo2", "20"}, N{"bar2", "21"}, N{"baz2", "22"}}}, - } -); - -ADD_CASE_TO_GROUP("nested map x2", -R"( -foo: - foo0: 00 - bar0: 01 - baz0: 02 -bar: - foo1: 10 - bar1: 11 - baz1: 12 -baz: - foo2: 20 - bar2: 21 - baz2: 22 -)", - L{ - N{"foo", L{N{"foo0", "00"}, N{"bar0", "01"}, N{"baz0", "02"}}}, - N{"bar", L{N{"foo1", "10"}, N{"bar1", "11"}, N{"baz1", "12"}}}, - N{"baz", L{N{"foo2", "20"}, N{"bar2", "21"}, N{"baz2", "22"}}}, - } -); - - -ADD_CASE_TO_GROUP("nested map x2, commented", - R"( -send_to: - #host: 192.168.1.100 - #port: 7000 - host: 192.168.1.101 - port: 7001 - #host: 192.168.1.102 - #port: 7002 -)", - L{ - N("send_to", L{ - N("host", "192.168.1.101"), - N("port", "7001") }) - } -); -} - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_nested_mapx3.cpp b/thirdparty/ryml/test/test_nested_mapx3.cpp deleted file mode 100644 index 2ae163475..000000000 --- a/thirdparty/ryml/test/test_nested_mapx3.cpp +++ /dev/null @@ -1,103 +0,0 @@ -#include "./test_group.hpp" - -namespace c4 { -namespace yml { - -CASE_GROUP(NESTED_MAPX3) -{ - -ADD_CASE_TO_GROUP("nested map x3, explicit", -R"({ - foo0: { - foo1: {foo2: 000, bar2: 001, baz2: 002}, - bar1: {foo2: 010, bar2: 011, baz2: 012}, - baz1: {foo2: 020, bar2: 021, baz2: 022} - }, - bar0: { - foo1: {foo2: 100, bar2: 101, baz2: 102}, - bar1: {foo2: 110, bar2: 111, baz2: 112}, - baz1: {foo2: 120, bar2: 121, baz2: 122} - }, - baz0: { - foo1: {foo2: 200, bar2: 201, baz2: 202}, - bar1: {foo2: 210, bar2: 211, baz2: 212}, - baz1: {foo2: 220, bar2: 221, baz2: 222} - } -})", - L{ - N{"foo0", L{ - N{"foo1", L{N{"foo2", "000"}, N{"bar2", "001"}, N{"baz2", "002"}}}, - N{"bar1", L{N{"foo2", "010"}, N{"bar2", "011"}, N{"baz2", "012"}}}, - N{"baz1", L{N{"foo2", "020"}, N{"bar2", "021"}, N{"baz2", "022"}}} }}, - N{"bar0", L{ - N{"foo1", L{N{"foo2", "100"}, N{"bar2", "101"}, N{"baz2", "102"}}}, - N{"bar1", L{N{"foo2", "110"}, N{"bar2", "111"}, N{"baz2", "112"}}}, - N{"baz1", L{N{"foo2", "120"}, N{"bar2", "121"}, N{"baz2", "122"}}} }}, - N{"baz0", L{ - N{"foo1", L{N{"foo2", "200"}, N{"bar2", "201"}, N{"baz2", "202"}}}, - N{"bar1", L{N{"foo2", "210"}, N{"bar2", "211"}, N{"baz2", "212"}}}, - N{"baz1", L{N{"foo2", "220"}, N{"bar2", "221"}, N{"baz2", "222"}}} }}, - } -); - -ADD_CASE_TO_GROUP("nested map x3", -R"( -foo0: - foo1: - foo2: 000 - bar2: 001 - baz2: 002 - bar1: - foo2: 010 - bar2: 011 - baz2: 012 - baz1: - foo2: 020 - bar2: 021 - baz2: 022 -bar0: - foo1: - foo2: 100 - bar2: 101 - baz2: 102 - bar1: - foo2: 110 - bar2: 111 - baz2: 112 - baz1: - foo2: 120 - bar2: 121 - baz2: 122 -baz0: - foo1: - foo2: 200 - bar2: 201 - baz2: 202 - bar1: - foo2: 210 - bar2: 211 - baz2: 212 - baz1: - foo2: 220 - bar2: 221 - baz2: 222 -)", - L{ - N{"foo0", L{ - N{"foo1", L{N{"foo2", "000"}, N{"bar2", "001"}, N{"baz2", "002"}}}, - N{"bar1", L{N{"foo2", "010"}, N{"bar2", "011"}, N{"baz2", "012"}}}, - N{"baz1", L{N{"foo2", "020"}, N{"bar2", "021"}, N{"baz2", "022"}}} }}, - N{"bar0", L{ - N{"foo1", L{N{"foo2", "100"}, N{"bar2", "101"}, N{"baz2", "102"}}}, - N{"bar1", L{N{"foo2", "110"}, N{"bar2", "111"}, N{"baz2", "112"}}}, - N{"baz1", L{N{"foo2", "120"}, N{"bar2", "121"}, N{"baz2", "122"}}} }}, - N{"baz0", L{ - N{"foo1", L{N{"foo2", "200"}, N{"bar2", "201"}, N{"baz2", "202"}}}, - N{"bar1", L{N{"foo2", "210"}, N{"bar2", "211"}, N{"baz2", "212"}}}, - N{"baz1", L{N{"foo2", "220"}, N{"bar2", "221"}, N{"baz2", "222"}}} }}, - } -); -} - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_nested_mapx4.cpp b/thirdparty/ryml/test/test_nested_mapx4.cpp deleted file mode 100644 index 1d40f2cb1..000000000 --- a/thirdparty/ryml/test/test_nested_mapx4.cpp +++ /dev/null @@ -1,190 +0,0 @@ -#include "./test_group.hpp" - -namespace c4 { -namespace yml { - -CASE_GROUP(NESTED_MAPX4) -{ - -ADD_CASE_TO_GROUP("nested map x4, explicit", -R"({ - foo0: { - foo1: { foo2: {foo3: 0000, bar3: 0001, baz3: 0002}, bar2: {foo3: 0010, bar3: 0011, baz3: 0012}, baz2: {foo3: 0020, bar3: 0021, baz3: 0022} }, - bar1: { foo2: {foo3: 0100, bar3: 0101, baz3: 0102}, bar2: {foo3: 0110, bar3: 0111, baz3: 0112}, baz2: {foo3: 0120, bar3: 0121, baz3: 0122} }, - baz1: { foo2: {foo3: 0200, bar3: 0201, baz3: 0202}, bar2: {foo3: 0210, bar3: 0211, baz3: 0212}, baz2: {foo3: 0220, bar3: 0221, baz3: 0222} }, - }, - bar0: { - foo1: { foo2: {foo3: 1000, bar3: 1001, baz3: 1002}, bar2: {foo3: 1010, bar3: 1011, baz3: 1012}, baz2: {foo3: 1020, bar3: 1021, baz3: 1022} }, - bar1: { foo2: {foo3: 1100, bar3: 1101, baz3: 1102}, bar2: {foo3: 1110, bar3: 1111, baz3: 1112}, baz2: {foo3: 1120, bar3: 1121, baz3: 1122} }, - baz1: { foo2: {foo3: 1200, bar3: 1201, baz3: 1202}, bar2: {foo3: 1210, bar3: 1211, baz3: 1212}, baz2: {foo3: 1220, bar3: 1221, baz3: 1222} }, - }, - baz0: { - foo1: { foo2: {foo3: 2000, bar3: 2001, baz3: 2002}, bar2: {foo3: 2010, bar3: 2011, baz3: 2012}, baz2: {foo3: 2020, bar3: 2021, baz3: 2022} }, - bar1: { foo2: {foo3: 2100, bar3: 2101, baz3: 2102}, bar2: {foo3: 2110, bar3: 2111, baz3: 2112}, baz2: {foo3: 2120, bar3: 2121, baz3: 2122} }, - baz1: { foo2: {foo3: 2200, bar3: 2201, baz3: 2202}, bar2: {foo3: 2210, bar3: 2211, baz3: 2212}, baz2: {foo3: 2220, bar3: 2221, baz3: 2222} }, - }, -})", - L{ - N("foo0", L{ - N("foo1", L{N("foo2", L{N("foo3", "0000"), N("bar3", "0001"), N("baz3", "0002")}), N("bar2", L{N("foo3", "0010"), N("bar3", "0011"), N("baz3", "0012")}), N("baz2", L{N("foo3", "0020"), N("bar3", "0021"), N("baz3", "0022")})}), - N("bar1", L{N("foo2", L{N("foo3", "0100"), N("bar3", "0101"), N("baz3", "0102")}), N("bar2", L{N("foo3", "0110"), N("bar3", "0111"), N("baz3", "0112")}), N("baz2", L{N("foo3", "0120"), N("bar3", "0121"), N("baz3", "0122")})}), - N("baz1", L{N("foo2", L{N("foo3", "0200"), N("bar3", "0201"), N("baz3", "0202")}), N("bar2", L{N("foo3", "0210"), N("bar3", "0211"), N("baz3", "0212")}), N("baz2", L{N("foo3", "0220"), N("bar3", "0221"), N("baz3", "0222")})}), - }), - N("bar0", L{ - N("foo1", L{N("foo2", L{N("foo3", "1000"), N("bar3", "1001"), N("baz3", "1002")}), N("bar2", L{N("foo3", "1010"), N("bar3", "1011"), N("baz3", "1012")}), N("baz2", L{N("foo3", "1020"), N("bar3", "1021"), N("baz3", "1022")})}), - N("bar1", L{N("foo2", L{N("foo3", "1100"), N("bar3", "1101"), N("baz3", "1102")}), N("bar2", L{N("foo3", "1110"), N("bar3", "1111"), N("baz3", "1112")}), N("baz2", L{N("foo3", "1120"), N("bar3", "1121"), N("baz3", "1122")})}), - N("baz1", L{N("foo2", L{N("foo3", "1200"), N("bar3", "1201"), N("baz3", "1202")}), N("bar2", L{N("foo3", "1210"), N("bar3", "1211"), N("baz3", "1212")}), N("baz2", L{N("foo3", "1220"), N("bar3", "1221"), N("baz3", "1222")})}), - }), - N("baz0", L{ - N("foo1", L{N("foo2", L{N("foo3", "2000"), N("bar3", "2001"), N("baz3", "2002")}), N("bar2", L{N("foo3", "2010"), N("bar3", "2011"), N("baz3", "2012")}), N("baz2", L{N("foo3", "2020"), N("bar3", "2021"), N("baz3", "2022")})}), - N("bar1", L{N("foo2", L{N("foo3", "2100"), N("bar3", "2101"), N("baz3", "2102")}), N("bar2", L{N("foo3", "2110"), N("bar3", "2111"), N("baz3", "2112")}), N("baz2", L{N("foo3", "2120"), N("bar3", "2121"), N("baz3", "2122")})}), - N("baz1", L{N("foo2", L{N("foo3", "2200"), N("bar3", "2201"), N("baz3", "2202")}), N("bar2", L{N("foo3", "2210"), N("bar3", "2211"), N("baz3", "2212")}), N("baz2", L{N("foo3", "2220"), N("bar3", "2221"), N("baz3", "2222")})}), - }) - } -); - -ADD_CASE_TO_GROUP("nested map x4", -R"( -foo0: - foo1: - foo2: - foo3: 0000 - bar3: 0001 - baz3: 0002 - bar2: - foo3: 0010 - bar3: 0011 - baz3: 0012 - baz2: - foo3: 0020 - bar3: 0021 - baz3: 0022 - bar1: - foo2: - foo3: 0100 - bar3: 0101 - baz3: 0102 - bar2: - foo3: 0110 - bar3: 0111 - baz3: 0112 - baz2: - foo3: 0120 - bar3: 0121 - baz3: 0122 - baz1: - foo2: - foo3: 0200 - bar3: 0201 - baz3: 0202 - bar2: - foo3: 0210 - bar3: 0211 - baz3: 0212 - baz2: - foo3: 0220 - bar3: 0221 - baz3: 0222 -bar0: - foo1: - foo2: - foo3: 1000 - bar3: 1001 - baz3: 1002 - bar2: - foo3: 1010 - bar3: 1011 - baz3: 1012 - baz2: - foo3: 1020 - bar3: 1021 - baz3: 1022 - bar1: - foo2: - foo3: 1100 - bar3: 1101 - baz3: 1102 - bar2: - foo3: 1110 - bar3: 1111 - baz3: 1112 - baz2: - foo3: 1120 - bar3: 1121 - baz3: 1122 - baz1: - foo2: - foo3: 1200 - bar3: 1201 - baz3: 1202 - bar2: - foo3: 1210 - bar3: 1211 - baz3: 1212 - baz2: - foo3: 1220 - bar3: 1221 - baz3: 1222 -baz0: - foo1: - foo2: - foo3: 2000 - bar3: 2001 - baz3: 2002 - bar2: - foo3: 2010 - bar3: 2011 - baz3: 2012 - baz2: - foo3: 2020 - bar3: 2021 - baz3: 2022 - bar1: - foo2: - foo3: 2100 - bar3: 2101 - baz3: 2102 - bar2: - foo3: 2110 - bar3: 2111 - baz3: 2112 - baz2: - foo3: 2120 - bar3: 2121 - baz3: 2122 - baz1: - foo2: - foo3: 2200 - bar3: 2201 - baz3: 2202 - bar2: - foo3: 2210 - bar3: 2211 - baz3: 2212 - baz2: - foo3: 2220 - bar3: 2221 - baz3: 2222 -)", - L{ - N("foo0", L{ - N("foo1", L{N("foo2", L{N("foo3", "0000"), N("bar3", "0001"), N("baz3", "0002")}), N("bar2", L{N("foo3", "0010"), N("bar3", "0011"), N("baz3", "0012")}), N("baz2", L{N("foo3", "0020"), N("bar3", "0021"), N("baz3", "0022")})}), - N("bar1", L{N("foo2", L{N("foo3", "0100"), N("bar3", "0101"), N("baz3", "0102")}), N("bar2", L{N("foo3", "0110"), N("bar3", "0111"), N("baz3", "0112")}), N("baz2", L{N("foo3", "0120"), N("bar3", "0121"), N("baz3", "0122")})}), - N("baz1", L{N("foo2", L{N("foo3", "0200"), N("bar3", "0201"), N("baz3", "0202")}), N("bar2", L{N("foo3", "0210"), N("bar3", "0211"), N("baz3", "0212")}), N("baz2", L{N("foo3", "0220"), N("bar3", "0221"), N("baz3", "0222")})}), - }), - N("bar0", L{ - N("foo1", L{N("foo2", L{N("foo3", "1000"), N("bar3", "1001"), N("baz3", "1002")}), N("bar2", L{N("foo3", "1010"), N("bar3", "1011"), N("baz3", "1012")}), N("baz2", L{N("foo3", "1020"), N("bar3", "1021"), N("baz3", "1022")})}), - N("bar1", L{N("foo2", L{N("foo3", "1100"), N("bar3", "1101"), N("baz3", "1102")}), N("bar2", L{N("foo3", "1110"), N("bar3", "1111"), N("baz3", "1112")}), N("baz2", L{N("foo3", "1120"), N("bar3", "1121"), N("baz3", "1122")})}), - N("baz1", L{N("foo2", L{N("foo3", "1200"), N("bar3", "1201"), N("baz3", "1202")}), N("bar2", L{N("foo3", "1210"), N("bar3", "1211"), N("baz3", "1212")}), N("baz2", L{N("foo3", "1220"), N("bar3", "1221"), N("baz3", "1222")})}), - }), - N("baz0", L{ - N("foo1", L{N("foo2", L{N("foo3", "2000"), N("bar3", "2001"), N("baz3", "2002")}), N("bar2", L{N("foo3", "2010"), N("bar3", "2011"), N("baz3", "2012")}), N("baz2", L{N("foo3", "2020"), N("bar3", "2021"), N("baz3", "2022")})}), - N("bar1", L{N("foo2", L{N("foo3", "2100"), N("bar3", "2101"), N("baz3", "2102")}), N("bar2", L{N("foo3", "2110"), N("bar3", "2111"), N("baz3", "2112")}), N("baz2", L{N("foo3", "2120"), N("bar3", "2121"), N("baz3", "2122")})}), - N("baz1", L{N("foo2", L{N("foo3", "2200"), N("bar3", "2201"), N("baz3", "2202")}), N("bar2", L{N("foo3", "2210"), N("bar3", "2211"), N("baz3", "2212")}), N("baz2", L{N("foo3", "2220"), N("bar3", "2221"), N("baz3", "2222")})}), - }) - } -); -} - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_nested_seqx2.cpp b/thirdparty/ryml/test/test_nested_seqx2.cpp deleted file mode 100644 index 1361ae0ab..000000000 --- a/thirdparty/ryml/test/test_nested_seqx2.cpp +++ /dev/null @@ -1,133 +0,0 @@ -#include "./test_group.hpp" - -namespace c4 { -namespace yml { - -CASE_GROUP(NESTED_SEQX2) -{ - -ADD_CASE_TO_GROUP("nested seq x2, empty, oneline", -R"([[], [], []])", - L{SEQ, SEQ, SEQ} -); - -ADD_CASE_TO_GROUP("nested seq x2, explicit, same line", -R"([[00, 01, 02], [10, 11, 12], [20, 21, 22]])", - L{ - N{L{N{"00"}, N{"01"}, N{"02"}}}, - N{L{N{"10"}, N{"11"}, N{"12"}}}, - N{L{N{"20"}, N{"21"}, N{"22"}}}, - } -); - -ADD_CASE_TO_GROUP("nested seq x2, explicit first+last level, same line, no spaces", -R"([[00,01,02],[10,11,12],[20,21,22]])", - L{ - N{L{N{"00"}, N{"01"}, N{"02"}}}, - N{L{N{"10"}, N{"11"}, N{"12"}}}, - N{L{N{"20"}, N{"21"}, N{"22"}}}, - } -); - -ADD_CASE_TO_GROUP("nested seq x2, explicit", -R"([ -[00, 01, 02], -[10, 11, 12], -[20, 21, 22], -])", - L{ - N{L{N{"00"}, N{"01"}, N{"02"}}}, - N{L{N{"10"}, N{"11"}, N{"12"}}}, - N{L{N{"20"}, N{"21"}, N{"22"}}}, - } -); - -ADD_CASE_TO_GROUP("nested seq x2", -R"( -- - 00 - - 01 - - 02 -- - 10 - - 11 - - 12 -- - 20 - - 21 - - 22 -)", - L{ - N{L{N{"00"}, N{"01"}, N{"02"}}}, - N{L{N{"10"}, N{"11"}, N{"12"}}}, - N{L{N{"20"}, N{"21"}, N{"22"}}}, - } -); - -ADD_CASE_TO_GROUP("nested seq x2, next line", -R"( -- - - 00 - - 01 - - 02 -- - - 10 - - 11 - - 12 -- - - 20 - - 21 - - 22 -)", - L{ - N{L{N{"00"}, N{"01"}, N{"02"}}}, - N{L{N{"10"}, N{"11"}, N{"12"}}}, - N{L{N{"20"}, N{"21"}, N{"22"}}}, - } -); - -ADD_CASE_TO_GROUP("nested seq x2, all next line", -R"( -- - - - 00 - - - 01 - - - 02 -- - - - 10 - - - 11 - - - 12 -- - - - 20 - - - 21 - - - 22 -)", - L{ - N{L{N{"00"}, N{"01"}, N{"02"}}}, - N{L{N{"10"}, N{"11"}, N{"12"}}}, - N{L{N{"20"}, N{"21"}, N{"22"}}}, - } -); - -ADD_CASE_TO_GROUP("nested seq x2, implicit first, explicit last level", -R"( -- [00, 01, 02] -- [10, 11, 12] -- [20, 21, 22] -)", - L{ - N{L{N{"00"}, N{"01"}, N{"02"}}}, - N{L{N{"10"}, N{"11"}, N{"12"}}}, - N{L{N{"20"}, N{"21"}, N{"22"}}}, - } -); -} - - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_nested_seqx3.cpp b/thirdparty/ryml/test/test_nested_seqx3.cpp deleted file mode 100644 index d1cc0beec..000000000 --- a/thirdparty/ryml/test/test_nested_seqx3.cpp +++ /dev/null @@ -1,187 +0,0 @@ -#include "./test_group.hpp" - -namespace c4 { -namespace yml { - - -CASE_GROUP(NESTED_SEQX3) -{ - -ADD_CASE_TO_GROUP("nested seq x3, explicit", -R"([ -[[000, 001, 002], [010, 011, 012], [020, 021, 022]], -[[100, 101, 102], [110, 111, 112], [120, 121, 122]], -[[200, 201, 202], [210, 211, 212], [220, 221, 222]], -])", - L{ - N{L{N{L{N{"000"}, N{"001"}, N{"002"}}}, N{L{N{"010"}, N{"011"}, N{"012"}}}, N{L{N{"020"}, N{"021"}, N{"022"}}}}}, - N{L{N{L{N{"100"}, N{"101"}, N{"102"}}}, N{L{N{"110"}, N{"111"}, N{"112"}}}, N{L{N{"120"}, N{"121"}, N{"122"}}}}}, - N{L{N{L{N{"200"}, N{"201"}, N{"202"}}}, N{L{N{"210"}, N{"211"}, N{"212"}}}, N{L{N{"220"}, N{"221"}, N{"222"}}}}}, - } -); - -ADD_CASE_TO_GROUP("nested seq x3", -R"( -- - - 000 - - 001 - - 002 - - - 010 - - 011 - - 012 - - - 020 - - 021 - - 022 -- - - 100 - - 101 - - 102 - - - 110 - - 111 - - 112 - - - 120 - - 121 - - 122 -- - - 200 - - 201 - - 202 - - - 210 - - 211 - - 212 - - - 220 - - 221 - - 222 -)", - L{ - N{L{N{L{N{"000"}, N{"001"}, N{"002"}}}, N{L{N{"010"}, N{"011"}, N{"012"}}}, N{L{N{"020"}, N{"021"}, N{"022"}}}}}, - N{L{N{L{N{"100"}, N{"101"}, N{"102"}}}, N{L{N{"110"}, N{"111"}, N{"112"}}}, N{L{N{"120"}, N{"121"}, N{"122"}}}}}, - N{L{N{L{N{"200"}, N{"201"}, N{"202"}}}, N{L{N{"210"}, N{"211"}, N{"212"}}}, N{L{N{"220"}, N{"221"}, N{"222"}}}}}, - } -); - -ADD_CASE_TO_GROUP("nested seq x3, continued on next line", -R"( -- - - - - 000 - - 001 - - 002 - - - - 010 - - 011 - - 012 - - - - 020 - - 021 - - 022 -- - - - - 100 - - 101 - - 102 - - - - 110 - - 111 - - 112 - - - - 120 - - 121 - - 122 -- - - - - 200 - - 201 - - 202 - - - - 210 - - 211 - - 212 - - - - 220 - - 221 - - 222 -)", - L{ - N{L{N{L{N{"000"}, N{"001"}, N{"002"}}}, N{L{N{"010"}, N{"011"}, N{"012"}}}, N{L{N{"020"}, N{"021"}, N{"022"}}}}}, - N{L{N{L{N{"100"}, N{"101"}, N{"102"}}}, N{L{N{"110"}, N{"111"}, N{"112"}}}, N{L{N{"120"}, N{"121"}, N{"122"}}}}}, - N{L{N{L{N{"200"}, N{"201"}, N{"202"}}}, N{L{N{"210"}, N{"211"}, N{"212"}}}, N{L{N{"220"}, N{"221"}, N{"222"}}}}}, - } -); - -ADD_CASE_TO_GROUP("nested seq x3, all continued on next line", -R"( -- - - - - - 000 - - - 001 - - - 002 - - - - - 010 - - - 011 - - - 012 - - - - - 020 - - - 021 - - - 022 -- - - - - - 100 - - - 101 - - - 102 - - - - - 110 - - - 111 - - - 112 - - - - - 120 - - - 121 - - - 122 -- - - - - - 200 - - - 201 - - - 202 - - - - - 210 - - - 211 - - - 212 - - - - - 220 - - - 221 - - - 222 -)", - L{ - N{L{N{L{N{"000"}, N{"001"}, N{"002"}}}, N{L{N{"010"}, N{"011"}, N{"012"}}}, N{L{N{"020"}, N{"021"}, N{"022"}}}}}, - N{L{N{L{N{"100"}, N{"101"}, N{"102"}}}, N{L{N{"110"}, N{"111"}, N{"112"}}}, N{L{N{"120"}, N{"121"}, N{"122"}}}}}, - N{L{N{L{N{"200"}, N{"201"}, N{"202"}}}, N{L{N{"210"}, N{"211"}, N{"212"}}}, N{L{N{"220"}, N{"221"}, N{"222"}}}}}, - } -); -} - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_nested_seqx4.cpp b/thirdparty/ryml/test/test_nested_seqx4.cpp deleted file mode 100644 index b63c4bac8..000000000 --- a/thirdparty/ryml/test/test_nested_seqx4.cpp +++ /dev/null @@ -1,124 +0,0 @@ -#include "./test_group.hpp" - -namespace c4 { -namespace yml { - - -CASE_GROUP(NESTED_SEQX4) -{ - -ADD_CASE_TO_GROUP("nested seq x4, explicit", -R"([ -[[[0000, 0001, 0002], [0010, 0011, 0012], [0020, 0021, 0022]], - [[0100, 0101, 0102], [0110, 0111, 0112], [0120, 0121, 0122]], - [[0200, 0201, 0202], [0210, 0211, 0212], [0220, 0221, 0222]]], - -[[[1000, 1001, 1002], [1010, 1011, 1012], [1020, 1021, 1022]], - [[1100, 1101, 1102], [1110, 1111, 1112], [1120, 1121, 1122]], - [[1200, 1201, 1202], [1210, 1211, 1212], [1220, 1221, 1222]]], - -[[[2000, 2001, 2002], [2010, 2011, 2012], [2020, 2021, 2022]], - [[2100, 2101, 2102], [2110, 2111, 2112], [2120, 2121, 2122]], - [[2200, 2201, 2202], [2210, 2211, 2212], [2220, 2221, 2222]]], -])", - L{ - N{L{N{L{N{L{N{"0000"}, N{"0001"}, N{"0002"}}}, N{L{N{"0010"}, N{"0011"}, N{"0012"}}}, N{L{N{"0020"}, N{"0021"}, N{"0022"}}}}}, N{L{N{L{N{"0100"}, N{"0101"}, N{"0102"}}}, N{L{N{"0110"}, N{"0111"}, N{"0112"}}}, N{L{N{"0120"}, N{"0121"}, N{"0122"}}}}}, N{L{N{L{N{"0200"}, N{"0201"}, N{"0202"}}}, N{L{N{"0210"}, N{"0211"}, N{"0212"}}}, N{L{N{"0220"}, N{"0221"}, N{"0222"}}}}}}}, - N{L{N{L{N{L{N{"1000"}, N{"1001"}, N{"1002"}}}, N{L{N{"1010"}, N{"1011"}, N{"1012"}}}, N{L{N{"1020"}, N{"1021"}, N{"1022"}}}}}, N{L{N{L{N{"1100"}, N{"1101"}, N{"1102"}}}, N{L{N{"1110"}, N{"1111"}, N{"1112"}}}, N{L{N{"1120"}, N{"1121"}, N{"1122"}}}}}, N{L{N{L{N{"1200"}, N{"1201"}, N{"1202"}}}, N{L{N{"1210"}, N{"1211"}, N{"1212"}}}, N{L{N{"1220"}, N{"1221"}, N{"1222"}}}}}}}, - N{L{N{L{N{L{N{"2000"}, N{"2001"}, N{"2002"}}}, N{L{N{"2010"}, N{"2011"}, N{"2012"}}}, N{L{N{"2020"}, N{"2021"}, N{"2022"}}}}}, N{L{N{L{N{"2100"}, N{"2101"}, N{"2102"}}}, N{L{N{"2110"}, N{"2111"}, N{"2112"}}}, N{L{N{"2120"}, N{"2121"}, N{"2122"}}}}}, N{L{N{L{N{"2200"}, N{"2201"}, N{"2202"}}}, N{L{N{"2210"}, N{"2211"}, N{"2212"}}}, N{L{N{"2220"}, N{"2221"}, N{"2222"}}}}}}}, - } -); - -ADD_CASE_TO_GROUP("nested seq x4", -R"( -- - - - 0000 - - 0001 - - 0002 - - - 0010 - - 0011 - - 0012 - - - 0020 - - 0021 - - 0022 - - - - 0100 - - 0101 - - 0102 - - - 0110 - - 0111 - - 0112 - - - 0120 - - 0121 - - 0122 - - - - 0200 - - 0201 - - 0202 - - - 0210 - - 0211 - - 0212 - - - 0220 - - 0221 - - 0222 -- - - - 1000 - - 1001 - - 1002 - - - 1010 - - 1011 - - 1012 - - - 1020 - - 1021 - - 1022 - - - - 1100 - - 1101 - - 1102 - - - 1110 - - 1111 - - 1112 - - - 1120 - - 1121 - - 1122 - - - - 1200 - - 1201 - - 1202 - - - 1210 - - 1211 - - 1212 - - - 1220 - - 1221 - - 1222 -- - - - 2000 - - 2001 - - 2002 - - - 2010 - - 2011 - - 2012 - - - 2020 - - 2021 - - 2022 - - - - 2100 - - 2101 - - 2102 - - - 2110 - - 2111 - - 2112 - - - 2120 - - 2121 - - 2122 - - - - 2200 - - 2201 - - 2202 - - - 2210 - - 2211 - - 2212 - - - 2220 - - 2221 - - 2222 -)", - L{ - N{L{N{L{N{L{N{"0000"}, N{"0001"}, N{"0002"}}}, N{L{N{"0010"}, N{"0011"}, N{"0012"}}}, N{L{N{"0020"}, N{"0021"}, N{"0022"}}}}}, N{L{N{L{N{"0100"}, N{"0101"}, N{"0102"}}}, N{L{N{"0110"}, N{"0111"}, N{"0112"}}}, N{L{N{"0120"}, N{"0121"}, N{"0122"}}}}}, N{L{N{L{N{"0200"}, N{"0201"}, N{"0202"}}}, N{L{N{"0210"}, N{"0211"}, N{"0212"}}}, N{L{N{"0220"}, N{"0221"}, N{"0222"}}}}}}}, - N{L{N{L{N{L{N{"1000"}, N{"1001"}, N{"1002"}}}, N{L{N{"1010"}, N{"1011"}, N{"1012"}}}, N{L{N{"1020"}, N{"1021"}, N{"1022"}}}}}, N{L{N{L{N{"1100"}, N{"1101"}, N{"1102"}}}, N{L{N{"1110"}, N{"1111"}, N{"1112"}}}, N{L{N{"1120"}, N{"1121"}, N{"1122"}}}}}, N{L{N{L{N{"1200"}, N{"1201"}, N{"1202"}}}, N{L{N{"1210"}, N{"1211"}, N{"1212"}}}, N{L{N{"1220"}, N{"1221"}, N{"1222"}}}}}}}, - N{L{N{L{N{L{N{"2000"}, N{"2001"}, N{"2002"}}}, N{L{N{"2010"}, N{"2011"}, N{"2012"}}}, N{L{N{"2020"}, N{"2021"}, N{"2022"}}}}}, N{L{N{L{N{"2100"}, N{"2101"}, N{"2102"}}}, N{L{N{"2110"}, N{"2111"}, N{"2112"}}}, N{L{N{"2120"}, N{"2121"}, N{"2122"}}}}}, N{L{N{L{N{"2200"}, N{"2201"}, N{"2202"}}}, N{L{N{"2210"}, N{"2211"}, N{"2212"}}}, N{L{N{"2220"}, N{"2221"}, N{"2222"}}}}}}}, - } -); -} - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_noderef.cpp b/thirdparty/ryml/test/test_noderef.cpp deleted file mode 100644 index cfd3363c3..000000000 --- a/thirdparty/ryml/test/test_noderef.cpp +++ /dev/null @@ -1,813 +0,0 @@ -#ifndef RYML_SINGLE_HEADER -#include "c4/yml/std/std.hpp" -#include "c4/yml/parse.hpp" -#include "c4/yml/emit.hpp" -#include -#include -#include -#endif -#include "./test_case.hpp" -#include "./callbacks_tester.hpp" - -#include - -#if defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable: 4389) // signed/unsigned mismatch -#elif defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdollar-in-identifier-extension" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -#endif - -namespace c4 { -namespace yml { - -TEST(NodeRef, general) -{ - Tree t; - - NodeRef root(&t); - - //using S = csubstr; - //using V = NodeScalar; - using N = NodeInit; - - root = N{MAP}; - root.append_child({"a", "0"}); - root.append_child({MAP, "b"}); - root["b"].append_child({SEQ, "seq"}); - root["b"]["seq"].append_child({"0"}); - root["b"]["seq"].append_child({"1"}); - root["b"]["seq"].append_child({"2"}); - root["b"]["seq"].append_child({NodeScalar{"!!str", "3"}}); - auto ch4 = root["b"]["seq"][3].append_sibling({"4"}); - EXPECT_EQ(ch4.id(), root["b"]["seq"][4].id()); - EXPECT_EQ(ch4.get(), root["b"]["seq"][4].get()); - EXPECT_EQ((type_bits)root["b"]["seq"][4].type(), (type_bits)VAL); - EXPECT_EQ(root["b"]["seq"][4].val(), "4"); - root["b"]["seq"].append_sibling({NodeScalar{"!!str", "aaa"}, NodeScalar{"!!int", "0"}}); - EXPECT_EQ((type_bits)root["b"]["seq"][4].type(), (type_bits)VAL); - EXPECT_EQ(root["b"]["seq"][4].val(), "4"); - - root["b"]["key"] = "val"; - auto seq = root["b"]["seq"]; - auto seq2 = root["b"]["seq2"]; - EXPECT_TRUE(seq2.is_seed()); - root["b"]["seq2"] = N(SEQ); - seq2 = root["b"]["seq2"]; - EXPECT_FALSE(seq2.is_seed()); - EXPECT_TRUE(seq2.is_seq()); - EXPECT_EQ(seq2.num_children(), 0); - EXPECT_EQ(root["b"]["seq2"].get(), seq2.get()); - auto seq20 = seq2[0]; - EXPECT_TRUE(seq20.is_seed()); - EXPECT_TRUE(seq2[0].is_seed()); - EXPECT_EQ(seq2.num_children(), 0); - EXPECT_TRUE(seq2[0].is_seed()); - EXPECT_TRUE(seq20.is_seed()); - EXPECT_NE(seq.get(), seq2.get()); - seq20 = root["b"]["seq2"][0]; - EXPECT_TRUE(seq20.is_seed()); - root["b"]["seq2"][0] = "00"; - seq20 = root["b"]["seq2"][0]; - EXPECT_FALSE(seq20.is_seed()); - NodeRef before = root["b"]["key"]; - EXPECT_EQ(before.key(), "key"); - EXPECT_EQ(before.val(), "val"); - root["b"]["seq2"][1] = "01"; - NodeRef after = root["b"]["key"]; - EXPECT_EQ(before.key(), "key"); - EXPECT_EQ(before.val(), "val"); - EXPECT_EQ(after.key(), "key"); - EXPECT_EQ(after.val(), "val"); - root["b"]["seq2"][2] = "02"; - root["b"]["seq2"][3] = "03"; - int iv = 0; - root["b"]["seq2"][4] << 55; root["b"]["seq2"][4] >> iv; - EXPECT_EQ(iv, 55); - size_t zv = 0; - root["b"]["seq2"][5] << size_t(55); root["b"]["seq2"][5] >> zv; - EXPECT_EQ(zv, size_t(55)); - float fv = 0; - root["b"]["seq2"][6] << 2.0f; root["b"]["seq2"][6] >> fv; - EXPECT_EQ(fv, 2.f); - float dv = 0; - root["b"]["seq2"][7] << 2.0; root["b"]["seq2"][7] >> dv; - EXPECT_EQ(dv, 2.0); - - EXPECT_EQ(root["b"]["key"].key(), "key"); - EXPECT_EQ(root["b"]["key"].val(), "val"); - - - emit_yaml(t); - - EXPECT_TRUE(root.type().is_map()); - EXPECT_TRUE(root["a"].type().is_keyval()); - EXPECT_EQ(root["a"].key(), "a"); - EXPECT_EQ(root["a"].val(), "0"); - - EXPECT_TRUE(root["b"].type().has_key()); - EXPECT_TRUE(root["b"].type().is_map()); - - EXPECT_TRUE(root["b"]["seq"].type().has_key()); - EXPECT_TRUE(root["b"]["seq"].type().is_seq()); - EXPECT_EQ (root["b"]["seq"].key(), "seq"); - EXPECT_TRUE(root["b"]["seq"][0].type().is_val()); - EXPECT_EQ( root["b"]["seq"][0].val(), "0"); - EXPECT_TRUE(root["b"]["seq"][1].type().is_val()); - EXPECT_EQ( root["b"]["seq"][1].val(), "1"); - EXPECT_TRUE(root["b"]["seq"][2].type().is_val()); - EXPECT_EQ( root["b"]["seq"][2].val(), "2"); - EXPECT_TRUE(root["b"]["seq"][3].type().is_val()); - EXPECT_EQ( root["b"]["seq"][3].val(), "3"); - EXPECT_EQ( root["b"]["seq"][3].val_tag(), "!!str"); - EXPECT_TRUE(root["b"]["seq"][4].type().is_val()); - EXPECT_EQ( root["b"]["seq"][4].val(), "4"); - - int tv; - EXPECT_EQ(root["b"]["key"].key(), "key"); - EXPECT_EQ(root["b"]["key"].val(), "val"); - EXPECT_EQ(root["b"]["seq2"][0].val(), "00"); root["b"]["seq2"][0] >> tv; EXPECT_EQ(tv, 0); - EXPECT_EQ(root["b"]["seq2"][1].val(), "01"); root["b"]["seq2"][1] >> tv; EXPECT_EQ(tv, 1); - EXPECT_EQ(root["b"]["seq2"][2].val(), "02"); root["b"]["seq2"][2] >> tv; EXPECT_EQ(tv, 2); - EXPECT_EQ(root["b"]["seq2"][3].val(), "03"); root["b"]["seq2"][3] >> tv; EXPECT_EQ(tv, 3); - EXPECT_EQ(root["b"]["seq2"][4].val(), "55"); EXPECT_EQ(iv, 55); - EXPECT_EQ(root["b"]["seq2"][5].val(), "55"); EXPECT_EQ(zv, size_t(55)); - EXPECT_EQ(root["b"]["seq2"][6].val(), "2"); EXPECT_EQ(fv, 2.f); - EXPECT_EQ(root["b"]["seq2"][6].val(), "2"); EXPECT_EQ(dv, 2.); - - root["b"]["seq"][2].set_val_serialized(22); - - emit_yaml(t); - - EXPECT_TRUE(root["b"]["aaa"].type().is_keyval()); - EXPECT_EQ(root["b"]["aaa"].key_tag(), "!!str"); - EXPECT_EQ(root["b"]["aaa"].key(), "aaa"); - EXPECT_EQ(root["b"]["aaa"].val_tag(), "!!int"); - EXPECT_EQ(root["b"]["aaa"].val(), "0"); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -void noderef_check_tree(ConstNodeRef const& root) -{ - test_invariants(*root.tree()); - - EXPECT_EQ(root.tree()->size(), 7u); - EXPECT_EQ(root.num_children(), 6u); - EXPECT_EQ(root.is_container(), true); - EXPECT_EQ(root.is_seq(), true); - - EXPECT_TRUE(root[0].type().is_val()); - EXPECT_EQ( root[0].val(), "0"); - EXPECT_TRUE(root[1].type().is_val()); - EXPECT_EQ( root[1].val(), "1"); - EXPECT_TRUE(root[2].type().is_val()); - EXPECT_EQ( root[2].val(), "2"); - EXPECT_TRUE(root[3].type().is_val()); - EXPECT_EQ( root[3].val(), "3"); - EXPECT_TRUE(root[4].type().is_val()); - EXPECT_EQ( root[4].val(), "4"); - EXPECT_TRUE(root[5].type().is_val()); - EXPECT_EQ( root[5].val(), "5"); -} - -TEST(NodeRef, append_child) -{ - Tree t; - - NodeRef root(&t); - - root |= SEQ; - root.append_child({"0"}); - root.append_child({"1"}); - root.append_child({"2"}); - root.append_child({"3"}); - root.append_child({"4"}); - root.append_child({"5"}); - - noderef_check_tree(root); -} - -TEST(NodeRef, prepend_child) -{ - Tree t; - - NodeRef root(&t); - - root |= SEQ; - root.prepend_child({"5"}); - root.prepend_child({"4"}); - root.prepend_child({"3"}); - root.prepend_child({"2"}); - root.prepend_child({"1"}); - root.prepend_child({"0"}); - - noderef_check_tree(root); -} - -TEST(NodeRef, insert_child) -{ - Tree t; - - NodeRef root(&t); - NodeRef none(&t, NONE); - - root |= SEQ; - root.insert_child({"3"}, none); - root.insert_child({"4"}, root[0]); - root.insert_child({"0"}, none); - root.insert_child({"5"}, root[2]); - root.insert_child({"1"}, root[0]); - root.insert_child({"2"}, root[1]); - - noderef_check_tree(root); -} - -TEST(NodeRef, remove_child) -{ - Tree t; - - NodeRef root(&t); - NodeRef none(&t, NONE); - - root |= SEQ; - root.insert_child({"3"}, none); - root.insert_child({"4"}, root[0]); - root.insert_child({"0"}, none); - root.insert_child({"5"}, root[2]); - root.insert_child({"1"}, root[0]); - root.insert_child({"2"}, root[1]); - - std::vector vec({10, 20, 30, 40, 50, 60, 70, 80, 90}); - root.insert_child(root[0]) << vec; // 1 - root.insert_child(root[2]) << vec; // 3 - root.insert_child(root[4]) << vec; // 5 - root.insert_child(root[6]) << vec; // 7 - root.insert_child(root[8]) << vec; // 9 - root.append_child() << vec; // 10 - - root.remove_child(11); - root.remove_child(9); - root.remove_child(7); - root.remove_child(5); - root.remove_child(3); - root.remove_child(1); - - noderef_check_tree(root); - - std::vector> vec2({{100, 200}, {300, 400}, {500, 600}, {700, 800, 900}}); - root.prepend_child() << vec2; // 0 - root.insert_child(root[1]) << vec2; // 2 - root.insert_child(root[3]) << vec2; // 4 - root.insert_child(root[5]) << vec2; // 6 - root.insert_child(root[7]) << vec2; // 8 - root.insert_child(root[9]) << vec2; // 10 - root.append_child() << vec2; // 12 - - root.remove_child(12); - root.remove_child(10); - root.remove_child(8); - root.remove_child(6); - root.remove_child(4); - root.remove_child(2); - root.remove_child(0); - - noderef_check_tree(root); -} - -TEST(NodeRef, move_in_same_parent) -{ - Tree t; - NodeRef r = t; - - std::vector> vec2({{100, 200}, {300, 400}, {500, 600}, {700, 800, 900}}); - std::map map2({{"foo", 100}, {"bar", 200}, {"baz", 300}}); - - r |= SEQ; - r.append_child() << vec2; - r.append_child() << map2; - r.append_child() << "elm2"; - r.append_child() << "elm3"; - - auto s = r[0]; - auto m = r[1]; - EXPECT_TRUE(s.is_seq()); - EXPECT_TRUE(m.is_map()); - EXPECT_EQ(s.num_children(), vec2.size()); - EXPECT_EQ(m.num_children(), map2.size()); - //printf("fonix"); print_tree(t); emit_yaml(r); - r[0].move(r[1]); - //printf("fonix"); print_tree(t); emit_yaml(r); - EXPECT_EQ(r[0].get(), m.get()); - EXPECT_EQ(r[0].num_children(), map2.size()); - EXPECT_EQ(r[1].get(), s.get()); - EXPECT_EQ(r[1].num_children(), vec2.size()); - test_invariants(t); -} - -TEST(NodeRef, move_in_same_parent_to_first_position) -{ - Tree t = parse_in_arena("[1, 2, 3, 0, 4]"); - NodeRef r = t; - - EXPECT_TRUE(r[0].val() == "1"); - EXPECT_TRUE(r[1].val() == "2"); - EXPECT_TRUE(r[2].val() == "3"); - EXPECT_TRUE(r[3].val() == "0"); - EXPECT_TRUE(r[4].val() == "4"); - r[3].move({}); - EXPECT_TRUE(r[0].val() == "0"); - EXPECT_TRUE(r[1].val() == "1"); - EXPECT_TRUE(r[2].val() == "2"); - EXPECT_TRUE(r[3].val() == "3"); - EXPECT_TRUE(r[4].val() == "4"); - test_invariants(t); - r[0].move({}); // should have no effect - EXPECT_TRUE(r[0].val() == "0"); - EXPECT_TRUE(r[1].val() == "1"); - EXPECT_TRUE(r[2].val() == "2"); - EXPECT_TRUE(r[3].val() == "3"); - EXPECT_TRUE(r[4].val() == "4"); - test_invariants(t); - r[4].move({}); - EXPECT_TRUE(r[0].val() == "4"); - EXPECT_TRUE(r[1].val() == "0"); - EXPECT_TRUE(r[2].val() == "1"); - EXPECT_TRUE(r[3].val() == "2"); - EXPECT_TRUE(r[4].val() == "3"); - test_invariants(t); -} - -TEST(NodeRef, move_to_other_parent) -{ - Tree t; - NodeRef r = t; - - std::vector> vec2({{100, 200}, {300, 400}, {500, 600}, {700, 800, 900}}); - std::map map2({{"foo", 100}, {"bar", 200}, {"baz", 300}}); - - r |= SEQ; - r.append_child() << vec2; - r.append_child() << map2; - r.append_child() << "elm2"; - r.append_child() << "elm3"; - - NodeData *elm2 = r[2].get(); - EXPECT_EQ(r[2].val(), "elm2"); - //printf("fonix"); print_tree(t); emit_yaml(r); - r[2].move(r[0], r[0][0]); - EXPECT_EQ(r[0][1].get(), elm2); - EXPECT_EQ(r[0][1].val(), "elm2"); - //printf("fonix"); print_tree(t); emit_yaml(r); - test_invariants(t); -} - -TEST(NodeRef, move_to_other_parent_to_first_position) -{ - Tree t = parse_in_arena("[[0, 1, 2, 3, 4], [00, 10, 20, 30, 40]]"); - NodeRef r = t; - - EXPECT_TRUE(r[0][0].val() == "0"); - EXPECT_TRUE(r[0][1].val() == "1"); - EXPECT_TRUE(r[0][2].val() == "2"); - EXPECT_TRUE(r[0][3].val() == "3"); - EXPECT_TRUE(r[0][4].val() == "4"); - EXPECT_TRUE(r[1][0].val() == "00"); - EXPECT_TRUE(r[1][1].val() == "10"); - EXPECT_TRUE(r[1][2].val() == "20"); - EXPECT_TRUE(r[1][3].val() == "30"); - EXPECT_TRUE(r[1][4].val() == "40"); - test_invariants(t); - r[0][0].move(r[1], {}); - EXPECT_TRUE(r[0][0].val() == "1"); - EXPECT_TRUE(r[0][1].val() == "2"); - EXPECT_TRUE(r[0][2].val() == "3"); - EXPECT_TRUE(r[0][3].val() == "4"); - EXPECT_TRUE(r[1][0].val() == "0"); - EXPECT_TRUE(r[1][1].val() == "00"); - EXPECT_TRUE(r[1][2].val() == "10"); - EXPECT_TRUE(r[1][3].val() == "20"); - EXPECT_TRUE(r[1][4].val() == "30"); - EXPECT_TRUE(r[1][5].val() == "40"); - test_invariants(t); - r[1][0].move(r[0], {}); - EXPECT_TRUE(r[0][0].val() == "0"); - EXPECT_TRUE(r[0][1].val() == "1"); - EXPECT_TRUE(r[0][2].val() == "2"); - EXPECT_TRUE(r[0][3].val() == "3"); - EXPECT_TRUE(r[0][4].val() == "4"); - EXPECT_TRUE(r[1][0].val() == "00"); - EXPECT_TRUE(r[1][1].val() == "10"); - EXPECT_TRUE(r[1][2].val() == "20"); - EXPECT_TRUE(r[1][3].val() == "30"); - EXPECT_TRUE(r[1][4].val() == "40"); - test_invariants(t); -} - -TEST(NodeRef, move_to_other_tree) -{ - Tree t0 = parse_in_arena("[0, 1, 2, 3, 4]"); - Tree t1 = parse_in_arena("[00, 10, 20, 30, 40]"); - NodeRef r0 = t0; - NodeRef r1 = t1; - - EXPECT_TRUE(r0[0].val() == "0"); - EXPECT_TRUE(r0[1].val() == "1"); - EXPECT_TRUE(r0[2].val() == "2"); - EXPECT_TRUE(r0[3].val() == "3"); - EXPECT_TRUE(r0[4].val() == "4"); - EXPECT_TRUE(r1[0].val() == "00"); - EXPECT_TRUE(r1[1].val() == "10"); - EXPECT_TRUE(r1[2].val() == "20"); - EXPECT_TRUE(r1[3].val() == "30"); - EXPECT_TRUE(r1[4].val() == "40"); - r0[0].move(r1, r1[0]); - test_invariants(t0); - test_invariants(t1); - EXPECT_TRUE(r0[0].val() == "1"); - EXPECT_TRUE(r0[1].val() == "2"); - EXPECT_TRUE(r0[2].val() == "3"); - EXPECT_TRUE(r0[3].val() == "4"); - EXPECT_TRUE(r1[0].val() == "00"); - EXPECT_TRUE(r1[1].val() == "0"); - EXPECT_TRUE(r1[2].val() == "10"); - EXPECT_TRUE(r1[3].val() == "20"); - EXPECT_TRUE(r1[4].val() == "30"); - EXPECT_TRUE(r1[5].val() == "40"); - test_invariants(t0); - test_invariants(t1); - r1[1].move(r0, r0[0]); - EXPECT_TRUE(r0[0].val() == "1"); - EXPECT_TRUE(r0[1].val() == "0"); - EXPECT_TRUE(r0[2].val() == "2"); - EXPECT_TRUE(r0[3].val() == "3"); - EXPECT_TRUE(r0[4].val() == "4"); - EXPECT_TRUE(r1[0].val() == "00"); - EXPECT_TRUE(r1[1].val() == "10"); - EXPECT_TRUE(r1[2].val() == "20"); - EXPECT_TRUE(r1[3].val() == "30"); - EXPECT_TRUE(r1[4].val() == "40"); - test_invariants(t0); - test_invariants(t1); -} - -TEST(NodeRef, move_to_other_tree_to_first_position) -{ - Tree t0 = parse_in_arena("[0, 1, 2, 3, 4]"); - Tree t1 = parse_in_arena("[00, 10, 20, 30, 40]"); - NodeRef r0 = t0; - NodeRef r1 = t1; - - EXPECT_TRUE(r0[0].val() == "0"); - EXPECT_TRUE(r0[1].val() == "1"); - EXPECT_TRUE(r0[2].val() == "2"); - EXPECT_TRUE(r0[3].val() == "3"); - EXPECT_TRUE(r0[4].val() == "4"); - EXPECT_TRUE(r1[0].val() == "00"); - EXPECT_TRUE(r1[1].val() == "10"); - EXPECT_TRUE(r1[2].val() == "20"); - EXPECT_TRUE(r1[3].val() == "30"); - EXPECT_TRUE(r1[4].val() == "40"); - test_invariants(t0); - test_invariants(t1); - r0[0].move(r1, {}); - EXPECT_TRUE(r0[0].val() == "1"); - EXPECT_TRUE(r0[1].val() == "2"); - EXPECT_TRUE(r0[2].val() == "3"); - EXPECT_TRUE(r0[3].val() == "4"); - EXPECT_TRUE(r1[0].val() == "0"); - EXPECT_TRUE(r1[1].val() == "00"); - EXPECT_TRUE(r1[2].val() == "10"); - EXPECT_TRUE(r1[3].val() == "20"); - EXPECT_TRUE(r1[4].val() == "30"); - EXPECT_TRUE(r1[5].val() == "40"); - test_invariants(t0); - test_invariants(t1); - r1[0].move(r0, {}); - EXPECT_TRUE(r0[0].val() == "0"); - EXPECT_TRUE(r0[1].val() == "1"); - EXPECT_TRUE(r0[2].val() == "2"); - EXPECT_TRUE(r0[3].val() == "3"); - EXPECT_TRUE(r0[4].val() == "4"); - EXPECT_TRUE(r1[0].val() == "00"); - EXPECT_TRUE(r1[1].val() == "10"); - EXPECT_TRUE(r1[2].val() == "20"); - EXPECT_TRUE(r1[3].val() == "30"); - EXPECT_TRUE(r1[4].val() == "40"); - test_invariants(t0); - test_invariants(t1); -} - -TEST(NodeRef, duplicate_to_same_tree) -{ - Tree t = parse_in_arena("[{a0: [b0, c0], a1: [b1, c1], a2: [b2, c2], a3: [b3, c3]}]"); - auto checkseq = [](ConstNodeRef const& s){ - ASSERT_EQ(s.num_children(), 4u); - ASSERT_EQ(s[0].num_children(), 2u); - ASSERT_EQ(s[1].num_children(), 2u); - ASSERT_EQ(s[2].num_children(), 2u); - ASSERT_EQ(s[3].num_children(), 2u); - EXPECT_EQ(s[0].key(), "a0"); - EXPECT_EQ(s[0][0].val(), "b0"); - EXPECT_EQ(s[0][1].val(), "c0"); - EXPECT_EQ(s[1].key(), "a1"); - EXPECT_EQ(s[1][0].val(), "b1"); - EXPECT_EQ(s[1][1].val(), "c1"); - EXPECT_EQ(s[2].key(), "a2"); - EXPECT_EQ(s[2][0].val(), "b2"); - EXPECT_EQ(s[2][1].val(), "c2"); - EXPECT_EQ(s[3].key(), "a3"); - EXPECT_EQ(s[3][0].val(), "b3"); - EXPECT_EQ(s[3][1].val(), "c3"); - }; - { - SCOPED_TRACE("at the beginning"); - t[0].duplicate({}); - test_check_emit_check(t, [&checkseq](ConstNodeRef r){ - checkseq(r[0]); - checkseq(r[1]); - }); - } - { - SCOPED_TRACE("at the end"); - t[0].duplicate(t.rootref().last_child()); - test_check_emit_check(t, [&checkseq](ConstNodeRef r){ - checkseq(r[0]); - checkseq(r[1]); - checkseq(r[2]); - }); - } - { - SCOPED_TRACE("in the middle"); - t[0].duplicate(t.rootref().first_child()); - test_check_emit_check(t, [&checkseq](ConstNodeRef r){ - checkseq(r[0]); - checkseq(r[1]); - checkseq(r[2]); - }); - } -} - -TEST(NodeRef, duplicate_to_different_tree) -{ - Tree t = parse_in_arena("[{a0: [b0, c0], a1: [b1, c1], a2: [b2, c2], a3: [b3, c3]}]"); - auto checkseq = [](ConstNodeRef const& s){ - ASSERT_EQ(s.num_children(), 4u); - ASSERT_EQ(s[0].num_children(), 2u); - ASSERT_EQ(s[1].num_children(), 2u); - ASSERT_EQ(s[2].num_children(), 2u); - ASSERT_EQ(s[3].num_children(), 2u); - EXPECT_EQ(s[0].key(), "a0"); - EXPECT_EQ(s[0][0].val(), "b0"); - EXPECT_EQ(s[0][1].val(), "c0"); - EXPECT_EQ(s[1].key(), "a1"); - EXPECT_EQ(s[1][0].val(), "b1"); - EXPECT_EQ(s[1][1].val(), "c1"); - EXPECT_EQ(s[2].key(), "a2"); - EXPECT_EQ(s[2][0].val(), "b2"); - EXPECT_EQ(s[2][1].val(), "c2"); - EXPECT_EQ(s[3].key(), "a3"); - EXPECT_EQ(s[3][0].val(), "b3"); - EXPECT_EQ(s[3][1].val(), "c3"); - }; - auto check_orig = [&checkseq](ConstNodeRef const& r){ - ASSERT_TRUE(r.is_seq()); - ASSERT_GE(r.num_children(), 1u); - checkseq(r[0]); - }; - Tree d = parse_in_arena("[]"); - { - SCOPED_TRACE("at the beginning"); - t[0].duplicate(d, {}); - test_check_emit_check(t, check_orig); - test_check_emit_check(d, check_orig); - } - { - SCOPED_TRACE("at the end"); - t[0].duplicate(d, d.rootref().last_child()); - test_check_emit_check(t, check_orig); - test_check_emit_check(d, check_orig); - test_check_emit_check(d, [&checkseq](ConstNodeRef r){ - checkseq(r[1]); - }); - } - { - SCOPED_TRACE("in the middle"); - t[0].duplicate(d, d.rootref().first_child()); - test_check_emit_check(t, check_orig); - test_check_emit_check(d, check_orig); - test_check_emit_check(d, [&checkseq](ConstNodeRef r){ - checkseq(r[1]); - checkseq(r[2]); - }); - } -} - -TEST(NodeRef, intseq) -{ - Tree t = parse_in_arena("iseq: [8, 10]"); - NodeRef n = t["iseq"]; - int a, b; - n[0] >> a; - n[1] >> b; - EXPECT_EQ(a, 8); - EXPECT_EQ(b, 10); - test_invariants(t); -} - -TEST(NodeRef, vsConstNodeRef) -{ - Tree t = parse_in_arena("iseq: [8, 10]"); - Tree const& ct = t; - NodeRef mseq = t["iseq"]; - ConstNodeRef seq = t["iseq"]; - EXPECT_EQ(mseq.tree(), seq.tree()); - EXPECT_EQ(mseq.id(), seq.id()); - EXPECT_TRUE(mseq == seq); - EXPECT_FALSE(mseq != seq); - EXPECT_TRUE(seq == mseq); - EXPECT_FALSE(seq != mseq); - // mseq = ct["iseq"]; // deliberate compile error - seq = ct["iseq"]; // ok - // mseq = seq; // deliberate compilation error - seq = mseq; // ok - { - NodeData *nd = mseq.get(); - // nd = seq.get(); // deliberate compile error - C4_UNUSED(nd); - } - { - NodeData const* nd = seq.get(); - nd = seq.get(); // ok - C4_UNUSED(nd); - } - test_invariants(t); -} - - -// see https://github.com/biojppm/rapidyaml/issues/294 -TEST(NodeRef, overload_sets) -{ - // doc() - { - Tree t = parse_in_arena("a\n---\nb"); - NodeRef n = t; - NodeRef const nc = t; - ConstNodeRef const cn = t; - EXPECT_EQ(n.doc(0), nc.doc(0)); - EXPECT_EQ(n.doc(0), cn.doc(0)); - } - Tree t = parse_in_arena("{iseq: [8, 10], imap: {a: b, c: d}}"); - NodeRef n = t; - NodeRef const nc = t; - ConstNodeRef const cn = t; - // get() - { - EXPECT_EQ(n["iseq"].get(), nc["iseq"].get()); - EXPECT_EQ(n["iseq"].get(), cn["iseq"].get()); - } - // parent() - { - EXPECT_EQ(n["iseq"].parent(), nc["iseq"].parent()); - EXPECT_EQ(n["iseq"].parent(), cn["iseq"].parent()); - } - // child_pos() - { - EXPECT_EQ(n["iseq"].child_pos(n["iseq"][0]), nc["iseq"].child_pos(n["iseq"][0])); - EXPECT_EQ(n["iseq"].child_pos(n["iseq"][0]), cn["iseq"].child_pos(n["iseq"][0])); - } - // num_children() - { - EXPECT_EQ(n["iseq"].num_children(), nc["iseq"].num_children()); - EXPECT_EQ(n["iseq"].num_children(), cn["iseq"].num_children()); - } - // first_child() - { - EXPECT_EQ(n["iseq"].first_child(), nc["iseq"].first_child()); - EXPECT_EQ(n["iseq"].first_child(), cn["iseq"].first_child()); - } - // last_child() - { - EXPECT_EQ(n["iseq"].last_child(), nc["iseq"].last_child()); - EXPECT_EQ(n["iseq"].last_child(), cn["iseq"].last_child()); - } - // child() - { - EXPECT_EQ(n["iseq"].child(0), nc["iseq"].child(0)); - EXPECT_EQ(n["iseq"].child(0), cn["iseq"].child(0)); - } - // find_child() - { - EXPECT_EQ(n.find_child("iseq"), nc.find_child("iseq")); - EXPECT_EQ(n.find_child("iseq"), cn.find_child("iseq")); - } - // prev_sibling() - { - EXPECT_EQ(n["iseq"][1].prev_sibling(), nc["iseq"][1].prev_sibling()); - EXPECT_EQ(n["iseq"][1].prev_sibling(), cn["iseq"][1].prev_sibling()); - } - // next_sibling() - { - EXPECT_EQ(n["iseq"][0].next_sibling(), nc["iseq"][0].next_sibling()); - EXPECT_EQ(n["iseq"][0].next_sibling(), cn["iseq"][0].next_sibling()); - } - // first_sibling() - { - EXPECT_EQ(n["iseq"][1].first_sibling(), nc["iseq"][1].first_sibling()); - EXPECT_EQ(n["iseq"][1].first_sibling(), cn["iseq"][1].first_sibling()); - } - // last_sibling() - { - EXPECT_EQ(n["iseq"][0].last_sibling(), nc["iseq"][0].last_sibling()); - EXPECT_EQ(n["iseq"][0].last_sibling(), cn["iseq"][0].last_sibling()); - } - // sibling() - { - EXPECT_EQ(n["iseq"][1].sibling(0), nc["iseq"][1].sibling(0)); - EXPECT_EQ(n["iseq"][1].sibling(0), cn["iseq"][1].sibling(0)); - } - // find_sibling() - { - EXPECT_EQ(n["iseq"].find_sibling("imap"), nc["iseq"].find_sibling("imap")); - EXPECT_EQ(n["iseq"].find_sibling("imap"), cn["iseq"].find_sibling("imap")); - } - // operator[](csubstr) - { - EXPECT_EQ(n["iseq"].id(), nc["iseq"].id()); - EXPECT_EQ(n["iseq"].id(), cn["iseq"].id()); - } - // operator[](size_t) - { - EXPECT_EQ(n["iseq"][0].id(), nc["iseq"][0].id()); - EXPECT_EQ(n["iseq"][0].id(), cn["iseq"][0].id()); - } - // begin() - { - EXPECT_EQ(n["iseq"].begin().m_child_id, nc["iseq"].begin().m_child_id); - EXPECT_EQ(n["iseq"].begin().m_child_id, cn["iseq"].begin().m_child_id); - } - // end() - { - EXPECT_EQ(n["iseq"].end().m_child_id, nc["iseq"].end().m_child_id); - EXPECT_EQ(n["iseq"].end().m_child_id, cn["iseq"].end().m_child_id); - } - // cbegin() - { - EXPECT_EQ(n["iseq"].cbegin().m_child_id, nc["iseq"].cbegin().m_child_id); - EXPECT_EQ(n["iseq"].cbegin().m_child_id, cn["iseq"].cbegin().m_child_id); - } - // cend() - { - EXPECT_EQ(n["iseq"].cend().m_child_id, nc["iseq"].cend().m_child_id); - EXPECT_EQ(n["iseq"].cend().m_child_id, cn["iseq"].cend().m_child_id); - } - // children() - { - EXPECT_EQ(n["iseq"].children().b.m_child_id, nc["iseq"].children().b.m_child_id); - EXPECT_EQ(n["iseq"].children().b.m_child_id, cn["iseq"].children().b.m_child_id); - } - // cchildren() - { - EXPECT_EQ(n["iseq"].cchildren().b.m_child_id, nc["iseq"].cchildren().b.m_child_id); - EXPECT_EQ(n["iseq"].cchildren().b.m_child_id, cn["iseq"].cchildren().b.m_child_id); - } - // siblings() - { - EXPECT_EQ(n["iseq"][0].siblings().b.m_child_id, nc["iseq"][0].siblings().b.m_child_id); - EXPECT_EQ(n["iseq"][0].siblings().b.m_child_id, cn["iseq"][0].siblings().b.m_child_id); - EXPECT_EQ(n.siblings().b.m_child_id, nc.siblings().b.m_child_id); - EXPECT_EQ(n.siblings().b.m_child_id, cn.siblings().b.m_child_id); - } - // csiblings() - { - EXPECT_EQ(n["iseq"][0].csiblings().b.m_child_id, nc["iseq"][0].csiblings().b.m_child_id); - EXPECT_EQ(n["iseq"][0].csiblings().b.m_child_id, cn["iseq"][0].csiblings().b.m_child_id); - EXPECT_EQ(n.csiblings().b.m_child_id, nc.csiblings().b.m_child_id); - EXPECT_EQ(n.csiblings().b.m_child_id, cn.csiblings().b.m_child_id); - } -} - - -//------------------------------------------- -// this is needed to use the test case library -Case const* get_case(csubstr /*name*/) -{ - return nullptr; -} - -} // namespace yml -} // namespace c4 - -#if defined(_MSC_VER) -# pragma warning(pop) -#elif defined(__clang__) -# pragma clang diagnostic pop -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#endif diff --git a/thirdparty/ryml/test/test_null_val.cpp b/thirdparty/ryml/test/test_null_val.cpp deleted file mode 100644 index 4bdd6d419..000000000 --- a/thirdparty/ryml/test/test_null_val.cpp +++ /dev/null @@ -1,519 +0,0 @@ -#include "./test_group.hpp" -#include "c4/error.hpp" - -namespace c4 { -namespace yml { - -C4_SUPPRESS_WARNING_GCC_WITH_PUSH("-Wuseless-cast") - -csubstr getafter(csubstr yaml, csubstr pattern) -{ - size_t pos = yaml.find(pattern); - RYML_ASSERT(pos != npos); - RYML_ASSERT(yaml.sub(pos).begins_with(pattern)); - return yaml.sub(pos + pattern.len); -} - -#define _check_null_pointing_at(expr_, which, pattern, arena) \ - do \ - { \ - csubstr expr = expr_.which(); \ - if(expr.empty()) \ - { \ - EXPECT_EQ(expr, nullptr); \ - EXPECT_EQ(expr.len, 0u); \ - EXPECT_EQ(expr.str, nullptr); \ - } \ - EXPECT_TRUE(expr_.which##_is_null()); \ - } while(0) - - -TEST(null_val, simple) -{ - Tree tree = parse_in_arena("{foo: , bar: '', baz: [,,,], bat: [ , , , ], two: [,,], one: [,], empty: []}"); - _check_null_pointing_at(tree["foo"], val, " ,", tree.arena()); - ASSERT_EQ(tree["baz"].num_children(), 3u); - _check_null_pointing_at(tree["baz"][0], val, "[,,,]", tree.arena()); - _check_null_pointing_at(tree["baz"][1], val, ",,,]", tree.arena()); - _check_null_pointing_at(tree["baz"][2], val, ",,]", tree.arena()); - ASSERT_EQ(tree["bat"].num_children(), 3u); - _check_null_pointing_at(tree["bat"][0], val, " , , , ]", tree.arena()); - _check_null_pointing_at(tree["bat"][1], val, " , , ]", tree.arena()); - _check_null_pointing_at(tree["bat"][2], val, " , ]", tree.arena()); - ASSERT_EQ(tree["two"].num_children(), 2u); - _check_null_pointing_at(tree["two"][0], val, "[,,]", tree.arena()); - _check_null_pointing_at(tree["two"][1], val, ",,]", tree.arena()); - ASSERT_EQ(tree["one"].num_children(), 1u); - _check_null_pointing_at(tree["one"][0], val, "[,]", tree.arena()); - ASSERT_EQ(tree["empty"].num_children(), 0u); -} - -TEST(null_val, block_seq) -{ - csubstr yaml = R"( -# nospace -- -- -- -# onespace -- -- -- -# null -- null -- null -- null -- ~ -)"; - ASSERT_EQ(yaml.count('\r'), 0u); - Tree tree = parse_in_arena(yaml); - ASSERT_EQ(tree.rootref().num_children(), 10u); - // FIXME: empty vals in block seqs are pointing at the next item! - _check_null_pointing_at(tree[0], val, after("nospace\n-\n"), tree.arena()); - _check_null_pointing_at(tree[1], val, after("nospace\n-\n-\n"), tree.arena()); - _check_null_pointing_at(tree[2], val, after("nospace\n-\n-\n-\n# onespace\n"), tree.arena()); - _check_null_pointing_at(tree[3], val, after("onespace\n- \n"), tree.arena()); - _check_null_pointing_at(tree[4], val, after("onespace\n- \n- \n"), tree.arena()); - _check_null_pointing_at(tree[5], val, after("onespace\n- \n- \n- \n# null\n"), tree.arena()); - // but explicitly null vals are ok: - _check_null_pointing_at(tree[6], val, "null\n- null\n- null\n- ~\n", tree.arena()); - _check_null_pointing_at(tree[7], val, "null\n- null\n- ~", tree.arena()); - _check_null_pointing_at(tree[8], val, "null\n- ~\n", tree.arena()); - _check_null_pointing_at(tree[9], val, "~\n", tree.arena()); -} - -TEST(null_val, block_map) -{ - csubstr yaml = R"( -# nospace -val0: -val1: -val2: -# onespace -val3: -val4: -val5: -# null -val6: null -val7: null -val8: null -val9: ~ -)"; - ASSERT_EQ(yaml.count('\r'), 0u); - Tree tree = parse_in_arena(yaml); - ASSERT_EQ(tree.rootref().num_children(), 10u); - // FIXME: empty vals in block seqs are pointing at the next item! - _check_null_pointing_at(tree["val0"], val, after("val0:"), tree.arena()); - _check_null_pointing_at(tree["val1"], val, after("val1:"), tree.arena()); - _check_null_pointing_at(tree["val2"], val, after("val2:\n# onespace"), tree.arena()); - _check_null_pointing_at(tree["val3"], val, after("val3: "), tree.arena()); - _check_null_pointing_at(tree["val4"], val, after("val4: "), tree.arena()); - _check_null_pointing_at(tree["val5"], val, after("val5: \n# null"), tree.arena()); - // but explicitly null vals are ok: - _check_null_pointing_at(tree["val6"], val, "null\nval7:", tree.arena()); - _check_null_pointing_at(tree["val7"], val, "null\nval8:", tree.arena()); - _check_null_pointing_at(tree["val8"], val, "null\nval9:", tree.arena()); - _check_null_pointing_at(tree["val9"], val, "~\n", tree.arena()); -} - - -TEST(null_val, issue103) -{ - C4_SUPPRESS_WARNING_GCC_WITH_PUSH("-Wuseless-cast") - Tree tree; - - tree = parse_in_arena(R"({null: null})"); - ASSERT_EQ(tree.size(), 2u); - EXPECT_EQ(tree.root_id(), 0u); - EXPECT_EQ(tree.first_child(0), 1u); - EXPECT_TRUE(tree.type(1).is_keyval()); - EXPECT_EQ(tree.key(1), "null"); - EXPECT_EQ(tree.val(1), "null"); - EXPECT_TRUE(tree.key_is_null(1)); - EXPECT_TRUE(tree.val_is_null(1)); - EXPECT_TRUE(tree[0].key_is_null()); - EXPECT_TRUE(tree[0].val_is_null()); - _check_null_pointing_at(tree[0], key, "null:", tree.arena()); - _check_null_pointing_at(tree[0], val, "null}", tree.arena()); - - tree = parse_in_arena(R"({Null: Null})"); - ASSERT_EQ(tree.size(), 2u); - EXPECT_EQ(tree.root_id(), 0u); - EXPECT_EQ(tree.first_child(0), 1u); - EXPECT_TRUE(tree.type(1).is_keyval()); - EXPECT_EQ(tree.key(1), "Null"); - EXPECT_EQ(tree.val(1), "Null"); - EXPECT_TRUE(tree.key_is_null(1)); - EXPECT_TRUE(tree.val_is_null(1)); - EXPECT_TRUE(tree[0].key_is_null()); - EXPECT_TRUE(tree[0].val_is_null()); - _check_null_pointing_at(tree[0], key, "Null:", tree.arena()); - _check_null_pointing_at(tree[0], val, "Null}", tree.arena()); - - tree = parse_in_arena(R"({NULL: NULL})"); - ASSERT_EQ(tree.size(), 2u); - EXPECT_EQ(tree.root_id(), 0u); - EXPECT_EQ(tree.first_child(0), 1u); - EXPECT_TRUE(tree.type(1).is_keyval()); - EXPECT_EQ(tree.key(1), "NULL"); - EXPECT_EQ(tree.val(1), "NULL"); - EXPECT_TRUE(tree.key_is_null(1)); - EXPECT_TRUE(tree.val_is_null(1)); - EXPECT_TRUE(tree[0].key_is_null()); - EXPECT_TRUE(tree[0].val_is_null()); - _check_null_pointing_at(tree[0], key, "NULL:", tree.arena()); - _check_null_pointing_at(tree[0], val, "NULL}", tree.arena()); - - tree = parse_in_arena(R"({ : })"); - ASSERT_EQ(tree.size(), 2u); - EXPECT_EQ(tree.root_id(), 0u); - EXPECT_EQ(tree.first_child(0), 1u); - EXPECT_TRUE(tree.type(1).is_keyval()); - EXPECT_EQ(tree.key(1), nullptr); - EXPECT_EQ(tree.val(1), nullptr); - EXPECT_TRUE(tree.key_is_null(1)); - EXPECT_TRUE(tree.val_is_null(1)); - EXPECT_TRUE(tree[0].key_is_null()); - EXPECT_TRUE(tree[0].val_is_null()); - _check_null_pointing_at(tree[0], key, ": }", tree.arena()); - _check_null_pointing_at(tree[0], val, " }", tree.arena()); - - tree = parse_in_arena(R"({~: ~})"); - ASSERT_EQ(tree.size(), 2u); - EXPECT_EQ(tree.root_id(), 0u); - EXPECT_EQ(tree.first_child(0), 1u); - EXPECT_TRUE(tree.type(1).is_keyval()); - EXPECT_EQ(tree.key(1), "~"); - EXPECT_EQ(tree.val(1), "~"); - EXPECT_TRUE(tree.key_is_null(1)); - EXPECT_TRUE(tree.val_is_null(1)); - EXPECT_TRUE(tree[0].key_is_null()); - EXPECT_TRUE(tree[0].val_is_null()); - _check_null_pointing_at(tree[0], key, "~:", tree.arena()); - _check_null_pointing_at(tree[0], val, "~}", tree.arena()); - - tree = parse_in_arena(R"({"~": "~"})"); - ASSERT_EQ(tree.size(), 2u); - EXPECT_EQ(tree.root_id(), 0u); - EXPECT_EQ(tree.first_child(0), 1u); - EXPECT_TRUE(tree.type(1).is_keyval()); - EXPECT_EQ(tree.key(1), "~"); - EXPECT_EQ(tree.val(1), "~"); - EXPECT_NE(tree.key(1), nullptr); - EXPECT_NE(tree.val(1), nullptr); - EXPECT_FALSE(tree.key_is_null(1)); - EXPECT_FALSE(tree.val_is_null(1)); - EXPECT_FALSE(tree[0].key_is_null()); - EXPECT_FALSE(tree[0].val_is_null()); - - tree = parse_in_arena(R"({"null": "null"})"); - ASSERT_EQ(tree.size(), 2u); - EXPECT_EQ(tree.root_id(), 0u); - EXPECT_EQ(tree.first_child(0), 1u); - EXPECT_TRUE(tree.type(1).is_keyval()); - EXPECT_EQ(tree.key(1), "null"); - EXPECT_EQ(tree.val(1), "null"); - EXPECT_NE(tree.key(1), nullptr); - EXPECT_NE(tree.val(1), nullptr); - EXPECT_FALSE(tree[0].key_is_null()); - EXPECT_FALSE(tree[0].val_is_null()); - - tree = parse_in_arena(R"({"Null": "Null"})"); - ASSERT_EQ(tree.size(), 2u); - EXPECT_EQ(tree.root_id(), 0u); - EXPECT_EQ(tree.first_child(0), 1u); - EXPECT_TRUE(tree.type(1).is_keyval()); - EXPECT_EQ(tree.key(1), "Null"); - EXPECT_EQ(tree.val(1), "Null"); - EXPECT_NE(tree.key(1), nullptr); - EXPECT_NE(tree.val(1), nullptr); - EXPECT_FALSE(tree.key_is_null(1)); - EXPECT_FALSE(tree.val_is_null(1)); - EXPECT_FALSE(tree[0].key_is_null()); - EXPECT_FALSE(tree[0].val_is_null()); - - tree = parse_in_arena(R"({"NULL": "NULL"})"); - ASSERT_EQ(tree.size(), 2u); - EXPECT_EQ(tree.root_id(), 0u); - EXPECT_EQ(tree.first_child(0), 1u); - EXPECT_TRUE(tree.type(1).is_keyval()); - EXPECT_EQ(tree.key(1), "NULL"); - EXPECT_EQ(tree.val(1), "NULL"); - EXPECT_NE(tree.key(1), nullptr); - EXPECT_NE(tree.val(1), nullptr); - EXPECT_FALSE(tree.key_is_null(1)); - EXPECT_FALSE(tree.val_is_null(1)); - EXPECT_FALSE(tree[0].key_is_null()); - EXPECT_FALSE(tree[0].val_is_null()); - - C4_SUPPRESS_WARNING_GCC_POP -} - - -TEST(null_val, null_key) -{ - auto tree = parse_in_arena(R"({null: null})"); - - ASSERT_EQ(tree.size(), 2u); - _check_null_pointing_at(tree[0], key, "null: ", tree.arena()); - _check_null_pointing_at(tree[0], val, "null}", tree.arena()); -} - - -TEST(null_val, readme_example) -{ - csubstr yaml = R"( -seq: - - ~ - - null - - - - - # a comment - - -map: - val0: ~ - val1: null - val2: - val3: - # a comment - val4: -)"; - Parser p; - Tree t = p.parse_in_arena("file.yml", yaml); - // as expected: (len is null, str is pointing at the value where the node starts) - EXPECT_EQ(t["seq"][0].val(), "~"); - EXPECT_EQ(t["seq"][1].val(), "null"); - EXPECT_EQ(t["seq"][2].val(), nullptr); - EXPECT_EQ(t["seq"][3].val(), nullptr); - EXPECT_EQ(t["seq"][4].val(), nullptr); - EXPECT_EQ(t["map"][0].val(), "~"); - EXPECT_EQ(t["map"][1].val(), "null"); - EXPECT_EQ(t["map"][2].val(), nullptr); - EXPECT_EQ(t["map"][3].val(), nullptr); - EXPECT_EQ(t["map"][4].val(), nullptr); - // standard null values point at the expected location: - EXPECT_EQ(csubstr(t["seq"][0].val().str, 1), csubstr("~")); - EXPECT_EQ(csubstr(t["seq"][1].val().str, 4), csubstr("null")); - EXPECT_EQ(csubstr(t["map"]["val0"].val().str, 1), csubstr("~")); - EXPECT_EQ(csubstr(t["map"]["val1"].val().str, 4), csubstr("null")); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -CASE_GROUP(NULL_VAL) -{ - -ADD_CASE_TO_GROUP("all null", -R"( -- -- # with space -- null -- Null -- NULL -- ~ -- null: null -- Null: Null -- NULL: NULL -- ~: ~ -- ~: null -- null: ~ -)", -L{ -N(VAL, nullptr), -N(VAL, nullptr), -N(VAL, "null"), -N(VAL, "Null"), -N(VAL, "NULL"), -N(VAL, "~"), -N(MAP, L{N(KEYVAL, "null", "null")}), -N(MAP, L{N(KEYVAL, "Null", "Null")}), -N(MAP, L{N(KEYVAL, "NULL", "NULL")}), -N(MAP, L{N(KEYVAL, "~", "~")}), -N(MAP, L{N(KEYVAL, "~", "null")}), -N(MAP, L{N(KEYVAL, "null", "~")}), -}); - -ADD_CASE_TO_GROUP("null map vals, expl", -R"({foo: , bar: , baz: } -)", -L{N(KEYVAL, "foo", nullptr), N(KEYVAL, "bar", nullptr), N(KEYVAL, "baz", nullptr)} -); - -ADD_CASE_TO_GROUP("null map vals, impl", -R"( -foo: -bar: -baz: -)", -L{N(KEYVAL, "foo", nullptr), N(KEYVAL, "bar", nullptr), N(KEYVAL, "baz", nullptr)} -); - -ADD_CASE_TO_GROUP("null seq vals, impl", -R"(- -- -- -)", -L{N(VAL, nullptr), N(VAL, nullptr), N(VAL, nullptr)} -); - -ADD_CASE_TO_GROUP("null seq vals in map, impl, mixed 1", -R"( -foo: - - - - - - -bar: -baz: -)", -L{N("foo", L{N(VAL, nullptr), N(VAL, nullptr), N(VAL, nullptr)}), N(KEYVAL, "bar", nullptr), N(KEYVAL, "baz", nullptr)} -); - -ADD_CASE_TO_GROUP("null seq vals in map, impl, mixed 2", -R"( -foo: -bar: - - - - - - -baz: -)", -L{N(KEYVAL, "foo", nullptr), N("bar", L{N(VAL, nullptr), N(VAL, nullptr), N(VAL, nullptr)}), N(KEYVAL, "baz", nullptr)} -); - -ADD_CASE_TO_GROUP("null seq vals in map, impl, mixed 3", -R"( -foo: -bar: -baz: - - - - - - -)", -L{N(KEYVAL, "foo", nullptr), N(KEYVAL, "bar", nullptr), N("baz", L{N(VAL, nullptr), N(VAL, nullptr), N(VAL, nullptr)})} -); - -ADD_CASE_TO_GROUP("null map vals in seq, impl, mixed 1", -R"( -- foo: - bar: - baz: -- -- -)", -L{N(L{N(KEYVAL, "foo", nullptr), N(KEYVAL, "bar", nullptr), N(KEYVAL, "baz", nullptr)}), N(VAL, nullptr), N(VAL, nullptr)} -); - -ADD_CASE_TO_GROUP("null map vals in seq, impl, mixed 2", -R"( -- -- foo: - bar: - baz: -- -)", -L{N(VAL, nullptr), N(L{N(KEYVAL, "foo", nullptr), N(KEYVAL, "bar", nullptr), N(KEYVAL, "baz", nullptr)}), N(VAL, nullptr)} -); - -ADD_CASE_TO_GROUP("null map vals in seq, impl, mixed 3", -R"( -- -- -- foo: - bar: - baz: -)", -L{N(VAL, nullptr), N(VAL, nullptr), N(L{N(KEYVAL, "foo", nullptr), N(KEYVAL, "bar", nullptr), N(KEYVAL, "baz", nullptr)})} -); - -ADD_CASE_TO_GROUP("issue84.1", -R"( -fixed case: - foo: a - bar: -your case: - foo: a - bar: '' -whatever: baz -)", -L{ -N("fixed case", L{N("foo", "a"), N(KEYVAL, "bar", nullptr)}), -N("your case", L{N("foo", "a"), N(QV, "bar", "")}), -N("whatever", "baz"), -}); - -ADD_CASE_TO_GROUP("issue84.2", -R"( -version: 0 -type: xml -param_root: - objects: - System: {SameGroupActorName: '', IsGetItemSelf: false} - General: - Speed: 1.0 - Life: 100 - IsLifeInfinite: false - ElectricalDischarge: 1.0 - IsBurnOutBorn: false - BurnOutBornName: - IsBurnOutBornIdent: false - ChangeDropTableName: '' -)", -L{ -N("version", "0"), -N("type", "xml"), -N("param_root", L{ - N("objects", L{ - N("System", L{ - N(QV, "SameGroupActorName", ""), - N("IsGetItemSelf", "false") - }), - N("General", L{ - N("Speed", "1.0"), - N("Life", "100"), - N("IsLifeInfinite", "false"), - N("ElectricalDischarge", "1.0"), - N("IsBurnOutBorn", "false"), - N(KEYVAL, "BurnOutBornName", nullptr), - N("IsBurnOutBornIdent", "false"), - N(QV, "ChangeDropTableName", ""), - }), - }) -}), -}); - -ADD_CASE_TO_GROUP("issue84.3", -R"( -version: 10 -type: test -param_root: - objects: - TestContent: - Str64_empty: '' - Str64_empty2: - Str64_empty3: '' - lists: {} -)", -L{ -N("version", "10"), -N("type", "test"), -N("param_root", L{ - N("objects", L{ - N("TestContent", L{ - N(QV, "Str64_empty", ""), - N(KEYVAL, "Str64_empty2", nullptr), - N(QV, "Str64_empty3", ""), - }), - }), - N(KEYMAP, "lists", L{}) -}), -}); - -} - -} // namespace yml -} // namespace c4 - -C4_SUPPRESS_WARNING_GCC_POP diff --git a/thirdparty/ryml/test/test_number.cpp b/thirdparty/ryml/test/test_number.cpp deleted file mode 100644 index 41c388ae6..000000000 --- a/thirdparty/ryml/test/test_number.cpp +++ /dev/null @@ -1,217 +0,0 @@ -#include "./test_group.hpp" - -namespace c4 { -namespace yml { - -template -auto mkvals() -> typename std::enable_if::value, std::vector>::type -{ - return std::vector({std::numeric_limits::min(), -10, -5, -1, 0, 1, 5, 10, std::numeric_limits::max(),}); -} -template -auto mkvals() -> typename std::enable_if::value, std::vector>::type -{ - return std::vector({0, 1, 5, 10, std::numeric_limits::max(),}); -} -template -void test_ints() -{ - C4_SUPPRESS_WARNING_GCC_WITH_PUSH("-Wuseless-cast") - std::vector values = mkvals(); - Tree t = parse_in_arena("{dec: [], hex: [], bin: [], oct: [], versions: ['0.1', 0.1.2, 0.1.2.3, 0.1.2.3.4]}"); - NodeRef r = t.rootref(); - for(I val : values) - { - I out; - r["dec"].append_child() << val; - r["hex"].append_child() << fmt::hex(val); - r["bin"].append_child() << fmt::bin(val); - r["oct"].append_child() << fmt::oct(val); - out = (I)(val + I(1)); - r["dec"].last_child() >> out; - EXPECT_EQ(out, val); - out = (I)(val + I(1)); - r["hex"].last_child() >> out; - EXPECT_EQ(out, val); - out = (I)(val + I(1)); - r["bin"].last_child() >> out; - EXPECT_EQ(out, val); - out = (I)(val + I(1)); - r["oct"].last_child() >> out; - EXPECT_EQ(out, val); - } - { - std::string emitted = emitrs_yaml(t); - Tree parsed = parse_in_place(to_substr(emitted)); - ASSERT_EQ(parsed["dec"].num_children(), values.size()); - ASSERT_EQ(parsed["hex"].num_children(), values.size()); - ASSERT_EQ(parsed["bin"].num_children(), values.size()); - ASSERT_EQ(parsed["oct"].num_children(), values.size()); - ASSERT_EQ(parsed["versions"].num_children(), 4u); - size_t pos = 0; - for(I val : values) - { - I out = (I)(val + I(1)); - parsed["dec"][pos] >> out; - EXPECT_EQ(out, val); - out = (I)(val + I(1)); - parsed["hex"][pos] >> out; - EXPECT_EQ(out, val); - out = (I)(val + I(1)); - parsed["bin"][pos]>> out; - EXPECT_EQ(out, val); - out = (I)(val + I(1)); - parsed["oct"][pos] >> out; - EXPECT_EQ(out, val); - ++pos; - } - EXPECT_EQ(parsed["versions"][0], "0.1"); - EXPECT_EQ(parsed["versions"][1], "0.1.2"); - EXPECT_EQ(parsed["versions"][2], "0.1.2.3"); - EXPECT_EQ(parsed["versions"][3], "0.1.2.3.4"); - } - { - std::string emitted = emitrs_json(t); - Tree parsed = parse_in_place(to_substr(emitted)); - ASSERT_EQ(parsed["dec"].num_children(), values.size()); - ASSERT_EQ(parsed["hex"].num_children(), values.size()); - ASSERT_EQ(parsed["bin"].num_children(), values.size()); - ASSERT_EQ(parsed["oct"].num_children(), values.size()); - ASSERT_EQ(parsed["versions"].num_children(), 4u); - size_t pos = 0; - for(I val : values) - { - I out = (I)(val + I(1)); - parsed["dec"][pos] >> out; - EXPECT_EQ(out, val); - out = (I)(val + I(1)); - parsed["hex"][pos] >> out; - EXPECT_EQ(out, val); - out = (I)(val + I(1)); - parsed["bin"][pos]>> out; - EXPECT_EQ(out, val); - out = (I)(val + I(1)); - parsed["oct"][pos] >> out; - EXPECT_EQ(out, val); - ++pos; - } - EXPECT_EQ(parsed["versions"][0], "0.1"); - EXPECT_EQ(parsed["versions"][1], "0.1.2"); - EXPECT_EQ(parsed["versions"][2], "0.1.2.3"); - EXPECT_EQ(parsed["versions"][3], "0.1.2.3.4"); - } - C4_SUPPRESS_WARNING_GCC_POP -} - -TEST(number, idec) -{ - test_ints(); - test_ints(); - test_ints(); - test_ints(); - test_ints(); - test_ints(); - test_ints(); - test_ints(); -} - - - -CASE_GROUP(NUMBER) -{ - -ADD_CASE_TO_GROUP("integer numbers, flow", JSON_ALSO, -R"(translation: [-2, -2, 5, 0xa, -0xb, 0XA, -0XA, 0b10, -0b10, 0B10, -0B10, 0o17, -0o17, 0O17, -0O17])", -L{N("translation", L{ - N("-2"), N("-2"), N("5"), - N("0xa"), N("-0xb"), - N("0XA"), N("-0XA"), - N("0b10"), N("-0b10"), - N("0B10"), N("-0B10"), - N("0o17"), N("-0o17"), - N("0O17"), N("-0O17"), -})}); - -ADD_CASE_TO_GROUP("integer numbers, block", JSON_ALSO, -R"(translation: - - -2 - - -2 - - -5 -)", -L{N("translation", L{N("-2"), N("-2"), N("-5")})} -); - -ADD_CASE_TO_GROUP("floating point numbers, flow", JSON_ALSO, -R"([-2.0, -2.1, 0.1, .1, -.2, -2.e+6, -3e-6, 1.12345e+011])", -L{N("-2.0"), N("-2.1"), N("0.1"), N(".1"), N("-.2"), N("-2.e+6"), N("-3e-6"), N("1.12345e+011")} -); - -ADD_CASE_TO_GROUP("floating point numbers, block", JSON_ALSO, -R"( -- -2.0 -- -2.1 -- 0.1 -- .1 -- -.2 -- -2.e+6 -- -3e-6 -- 1.12345e+011 -)", -L{N("-2.0"), N("-2.1"), N("0.1"), N(".1"), N("-.2"), N("-2.e+6"), N("-3e-6"), N("1.12345e+011")} -); - -ADD_CASE_TO_GROUP("hex floating point numbers, block", JSON_ALSO, -R"( -- -2.0 -- -2.1 -- 0.1 -- .1 -- -.2 -- -2.e+6 -- -3e-6 -- 1.12345e+011 -)", -L{N("-2.0"), N("-2.1"), N("0.1"), N(".1"), N("-.2"), N("-2.e+6"), N("-3e-6"), N("1.12345e+011")} -); - -ADD_CASE_TO_GROUP("version numbers", JSON_ALSO, -R"( -- 1.2.3 -- 1.2.3.4 -- [1.2.3, 4.5.6] -- [1.2.3.4, 4.5.6.7] -- - 1.2.3 - - 4.5.6 -- - 1.2.3.4 - - 4.5.6.7 -- a: 1.2.3 -- a: 1.2.3.4 -- {a: 1.2.3} -- {a: 1.2.3.4} -- a: 1.2.3 - b: 4.5.6 -- a: 1.2.3.4 - b: 4.5.6.7 -- {a: 1.2.3, b: 4.5.6} -- {a: 1.2.3.4, b: 4.5.6.7} -)", -L{ - N("1.2.3"), - N("1.2.3.4"), - N(L{N("1.2.3"), N("4.5.6")}), - N(L{N("1.2.3.4"), N("4.5.6.7")}), - N(L{N("1.2.3"), N("4.5.6")}), - N(L{N("1.2.3.4"), N("4.5.6.7")}), - N(L{N("a", "1.2.3")}), - N(L{N("a", "1.2.3.4")}), - N(L{N("a", "1.2.3")}), - N(L{N("a", "1.2.3.4")}), - N(L{N("a", "1.2.3"), N("b", "4.5.6")}), - N(L{N("a", "1.2.3.4"), N("b", "4.5.6.7")}), - N(L{N("a", "1.2.3"), N("b", "4.5.6")}), - N(L{N("a", "1.2.3.4"), N("b", "4.5.6.7")}), -}); -} - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_parser.cpp b/thirdparty/ryml/test/test_parser.cpp deleted file mode 100644 index 3ef9ee145..000000000 --- a/thirdparty/ryml/test/test_parser.cpp +++ /dev/null @@ -1,566 +0,0 @@ -#ifdef RYML_SINGLE_HEADER -#include "ryml_all.hpp" -#else -#include "c4/yml/parse.hpp" -#endif -#include -#include "./callbacks_tester.hpp" - - -namespace c4 { -namespace yml { - -// TODO: add this as a method to csubstr -bool is_same(csubstr lhs, csubstr rhs) -{ - return lhs.str == rhs.str && lhs.len == rhs.len; -} - -void mklarge(Parser *p, Callbacks const& cb) -{ - p->~Parser(); - new ((void*)p) Parser(cb); - p->reserve_stack(20); // cause an allocation - p->reserve_locations(128); // cause an allocation - p->reserve_filter_arena(128); // cause an allocation -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -TEST(Parser, empty_ctor) -{ - Parser parser; - EXPECT_EQ(parser.callbacks(), get_callbacks()); -} - -TEST(Parser, callbacks_ctor) -{ - CallbacksTester cbt; - { - Parser parser(cbt.callbacks()); - EXPECT_EQ(parser.callbacks(), cbt.callbacks()); - } - EXPECT_EQ(cbt.num_allocs, 0u); - EXPECT_EQ(cbt.num_deallocs, 0u); -} - -TEST(Parser, reserve_capacity) -{ - CallbacksTester cbt("test", 20000/*Bytes*/); - { - Parser parser(cbt.callbacks()); - EXPECT_EQ(cbt.num_allocs, 0u); - EXPECT_EQ(cbt.num_deallocs, 0u); - parser.reserve_stack(18); - EXPECT_EQ(cbt.num_allocs, 1u); - EXPECT_EQ(cbt.num_deallocs, 0u); - parser.reserve_stack(24); - EXPECT_EQ(cbt.num_allocs, 2u); - EXPECT_EQ(cbt.num_deallocs, 1u); - parser.reserve_stack(28); - EXPECT_EQ(cbt.num_allocs, 3u); - EXPECT_EQ(cbt.num_deallocs, 2u); - } - EXPECT_EQ(cbt.num_allocs, 3u); - EXPECT_EQ(cbt.num_deallocs, 3u); - cbt.check(); -} - -TEST(Parser, reserve_locations) -{ - CallbacksTester ts; - { - Parser parser(ts.callbacks()); - EXPECT_EQ(parser.callbacks(), ts.callbacks()); - EXPECT_EQ(ts.num_allocs, 0u); - EXPECT_EQ(ts.num_deallocs, 0u); - parser.reserve_locations(128); - EXPECT_EQ(ts.num_allocs, 1u); - EXPECT_EQ(ts.num_deallocs, 0u); - EXPECT_EQ(ts.alloc_size, 128u * sizeof(size_t)); - EXPECT_EQ(ts.dealloc_size, 0u); - } - EXPECT_EQ(ts.num_allocs, 1u); - EXPECT_EQ(ts.num_deallocs, 1u); - EXPECT_EQ(ts.alloc_size, 128u * sizeof(size_t)); - EXPECT_EQ(ts.dealloc_size, 128u * sizeof(size_t)); -} - -TEST(Parser, reserve_filter_arena) -{ - size_t cap = 256u; - CallbacksTester ts; - { - Parser parser(ts.callbacks()); - EXPECT_EQ(parser.filter_arena_capacity(), 0u); - EXPECT_EQ(parser.callbacks(), ts.callbacks()); - EXPECT_EQ(ts.num_allocs, 0u); - EXPECT_EQ(ts.num_deallocs, 0u); - parser.reserve_filter_arena(cap); - EXPECT_EQ(ts.num_allocs, 1u); - EXPECT_EQ(ts.num_deallocs, 0u); - EXPECT_EQ(ts.alloc_size, cap); - EXPECT_EQ(ts.dealloc_size, 0u); - } - EXPECT_EQ(ts.num_allocs, 1u); - EXPECT_EQ(ts.num_deallocs, 1u); - EXPECT_EQ(ts.alloc_size, cap); - EXPECT_EQ(ts.dealloc_size, cap); -} - -TEST(Parser, copy_ctor) -{ - { - Parser src; - mklarge(&src, get_callbacks()); - EXPECT_EQ(src.callbacks(), get_callbacks()); - Parser dst(src); - EXPECT_EQ(src.callbacks(), get_callbacks()); - EXPECT_EQ(dst.callbacks(), get_callbacks()); - } - { - CallbacksTester ts; - { - Parser src; - mklarge(&src, ts.callbacks()); - ASSERT_EQ(src.callbacks(), ts.callbacks()); - size_t nbefore = ts.num_allocs; - EXPECT_GT(ts.num_allocs, 0u); - Parser dst(src); - ASSERT_EQ(src.callbacks(), ts.callbacks()); - ASSERT_EQ(dst.callbacks(), ts.callbacks()); - EXPECT_GT(ts.num_allocs, nbefore); - } - EXPECT_EQ(ts.num_allocs, ts.num_deallocs); - EXPECT_EQ(ts.alloc_size, ts.dealloc_size); - } -} - -TEST(Parser, move_ctor) -{ - { - Parser src; - mklarge(&src, get_callbacks()); - EXPECT_EQ(src.callbacks(), get_callbacks()); - Parser dst(std::move(src)); - EXPECT_EQ(src.callbacks(), get_callbacks()); - EXPECT_EQ(dst.callbacks(), get_callbacks()); - } - { - CallbacksTester ts; - { - Parser src; - mklarge(&src, ts.callbacks()); - ASSERT_EQ(src.callbacks(), ts.callbacks()); - size_t nbefore = ts.num_allocs; - EXPECT_GT(ts.num_allocs, 0u); - Parser dst(std::move(src)); - ASSERT_EQ(src.callbacks(), ts.callbacks()); - ASSERT_EQ(dst.callbacks(), ts.callbacks()); - EXPECT_EQ(ts.num_allocs, nbefore); - } - EXPECT_EQ(ts.num_allocs, ts.num_deallocs); - EXPECT_EQ(ts.alloc_size, ts.dealloc_size); - } -} - -TEST(Parser, copy_assign_same_callbacks) -{ - CallbacksTester ts; - { - Parser src; - Parser dst; - mklarge(&src, ts.callbacks()); - mklarge(&dst, ts.callbacks()); - ASSERT_EQ(src.callbacks(), ts.callbacks()); - ASSERT_EQ(dst.callbacks(), ts.callbacks()); - size_t nbefore = ts.num_allocs; - EXPECT_GT(ts.num_allocs, 0u); - EXPECT_GT(ts.num_allocs, 0u); - dst = src; - ASSERT_EQ(src.callbacks(), ts.callbacks()); - ASSERT_EQ(dst.callbacks(), ts.callbacks()); - EXPECT_GT(ts.num_allocs, nbefore); - } - EXPECT_EQ(ts.num_allocs, ts.num_deallocs); - EXPECT_EQ(ts.alloc_size, ts.dealloc_size); -} - -TEST(Parser, copy_assign_diff_callbacks) -{ - CallbacksTester ts("src"); - CallbacksTester td("dst"); - { - Parser src; - Parser dst; - mklarge(&src, ts.callbacks()); - mklarge(&dst, td.callbacks()); - ASSERT_EQ(src.callbacks(), ts.callbacks()); - ASSERT_EQ(dst.callbacks(), td.callbacks()); - size_t nbefore = ts.num_allocs; - EXPECT_GT(ts.num_allocs, 0u); - EXPECT_GT(td.num_allocs, 0u); - dst = src; - ASSERT_EQ(src.callbacks(), ts.callbacks()); - ASSERT_EQ(dst.callbacks(), ts.callbacks()); - EXPECT_GT(ts.num_allocs, nbefore); - EXPECT_EQ(td.num_allocs, nbefore); - } - EXPECT_EQ(ts.num_allocs, ts.num_deallocs); - EXPECT_EQ(ts.alloc_size, ts.dealloc_size); - EXPECT_EQ(td.num_allocs, td.num_deallocs); - EXPECT_EQ(td.alloc_size, td.dealloc_size); -} - -TEST(Parser, move_assign_same_callbacks) -{ - CallbacksTester ts; - { - Parser src; - Parser dst; - mklarge(&src, ts.callbacks()); - mklarge(&dst, ts.callbacks()); - ASSERT_EQ(src.callbacks(), ts.callbacks()); - ASSERT_EQ(dst.callbacks(), ts.callbacks()); - size_t nbefore = ts.num_allocs; - EXPECT_GT(ts.num_allocs, 0u); - EXPECT_GT(ts.num_allocs, 0u); - dst = std::move(src); - ASSERT_EQ(src.callbacks(), ts.callbacks()); - ASSERT_EQ(dst.callbacks(), ts.callbacks()); - EXPECT_EQ(ts.num_allocs, nbefore); - } - EXPECT_EQ(ts.num_allocs, ts.num_deallocs); - EXPECT_EQ(ts.alloc_size, ts.dealloc_size); -} - -TEST(Parser, move_assign_diff_callbacks) -{ - CallbacksTester ts("src"); - CallbacksTester td("dst"); - { - Parser src; - Parser dst; - mklarge(&src, ts.callbacks()); - mklarge(&dst, td.callbacks()); - ASSERT_EQ(src.callbacks(), ts.callbacks()); - ASSERT_EQ(dst.callbacks(), td.callbacks()); - size_t nbefore = ts.num_allocs; - EXPECT_GT(ts.num_allocs, 0u); - EXPECT_GT(td.num_allocs, 0u); - dst = std::move(src); - ASSERT_EQ(src.callbacks(), ts.callbacks()); - ASSERT_EQ(dst.callbacks(), ts.callbacks()); - EXPECT_EQ(td.num_allocs, nbefore); // dst frees with td - EXPECT_EQ(ts.num_allocs, nbefore); // dst moves from ts - } - EXPECT_EQ(ts.num_allocs, ts.num_deallocs); - EXPECT_EQ(ts.alloc_size, ts.dealloc_size); - EXPECT_EQ(td.num_allocs, td.num_deallocs); - EXPECT_EQ(td.alloc_size, td.dealloc_size); -} - -TEST(Parser, new_tree_receives_callbacks) -{ - char src_[] = "{a: b}"; - substr src = src_; - csubstr csrc = src_; - { - { - Parser parser; - EXPECT_EQ(parser.callbacks(), get_callbacks()); - Tree t = parser.parse_in_arena("file0", csrc); - EXPECT_EQ(t.callbacks(), get_callbacks()); - } - CallbacksTester cbt("test", 20000/*Bytes*/); - { - Parser parser(cbt.callbacks()); - EXPECT_EQ(parser.callbacks(), cbt.callbacks()); - Tree t = parser.parse_in_arena("file1", csrc); - EXPECT_EQ(t.callbacks(), cbt.callbacks()); - } - cbt.check(); - } - { - { - Parser parser; - EXPECT_EQ(parser.callbacks(), get_callbacks()); - Tree t = parser.parse_in_place("file", src); - EXPECT_EQ(t.callbacks(), get_callbacks()); - } - CallbacksTester cbt("test", 20000/*Bytes*/); - { - Parser parser(cbt.callbacks()); - EXPECT_EQ(parser.callbacks(), cbt.callbacks()); - Tree t = parser.parse_in_place("file", src); - EXPECT_EQ(t.callbacks(), cbt.callbacks()); - } - cbt.check(); - } -} - -TEST(Parser, existing_tree_overwrites_parser_callbacks) -{ - char src_[] = "{a: b}"; - substr src = src_; - csubstr csrc = src_; - { - CallbacksTester cbp("parser"); - CallbacksTester cbt("tree"); - { - Tree tree(cbt.callbacks()); - Parser parser(cbp.callbacks()); - EXPECT_EQ(tree.callbacks(), cbt.callbacks()); - EXPECT_EQ(parser.callbacks(), cbp.callbacks()); - parser.parse_in_arena("file", csrc, &tree); - EXPECT_EQ(tree.callbacks(), cbt.callbacks()); - EXPECT_EQ(parser.callbacks(), cbp.callbacks()); - } - cbp.check(); - cbt.check(); - } - { - CallbacksTester cbp("parser"); - CallbacksTester cbt("tree"); - { - Tree tree(cbt.callbacks()); - Parser parser(cbp.callbacks()); - EXPECT_EQ(tree.callbacks(), cbt.callbacks()); - EXPECT_EQ(parser.callbacks(), cbp.callbacks()); - parser.parse_in_place("file", src, &tree); - EXPECT_EQ(tree.callbacks(), cbt.callbacks()); - EXPECT_EQ(parser.callbacks(), cbp.callbacks()); - } - cbp.check(); - cbt.check(); - } -} - -TEST(Parser, filename_and_buffer_are_stored) -{ - char src_[] = "{a: b}"; - substr src = src_; - csubstr csrc = src_; - Parser parser; - EXPECT_EQ(parser.filename(), csubstr{}); - { - Tree tree = parser.parse_in_place("file0", src); - EXPECT_EQ(parser.filename(), "file0"); - EXPECT_TRUE(is_same(parser.source(), src)); - } - { - Tree tree = parser.parse_in_arena("file1", csrc); - EXPECT_EQ(parser.filename(), "file1"); - EXPECT_TRUE(!is_same(parser.source(), src)); - } - { - Tree tree = parser.parse_in_place("file2", src); - EXPECT_EQ(parser.filename(), "file2"); - EXPECT_TRUE(is_same(parser.source(), src)); - } - { - Tree tree = parser.parse_in_arena({}, csrc); - EXPECT_EQ(parser.filename(), csubstr{}); - EXPECT_TRUE(!is_same(parser.source(), src)); - } -} - -TEST(parse_in_place, overloads) -{ - char src1_[] = "{a: b}"; - char src2_[] = "{c: d, e: {}}"; - { - Tree tree = parse_in_place(src1_); - EXPECT_EQ(tree["a"].val(), "b"); - } - { - Tree tree = parse_in_place("src1", src1_); - EXPECT_EQ(tree["a"].val(), "b"); - } - { - Tree tree; - parse_in_place(src1_, &tree); - EXPECT_EQ(tree["a"].val(), "b"); - } - { - Tree tree; - parse_in_place("src1", src1_, &tree); - EXPECT_EQ(tree["a"].val(), "b"); - } - { - Tree tree = parse_in_place(src2_); - EXPECT_EQ(tree["c"].val(), "d"); - EXPECT_EQ(tree["e"].is_map(), true); - EXPECT_EQ(tree["e"].has_children(), false); - size_t e = tree.find_child(tree.root_id(), "e"); - ASSERT_NE(e, (size_t)NONE); - parse_in_place(src1_, &tree, e); - EXPECT_EQ(tree["c"].val(), "d"); - EXPECT_EQ(tree["e"].has_children(), true); - EXPECT_EQ(tree["e"]["a"].val(), "b"); - } - { - Tree tree = parse_in_place("src2", src2_); - EXPECT_EQ(tree["c"].val(), "d"); - EXPECT_EQ(tree["e"].is_map(), true); - EXPECT_EQ(tree["e"].has_children(), false); - size_t e = tree.find_child(tree.root_id(), "e"); - ASSERT_NE(e, (size_t)NONE); - parse_in_place("src1", src1_, &tree, e); - EXPECT_EQ(tree["c"].val(), "d"); - EXPECT_EQ(tree["e"].has_children(), true); - EXPECT_EQ(tree["e"]["a"].val(), "b"); - } - { - Tree tree = parse_in_place(src2_); - EXPECT_EQ(tree["c"].val(), "d"); - EXPECT_EQ(tree["e"].is_map(), true); - EXPECT_EQ(tree["e"].has_children(), false); - parse_in_place(src1_, tree["e"]); - EXPECT_EQ(tree["c"].val(), "d"); - EXPECT_EQ(tree["e"].has_children(), true); - EXPECT_EQ(tree["e"]["a"].val(), "b"); - } - { - Tree tree = parse_in_place("src2", src2_); - EXPECT_EQ(tree["c"].val(), "d"); - EXPECT_EQ(tree["e"].is_map(), true); - EXPECT_EQ(tree["e"].has_children(), false); - parse_in_place("src1", src1_, tree["e"]); - EXPECT_EQ(tree["c"].val(), "d"); - EXPECT_EQ(tree["e"].has_children(), true); - EXPECT_EQ(tree["e"]["a"].val(), "b"); - } -} - -TEST(parse_in_arena, overloads) -{ - csubstr src1 = "{a: b}"; - csubstr src2 = "{c: d, e: {}}"; - { - Tree tree = parse_in_arena(src1); - EXPECT_EQ(tree["a"].val(), "b"); - EXPECT_FALSE(tree.arena().empty()); - EXPECT_NE(tree.arena().find(src1), (size_t)npos); - } - { - Tree tree = parse_in_arena("src1", src1); - EXPECT_EQ(tree["a"].val(), "b"); - EXPECT_FALSE(tree.arena().empty()); - EXPECT_NE(tree.arena().find(src1), (size_t)npos); - } - { - Tree tree; - parse_in_arena(src1, &tree); - EXPECT_EQ(tree["a"].val(), "b"); - EXPECT_FALSE(tree.arena().empty()); - EXPECT_NE(tree.arena().find(src1), (size_t)npos); - } - { - Tree tree; - parse_in_arena("src1", src1, &tree); - EXPECT_EQ(tree["a"].val(), "b"); - EXPECT_FALSE(tree.arena().empty()); - EXPECT_NE(tree.arena().find(src1), (size_t)npos); - } - { - Tree tree = parse_in_arena(src2); - EXPECT_EQ(tree["c"].val(), "d"); - EXPECT_EQ(tree["e"].is_map(), true); - EXPECT_EQ(tree["e"].has_children(), false); - EXPECT_FALSE(tree.arena().empty()); - EXPECT_NE(tree.arena().find(src2), (size_t)npos); - size_t e = tree.find_child(tree.root_id(), "e"); - ASSERT_NE(e, (size_t)NONE); - parse_in_arena(src1, &tree, e); - EXPECT_EQ(tree["c"].val(), "d"); - EXPECT_EQ(tree["e"].has_children(), true); - EXPECT_EQ(tree["e"]["a"].val(), "b"); - EXPECT_FALSE(tree.arena().empty()); - EXPECT_NE(tree.arena().find(src1), (size_t)npos); - EXPECT_NE(tree.arena().find(src2), (size_t)npos); - } - { - Tree tree = parse_in_arena("src2", src2); - EXPECT_EQ(tree["c"].val(), "d"); - EXPECT_EQ(tree["e"].is_map(), true); - EXPECT_EQ(tree["e"].has_children(), false); - EXPECT_FALSE(tree.arena().empty()); - EXPECT_NE(tree.arena().find(src2), (size_t)npos); - size_t e = tree.find_child(tree.root_id(), "e"); - ASSERT_NE(e, (size_t)NONE); - parse_in_arena("src1", src1, &tree, e); - EXPECT_EQ(tree["c"].val(), "d"); - EXPECT_EQ(tree["e"].has_children(), true); - EXPECT_EQ(tree["e"]["a"].val(), "b"); - EXPECT_FALSE(tree.arena().empty()); - EXPECT_NE(tree.arena().find(src1), (size_t)npos); - EXPECT_NE(tree.arena().find(src2), (size_t)npos); - } - { - Tree tree = parse_in_arena(src2); - EXPECT_EQ(tree["c"].val(), "d"); - EXPECT_EQ(tree["e"].is_map(), true); - EXPECT_EQ(tree["e"].has_children(), false); - EXPECT_FALSE(tree.arena().empty()); - EXPECT_NE(tree.arena().find(src2), (size_t)npos); - parse_in_arena(src1, tree["e"]); - EXPECT_EQ(tree["c"].val(), "d"); - EXPECT_EQ(tree["e"].has_children(), true); - EXPECT_EQ(tree["e"]["a"].val(), "b"); - EXPECT_FALSE(tree.arena().empty()); - EXPECT_NE(tree.arena().find(src1), (size_t)npos); - EXPECT_NE(tree.arena().find(src2), (size_t)npos); - } - { - Tree tree = parse_in_arena("src2", src2); - EXPECT_EQ(tree["c"].val(), "d"); - EXPECT_EQ(tree["e"].is_map(), true); - EXPECT_EQ(tree["e"].has_children(), false); - EXPECT_FALSE(tree.arena().empty()); - EXPECT_NE(tree.arena().find(src2), (size_t)npos); - parse_in_arena("src1", src1, tree["e"]); - EXPECT_EQ(tree["c"].val(), "d"); - EXPECT_EQ(tree["e"].has_children(), true); - EXPECT_EQ(tree["e"]["a"].val(), "b"); - EXPECT_FALSE(tree.arena().empty()); - EXPECT_NE(tree.arena().find(src1), (size_t)npos); - EXPECT_NE(tree.arena().find(src2), (size_t)npos); - } -} - -TEST(parse_in_place, version_numbers) -{ - char src1_[] = "{a: 1.2.3}"; - { - Tree tree = parse_in_place(src1_); - EXPECT_EQ(tree["a"].val(), "1.2.3"); - } -} - -} // namespace yml -} // namespace c4 - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -// this is needed to use the test case library - -#ifndef RYML_SINGLE_HEADER -#include "c4/substr.hpp" -#endif - -namespace c4 { -namespace yml { -struct Case; -Case const* get_case(csubstr /*name*/) -{ - return nullptr; -} -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_plain_scalar.cpp b/thirdparty/ryml/test/test_plain_scalar.cpp deleted file mode 100644 index ec147c5d8..000000000 --- a/thirdparty/ryml/test/test_plain_scalar.cpp +++ /dev/null @@ -1,800 +0,0 @@ -#include "./test_group.hpp" - -namespace c4 { -namespace yml { - -TEST(plain_scalar, issue153_seq) -{ - Tree t = parse_in_arena("- A\n \n"); - EXPECT_EQ(t[0].val(), "A"); -} - -TEST(plain_scalar, issue153_map) -{ - Tree t = parse_in_arena("foo: A\n \n"); - EXPECT_EQ(t["foo"].val(), "A"); -} - - -TEST(plain_scalar, test_suite_7TMG) -{ - csubstr yaml = R"(--- -word1 -# comment ---- -# first value is NOT a multiline plain scalar -[ word1 -# comment -, word2] -)"; - test_check_emit_check(yaml, [](Tree const &t){ - EXPECT_TRUE(t.rootref().is_stream()); - ConstNodeRef doc = t.rootref().first_child(); - ASSERT_TRUE(doc.is_doc()); - ASSERT_TRUE(doc.is_val()); - EXPECT_EQ(doc.val(), "word1"); - doc = t.rootref().child(1); - ASSERT_TRUE(doc.is_doc()); - ASSERT_TRUE(doc.is_seq()); - EXPECT_EQ(doc[0].val(), "word1"); - EXPECT_EQ(doc[1].val(), "word2"); - }); -} - - -TEST(plain_scalar, test_suite_82AN) -{ - csubstr yaml = R"( ----word1 -word2 -)"; - test_check_emit_check(yaml, [](Tree const &t){ - ASSERT_TRUE(t.rootref().is_doc()); - ASSERT_TRUE(t.rootref().is_val()); - EXPECT_EQ(t.rootref().val(), csubstr("---word1 word2")); - }); -} - -TEST(plain_scalar, test_suite_EXG3) -{ - csubstr yaml = R"( ---- ----word1 -word2 -)"; - test_check_emit_check(yaml, [](Tree const &t){ - ASSERT_TRUE(t.rootref().is_stream()); - ASSERT_TRUE(t.rootref().first_child().is_doc()); - ASSERT_TRUE(t.rootref().first_child().is_val()); - EXPECT_EQ(t.rootref().first_child().val(), csubstr("---word1 word2")); - }); -} - - -TEST(plain_scalar, test_suite_9YRD) -{ - csubstr yaml = R"( -a -b - c -d - -e -)"; - test_check_emit_check(yaml, [](Tree const &t){ - ASSERT_TRUE(t.rootref().is_doc()); - ASSERT_TRUE(t.rootref().is_val()); - EXPECT_EQ(t.rootref().val(), csubstr("a b c d\ne")); - }); -} - -TEST(plain_scalar, test_suite_EX5H) -{ - csubstr yaml = R"( ---- -a -b - c -d - -e -)"; - test_check_emit_check(yaml, [](Tree const &t){ - ASSERT_TRUE(t.rootref().is_stream()); - ASSERT_TRUE(t.rootref().child(0).is_doc()); - ASSERT_TRUE(t.rootref().child(0).is_val()); - EXPECT_EQ(t.rootref().child(0).val(), csubstr("a b c d\ne")); - }); -} - - -TEST(plain_scalar, test_suite_M7A3) -{ - csubstr yaml = R"( -Bare -document -... -# No document -... -| -%!PS-Adobe-2.0 # Not the first line -)"; - test_check_emit_check(yaml, [](Tree const &t){ - ASSERT_TRUE(t.rootref().is_stream()); - ASSERT_EQ(t.rootref().num_children(), 2u); - EXPECT_EQ(t.rootref().child(0).val(), csubstr("Bare document")); - EXPECT_EQ(t.rootref().child(1).val(), csubstr("%!PS-Adobe-2.0 # Not the first line\n")); - }); -} - - -TEST(plain_scalar, test_suite_HS5T) -{ - csubstr yaml = R"( -1st non-empty - - 2nd non-empty - 3rd non-empty -)"; - test_check_emit_check(yaml, [](Tree const &t){ - ASSERT_TRUE(t.rootref().is_doc()); - ASSERT_TRUE(t.rootref().is_val()); - EXPECT_EQ(t.rootref().val(), csubstr("1st non-empty\n2nd non-empty 3rd non-empty")); - }); -} - -TEST(plain_scalar, test_suite_NB6Z) -{ - csubstr yaml = R"( -key: - value - with - - tabs - tabs - - foo - - bar - baz - -key1: - value - with - - tabs - tabs - - foo - - bar - baz - -key2: something - else -key3: something - else -)"; - test_check_emit_check(yaml, [](Tree const &t){ - ASSERT_TRUE(t.rootref().is_map()); - ASSERT_TRUE(t.rootref().has_child("key")); - ASSERT_TRUE(t.rootref().has_child("key1")); - ASSERT_TRUE(t.rootref().has_child("key2")); - ASSERT_TRUE(t.rootref().has_child("key3")); - EXPECT_EQ(t["key"].val(), csubstr("value with\ntabs tabs\nfoo\nbar baz")); - EXPECT_EQ(t["key1"].val(), csubstr("value with\ntabs tabs\nfoo\nbar baz")); - EXPECT_EQ(t["key2"].val(), csubstr("something else")); - EXPECT_EQ(t["key3"].val(), csubstr("something else")); - }); -} - -TEST(plain_scalar, test_suite_NB6Z_seq) -{ - csubstr yaml = R"( -- value - with - - tabs - tabs - - foo - - bar - baz - -- value - with - - tabs - tabs - - foo - - bar - baz - -- more - value -)"; - test_check_emit_check(yaml, [](Tree const &t){ - ASSERT_TRUE(t.rootref().is_seq()); - ASSERT_EQ(t.rootref().num_children(), 3u); - EXPECT_EQ(t[0].val(), csubstr("value with\ntabs tabs\nfoo\nbar baz")); - EXPECT_EQ(t[1].val(), csubstr("value with\ntabs tabs\nfoo\nbar baz")); - EXPECT_EQ(t[2].val(), csubstr("more value")); - }); -} - -TEST(plain_scalar, test_suite_NB6Z_docval) -{ - csubstr yaml = R"( -value -with - -tabs -tabs - - foo - - bar - baz - -)"; - test_check_emit_check(yaml, [](Tree const &t){ - ASSERT_TRUE(t.rootref().is_doc()); - ASSERT_TRUE(t.rootref().is_val()); - EXPECT_EQ(t.rootref().val(), csubstr("value with\ntabs tabs\nfoo\nbar baz")); - }); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -CASE_GROUP(PLAIN_SCALAR) -{ -// -ADD_CASE_TO_GROUP("plain scalar, 1 word only", -R"(a_single_word_scalar_to_test)", - N(DOCVAL, "a_single_word_scalar_to_test") -); - -ADD_CASE_TO_GROUP("plain scalar, 1 line with spaces", -R"(a scalar with spaces in it all in one line)", - N(DOCVAL, "a scalar with spaces in it all in one line") -); - -ADD_CASE_TO_GROUP("plain scalar, multiline", -R"( -a scalar with several lines in it - of course also with spaces but for now there are no quotes - and also no blank lines to speak of)", - N(DOCVAL, "a scalar with several lines in it of course also with spaces but for now there are no quotes and also no blank lines to speak of") -); - -ADD_CASE_TO_GROUP("plain scalar, multiline, unindented", -R"( -a scalar with several lines in it - of course also with spaces but for now there are no quotes - and also no blank lines to speak of)", - N(DOCVAL, "a scalar with several lines in it of course also with spaces but for now there are no quotes and also no blank lines to speak of") -); - -ADD_CASE_TO_GROUP("plain scalar, multiline, quotes, escapes", -R"( -a scalar with several lines in it and also 'single quotes' - and "double quotes" and assorted escapes such as \r or \n)", - N(DOCVAL, "a scalar with several lines in it and also 'single quotes' and \"double quotes\" and assorted escapes such as \\r or \\n") -); - -ADD_CASE_TO_GROUP("plain scalar, multiline, quotes, escapes, blank lines middle", -R"( -A scalar with several lines in it and also 'single quotes'. - A blank line follows after this one. - - And "double quotes" and assorted escapes such as \r or \n)", - N(DOCVAL, "A scalar with several lines in it and also 'single quotes'. A blank line follows after this one.\nAnd \"double quotes\" and assorted escapes such as \\r or \\n") -); - -ADD_CASE_TO_GROUP("plain scalar, multiline, quotes, escapes, blank lines first", -R"( -A scalar with several lines in it and also 'single quotes'. - - A blank line precedes this one. - And "double quotes" and assorted escapes such as \r or \n)", - N(DOCVAL, "A scalar with several lines in it and also 'single quotes'.\nA blank line precedes this one. And \"double quotes\" and assorted escapes such as \\r or \\n") -); - -ADD_CASE_TO_GROUP("plain scalar, multiline, quotes, escapes, blank lines last", -R"( -A scalar with several lines in it and also 'single quotes'. - And "double quotes" and assorted escapes such as \r or \n. - A blank line follows after this one. - - )", - N(DOCVAL, "A scalar with several lines in it and also 'single quotes'. And \"double quotes\" and assorted escapes such as \\r or \\n. A blank line follows after this one.") -); - -ADD_CASE_TO_GROUP("plain scalar, example", -R"( -Several lines of text - with some "quotes" of various 'types'. - Escapes (like \n) don't do anything. - - Newlines can be added by leaving a blank line. - Additional leading whitespace is ignored.)", - N(DOCVAL, "Several lines of text with some \"quotes\" of various 'types'. Escapes (like \\n) don't do anything.\nNewlines can be added by leaving a blank line. Additional leading whitespace is ignored.") -); - -ADD_CASE_TO_GROUP("plain scalar, map example 1", -R"( -example: Several lines of text, - with some "quotes" of various 'types'. - Escapes (like \n) don't do anything. - - Newlines can be added by leaving a blank line. - Additional leading whitespace is ignored. - -another example: Several lines of text, - - but the second line is empty, and _indented_. - There are more lines that follow. - -yet another example: Several lines of text, - - but the second line is empty, and _unindented_. - There are more lines that follow. -final example: Several lines of text, - - - but the second line is empty, and _unindented_. - There are more lines that follow. And the last line - terminates at the end of the file.)", - L{ - N("example", "Several lines of text, with some \"quotes\" of various 'types'. " - "Escapes (like \\n) don't do anything.\n" - "Newlines can be added by leaving a blank line. " - "Additional leading whitespace is ignored."), - N("another example", "Several lines of text,\n" - "but the second line is empty, and _indented_. " - "There are more lines that follow."), - N("yet another example", "Several lines of text,\n" - "but the second line is empty, and _unindented_. " - "There are more lines that follow."), - N("final example", "Several lines of text,\n\n" - "but the second line is empty, and _unindented_. " - "There are more lines that follow. " - "And the last line terminates at the end of the file."), - } -); - -/* -ADD_CASE_TO_GROUP("plain scalar, map example 2", IGNORE_LIBYAML_PARSE_FAIL|IGNORE_YAMLCPP_PARSE_FAIL, -R"( -example: - Several lines of text, - with some "quotes" of various 'types'. - Escapes (like \n) don't do anything. - - Newlines can be added by leaving a blank line. - Additional leading whitespace is ignored. -)", - L{N("example", "Several lines of text, with some \"quotes\" of various 'types'. Escapes (like \\n) don't do anything.\nNewlines can be added by leaving a blank line. Additional leading whitespace is ignored.")} -); -*/ - -ADD_CASE_TO_GROUP("plain scalar, seq example 1", -R"( -- Several lines of text, - with some "quotes" of various 'types'. - Escapes (like \n) don't do anything. - - Newlines can be added by leaving a blank line. - Additional leading whitespace is ignored.)", - L{N("Several lines of text, with some \"quotes\" of various 'types'. " - "Escapes (like \\n) don't do anything.\n" - "Newlines can be added by leaving a blank line. " - "Additional leading whitespace is ignored.")} -); - -/* -ADD_CASE_TO_GROUP("plain scalar, seq example 2", IGNORE_LIBYAML_PARSE_FAIL|IGNORE_YAMLCPP_PARSE_FAIL, -R"( -- - Several lines of text, - with some "quotes" of various 'types'. - Escapes (like \n) don't do anything. - - Newlines can be added by leaving a blank line. - Additional leading whitespace is ignored. -)", - L{N("Several lines of text, with some \"quotes\" of various 'types'. Escapes (like \\n) don't do anything.\nNewlines can be added by leaving a blank line. Additional leading whitespace is ignored.")} -); -*/ - -ADD_CASE_TO_GROUP("plain scalar, special characters 1", -R"( -- Several lines of text, - with special:characters, like:this-or-this - - - and some "quotes" of various 'types'. - How about empty lines? - - Can we also have [] or {} inside? - Guess we can. - And how about at the beginning? - { - for example } - [ - for example ] - - - for example - ::- for example - - and now two empty lines - - - - and now three empty lines - - - - - and an empty line, unindented - - - followed by more text - and another four at the end - - - - - -)", - L{N("Several lines of text, with special:characters, like:this-or-this - - and some \"quotes\" of various 'types'. " - "How about empty lines?\n" - "Can we also have [] or {} inside? Guess we can. " - "And how about at the beginning? { - for example } [ - for example ] - - for example ::- for example\n" - "and now two empty lines -\n\n" - "and now three empty lines -\n\n\n" - "and an empty line, unindented -\n" - "followed by more text " - "and another four at the end -" - )} -); - -ADD_CASE_TO_GROUP("plain scalar, special characters 3MYT", -R"(--- # ZWK4 -a: 1 -? b -&anchor c: 3 # the anchor is for the scalar 'c' -? d -!!str e: 4 -? f ---- -k:#foo &a !t s ---- -"k:#foo &a !t s" ---- -'k:#foo &a !t s' - ---- # 3MYT -k:#foo - &a !t s ---- -k:#foo - &a !t s ---- -k:#foo - &a !t s ---- -k:#foo - &a !t s - ---- # 3MYT -k:#foo - !t s ---- -k:#foo - !t s ---- -k:#foo - !t s ---- -k:#foo - !t s -)", - N(STREAM, L{ - N(DOCMAP, L{ - N("a", "1"), - N(KEYVAL, "b", {}), - N("c", AR(KEYANCH, "anchor"), "3"), - N(KEYVAL, "d", {}), - N(TS("!!str", "e"), "4"), - N(KEYVAL, "f", {}), - }), - - N(DOCVAL, "k:#foo &a !t s"), - N(DOCVAL|VALQUO, "k:#foo &a !t s"), - N(DOCVAL|VALQUO, "k:#foo &a !t s"), - - N(DOCVAL, "k:#foo &a !t s"), - N(DOCVAL, "k:#foo &a !t s"), - N(DOCVAL, "k:#foo &a !t s"), - N(DOCVAL, "k:#foo &a !t s"), - - N(DOCVAL, "k:#foo !t s"), - N(DOCVAL, "k:#foo !t s"), - N(DOCVAL, "k:#foo !t s"), - N(DOCVAL, "k:#foo !t s"), - }) - ); - -// make sure there is no ambiguity with this case -ADD_CASE_TO_GROUP("plain scalar, sequence ambiguity", -R"( -- - some text - - and this is a sequence -- some text - - and this is /not/ a sequence -- - some text - - and this is a sequence -- some text - - and this is /not/ a sequence -)", - L{ - N(L{N("some text"), N("and this is a sequence")}), - N("some text - and this is /not/ a sequence"), - N(L{N("some text"), N("and this is a sequence")}), - N("some text - and this is /not/ a sequence"), - } -); - -ADD_CASE_TO_GROUP("plain scalar, empty lines at the beginning", -R"( -- - - - Several lines of text, - with special:characters, like:this-or-this - - - and some "quotes" of various 'types'. -- - - Several lines of text, - with special:characters, like:this-or-this - - - and some "quotes" of various 'types'. -- - Several lines of text, - with special:characters, like:this-or-this - - - and some "quotes" of various 'types'. -)", - L{ - N("Several lines of text, with special:characters, like:this-or-this - - and some \"quotes\" of various 'types'."), - N("Several lines of text, with special:characters, like:this-or-this - - and some \"quotes\" of various 'types'."), - N("Several lines of text, with special:characters, like:this-or-this - - and some \"quotes\" of various 'types'."), - } -); - -ADD_CASE_TO_GROUP("plain scalar, empty continuation lines", -R"( -- the next lines have 2cols, 0cols, 2cols, - - - - and this line has some text in it. -> 0 - - now 0, 0, 2, 2, 0, 1, 1, 0, 4, 4, 0, 0 - - - - - - - - - - - - - and finally some more text -)", - L{ - N("the next lines have 2cols, 0cols, 2cols," - "\n\n\n" - "and this line has some text in it. -> 0" - "\n" - "now 0, 0, 2, 2, 0, 1, 1, 0, 4, 4, 0, 0" - "\n\n\n\n\n\n\n\n\n\n\n\n" - "and finally some more text"), - } -); - - -ADD_CASE_TO_GROUP("plain scalar, indented first line", -R"( -- Several lines of text, - - with special:characters, like:this-or-this - - - and some "quotes" of various 'types'. -- - - Several lines of text, - with special:characters, like:this-or-this - - - and some "quotes" of various 'types'. -- - Several lines of text, - with special:characters, like:this-or-this - - - and some "quotes" of various 'types'. -)", - L{ - N("Several lines of text,\nwith special:characters, like:this-or-this - - and some \"quotes\" of various 'types'."), - N("Several lines of text, with special:characters, like:this-or-this - - and some \"quotes\" of various 'types'."), - N("Several lines of text, with special:characters, like:this-or-this - - and some \"quotes\" of various 'types'."), - } -); - -ADD_CASE_TO_GROUP("plain scalar, do not accept ': ' mid line", EXPECT_PARSE_ERROR, -R"(- Several lines of text, - with special:characters, like:this-or-this - - - and some "quotes" of various 'types'. - But this: must cause a parse error. -)", - LineCol(4, 11) -); - -ADD_CASE_TO_GROUP("plain scalar, do not accept ': ' start line", EXPECT_PARSE_ERROR, -R"( -- Several lines of text, - with special:characters, like:this-or-this - - - and some "quotes" of various 'types'. - But this must cause a parse error - - : foo bar -)", - LineCol(6, 3) -); - -ADD_CASE_TO_GROUP("plain scalar, do not accept ': ' at line end", EXPECT_PARSE_ERROR, -R"(- Several lines of text, - with special:characters, like:this-or-this - - - and some "quotes" of various 'types'. - But this must cause a parse error: -)", - LineCol(4, 36) -); - -ADD_CASE_TO_GROUP("plain scalar, do not accept ':' at line end", EXPECT_PARSE_ERROR, -R"(- Several lines of text, - with special:characters, like:this-or-this - - - and some "quotes" of various 'types'. - But this must cause a parse error: - - well, did it? -)", - LineCol(4, 36) -); - -ADD_CASE_TO_GROUP("plain scalar, accept ' #' at line start", -R"(- Several lines of text, - and this is valid - - #with special:characters, like:this-or-this - -)", - L{N("Several lines of text, and this is valid -"),} -); - -ADD_CASE_TO_GROUP("plain scalar, accept ' #' on first line", -R"(- Several lines of text, and this is valid - - #with special:characters, like:this-or-this - -)", - L{N("Several lines of text, and this is valid -")} -); - -ADD_CASE_TO_GROUP("plain scalar, accept ' #' at line end", -R"(- Several lines of text, - with special:characters, #comment at the end -)", - L{N("Several lines of text, with special:characters,")} -); - -ADD_CASE_TO_GROUP("plain scalar, accept '#'", -R"( -- Several lines of text, # with a comment -- Several lines of text, - with special#characters, like#this_#_-or-#-:this - - - and some "quotes" of various 'types'. -)", - L{ - N("Several lines of text,"), - N("Several lines of text, " - "with special#characters, like#this_#_-or-#-:this - " - "- and some \"quotes\" of various 'types'."), - } -); - -ADD_CASE_TO_GROUP("plain scalar, explicit", -R"( -[ - a plain scalar - with several lines - - and blank lines - - as well - , - and another plain scalar - , - and yet another one - - - -with many lines - -and yet more, deindented -] -)", - L{ - N("a plain scalar with several lines\nand blank lines\nas well"), - N("and another plain scalar"), - N("and yet another one\n\n\nwith many lines\nand yet more"), - N("deindented"), - } -); - -ADD_CASE_TO_GROUP("plain scalar, explicit, early end, seq", EXPECT_PARSE_ERROR, -R"([ - a plain scalar - with several lines -)", - LineCol(4, 1) -); - -ADD_CASE_TO_GROUP("plain scalar, explicit, early end, map", EXPECT_PARSE_ERROR, -R"({foo: - a plain scalar - with several lines -)", - LineCol(4, 1) -); - -ADD_CASE_TO_GROUP("plain scalar, multiple docs", -R"(--- -- a plain scalar - with several lines ---- -- a second plain scalar - with several lines -)", - N(STREAM, L{ - N(DOCSEQ, L{N("a plain scalar with several lines")}), - N(DOCSEQ, L{N("a second plain scalar with several lines")}), - }) -); - -ADD_CASE_TO_GROUP("plain scalar, multiple docs, termination", -R"(--- -- a plain scalar - with several lines -... ---- -- a second plain scalar - with several lines -)", - N(STREAM, L{ - N(DOCSEQ, L{N("a plain scalar with several lines")}), - N(DOCSEQ, L{N("a second plain scalar with several lines")}), - }) -); - -ADD_CASE_TO_GROUP("plain scalar, trailing whitespace", - R"(--- -foo ---- -foo - ---- -foo - - - -)", - N(STREAM, L{ - N(DOCVAL, "foo"), - N(DOCVAL, "foo"), - N(DOCVAL, "foo"), - }) - ); -} - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_preprocess.cpp b/thirdparty/ryml/test/test_preprocess.cpp deleted file mode 100644 index 7f6719e5f..000000000 --- a/thirdparty/ryml/test/test_preprocess.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef RYML_SINGLE_HEADER -#include -#include -#endif -#include "./test_case.hpp" -#include - -namespace c4 { -namespace yml { - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -TEST(preprocess, rxmap_basic) -{ - #define _test(val, expected) \ - EXPECT_EQ(preprocess_rxmap(val), expected) - - _test("{}", "{}"); - _test("a", "{a: 1}"); - _test("{a}", "{a: 1}"); - _test("a, b, c", "{a: 1, b: 1, c: 1}"); - _test("a,b,c", "{a,b,c: 1}"); - _test("a a a a, b, c", "{a a a a: 1, b: 1, c: 1}"); - _test(",", "{,}"); - - _test("a: [b, c, d]", "{a: [b, c, d]}"); - _test("a:b: [b, c, d]", "{a:b: [b, c, d]}"); - _test("a,b: [b, c, d]", "{a,b: [b, c, d]}"); - _test("a: {b, c, d}", "{a: {b, c, d}}"); - _test("a: {b: {f, g}, c: {h, i}, d: {j, k}}", - "{a: {b: {f, g}, c: {h, i}, d: {j, k}}}"); - _test("a: {b: {f g}, c: {f g}, d: {j, k}}", - "{a: {b: {f g}, c: {f g}, d: {j, k}}}"); - - #undef _test -} - - - -// The other test executables are written to contain the declarative-style -// YmlTestCases. This executable does not have any but the build setup -// assumes it does, and links with the test lib, which requires an existing -// get_case() function. So this is here to act as placeholder until (if?) -// proper test cases are added here. -Case const* get_case(csubstr) -{ - return nullptr; -} - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_scalar_names.cpp b/thirdparty/ryml/test/test_scalar_names.cpp deleted file mode 100644 index b0d420349..000000000 --- a/thirdparty/ryml/test/test_scalar_names.cpp +++ /dev/null @@ -1,94 +0,0 @@ -#include "./test_group.hpp" - -#if defined(_MSC_VER) -# pragma warning(push) -//# pragma warning(disable: 4127/*conditional expression is constant*/) -//# pragma warning(disable: 4389/*'==': signed/unsigned mismatch*/) -#elif defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdollar-in-identifier-extension" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -#endif - -namespace c4 { -namespace yml { - -#define _(name) N(#name) // makes it simpler -#define __(name) N(#name, #name) // makes it simpler - -CASE_GROUP(SCALAR_NAMES) -{ - -ADD_CASE_TO_GROUP("funny names, seq", -R"( -- a -- b:b -- c{c -- cc{ -- c}c -- cc} -- c!c -- cc! -- .foo -- . -- -a -- +b -- /b -- :c -- $g -- "*" -- '*' -- >- - * -- "*a" -- '*a' -- >- - *a -)", -L{_(a), _(b:b), _(c{c), _(cc{), _(c}c), _(cc}), _(c!c), _(cc!), _(.foo), _(.), _(-a), _(+b), _(/b), _(:c), _($g), - N(QV, "*"), N(QV, "*"), N(QV, "*"), N(QV, "*a"), N(QV, "*a"), N(QV, "*a")} -); - -ADD_CASE_TO_GROUP("funny names, seq expl", -R"([a, b, c, .foo, ., -a, +b, /b, :c, $g])", -L{_(a), _(b), _(c), _(.foo), _(.), _(-a), _(+b), _(/b), _(:c), _($g)} -); - -ADD_CASE_TO_GROUP("funny names, map", -R"( -a: a -b: b -c: c -.foo: .foo -.: . --a: -a -+b: +b -/b: /b -:c: :c -$g: $g -'*': '*' -'*a': '*a' -)", -L{__(a), __(b), __(c), __(.foo), __(.), __(-a), __(+b), __(/b), __(:c), __($g), - N(QKV, "*", "*"), N(QKV, "*a", "*a")} -); - -ADD_CASE_TO_GROUP("funny names, map expl", -R"({a: a, b: b, c: c, .foo: .foo, .: ., -a: -a, +b: +b, /b: /b, :c: :c, $g: $g, - '*': '*', '*a':'*a'})", -L{__(a), __(b), __(c), __(.foo), __(.), __(-a), __(+b), __(/b), __(:c), __($g), - N(QKV, "*", "*"), N(QKV, "*a", "*a")} -); -} - -} // namespace yml -} // namespace c4 - -#if defined(_MSC_VER) -# pragma warning(pop) -#elif defined(__clang__) -# pragma clang diagnostic pop -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#endif diff --git a/thirdparty/ryml/test/test_seq_of_map.cpp b/thirdparty/ryml/test/test_seq_of_map.cpp deleted file mode 100644 index 90bbcbd79..000000000 --- a/thirdparty/ryml/test/test_seq_of_map.cpp +++ /dev/null @@ -1,348 +0,0 @@ -#include "./test_group.hpp" -#include "test_case.hpp" - -namespace c4 { -namespace yml { - -TEST(seq_of_map, with_anchors) -{ - { - // this case is vanilla: - csubstr yaml = R"(- a0: v0 - &a1 a1: v1 - &a2 a2: v2 - &a3 a3: v3 -- a0: w0 - *a1: w1 - *a2: w2 - *a3: w3 -- &seq - a4: v4 -)"; - Tree t = parse_in_arena(yaml); - EXPECT_EQ(emitrs_yaml(t), yaml); - ASSERT_EQ(t.rootref().num_children(), 3u); - ASSERT_EQ(t[2].has_val_anchor(), true); - ASSERT_EQ(t[2].val_anchor(), "seq"); - } - { - // but this case may fail because the indentation - // may be set from the scalar instead of the tag: - csubstr yaml = R"(- &a1 a1: v1 - &a2 a2: v2 - &a3 a3: v3 -- *a1: w1 - *a2: w2 - *a3: w3 -)"; - Tree t = parse_in_arena(yaml); - EXPECT_EQ(emitrs_yaml(t), yaml); - } -} - -TEST(seq_of_map, with_tags) -{ - { - // this case is vanilla: - csubstr yaml = R"(- a0: v0 - !!str a1: v1 - !!str a2: v2 - !!str a3: v3 -- a0: w0 - !!int a1: !!str w1 - !!int a2: !!str w2 - !!int a3: !!str w3 -- a0: v1 - !foo a1: v1 - !foo a2: v2 - !foo a3: v3 -)"; - Tree t = parse_in_arena(yaml); - EXPECT_EQ(emitrs_yaml(t), yaml); - } - { - // but this case may fail because the indentation - // may be set from the scalar instead of the tag: - csubstr yaml = R"(- !!str a1: v1 - !!str a2: v2 - !!str a3: v3 -- !!int a1: !!str w1 - !!int a2: !!str w2 - !!int a3: !!str w3 -- !foo a1: v1 - !foo a2: v2 - !foo a3: v3 -)"; - Tree t = parse_in_arena(yaml); - EXPECT_EQ(emitrs_yaml(t), yaml); - } -} - -TEST(seq_of_map, missing_scalars_v1) -{ - Tree t = parse_in_arena(R"(a: - - ~: ~ - - ~: ~ -)"); - #ifdef RYML_DBG - print_tree(t); - #endif - ASSERT_EQ(t["a"].num_children(), 2u); - ASSERT_EQ(t["a"][0].num_children(), 1u); - EXPECT_EQ(t["a"][0].first_child().key(), "~"); - EXPECT_EQ(t["a"][0].first_child().val(), "~"); - ASSERT_EQ(t["a"][1].num_children(), 1u); - EXPECT_EQ(t["a"][1].first_child().key(), "~"); - EXPECT_EQ(t["a"][1].first_child().val(), "~"); -} - -TEST(seq_of_map, missing_scalars_v2) -{ - Tree t = parse_in_arena(R"(a: - - : - - : -)"); - #ifdef RYML_DBG - print_tree(t); - #endif - ASSERT_EQ(t["a"].num_children(), 2u); - ASSERT_EQ(t["a"][0].num_children(), 1u); - EXPECT_EQ(t["a"][0].first_child().key(), nullptr); - EXPECT_EQ(t["a"][0].first_child().val(), nullptr); - ASSERT_EQ(t["a"][1].num_children(), 1u); - EXPECT_EQ(t["a"][1].first_child().key(), nullptr); - EXPECT_EQ(t["a"][1].first_child().val(), nullptr); -} - -TEST(seq_of_map, missing_scalars_v3) -{ - Tree t = parse_in_arena(R"(a: - - : - - : -)"); - #ifdef RYML_DBG - print_tree(t); - #endif - ASSERT_EQ(t["a"].num_children(), 2u); - ASSERT_EQ(t["a"][0].num_children(), 1u); - EXPECT_EQ(t["a"][0].first_child().key(), nullptr); - EXPECT_EQ(t["a"][0].first_child().val(), nullptr); - ASSERT_EQ(t["a"][1].num_children(), 1u); - EXPECT_EQ(t["a"][1].first_child().key(), nullptr); - EXPECT_EQ(t["a"][1].first_child().val(), nullptr); -} - -#ifdef RYML_WITH_TAB_TOKENS -TEST(seq_of_map, test_suite_6BCT) -{ - Tree t = parse_in_arena(R"( -- foo0: bar0 -- foo1 : bar1 -- foo2 : bar2 -)"); - #ifdef RYML_DBG - print_tree(t); - #endif - ASSERT_TRUE(t[0].is_map()); - ASSERT_TRUE(t[1].is_map()); - ASSERT_TRUE(t[2].is_map()); - EXPECT_EQ(t[0]["foo0"].val(), csubstr("bar0")); - EXPECT_EQ(t[1]["foo1"].val(), csubstr("bar1")); - EXPECT_EQ(t[2]["foo2"].val(), csubstr("bar2")); -} -#endif - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - - -CASE_GROUP(SEQ_OF_MAP) -{ - -ADD_CASE_TO_GROUP("seq of empty maps, one line", -R"([{}, {}, {}])", - L{MAP, MAP, MAP} -); - -ADD_CASE_TO_GROUP("seq of maps, one line", -R"([{name: John Smith, age: 33}, {name: Mary Smith, age: 27}])", - L{ - N{L{N("name", "John Smith"), N("age", "33")}}, - N{L{N("name", "Mary Smith"), N("age", "27")}} - } -); - -ADD_CASE_TO_GROUP("seq of maps, implicit seq, explicit maps", -R"( -- {name: John Smith, age: 33} -- {name: Mary Smith, age: 27} -)", - L{ - N{L{N("name", "John Smith"), N("age", "33")}}, - N{L{N("name", "Mary Smith"), N("age", "27")}} - } -); - -ADD_CASE_TO_GROUP("seq of maps", -R"( -- name: John Smith - age: 33 -- name: Mary Smith - age: 27 -)", - L{ - N{L{N("name", "John Smith"), N("age", "33")}}, - N{L{N("name", "Mary Smith"), N("age", "27")}} - } -); - -ADD_CASE_TO_GROUP("seq of maps, next line", -R"( -- - name: - John Smith - age: - 33 -- - name: - Mary Smith - age: - 27 -)", - L{ - N{L{N("name", "John Smith"), N("age", "33")}}, - N{L{N("name", "Mary Smith"), N("age", "27")}} - } -); - -ADD_CASE_TO_GROUP("seq of maps, bug #32 ex1", -R"( -- 'a': 1 - b: 2 -)", - L{ - N{L{N(QK, "a", "1"), N("b", "2")}} - } -); - -ADD_CASE_TO_GROUP("seq of maps, bug #32 ex2", -R"( -- a: 1 - b: 2 -- b: 2 - 'a': 1 -- b: 2 - 'a': 1 - c: 3 -- {'a': 1, b: 2} -)", - L{ - N{L{N("a", "1"), N("b", "2")}}, - N{L{N("b", "2"), N(QK, "a", "1")}}, - N{L{N("b", "2"), N(QK, "a", "1"), N("c", "3")}}, - N{L{N(QK, "a", "1"), N("b", "2")}}, - } -); - -ADD_CASE_TO_GROUP("seq of maps, bug #32 ex3", -R"( -'a': 1 -b: 2 -b: 2 -'a': 1 -)", -L{ - N(QK, "a", "1"), N("b", "2"), N("b", "2"), N(QK, "a", "1"), -}); - - -ADD_CASE_TO_GROUP("seq of maps, implicit map in seq", -R"('implicit block key' : [ - 'implicit flow key 1' : value1, - 'implicit flow key 2' : value2, - 'implicit flow key 3' : value3, - 'implicit flow key m' : {key1: val1, key2: val2}, - 'implicit flow key s' : [val1, val2], -])", -L{N(KEYSEQ|KEYQUO, "implicit block key", L{ - N(L{N(KEYVAL|KEYQUO, "implicit flow key 1", "value1")}), - N(L{N(KEYVAL|KEYQUO, "implicit flow key 2", "value2")}), - N(L{N(KEYVAL|KEYQUO, "implicit flow key 3", "value3")}), - N(L{N(KEYMAP|KEYQUO, "implicit flow key m", L{N("key1", "val1"), N("key2", "val2")})}), - N(L{N(KEYSEQ|KEYQUO, "implicit flow key s", L{N("val1"), N("val2")})}), -})}); - - -ADD_CASE_TO_GROUP("seq of maps, implicit map in seq, missing scalar", -R"({a : [ - : foo -], -b : [ - : -foo -], -c : [ - : -, - : -]})", -L{ - N("a", L{N(MAP, L{N("", "foo")}),}), - N("b", L{N(MAP, L{N("", "foo")}),}), - N("c", L{N(MAP, L{N(KEYVAL, "", {})}), N(MAP, L{N(KEYVAL, "", {})}),}), -}); - - -ADD_CASE_TO_GROUP("seq of maps, implicit with anchors, unresolved", -R"( -- &a1 a1: v1 - &a2 a2: v2 - &a3 a3: v3 -- *a1: w1 - *a2: w2 - *a3: w3 -)", -L{ - N(L{N( "a1", AR(KEYANCH, "a1"), "v1"), N( "a2", AR(KEYANCH, "a2"), "v2"), N( "a3", AR(KEYANCH, "a3"), "v3")}), - N(L{N("*a1", AR(KEYREF, "*a1"), "w1"), N("*a2", AR(KEYREF, "*a2"), "w2"), N("*a3", AR(KEYREF, "*a3"), "w3")}), -}); - - -ADD_CASE_TO_GROUP("seq of maps, implicit with anchors, resolved", RESOLVE_REFS, -R"( -- &a1 a1: v1 - &a2 a2: v2 - &a3 a3: v3 -- *a1: w1 - *a2: w2 - *a3: w3 -)", -L{ - N(L{N("a1", "v1"), N("a2", "v2"), N("a3", "v3")}), - N(L{N("a1", "w1"), N("a2", "w2"), N("a3", "w3")}), -}); - - -ADD_CASE_TO_GROUP("seq of maps, implicit with tags", -R"( -- !!str a1: v1 - !!str a2: v2 - !!str a3: v3 -- a1: !!str w1 - a2: !!str w2 - a3: !!str w3 -- !foo a1: v1 - !foo a2: v2 - !foo a3: v3 -)", -L{ - N(L{N(TS("!!str", "a1"), "v1"), N(TS("!!str", "a2"), "v2"), N(TS("!!str", "a3"), "v3")}), - N(L{N("a1", TS("!!str", "w1")), N("a2", TS("!!str", "w2")), N("a3", TS("!!str", "w3"))}), - N(L{N(TS("!foo", "a1"), "v1"), N(TS("!foo", "a2"), "v2"), N(TS("!foo", "a3"), "v3")}), -}); -} - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_serialize.cpp b/thirdparty/ryml/test/test_serialize.cpp deleted file mode 100644 index 979de7c79..000000000 --- a/thirdparty/ryml/test/test_serialize.cpp +++ /dev/null @@ -1,499 +0,0 @@ -#ifndef RYML_SINGLE_HEADER -#include "c4/yml/std/std.hpp" -#include "c4/yml/parse.hpp" -#include "c4/yml/emit.hpp" -#include -#include -#include -#endif - -#include "./test_case.hpp" - -#include - -#if defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable: 4389) // signed/unsigned mismatch -#elif defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdollar-in-identifier-extension" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -#endif - -namespace foo { - -template -struct vec2 -{ - T x, y; -}; -template -struct vec3 -{ - T x, y, z; -}; -template -struct vec4 -{ - T x, y, z, w; -}; - -template size_t to_chars(c4::substr buf, vec2 v) { return c4::format(buf, "({},{})", v.x, v.y); } -template size_t to_chars(c4::substr buf, vec3 v) { return c4::format(buf, "({},{},{})", v.x, v.y, v.z); } -template size_t to_chars(c4::substr buf, vec4 v) { return c4::format(buf, "({},{},{},{})", v.x, v.y, v.z, v.w); } - -template bool from_chars(c4::csubstr buf, vec2 *v) { size_t ret = c4::unformat(buf, "({},{})", v->x, v->y); return ret != c4::yml::npos; } -template bool from_chars(c4::csubstr buf, vec3 *v) { size_t ret = c4::unformat(buf, "({},{},{})", v->x, v->y, v->z); return ret != c4::yml::npos; } -template bool from_chars(c4::csubstr buf, vec4 *v) { size_t ret = c4::unformat(buf, "({},{},{},{})", v->x, v->y, v->z, v->w); return ret != c4::yml::npos; } - -TEST(serialize, type_as_str) -{ - c4::yml::Tree t; - - auto r = t.rootref(); - r |= c4::yml::MAP; - - vec2 v2in{10, 11}; - vec2 v2out{1, 2}; - r["v2"] << v2in; - r["v2"] >> v2out; - EXPECT_EQ(v2in.x, v2out.x); - EXPECT_EQ(v2in.y, v2out.y); - - vec3 v3in{100, 101, 102}; - vec3 v3out{1, 2, 3}; - r["v3"] << v3in; - r["v3"] >> v3out; - EXPECT_EQ(v3in.x, v3out.x); - EXPECT_EQ(v3in.y, v3out.y); - EXPECT_EQ(v3in.z, v3out.z); - - vec4 v4in{1000, 1001, 1002, 1003}; - vec4 v4out{1, 2, 3, 4}; - r["v4"] << v4in; - r["v4"] >> v4out; - EXPECT_EQ(v4in.x, v4out.x); - EXPECT_EQ(v4in.y, v4out.y); - EXPECT_EQ(v4in.z, v4out.z); - EXPECT_EQ(v4in.w, v4out.w); - - char buf[256]; - c4::csubstr ret = c4::yml::emit_yaml(t, buf); - EXPECT_EQ(ret, R"(v2: '(10,11)' -v3: '(100,101,102)' -v4: '(1000,1001,1002,1003)' -)"); -} -} // namespace foo - - -namespace c4 { -namespace yml { - -//------------------------------------------- -template -void do_test_serialize(Args&& ...args) -{ - using namespace c4::yml; - Container s(std::forward(args)...); - Container out; - - Tree t; - NodeRef n(&t); - - n << s; - //print_tree(t); - emit_yaml(t); - c4::yml::check_invariants(t); - n >> out; - EXPECT_EQ(s, out); -} - - -TEST(serialize, std_vector_int) -{ - using T = int; - using L = std::initializer_list; - do_test_serialize>(L{1, 2, 3, 4, 5}); -} -TEST(serialize, std_vector_bool) -{ - using T = bool; - using L = std::initializer_list; - do_test_serialize>(L{true, false, true, false, true, true}); -} -TEST(serialize, std_vector_string) -{ - using T = std::string; - using L = std::initializer_list; - do_test_serialize>(L{"0asdadk0", "1sdfkjdfgu1", "2fdfdjkhdfgkjhdfi2", "3e987dfgnfdg83", "4'd0fgºçdfg«4"}); -} -TEST(serialize, std_vector_std_vector_int) -{ - using T = std::vector; - using L = std::initializer_list; - do_test_serialize>(L{{1, 2, 3, 4, 5}, {6, 7, 8, 9, 0}}); -} - - -TEST(serialize, std_map__int_int) -{ - using M = std::map; - using L = std::initializer_list; - do_test_serialize(L{{10, 0}, {11, 1}, {22, 2}, {10001, 1000}, {20002, 2000}, {30003, 3000}}); -} -TEST(serialize, std_map__std_string_int) -{ - using M = std::map; - using L = std::initializer_list; - do_test_serialize(L{{"asdsdf", 0}, {"dfgdfgdfg", 1}, {"dfgjdfgkjh", 2}}); -} -TEST(serialize, std_map__string_vectori) -{ - using M = std::map>; - using L = std::initializer_list; - do_test_serialize(L{{"asdsdf", {0, 1, 2, 3}}, {"dfgdfgdfg", {4, 5, 6, 7}}, {"dfgjdfgkjh", {8, 9, 10, 11}}}); -} -TEST(serialize, std_vector__map_string_int) -{ - using V = std::vector< std::map>; - using M = typename V::value_type; - using L = std::initializer_list; - do_test_serialize(L{ - M{{"asdasf", 0}, {"dfgkjhdfg", 1}, {"fghffg", 2}, {"r5656kjnh9b'dfgwg+*", 3}}, - M{{"asdasf", 10}, {"dfgkjhdfg", 11}, {"fghffg", 12}, {"r5656kjnh9b'dfgwg+*", 13}}, - M{{"asdasf", 20}, {"dfgkjhdfg", 21}, {"fghffg", 22}, {"r5656kjnh9b'dfgwg+*", 23}}, - M{{"asdasf", 30}, {"dfgkjhdfg", 31}, {"fghffg", 32}, {"r5656kjnh9b'dfgwg+*", 33}}, - }); -} - - -TEST(serialize, bool) -{ - Tree t = parse_in_arena("{a: 0, b: false, c: 1, d: true}"); - bool v, w; - t["a"] >> v; - EXPECT_EQ(v, false); - t["b"] >> v; - EXPECT_EQ(v, false); - t["c"] >> v; - EXPECT_EQ(v, true); - t["d"] >> v; - EXPECT_EQ(v, true); - - t["e"] << true; - EXPECT_EQ(t["e"].val(), "1"); - t["e"] >> w; - EXPECT_EQ(w, true); - - t["e"] << false; - EXPECT_EQ(t["e"].val(), "0"); - t["e"] >> w; - EXPECT_EQ(w, false); - - t["e"] << fmt::boolalpha(true); - EXPECT_EQ(t["e"].val(), "true"); - t["e"] >> w; - EXPECT_EQ(w, true); - - t["e"] << fmt::boolalpha(false); - EXPECT_EQ(t["e"].val(), "false"); - t["e"] >> w; - EXPECT_EQ(w, false); -} - -TEST(serialize, nan) -{ - Tree t = parse_in_arena(R"( -good: - - .nan - - .nan - - .NaN - - .NAN - - nan - - - .nan -set: - - nothing - - nothing -})"); - t["set"][0] << std::numeric_limits::quiet_NaN(); - t["set"][1] << std::numeric_limits::quiet_NaN(); - EXPECT_EQ(t["set"][0].val(), ".nan"); - EXPECT_EQ(t["set"][1].val(), ".nan"); - EXPECT_EQ(t["good"][0].val(), ".nan"); - EXPECT_EQ(t["good"][1].val(), ".nan"); - EXPECT_EQ(t["good"][2].val(), ".NaN"); - EXPECT_EQ(t["good"][3].val(), ".NAN"); - EXPECT_EQ(t["good"][4].val(), "nan"); - EXPECT_EQ(t["good"][5].val(), ".nan"); - float f; - double d; - f = 0.f; - d = 0.; - t["good"][0] >> f; - t["good"][0] >> d; - EXPECT_TRUE(std::isnan(f)); - EXPECT_TRUE(std::isnan(d)); - f = 0.f; - d = 0.; - t["good"][1] >> f; - t["good"][1] >> d; - EXPECT_TRUE(std::isnan(f)); - EXPECT_TRUE(std::isnan(d)); - f = 0.f; - d = 0.; - t["good"][2] >> f; - t["good"][2] >> d; - EXPECT_TRUE(std::isnan(f)); - EXPECT_TRUE(std::isnan(d)); - f = 0.f; - d = 0.; - t["good"][3] >> f; - t["good"][3] >> d; - EXPECT_TRUE(std::isnan(f)); - EXPECT_TRUE(std::isnan(d)); - f = 0.f; - d = 0.; - t["good"][4] >> f; - t["good"][4] >> d; - EXPECT_TRUE(std::isnan(f)); - EXPECT_TRUE(std::isnan(d)); - f = 0.f; - d = 0.; - t["good"][5] >> f; - t["good"][5] >> d; - EXPECT_TRUE(std::isnan(f)); - EXPECT_TRUE(std::isnan(d)); -} - -TEST(serialize, inf) -{ - C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH("-Wfloat-equal"); - Tree t = parse_in_arena(R"( -good: - - .inf - - .inf - - .Inf - - .INF - - inf - - infinity - - - .inf -set: - - nothing - - nothing -})"); - float finf = std::numeric_limits::infinity(); - double dinf = std::numeric_limits::infinity(); - t["set"][0] << finf; - t["set"][1] << dinf; - EXPECT_EQ(t["set"][0].val(), ".inf"); - EXPECT_EQ(t["set"][1].val(), ".inf"); - EXPECT_EQ(t["good"][0].val(), ".inf"); - EXPECT_EQ(t["good"][1].val(), ".inf"); - EXPECT_EQ(t["good"][2].val(), ".Inf"); - EXPECT_EQ(t["good"][3].val(), ".INF"); - EXPECT_EQ(t["good"][4].val(), "inf"); - EXPECT_EQ(t["good"][5].val(), "infinity"); - EXPECT_EQ(t["good"][6].val(), ".inf"); - float f; - double d; - f = 0.f; - d = 0.; - t["good"][0] >> f; - t["good"][0] >> d; - EXPECT_TRUE(f == finf); - EXPECT_TRUE(d == dinf); - f = 0.f; - d = 0.; - t["good"][1] >> f; - t["good"][1] >> d; - EXPECT_TRUE(f == finf); - EXPECT_TRUE(d == dinf); - f = 0.f; - d = 0.; - t["good"][2] >> f; - t["good"][2] >> d; - EXPECT_TRUE(f == finf); - EXPECT_TRUE(d == dinf); - f = 0.f; - d = 0.; - t["good"][3] >> f; - t["good"][3] >> d; - EXPECT_TRUE(f == finf); - EXPECT_TRUE(d == dinf); - f = 0.f; - d = 0.; - t["good"][4] >> f; - t["good"][4] >> d; - EXPECT_TRUE(f == finf); - EXPECT_TRUE(d == dinf); - f = 0.f; - d = 0.; - t["good"][5] >> f; - t["good"][5] >> d; - EXPECT_TRUE(f == finf); - EXPECT_TRUE(d == dinf); - f = 0.f; - d = 0.; - t["good"][6] >> f; - t["good"][6] >> d; - EXPECT_TRUE(f == finf); - EXPECT_TRUE(d == dinf); - - t = parse_in_arena(R"( -good: - - -.inf - - -.inf - - -.Inf - - -.INF - - -inf - - -infinity - - - -.inf -set: - - nothing - - nothing -})"); - t["set"][0] << -finf; - t["set"][1] << -dinf; - EXPECT_EQ(t["set"][0].val(), "-.inf"); - EXPECT_EQ(t["set"][1].val(), "-.inf"); - EXPECT_EQ(t["good"][0].val(), "-.inf"); - EXPECT_EQ(t["good"][1].val(), "-.inf"); - EXPECT_EQ(t["good"][2].val(), "-.Inf"); - EXPECT_EQ(t["good"][3].val(), "-.INF"); - EXPECT_EQ(t["good"][4].val(), "-inf"); - EXPECT_EQ(t["good"][5].val(), "-infinity"); - EXPECT_EQ(t["good"][6].val(), "-.inf"); - f = 0.f; - d = 0.; - t["good"][0] >> f; - t["good"][0] >> d; - EXPECT_TRUE(f == -finf); - EXPECT_TRUE(d == -dinf); - f = 0.f; - d = 0.; - t["good"][1] >> f; - t["good"][1] >> d; - EXPECT_TRUE(f == -finf); - EXPECT_TRUE(d == -dinf); - f = 0.f; - d = 0.; - t["good"][2] >> f; - t["good"][2] >> d; - EXPECT_TRUE(f == -finf); - EXPECT_TRUE(d == -dinf); - f = 0.f; - d = 0.; - t["good"][3] >> f; - t["good"][3] >> d; - EXPECT_TRUE(f == -finf); - EXPECT_TRUE(d == -dinf); - f = 0.f; - d = 0.; - t["good"][4] >> f; - t["good"][4] >> d; - EXPECT_TRUE(f == -finf); - EXPECT_TRUE(d == -dinf); - f = 0.f; - d = 0.; - t["good"][5] >> f; - t["good"][5] >> d; - EXPECT_TRUE(f == -finf); - EXPECT_TRUE(d == -dinf); - f = 0.f; - d = 0.; - t["good"][6] >> f; - t["good"][6] >> d; - EXPECT_TRUE(f == -finf); - EXPECT_TRUE(d == -dinf); - C4_SUPPRESS_WARNING_GCC_CLANG_POP -} - -TEST(serialize, std_string) -{ - auto t = parse_in_arena("{foo: bar}"); - std::string s; - EXPECT_NE(s, "bar"); - t["foo"] >> s; - EXPECT_EQ(s, "bar"); -} - -TEST(serialize, anchor_and_ref_round_trip) -{ - const char yaml[] = R"(anchor_objects: - - &id001 - name: id001 - - &id002 - name: id002 - - name: id003 - - &id004 - name: id004 -references: - reference_key: *id001 - reference_list: - - *id002 - - *id004 -)"; - - Tree t = parse_in_arena(yaml); - std::string cmpbuf; - emitrs_yaml(t, &cmpbuf); - EXPECT_EQ(cmpbuf, yaml); -} - -TEST(serialize, create_anchor_ref_trip) -{ - const char expected_yaml[] = R"(anchor_objects: - - &id001 - name: a_name -reference_list: - - *id001 -)"; - - Tree tree; - auto root_id = tree.root_id(); - tree.to_map(root_id); - - auto anchor_list_id = tree.append_child(root_id); - tree.to_seq(anchor_list_id, "anchor_objects"); - - auto anchor_map0 = tree.append_child(anchor_list_id); - tree.to_map(anchor_map0); - tree.set_val_anchor(anchor_map0, "id001"); - - auto anchor_elem0 = tree.append_child(anchor_map0); - tree.to_keyval(anchor_elem0, "name", "a_name"); - - auto ref_list_id = tree.append_child(root_id); - tree.to_seq(ref_list_id, "reference_list"); - - auto elem0_id = tree.append_child(ref_list_id); - tree.set_val_ref(elem0_id, "id001"); - - std::string cmpbuf; - emitrs_yaml(tree, &cmpbuf); - EXPECT_EQ(cmpbuf, expected_yaml); -} - - -//------------------------------------------- -// this is needed to use the test case library -Case const* get_case(csubstr /*name*/) -{ - return nullptr; -} - -} // namespace yml -} // namespace c4 - -#if defined(_MSC_VER) -# pragma warning(pop) -#elif defined(__clang__) -# pragma clang diagnostic pop -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#endif diff --git a/thirdparty/ryml/test/test_simple_anchor.cpp b/thirdparty/ryml/test/test_simple_anchor.cpp deleted file mode 100644 index 0ee4a629f..000000000 --- a/thirdparty/ryml/test/test_simple_anchor.cpp +++ /dev/null @@ -1,1405 +0,0 @@ -#include "./test_group.hpp" - -namespace c4 { -namespace yml { - -TEST(anchors, circular) -{ - Tree t = parse_in_arena(R"(&x -- *x -)"); - ASSERT_TRUE(t.rootref().is_val_anchor()); - ASSERT_TRUE(t[0].is_val_ref()); - EXPECT_EQ(t.rootref().val_anchor(), "x"); - EXPECT_EQ(t[0].val_ref(), "x"); -} - -TEST(anchors, node_scalar_set_ref_when_empty) -{ - { - NodeScalar ns; - ns.set_ref_maybe_replacing_scalar("foo", /*has_scalar*/false); - EXPECT_EQ(ns.scalar, "foo"); - EXPECT_EQ(ns.anchor, "foo"); - } - { - NodeScalar ns; - ns.set_ref_maybe_replacing_scalar("*foo", /*has_scalar*/false); - EXPECT_EQ(ns.scalar, "*foo"); - EXPECT_EQ(ns.anchor, "foo"); - } -} - -TEST(anchors, node_scalar_set_ref_when_non_empty) -{ - { - NodeScalar ns; - ns.scalar = "whatever"; - ns.set_ref_maybe_replacing_scalar("foo", /*has_scalar*/true); - EXPECT_EQ(ns.scalar, "foo"); - EXPECT_EQ(ns.anchor, "foo"); - } - { - NodeScalar ns; - ns.scalar = "whatever"; - ns.set_ref_maybe_replacing_scalar("*foo", /*has_scalar*/true); - EXPECT_EQ(ns.scalar, "*foo"); - EXPECT_EQ(ns.anchor, "foo"); - ns.set_ref_maybe_replacing_scalar("foo", /*has_scalar*/true); - EXPECT_EQ(ns.scalar, "*foo"); // keep the previous as it is well formed - EXPECT_EQ(ns.anchor, "foo"); - ns.set_ref_maybe_replacing_scalar("bar", /*has_scalar*/true); - EXPECT_EQ(ns.scalar, "bar"); // replace previous as it is not well formed - EXPECT_EQ(ns.anchor, "bar"); - } -} - -TEST(anchors, no_ambiguity_when_key_scalars_begin_with_star) -{ - Tree t = parse_in_arena("{foo: &foo 1, *foo: 2, '*foo': 3}"); - - EXPECT_TRUE(t[1].is_key_ref()); - EXPECT_FALSE(t[2].is_key_ref()); - - EXPECT_FALSE(t[1].is_key_quoted()); - EXPECT_TRUE(t[2].is_key_quoted()); - - EXPECT_EQ(t[1].key(), "*foo"); - EXPECT_EQ(t[1].key_ref(), "foo"); - EXPECT_EQ(t[2].key(), "*foo"); - - EXPECT_EQ(emitrs_yaml(t), R"(foo: &foo 1 -*foo: 2 -'*foo': 3 -)"); - - t.resolve(); - - EXPECT_EQ(emitrs_yaml(t), R"(foo: 1 -1: 2 -'*foo': 3 -)"); -} - -TEST(anchors, no_ambiguity_when_val_scalars_begin_with_star) -{ - Tree t = parse_in_arena("{foo: &foo 1, ref: *foo, quo: '*foo'}"); - - EXPECT_TRUE(t["ref"].is_val_ref()); - EXPECT_FALSE(t["quo"].is_val_ref()); - - EXPECT_FALSE(t["ref"].is_val_quoted()); - EXPECT_TRUE(t["quo"].is_val_quoted()); - - EXPECT_EQ(t["ref"].val_ref(), "foo"); - EXPECT_EQ(t["ref"].val(), "*foo"); - EXPECT_EQ(t["quo"].val(), "*foo"); - - EXPECT_EQ(emitrs_yaml(t), R"(foo: &foo 1 -ref: *foo -quo: '*foo' -)"); - - t.resolve(); - - EXPECT_EQ(emitrs_yaml(t), R"(foo: 1 -ref: 1 -quo: '*foo' -)"); -} - -TEST(anchors, no_ambiguity_with_inheritance) -{ - Tree t = parse_in_arena("{foo: &foo {a: 1, b: 2}, bar: {<<: *foo}, sq: {'<<': haha}, dq: {\"<<\": hehe}}"); - - EXPECT_TRUE(t["bar"].has_child("<<")); - EXPECT_TRUE(t["bar"]["<<"].is_key_ref()); - EXPECT_TRUE(t["bar"]["<<"].is_val_ref()); - EXPECT_TRUE(t["sq"]["<<"].is_key_quoted()); - EXPECT_TRUE(t["dq"]["<<"].is_key_quoted()); - EXPECT_FALSE(t["sq"]["<<"].is_key_ref()); - EXPECT_FALSE(t["dq"]["<<"].is_key_ref()); - EXPECT_EQ(t["sq"]["<<"].key(), "<<"); - EXPECT_EQ(t["dq"]["<<"].key(), "<<"); - EXPECT_EQ(t["bar"]["<<"].key(), "<<"); - EXPECT_EQ(t["bar"]["<<"].val(), "*foo"); - EXPECT_EQ(t["bar"]["<<"].key_ref(), "<<"); - EXPECT_EQ(t["bar"]["<<"].val_ref(), "foo"); - - EXPECT_EQ(emitrs_yaml(t), R"(foo: &foo - a: 1 - b: 2 -bar: - <<: *foo -sq: - '<<': haha -dq: - '<<': hehe -)"); - t.resolve(); - EXPECT_EQ(emitrs_yaml(t), R"(foo: - a: 1 - b: 2 -bar: - a: 1 - b: 2 -sq: - '<<': haha -dq: - '<<': hehe -)"); -} - -TEST(anchors, programatic_key_ref) -{ - Tree t = parse_in_arena("{}"); - NodeRef r = t.rootref(); - r["kanchor"] = "2"; - r["kanchor"].set_key_anchor("kanchor"); - r["vanchor"] = "3"; - r["vanchor"].set_val_anchor("vanchor"); - r["*kanchor"] = "4"; - r["*vanchor"] = "5"; - NodeRef ch = r.append_child(); - ch.set_key_ref("kanchor"); - ch.set_val("6"); - ch = r.append_child(); - ch.set_key_ref("vanchor"); - ch.set_val("7"); - EXPECT_EQ(emitrs_yaml(t), R"(&kanchor kanchor: 2 -vanchor: &vanchor 3 -'*kanchor': 4 -'*vanchor': 5 -*kanchor: 6 -*vanchor: 7 -)"); - t.resolve(); - EXPECT_EQ(emitrs_yaml(t), R"(kanchor: 2 -vanchor: 3 -'*kanchor': 4 -'*vanchor': 5 -kanchor: 6 -3: 7 -)"); -} - -TEST(anchors, programatic_val_ref) -{ - Tree t = parse_in_arena("{}"); - t["kanchor"] = "2"; - t["kanchor"].set_key_anchor("kanchor"); - t["vanchor"] = "3"; - t["vanchor"].set_val_anchor("vanchor"); - - t["kref"].create(); - t["vref"].create(); - t["kref"].set_val_ref("kanchor"); - t["vref"].set_val_ref("vanchor"); - - EXPECT_EQ(emitrs_yaml(t), R"(&kanchor kanchor: 2 -vanchor: &vanchor 3 -kref: *kanchor -vref: *vanchor -)"); - t.resolve(); - EXPECT_EQ(emitrs_yaml(t), R"(kanchor: 2 -vanchor: 3 -kref: kanchor -vref: 3 -)"); -} - -TEST(anchors, programatic_inheritance) -{ - Tree t = parse_in_arena("{orig: &orig {foo: bar, baz: bat}, copy: {}, notcopy: {}, notref: {}}"); - - t["copy"]["<<"] = "*orig"; - t["copy"]["<<"].set_key_ref("<<"); - t["copy"]["<<"].set_val_ref("orig"); - - t["notcopy"]["test"] = "*orig"; - t["notcopy"]["test"].set_val_ref("orig"); - t["notcopy"]["<<"] = "*orig"; - t["notcopy"]["<<"].set_val_ref("orig"); - - t["notref"]["<<"] = "*orig"; - - EXPECT_EQ(emitrs_yaml(t), R"(orig: &orig - foo: bar - baz: bat -copy: - <<: *orig -notcopy: - test: *orig - '<<': *orig -notref: - '<<': '*orig' -)"); - t.resolve(); - EXPECT_EQ(emitrs_yaml(t), R"(orig: - foo: bar - baz: bat -copy: - foo: bar - baz: bat -notcopy: - test: - foo: bar - baz: bat - '<<': - foo: bar - baz: bat -notref: - '<<': '*orig' -)"); -} - -TEST(anchors, programatic_multiple_inheritance) -{ - Tree t = parse_in_arena("{orig1: &orig1 {foo: bar}, orig2: &orig2 {baz: bat}, orig3: &orig3 {and: more}, copy: {}}"); - - t["copy"]["<<"] |= SEQ; - t["copy"]["<<"].set_key_ref("<<"); - NodeRef ref1 = t["copy"]["<<"].append_child(); - NodeRef ref2 = t["copy"]["<<"].append_child(); - NodeRef ref3 = t["copy"]["<<"].append_child(); - ref1 = "*orig1"; - ref2 = "*orig2"; - ref3 = "*orig3"; - ref1.set_val_ref("orig1"); - ref2.set_val_ref("orig2"); - ref3.set_val_ref("orig3"); - - EXPECT_EQ(emitrs_yaml(t), R"(orig1: &orig1 - foo: bar -orig2: &orig2 - baz: bat -orig3: &orig3 - and: more -copy: - <<: - - *orig1 - - *orig2 - - *orig3 -)"); - t.resolve(); - EXPECT_EQ(emitrs_yaml(t), R"(orig1: - foo: bar -orig2: - baz: bat -orig3: - and: more -copy: - foo: bar - baz: bat - and: more -)"); -} - -TEST(anchors, set_anchor_leading_ampersand_is_optional) -{ - Tree t = parse_in_arena("{without: 0, with: 1}"); - - t["without"].set_key_anchor("without"); - t["with"].set_key_anchor("&with"); - EXPECT_EQ(t["without"].key_anchor(), "without"); - EXPECT_EQ(t["with"].key_anchor(), "with"); - EXPECT_EQ(emitrs_yaml(t), R"(&without without: 0 -&with with: 1 -)"); - - t["without"].set_val_anchor("without"); - t["with"].set_val_anchor("&with"); - EXPECT_EQ(t["without"].val_anchor(), "without"); - EXPECT_EQ(t["with"].val_anchor(), "with"); - EXPECT_EQ(emitrs_yaml(t), R"(&without without: &without 0 -&with with: &with 1 -)"); -} - -TEST(anchors, set_ref_leading_star_is_optional) -{ - Tree t = parse_in_arena("{}"); - - t["*without"] = "0"; - t["*with"] = "1"; - EXPECT_EQ(emitrs_yaml(t), R"('*without': 0 -'*with': 1 -)"); - - t["*without"].set_key_ref("without"); - t["*with"].set_key_ref("*with"); - EXPECT_EQ(t["*without"].key_ref(), "without"); - EXPECT_EQ(t["*with"].key_ref(), "with"); - EXPECT_EQ(emitrs_yaml(t), R"(*without: 0 -*with: 1 -)"); - - t["*without"].set_val_ref("without"); - t["*with"].set_val_ref("*with"); - EXPECT_EQ(t["*without"].val_ref(), "without"); - EXPECT_EQ(t["*with"].val_ref(), "with"); - EXPECT_EQ(emitrs_yaml(t), R"(*without: *without -*with: *with -)"); -} - -TEST(anchors, set_key_ref_also_sets_the_key_when_none_exists) -{ - Tree t = parse_in_arena("{}"); - NodeRef root = t.rootref(); - NodeRef without = root.append_child(); - NodeRef with = root.append_child(); - ASSERT_FALSE(without.has_key()); - ASSERT_FALSE(with.has_key()); - without.set_key_ref("without"); - with.set_key_ref("*with"); - without.set_val("0"); - with.set_val("1"); - ASSERT_TRUE(without.has_key()); - ASSERT_TRUE(with.has_key()); - EXPECT_EQ(without.key(), "without"); - EXPECT_EQ(with.key(), "*with"); - EXPECT_EQ(without.key_ref(), "without"); - EXPECT_EQ(with.key_ref(), "with"); - EXPECT_EQ(emitrs_yaml(t), R"(*without: 0 -*with: 1 -)"); -} - -TEST(anchors, set_val_ref_also_sets_the_val_when_none_exists) -{ - Tree t = parse_in_arena("{}"); - NodeRef root = t.rootref(); - NodeRef without = root.append_child(); - NodeRef with = root.append_child(); - without.set_key("without"); - with.set_key("with"); - ASSERT_FALSE(without.has_val()); - ASSERT_FALSE(with.has_val()); - without.set_val_ref("without"); - with.set_val_ref("*with"); - ASSERT_TRUE(without.has_val()); - ASSERT_TRUE(with.has_val()); - EXPECT_EQ(without.val(), "without"); - EXPECT_EQ(with.val(), "*with"); - EXPECT_EQ(without.val_ref(), "without"); - EXPECT_EQ(with.val_ref(), "with"); - EXPECT_EQ(emitrs_yaml(t), R"(without: *without -with: *with -)"); -} - -TEST(anchors, set_key_ref_replaces_existing_key) -{ - Tree t = parse_in_arena("{*foo: bar}"); - NodeRef root = t.rootref(); - EXPECT_TRUE(root.has_child("*foo")); - root["*foo"].set_key_ref("notfoo"); - EXPECT_FALSE(root.has_child("*foo")); - EXPECT_FALSE(root.has_child("*notfoo")); - EXPECT_TRUE(root.has_child("notfoo")); - EXPECT_EQ(emitrs_yaml(t), "*notfoo: bar\n"); -} - -TEST(anchors, set_val_ref_replaces_existing_key) -{ - Tree t = parse_in_arena("{foo: *bar}"); - NodeRef root = t.rootref(); - root["foo"].set_val_ref("notbar"); - EXPECT_EQ(root["foo"].val(), "notbar"); - root["foo"].set_val_ref("*notfoo"); - EXPECT_EQ(root["foo"].val(), "*notfoo"); - EXPECT_EQ(emitrs_yaml(t), "foo: *notfoo\n"); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -TEST(weird_anchor_cases_from_suite, 2SXE) -{ - Tree t = parse_in_arena(R"(&a: key: &a value -foo: - *a: -)"); - t.resolve(); - #ifdef THIS_IS_A_KNOWN_LIMITATION // since we do not allow colon in anchors, this would fail: - EXPECT_EQ(emitrs(t), R"(key: value -foo: key -)"); - #endif - // so we get this instead: - EXPECT_EQ(emitrs_yaml(t), R"(key: value -foo: - value: -)"); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -// SIMPLE_ANCHOR/YmlTestCase.parse_using_ryml/0 - -C4_SUPPRESS_WARNING_GCC_WITH_PUSH("-Wuseless-cast") - -/** verify that the reference class is working correctly (yay, testing the tests) */ -TEST(CaseNode, anchors) -{ - const NodeType mask = KEYREF|KEYANCH|VALREF|VALANCH; - - { - auto n = N("*vref", AR(KEYREF, "vref"), "c"); - EXPECT_EQ(n.key, "*vref"); - EXPECT_EQ(n.val, "c"); - EXPECT_EQ((type_bits)(n.type & mask), (type_bits)KEYREF); - EXPECT_EQ((type_bits)n.key_anchor.type, (type_bits)KEYREF); - EXPECT_EQ((type_bits)n.val_anchor.type, (type_bits)NOTYPE); - EXPECT_EQ(n.key_anchor.str, "vref"); - EXPECT_EQ(n.val_anchor.str, ""); - } - - { - CaseNode n("<<", "*base", AR(VALANCH, "base")); - EXPECT_EQ(n.key, "<<"); - EXPECT_EQ(n.val, "*base"); - EXPECT_EQ((type_bits)(n.type & mask), (type_bits)VALANCH); - EXPECT_EQ((type_bits)n.key_anchor.type, (type_bits)NOTYPE); - EXPECT_EQ((type_bits)n.val_anchor.type, (type_bits)VALANCH); - EXPECT_EQ(n.key_anchor.str, ""); - EXPECT_EQ(n.val_anchor.str, "base"); - } - - { - CaseNode n("base", L{N("name", "Everyone has same name")}, AR(VALANCH, "base")); - EXPECT_EQ(n.key, "base"); - EXPECT_EQ(n.val, ""); - EXPECT_NE(n.type.is_seq(), true); - EXPECT_EQ((type_bits)(n.type & mask), (type_bits)VALANCH); - EXPECT_EQ((type_bits)n.key_anchor.type, (type_bits)NOTYPE); - EXPECT_EQ((type_bits)n.val_anchor.type, (type_bits)VALANCH); - EXPECT_EQ(n.key_anchor.str, ""); - EXPECT_EQ(n.val_anchor.str, "base"); - } - - { - L l{N("<<", "*base", AR(VALREF, "base"))}; - CaseNode const& base = *l.begin(); - EXPECT_EQ(base.key, "<<"); - EXPECT_EQ(base.val, "*base"); - EXPECT_EQ(base.type.is_keyval(), true); - EXPECT_EQ((type_bits)(base.type & mask), (type_bits)VALREF); - EXPECT_EQ((type_bits)base.key_anchor.type, (type_bits)NOTYPE); - EXPECT_EQ((type_bits)base.val_anchor.type, (type_bits)VALREF); - EXPECT_EQ(base.key_anchor.str, ""); - EXPECT_EQ(base.val_anchor.str, "base"); - } - - { - L l{N("<<", "*base", AR(VALREF, "base")), N("age", "10")}; - CaseNode const& base = *l.begin(); - CaseNode const& age = *(&base + 1); - EXPECT_EQ(base.key, "<<"); - EXPECT_EQ(base.val, "*base"); - EXPECT_EQ(base.type.is_keyval(), true); - EXPECT_EQ((type_bits)(base.type & mask), (type_bits)VALREF); - EXPECT_EQ((type_bits)base.key_anchor.type, (type_bits)NOTYPE); - EXPECT_EQ((type_bits)base.val_anchor.type, (type_bits)VALREF); - EXPECT_EQ(base.key_anchor.str, ""); - EXPECT_EQ(base.val_anchor.str, "base"); - - EXPECT_EQ(age.key, "age"); - EXPECT_EQ(age.val, "10"); - EXPECT_EQ(age.type.is_keyval(), true); - EXPECT_EQ((type_bits)(age.type & mask), (type_bits)0); - EXPECT_EQ((type_bits)age.key_anchor.type, (type_bits)NOTYPE); - EXPECT_EQ((type_bits)age.val_anchor.type, (type_bits)NOTYPE); - EXPECT_EQ(age.key_anchor.str, ""); - EXPECT_EQ(age.val_anchor.str, ""); - } - - { - CaseNode n("foo", L{N("<<", "*base", AR(VALREF, "base")), N("age", "10")}, AR(VALANCH, "foo")); - EXPECT_EQ(n.key, "foo"); - EXPECT_EQ(n.val, ""); - EXPECT_EQ(n.type.has_key(), true); - EXPECT_EQ(n.type.is_map(), true); - EXPECT_EQ((type_bits)(n.type & mask), (type_bits)VALANCH); - EXPECT_EQ((type_bits)n.key_anchor.type, (type_bits)NOTYPE); - EXPECT_EQ((type_bits)n.val_anchor.type, (type_bits)VALANCH); - EXPECT_EQ(n.key_anchor.str, ""); - EXPECT_EQ(n.val_anchor.str, "foo"); - - CaseNode const& base = n.children[0]; - EXPECT_EQ(base.key, "<<"); - EXPECT_EQ(base.val, "*base"); - EXPECT_EQ(base.type.has_key() && base.type.has_val(), true); - EXPECT_EQ((type_bits)(base.type & mask), (type_bits)VALREF); - EXPECT_EQ((type_bits)base.key_anchor.type, (type_bits)NOTYPE); - EXPECT_EQ((type_bits)base.val_anchor.type, (type_bits)VALREF); - EXPECT_EQ(base.key_anchor.str, ""); - EXPECT_EQ(base.val_anchor.str, "base"); - } - -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -TEST(simple_anchor, resolve_works_on_an_empty_tree) -{ - Tree t; - t.resolve(); - EXPECT_TRUE(t.empty()); -} - -TEST(simple_anchor, resolve_works_on_a_tree_without_refs) -{ - Tree t = parse_in_arena("[a, b, c, d, e, f]"); - size_t size_before = t.size(); - t.resolve(); - EXPECT_EQ(t.size(), size_before); -} - -TEST(simple_anchor, resolve_works_on_keyrefvalref) -{ - Tree t = parse_in_arena("{&a a: &b b, *b: *a}"); - EXPECT_EQ(t["a"].has_key_anchor(), true); - EXPECT_EQ(t["a"].has_val_anchor(), true); - EXPECT_EQ(t["a"].key_anchor(), "a"); - EXPECT_EQ(t["a"].val_anchor(), "b"); - EXPECT_EQ(t["*b"].is_key_ref(), true); - EXPECT_EQ(t["*b"].is_val_ref(), true); - EXPECT_EQ(t["*b"].key_ref(), "b"); - EXPECT_EQ(t["*b"].val_ref(), "a"); - EXPECT_EQ(emitrs_yaml(t), R"(&a a: &b b -*b: *a -)"); - t.resolve(); - EXPECT_EQ(t["a"].val(), "b"); - EXPECT_EQ(t["b"].val(), "a"); - EXPECT_EQ(emitrs_yaml(t), R"(a: b -b: a -)"); -} - -TEST(simple_anchor, anchors_of_first_child_key_implicit) -{ - csubstr yaml = R"(&anchor0 -&anchor4 top4: - key4: scalar4 -top5: &anchor5 - key5: scalar5 -top6: - &anchor6 key6: scalar6 -top61: - &anchor61 key61: - scalar61 -top62: - &anchor62 - key62: - scalar62 -)"; - Tree t = parse_in_arena(yaml); - EXPECT_EQ(t.rootref().has_val_anchor(), true); - EXPECT_EQ(t.rootref().val_anchor(), "anchor0"); - EXPECT_EQ(t["top4"].has_key_anchor(), true); - EXPECT_EQ(t["top4"].has_val_anchor(), false); - EXPECT_EQ(t["top4"].key_anchor(), "anchor4"); - EXPECT_EQ(t["top4"]["key4"].val(), "scalar4"); - EXPECT_EQ(t["top4"]["key4"].has_key_anchor(), false); - EXPECT_EQ(t["top5"].has_key_anchor(), false); - EXPECT_EQ(t["top5"].has_val_anchor(), true); - EXPECT_EQ(t["top5"].val_anchor(), "anchor5"); - EXPECT_EQ(t["top5"]["key5"].val(), "scalar5"); - EXPECT_EQ(t["top5"]["key5"].has_key_anchor(), false); - EXPECT_EQ(t["top6"].has_key_anchor(), false); - EXPECT_EQ(t["top6"].has_val_anchor(), false); - EXPECT_EQ(t["top6"]["key6"].val(), "scalar6"); - ASSERT_EQ(t["top6"]["key6"].has_key_anchor(), true); - EXPECT_EQ(t["top6"]["key6"].key_anchor(), "anchor6"); - EXPECT_EQ(t["top61"].has_key_anchor(), false); - EXPECT_EQ(t["top61"].has_val_anchor(), false); - EXPECT_EQ(t["top61"]["key61"].val(), "scalar61"); - ASSERT_EQ(t["top61"]["key61"].has_key_anchor(), true); - EXPECT_EQ(t["top61"]["key61"].key_anchor(), "anchor61"); - EXPECT_EQ(t["top62"].has_key_anchor(), false); - EXPECT_EQ(t["top62"].has_val_anchor(), true); - EXPECT_EQ(t["top62"].val_anchor(), "anchor62"); - EXPECT_EQ(t["top62"]["key62"].val(), "scalar62"); - ASSERT_EQ(t["top62"]["key62"].has_key_anchor(), false); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - - -CASE_GROUP(SIMPLE_ANCHOR) -{ - -ADD_CASE_TO_GROUP("merge example, unresolved", -R"(# https://yaml.org/type/merge.html -- &CENTER { x: 1, y: 2 } -- &LEFT { x: 0, y: 2 } -- &BIG { r: 10 } -- &SMALL { r: 1 } - -# All the following maps are equal: - -- # Explicit keys - x: 1 - y: 2 - r: 10 - label: center/big - -- # Merge one map - << : *CENTER - r: 10 - label: center/big - -- # Merge multiple maps - << : [ *CENTER, *BIG ] - label: center/big - -- # Override - << : [ *BIG, *LEFT, *SMALL ] - x: 1 - label: center/big -)", -L{ - N(L{N("x", "1" ), N("y", "2")}, AR(VALANCH, "CENTER")), - N(L{N("x", "0" ), N("y", "2")}, AR(VALANCH, "LEFT" )), - N(L{N("r", "10") }, AR(VALANCH, "BIG" )), - N(L{N("r", "1" ) }, AR(VALANCH, "SMALL" )), - N(L{N("x", "1" ), N("y", "2"), N("r", "10"), N("label", "center/big")}), - N(L{N("<<", AR(KEYREF, "<<"), "*CENTER", AR(VALREF, "*CENTER")), N("r", "10"), N("label", "center/big")}), - N(L{N("<<", AR(KEYREF, "<<"), L{N("*CENTER", AR(VALREF, "*CENTER")), N("*BIG", AR(VALREF, "*BIG"))}), N("label", "center/big")}), - N(L{N("<<", AR(KEYREF, "<<"), L{N("*BIG", AR(VALREF, "*BIG")), N("*LEFT", AR(VALREF, "*LEFT")), N("*SMALL", AR(VALREF, "*SMALL"))}), N("x", "1"), N("label", "center/big")}), -}); - -ADD_CASE_TO_GROUP("merge example, resolved", RESOLVE_REFS, -R"(# https://yaml.org/type/merge.html -- &CENTER { x: 1, y: 2 } -- &LEFT { x: 0, y: 2 } -- &BIG { r: 10 } -- &SMALL { r: 1 } - -# All the following maps are equal: - -- # Explicit keys - x: 1 - y: 2 - r: 10 - label: center/big - -- # Merge one map - << : *CENTER - r: 10 - label: center/big - -- # Merge multiple maps - << : [ *CENTER, *BIG ] - label: center/big - -- # Override - << : [ *SMALL, *LEFT, *BIG ] - x: 1 - label: center/big -)", -L{ - N(L{N("x", "1" ), N("y", "2")}), - N(L{N("x", "0" ), N("y", "2")}), - N(L{N("r", "10") }), - N(L{N("r", "1" ) }), - N(L{N("x", "1" ), N("y", "2"), N("r", "10"), N("label", "center/big")}), - N(L{N("x", "1" ), N("y", "2"), N("r", "10"), N("label", "center/big")}), - N(L{N("x", "1" ), N("y", "2"), N("r", "10"), N("label", "center/big")}), - N(L{N("x", "1" ), N("y", "2"), N("r", "10"), N("label", "center/big")}), -}); - -ADD_CASE_TO_GROUP("simple anchor 1, implicit, unresolved", -R"( -anchored_content: &anchor_name This string will appear as the value of two keys. -other_anchor: *anchor_name -anchors_in_seqs: - - &anchor_in_seq this value appears in both elements of the sequence - - *anchor_in_seq -base: &base - name: Everyone has same name -foo: &foo - <<: *base - age: 10 -bar: &bar - <<: *base - age: 20 -)", - L{ - N("anchored_content", "This string will appear as the value of two keys.", AR(VALANCH, "anchor_name")), - N("other_anchor", "*anchor_name", AR(VALREF, "anchor_name")), - N("anchors_in_seqs", L{ - N("this value appears in both elements of the sequence", AR(VALANCH, "anchor_in_seq")), - N("*anchor_in_seq", AR(VALREF, "anchor_in_seq")), - }), - N("base", L{N("name", "Everyone has same name")}, AR(VALANCH, "base")), - N("foo", L{N("<<", AR(KEYREF, "<<"), "*base", AR(VALREF, "base")), N("age", "10")}, AR(VALANCH, "foo")), - N("bar", L{N("<<", AR(KEYREF, "<<"), "*base", AR(VALREF, "base")), N("age", "20")}, AR(VALANCH, "bar")), - } -); - -ADD_CASE_TO_GROUP("simple anchor 1, explicit, unresolved", -R"({ -anchored_content: &anchor_name This string will appear as the value of two keys., -other_anchor: *anchor_name, -anchors_in_seqs: [ - &anchor_in_seq this value appears in both elements of the sequence, - *anchor_in_seq - ], -base: &base { - name: Everyone has same name - }, -foo: &foo { - <<: *base, - age: 10 - }, -bar: &bar { - <<: *base, - age: 20 - } -})", - L{ - N("anchored_content", "This string will appear as the value of two keys.", AR(VALANCH, "anchor_name")), - N("other_anchor", "*anchor_name", AR(VALREF, "anchor_name")), - N("anchors_in_seqs", L{ - N("this value appears in both elements of the sequence", AR(VALANCH, "anchor_in_seq")), - N("*anchor_in_seq", AR(VALREF, "anchor_in_seq")), - }), - N("base", L{N("name", "Everyone has same name")}, AR(VALANCH, "base")), - N("foo", L{N("<<", AR(KEYREF, "<<"), "*base", AR(VALREF, "base")), N("age", "10")}, AR(VALANCH, "foo")), - N("bar", L{N("<<", AR(KEYREF, "<<"), "*base", AR(VALREF, "base")), N("age", "20")}, AR(VALANCH, "bar")), - } -); - -ADD_CASE_TO_GROUP("simple anchor 1, implicit, resolved", RESOLVE_REFS, -R"( -anchored_content: &anchor_name This string will appear as the value of two keys. -other_anchor: *anchor_name -anchors_in_seqs: - - &anchor_in_seq this value appears in both elements of the sequence - - *anchor_in_seq -base: &base - name: Everyone has same name -foo: &foo - <<: *base - age: 10 -bar: &bar - <<: *base - age: 20 -)", - L{ - N("anchored_content", "This string will appear as the value of two keys."), - N("other_anchor", "This string will appear as the value of two keys."), - N("anchors_in_seqs", L{ - N("this value appears in both elements of the sequence"), - N("this value appears in both elements of the sequence"), - }), - N("base", L{N("name", "Everyone has same name")}), - N("foo", L{N("name", "Everyone has same name"), N("age", "10")}), - N("bar", L{N("name", "Everyone has same name"), N("age", "20")}), - } -); - -ADD_CASE_TO_GROUP("simple anchor 1, explicit, resolved", RESOLVE_REFS, -R"({ -anchored_content: &anchor_name This string will appear as the value of two keys., -other_anchor: *anchor_name, -anchors_in_seqs: [ - &anchor_in_seq this value appears in both elements of the sequence, - *anchor_in_seq - ], -base: &base { - name: Everyone has same name - }, -foo: &foo { - <<: *base, - age: 10 - }, -bar: &bar { - <<: *base, - age: 20 - } -})", - L{ - N("anchored_content", "This string will appear as the value of two keys."), - N("other_anchor", "This string will appear as the value of two keys."), - N("anchors_in_seqs", L{ - N("this value appears in both elements of the sequence"), - N("this value appears in both elements of the sequence"), - }), - N("base", L{N("name", "Everyone has same name")}), - N("foo", L{N("name", "Everyone has same name"), N("age", "10")}), - N("bar", L{N("name", "Everyone has same name"), N("age", "20")}), - } -); - - -ADD_CASE_TO_GROUP("anchor example 2, unresolved", -R"( -receipt: Oz-Ware Purchase Invoice -date: 2012-08-06 -customer: - first_name: Dorothy - family_name: Gale -items: - - part_no: A4786 - descrip: Water Bucket (Filled) - price: 1.47 - quantity: 4 - - part_no: E1628 - descrip: High Heeled "Ruby" Slippers - size: 8 - price: 133.7 - quantity: 1 -bill-to: &id001 - street: | - 123 Tornado Alley - Suite 16 - city: East Centerville - state: KS -ship-to: *id001 -specialDelivery: > - Follow the Yellow Brick - Road to the Emerald City. - Pay no attention to the - man behind the curtain. -)", -L{ - N{"receipt", "Oz-Ware Purchase Invoice"}, - N{"date", "2012-08-06"}, - N{"customer", L{N{"first_name", "Dorothy"}, N{"family_name", "Gale"}}}, - N{"items", L{ - N{L{N{"part_no", "A4786"}, - N{"descrip", "Water Bucket (Filled)"}, - N{"price", "1.47"}, - N{"quantity", "4"},}}, - N{L{N{"part_no", "E1628"}, - N{"descrip", "High Heeled \"Ruby\" Slippers"}, - N{"size", "8"}, - N{"price", "133.7"}, - N{"quantity", "1"},}}}}, - N{"bill-to", L{ - N{QV, "street", "123 Tornado Alley\nSuite 16\n"}, - N{"city", "East Centerville"}, - N{"state", "KS"},}, AR(VALANCH, "id001")}, - N{"ship-to", "*id001", AR(VALREF, "id001")}, - N{QV, "specialDelivery", "Follow the Yellow Brick Road to the Emerald City. Pay no attention to the man behind the curtain.\n"} - } -); - - -ADD_CASE_TO_GROUP("anchor example 2, resolved", RESOLVE_REFS, -R"( -receipt: Oz-Ware Purchase Invoice -date: 2012-08-06 -customer: - first_name: Dorothy - family_name: Gale -items: - - part_no: A4786 - descrip: Water Bucket (Filled) - price: 1.47 - quantity: 4 - - part_no: E1628 - descrip: High Heeled "Ruby" Slippers - size: 8 - price: 133.7 - quantity: 1 -bill-to: &id001 - street: | - 123 Tornado Alley - Suite 16 - city: East Centerville - state: KS -ship-to: *id001 -specialDelivery: > - Follow the Yellow Brick - Road to the Emerald City. - Pay no attention to the - man behind the curtain. -)", -L{ - N{"receipt", "Oz-Ware Purchase Invoice"}, - N{"date", "2012-08-06"}, - N{"customer", L{N{"first_name", "Dorothy"}, N{"family_name", "Gale"}}}, - N{"items", L{ - N{L{N{"part_no", "A4786"}, - N{"descrip", "Water Bucket (Filled)"}, - N{"price", "1.47"}, - N{"quantity", "4"},}}, - N{L{N{"part_no", "E1628"}, - N{"descrip", "High Heeled \"Ruby\" Slippers"}, - N{"size", "8"}, - N{"price", "133.7"}, - N{"quantity", "1"},}}}}, - N{"bill-to", L{ - N{QV, "street", "123 Tornado Alley\nSuite 16\n"}, - N{"city", "East Centerville"}, - N{"state", "KS"},}}, - N{"ship-to", L{ - N{QV, "street", "123 Tornado Alley\nSuite 16\n"}, - N{"city", "East Centerville"}, - N{"state", "KS"},}}, - N{QV, "specialDelivery", "Follow the Yellow Brick Road to the Emerald City. Pay no attention to the man behind the curtain.\n"} - } -); - -ADD_CASE_TO_GROUP("anchor example 3, unresolved", -R"( -- step: &id001 # defines anchor label &id001 - instrument: Lasik 2000 - pulseEnergy: 5.4 - pulseDuration: 12 - repetition: 1000 - spotSize: 1mm -- step: &id002 - instrument: Lasik 2000 - pulseEnergy: 5.0 - pulseDuration: 10 - repetition: 500 - spotSize: 2mm -- step: *id001 # refers to the first step (with anchor &id001) -- step: *id002 # refers to the second step -- step: - <<: *id001 - spotSize: 2mm # redefines just this key, refers rest from &id001 -- step: *id002 -)", -L{N(L{ -N("step", L{ - N{"instrument", "Lasik 2000"}, - N{"pulseEnergy", "5.4"}, - N{"pulseDuration", "12"}, - N{"repetition", "1000"}, - N{"spotSize", "1mm"}, - }, AR(VALANCH, "id001")), - }), N(L{ -N("step", L{ - N{"instrument", "Lasik 2000"}, - N{"pulseEnergy", "5.0"}, - N{"pulseDuration", "10"}, - N{"repetition", "500"}, - N{"spotSize", "2mm"}, - }, AR(VALANCH, "id002")), - }), N(L{ -N{"step", "*id001", AR(VALREF, "id001")}, - }), N(L{ -N{"step", "*id002", AR(VALREF, "id002")}, - }), N(L{ -N{"step", L{ - N{"<<", AR(KEYREF, "<<"), "*id001", AR(VALREF, "id002")}, - N{"spotSize", "2mm"}, - }}, - }), N(L{ -N{"step", "*id002", AR(VALREF, "id002")}, - }), - } -); - -ADD_CASE_TO_GROUP("anchor example 3, resolved", RESOLVE_REFS, -R"( -- step: &id001 # defines anchor label &id001 - instrument: Lasik 2000 - pulseEnergy: 5.4 - pulseDuration: 12 - repetition: 1000 - spotSize: 1mm -- step: &id002 - instrument: Lasik 2000 - pulseEnergy: 5.0 - pulseDuration: 10 - repetition: 500 - spotSize: 2mm -- step: *id001 # refers to the first step (with anchor &id001) -- step: *id002 # refers to the second step -- step: - <<: *id001 - spotSize: 2mm # redefines just this key, refers rest from &id001 -- step: *id002 -)", - L{N(L{ -N{"step", L{ - N{"instrument", "Lasik 2000"}, - N{"pulseEnergy", "5.4"}, - N{"pulseDuration", "12"}, - N{"repetition", "1000"}, - N{"spotSize", "1mm"}, - }}, - }), N(L{ -N{"step", L{ - N{"instrument", "Lasik 2000"}, - N{"pulseEnergy", "5.0"}, - N{"pulseDuration", "10"}, - N{"repetition", "500"}, - N{"spotSize", "2mm"}, - }}, - }), N(L{ -N{"step", L{ - N{"instrument", "Lasik 2000"}, - N{"pulseEnergy", "5.4"}, - N{"pulseDuration", "12"}, - N{"repetition", "1000"}, - N{"spotSize", "1mm"}, - }}, - }), N(L{ -N{"step", L{ - N{"instrument", "Lasik 2000"}, - N{"pulseEnergy", "5.0"}, - N{"pulseDuration", "10"}, - N{"repetition", "500"}, - N{"spotSize", "2mm"}, - }}, - }), N(L{ -N{"step", L{ - N{"instrument", "Lasik 2000"}, - N{"pulseEnergy", "5.4"}, - N{"pulseDuration", "12"}, - N{"repetition", "1000"}, - N{"spotSize", "2mm"}, - }}, - }), N(L{ -N{"step", L{ - N{"instrument", "Lasik 2000"}, - N{"pulseEnergy", "5.0"}, - N{"pulseDuration", "10"}, - N{"repetition", "500"}, - N{"spotSize", "2mm"}, - }}, - }), - } -); - -ADD_CASE_TO_GROUP("tagged doc with anchors 9KAX", -R"( ---- -&a1 -!!str -scalar1 ---- &a1 !!str scalar1 ---- -!!str -&a1 -scalar1 ---- !!str &a1 scalar1 ---- -!!str -&a2 -scalar2 ---- &a2 !!str scalar2 ---- -&a3 -!!str scalar3 ---- &a3 !!str scalar3 ---- -&a4 !!map -&a5 !!str key5: value4 ---- &a4 !!map -&a5 !!str key5: value4 ---- -a6: 1 -&anchor6 b6: 2 ---- -!!map -&a8 !!str key8: value7 ---- !!map -&a8 !!str key8: value7 ---- -!!map -!!str &a10 key10: value9 ---- !!map -&a10 !!str key10: value9 ---- -!!str &a11 -value11 ---- &a11 !!str value11 -)", -N(STREAM, L{ - N(DOCVAL, TS("!!str", "scalar1"), AR(VALANCH, "a1")), - N(DOCVAL, TS("!!str", "scalar1"), AR(VALANCH, "a1")), - N(DOCVAL, TS("!!str", "scalar1"), AR(VALANCH, "a1")), - N(DOCVAL, TS("!!str", "scalar1"), AR(VALANCH, "a1")), - N(DOCVAL, TS("!!str", "scalar2"), AR(VALANCH, "a2")), - N(DOCVAL, TS("!!str", "scalar2"), AR(VALANCH, "a2")), - N(DOCVAL, TS("!!str", "scalar3"), AR(VALANCH, "a3")), - N(DOCVAL, TS("!!str", "scalar3"), AR(VALANCH, "a3")), - N(DOCMAP, TL("!!map", L{N(TS("!!str", "key5"), AR(KEYANCH, "a5"), "value4")}), AR(VALANCH, "a4")), - N(DOCMAP, TL("!!map", L{N(TS("!!str", "key5"), AR(KEYANCH, "a5"), "value4")}), AR(VALANCH, "a4")), - N(DOCMAP, L{N("a6", "1"), N("b6", AR(KEYANCH, "anchor6"), "2")}), - N(DOCMAP, TL("!!map", L{N(TS("!!str", "key8"), AR(KEYANCH, "a8"), "value7")})), - N(DOCMAP, TL("!!map", L{N(TS("!!str", "key8"), AR(KEYANCH, "a8"), "value7")})), - N(DOCMAP, TL("!!map", L{N(TS("!!str", "key10"), AR(KEYANCH, "a10"), "value9")})), - N(DOCMAP, TL("!!map", L{N(TS("!!str", "key10"), AR(KEYANCH, "a10"), "value9")})), - N(DOCVAL, TS("!!str", "value11"), AR(VALANCH, "a11")), - N(DOCVAL, TS("!!str", "value11"), AR(VALANCH, "a11")), -}) -); - -ADD_CASE_TO_GROUP("github131 1, unresolved", -R"( -a: &vref b -*vref: c -&kref aa: bb -aaa: &kvref bbb -foo: - *kref: cc - *kvref: cc -)", -L{ - N("a", "b", AR(VALANCH, "vref")), - N("*vref", AR(KEYREF, "vref"), "c"), - N("aa", AR(KEYANCH, "kref"), "bb"), - N("aaa", "bbb", AR(VALANCH, "kvref")), - N("foo", L{ - N("*kref", AR(KEYREF, "kref"), "cc"), - N("*kvref", AR(KEYREF, "kvref"), "cc"), - }) -}); - -ADD_CASE_TO_GROUP("github131 1, resolved", RESOLVE_REFS, -R"( -a: &vref b -*vref: c -&kref aa: bb -aaa: &kvref bbb -foo: - *kref: cc - *kvref: cc -)", -L{ - N("a", "b"), - N("b", "c"), - N("aa", "bb"), - N("aaa", "bbb"), - N("foo", L{N("aa", "cc"), N("bbb", "cc")}) -}); - - -ADD_CASE_TO_GROUP("anchors+refs on key+val, unresolved", -R"({&a0 a0: &b0 b0, *b0: *a0})", -L{ - N("a0", AR(KEYANCH, "a0"), "b0", AR(VALANCH, "b0")), - N(AR(KEYREF, "*b0"), AR(VALREF, "*a0")), -}); - -ADD_CASE_TO_GROUP("anchors+refs on key+val, resolved", RESOLVE_REFS, -R"({&a0 a0: &b0 b0, *b0: *a0})", -L{ - N("a0", "b0"), - N("b0", "a0"), -}); - - -ADD_CASE_TO_GROUP("ambiguous anchor, unresolved", -R"(&rootanchor -&a0 a0: &b0 b0 -*b0: *a0 -map1: - &a1 a1: &b1 b1 # &a1 must be a KEY anchor on a1, not a VAL anchor on map1 - *b1: *a1 -map2: - *b0: *a0 # ensure the anchor is enough to establish the indentation - &a2 a2: &b2 b2 - *b2: *a2 -map3: &a3 # &a3 must be a VAL anchor on map3, not a KEY anchor on a3 - a3: &b3 b3 - *b3: *b0 -map4: *a0 -map5: - &map5 - &a5 a5: &b5 b5 - *b5: *a5 -map6: - &map6 - a6: &b6 b6 - *b6: *b6 -)", -N(L{ - N("a0", AR(KEYANCH, "a0"), "b0", AR(VALANCH, "b0")), - N(AR(KEYREF, "*b0"), AR(VALREF, "*a0")), - N("map1", L{N("a1", AR(KEYANCH, "a1"), "b1", AR(VALANCH, "b1")), N(AR(KEYREF, "*b1"), AR(VALREF, "*a1")),}), - N("map2", L{N(AR(KEYREF, "*b0"), AR(VALREF, "*a0")), N("a2", AR(KEYANCH, "a2"), "b2", AR(VALANCH, "b2")), N(AR(KEYREF, "*b2"), AR(VALREF, "*a2")),}), - N("map3", L{N("a3", "b3", AR(VALANCH, "b3")), N(AR(KEYREF, "*b3"), AR(VALREF, "*b0")),}, AR(VALANCH, "a3")), - N("map4", "*a0", AR(VALREF, "a0")), - N("map5", L{N("a5", AR(KEYANCH, "a5"), "b5", AR(VALANCH, "b5")), N(AR(KEYREF, "*b5"), AR(VALREF, "*a5")),}, AR(VALANCH, "map5")), - N("map6", L{N("a6", "b6", AR(VALANCH, "b6")), N(AR(KEYREF, "*b6"), AR(VALREF, "*b6")),}, AR(VALANCH, "map6")), -}, AR(VALANCH, "rootanchor"))); - -ADD_CASE_TO_GROUP("ambiguous anchor, resolved", RESOLVE_REFS, -R"( -&a0 a0: &b0 b0 -*b0: *a0 -map1: - &a1 a1: &b1 b1 # &a1 must be a KEY anchor on a1, not a VAL anchor on map1 - *b1: *a1 -map2: - *b0: *a0 # ensure the anchor is enough to establish the indentation - &a2 a2: &b2 b2 - *b2: *a2 -map3: &a3 # &a3 must be a VAL anchor on map3, not a KEY anchor on a3 - a3: &b3 b3 - *b3: *b0 -map4: *a0 -map5: - &map5 - &a5 a5: &b5 b5 - *b5: *a5 -map6: - &map6 - a6: &b6 b6 - *b6: *b6 -)", -L{ - N("a0", "b0"), N("b0", "a0"), - N("map1", L{N("a1", "b1"), N("b1", "a1"),}), - N("map2", L{N("b0", "a0"), N("a2", "b2"), N("b2", "a2"),}), - N("map3", L{N("a3", "b3"), N("b3", "b0"),}), - N("map4", "a0"), - N("map5", L{N("a5", "b5"), N("b5", "a5"),}), - N("map6", L{N("a6", "b6"), N("b6", "b6"),}), -}); - - -ADD_CASE_TO_GROUP("ambiguous anchor in seq, unresolved", -R"( -&seq -- &a0 - &a1 k1: v1 - &a2 k2: v2 - &a3 k3: v3 -- &a4 k4: v4 - &a5 k5: v5 - &a6 k6: v6 -- &a7 - &a8 k8: v8 -- &a9 - k10: v10 -- *a1: w1 - *a2: w2 - *a3: w3 - *a4: w4 - *a5: w5 - *a6: w6 - *a8: w8 -- *a0 -- *a7 -- *a9 -)", -N(L{ - N(L{N("k1", AR(KEYANCH, "a1"), "v1"), N("k2", AR(KEYANCH, "a2"), "v2"), N("k3", AR(KEYANCH, "a3"), "v3")}, AR(VALANCH, "a0")), - N(L{N("k4", AR(KEYANCH, "a4"), "v4"), N("k5", AR(KEYANCH, "a5"), "v5"), N("k6", AR(KEYANCH, "a6"), "v6")}), - N(L{N("k8", AR(KEYANCH, "a8"), "v8")}, AR(VALANCH, "a7")), - N(L{N("k10", "v10")}, AR(VALANCH, "a9")), - N(L{ - N("*a1", AR(KEYREF, "*a1"), "w1"), - N("*a2", AR(KEYREF, "*a2"), "w2"), - N("*a3", AR(KEYREF, "*a3"), "w3"), - N("*a4", AR(KEYREF, "*a4"), "w4"), - N("*a5", AR(KEYREF, "*a5"), "w5"), - N("*a6", AR(KEYREF, "*a6"), "w6"), - N("*a8", AR(KEYREF, "*a8"), "w8"), - }), - N("*a0", AR(VALREF, "*a0")), - N("*a7", AR(VALREF, "*a7")), - N("*a9", AR(VALREF, "*a9")), -}, AR(VALANCH, "seq"))); - -ADD_CASE_TO_GROUP("ambiguous anchor in seq, resolved", RESOLVE_REFS, -R"( -&seq -- &a0 - &a1 k1: v1 - &a2 k2: v2 - &a3 k3: v3 -- &a4 k4: v4 - &a5 k5: v5 - &a6 k6: v6 -- &a7 - &a8 k8: v8 -- &a9 - k10: v10 -- *a1: w1 - *a2: w2 - *a3: w3 - *a4: w4 - *a5: w5 - *a6: w6 - *a8: w8 -- *a0 -- *a7 -- *a9 -)", -L{ - N(L{N("k1", "v1"), N("k2", "v2"), N("k3", "v3")}), - N(L{N("k4", "v4"), N("k5", "v5"), N("k6", "v6")}), - N(L{N("k8", "v8")}), - N(L{N("k10", "v10")}), - N(L{ - N("k1", "w1"), - N("k2", "w2"), - N("k3", "w3"), - N("k4", "w4"), - N("k5", "w5"), - N("k6", "w6"), - N("k8", "w8"), - }), - N(L{N("k1", AR(KEYANCH, "a1"), "v1"), N("k2", AR(KEYANCH, "a2"), "v2"), N("k3", AR(KEYANCH, "a3"), "v3")}), - N(L{N("k8", AR(KEYANCH, "a8"), "v8")}), - N(L{N("k10", "v10")}), -}); - -ADD_CASE_TO_GROUP("anchor after complex key without value ZWK4", -R"( -a: 1 -? b -&anchor c: 3 -)", - L{ - N("a", "1"), N(KEYVAL, "b", {}), N("c", AR(KEYANCH, "anchor"), "3") - } -); - -ADD_CASE_TO_GROUP("anchor mixed with tag HMQ5, unresolved", -R"( -!!str &a1 "foo": - !!str bar -&a2 baz : *a1 -)", - L{ - N(KEYVAL|KEYQUO, TS("!!str", "foo"), AR(KEYANCH, "a1"), TS("!!str", "bar")), - N("baz", AR(KEYANCH, "a2"), "*a1", AR(VALREF, "*a1")), - } -); - -ADD_CASE_TO_GROUP("anchor mixed with tag HMQ5, resolved", RESOLVE_REFS, -R"( -!!str &a1 "foo": - !!str bar -&a2 baz : *a1 -)", - L{ - N(KEYVAL|KEYQUO, TS("!!str", "foo"), TS("!!str", "bar")), - N("baz", "foo"), - } -); -} - - -C4_SUPPRESS_WARNING_GCC_POP - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_simple_doc.cpp b/thirdparty/ryml/test/test_simple_doc.cpp deleted file mode 100644 index 9e47c6b1e..000000000 --- a/thirdparty/ryml/test/test_simple_doc.cpp +++ /dev/null @@ -1,526 +0,0 @@ -#include "./test_group.hpp" - -namespace c4 { -namespace yml { - - -TEST(simple_doc, issue_251) -{ - { - csubstr yaml = R"( -... -)"; - test_check_emit_check(yaml, [](Tree const &t){ - EXPECT_EQ(t.rootref().type(), NOTYPE); - ASSERT_EQ(t.rootref().num_children(), 0u); - }); - } - { - Tree tree; - NodeRef root = tree.rootref(); - root |= MAP; - root["test"] = "..."; - root["test"] |= VALQUO; - - std::string s = emitrs_yaml(tree); - test_check_emit_check(to_csubstr(s), [](Tree const &t){ - EXPECT_EQ(t["test"].val(), "..."); - }); - } -} - - -TEST(simple_doc, test_suite_XLQ9) -{ - csubstr yaml = R"( ---- -scalar -%YAML 1.2 -)"; - test_check_emit_check(yaml, [](Tree const &t){ - ASSERT_TRUE(t.rootref().is_stream()); - ASSERT_EQ(t.rootref().num_children(), 1u); - ASSERT_TRUE(t.rootref().first_child().is_doc()); - ASSERT_TRUE(t.rootref().first_child().is_val()); - EXPECT_EQ(t.rootref().first_child().val(), csubstr("scalar %YAML 1.2")); - }); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -CASE_GROUP(SIMPLE_DOC) -{ - -ADD_CASE_TO_GROUP("one empty doc", -R"(--- -)", - N(STREAM, L{DOCVAL}) -); - -ADD_CASE_TO_GROUP("one empty doc, explicit termination", -R"(--- -... -)", - N(STREAM, L{DOCVAL}) -); - -ADD_CASE_TO_GROUP("two empty docs", -R"(--- ---- -)", - N(STREAM, L{DOCVAL, DOCVAL}) -); - -ADD_CASE_TO_GROUP("two empty docs, with termination", -R"(--- -... ---- -)", - N(STREAM, L{DOCVAL, DOCVAL}) -); - -ADD_CASE_TO_GROUP("doc with single scalar", -R"(a scalar -)", -N(DOCVAL, "a scalar") -); - -ADD_CASE_TO_GROUP("doc with single scalar, explicit", -R"(--- a scalar -)", -N(STREAM, L{N(DOCVAL, "a scalar")}) -); - -ADD_CASE_TO_GROUP("simple doc, empty docs", -R"(--- ---- ---- ---- -)", - N(STREAM, L{DOCVAL, DOCVAL, DOCVAL, DOCVAL}) -); - -ADD_CASE_TO_GROUP("simple doc, empty docs, indented", -R"( --- - --- - --- - --- -)", - N(STREAM, L{DOCVAL, DOCVAL, DOCVAL, DOCVAL}) -); - -ADD_CASE_TO_GROUP("simple doc, empty docs, term", -R"(--- -... - - ---- -... ---- -... ---- -... -)", - N(STREAM, L{DOCVAL, DOCVAL, DOCVAL, DOCVAL}) -); - -ADD_CASE_TO_GROUP("simple doc, empty docs, term, indented", -R"( - --- - ... - - - --- - ... - --- - ... - --- - ... -)", - N(STREAM, L{DOCVAL, DOCVAL, DOCVAL, DOCVAL}) -); - -ADD_CASE_TO_GROUP("simple doc, plain scalar, multiple docs, implicit 2nd doc", -R"(--- -- a plain scalar - with several lines -... -- a second plain scalar - with several lines -)", -N(STREAM, L{ - N(DOCSEQ, L{N("a plain scalar with several lines")}), - N(DOCSEQ, L{N("a second plain scalar with several lines")}), -})); - -ADD_CASE_TO_GROUP("simple doc, single scalar, implicit doc", -R"(a scalar with some spaces inside -)", - N(DOCVAL, "a scalar with some spaces inside") -); - -ADD_CASE_TO_GROUP("simple doc, single scalar, implicit doc, indented", -R"( a scalar with some spaces inside -)", - N(DOCVAL,"a scalar with some spaces inside") -); - -ADD_CASE_TO_GROUP("simple doc, multi scalar, implicit doc", -R"(a scalar with some spaces inside, -and yet another one with more spaces inside, -and it doesn't really stop -)", - N(L{ - N("a scalar with some spaces inside"), - N("and yet another one with more spaces inside"), - N("and it doesn't really stop"), - }) -); - -ADD_CASE_TO_GROUP("simple doc, multi scalar, implicit doc, indented", -R"( - a scalar with some spaces inside, - and yet another one with more spaces inside, - and it doesn't really stop -)", - N(L{ - N("a scalar with some spaces inside"), - N("and yet another one with more spaces inside"), - N("and it doesn't really stop"), - }) -); - -ADD_CASE_TO_GROUP("simple doc, single scalar, explicit doc, implicit termination", -R"(--- -a scalar with some spaces inside -)", - N(STREAM, L{N(DOCVAL, "a scalar with some spaces inside")}) -); - -ADD_CASE_TO_GROUP("simple doc, single scalar, explicit doc, implicit termination, indented", -R"( --- - a scalar with some spaces inside -)", - N(STREAM, L{N(DOCVAL, "a scalar with some spaces inside")}) -); - -ADD_CASE_TO_GROUP("simple doc, single scalar, explicit doc, explicit termination", -R"(--- -a scalar with some spaces inside -... -)", - N(STREAM, L{N(DOCVAL, "a scalar with some spaces inside")}) -); - -ADD_CASE_TO_GROUP("simple doc, single scalar, explicit doc, explicit termination, indented", -R"( --- - a scalar with some spaces inside - ... -)", - N(STREAM, L{N(DOCVAL, "a scalar with some spaces inside")}) -); - -ADD_CASE_TO_GROUP("simple doc, multi doc, seq-map", -R"(--- -- a -- b -- c -... ---- -a: 0 -b: 1 -c: 2 -)", - N(STREAM, L{ - N(DOCSEQ, L{N("a"), N("b"), N("c")}), - N(DOCMAP, L{N("a", "0"), N("b", "1"), N("c", "2")}) - }) -); - -ADD_CASE_TO_GROUP("simple doc, multi doc, seq-map, indented", -R"( --- - - a - - b - - c - ... - --- - a: 0 - b: 1 - c: 2 -)", - N(STREAM, L{ - N(DOCSEQ, L{N("a"), N("b"), N("c")}), - N(DOCMAP, L{N("a", "0"), N("b", "1"), N("c", "2")}) - }) -); - -ADD_CASE_TO_GROUP("simple doc, multi doc, seq-map, no term", -R"(--- -- a -- b -- c ---- -a: 0 -b: 1 -c: 2 -)", - N(STREAM, L{ - N(DOCSEQ, L{N("a"), N("b"), N("c")}), - N(DOCMAP, L{N("a", "0"), N("b", "1"), N("c", "2")}) - }) -); - -ADD_CASE_TO_GROUP("simple doc, multi doc, seq-map, no term, indented", -R"( - --- - - a - - b - - c - --- - a: 0 - b: 1 - c: 2 -)", - N(STREAM, L{ - N(DOCSEQ, L{N("a"), N("b"), N("c")}), - N(DOCMAP, L{N("a", "0"), N("b", "1"), N("c", "2")}) - }) -); - -ADD_CASE_TO_GROUP("simple doc, multi doc, map-seq", -R"(--- -a: 0 -b: 1 -c: 2 -... ---- -- a -- b -- c -... -)", - N(STREAM, L{ - N(DOCMAP, L{N("a", "0"), N("b", "1"), N("c", "2")}), - N(DOCSEQ, L{N("a"), N("b"), N("c")}) - }) -); - -ADD_CASE_TO_GROUP("simple doc, multi doc, map-seq, indented", -R"( - --- - a: 0 - b: 1 - c: 2 - ... - --- - - a - - b - - c - ... -)", - N(STREAM, L{ - N(DOCMAP, L{N("a", "0"), N("b", "1"), N("c", "2")}), - N(DOCSEQ, L{N("a"), N("b"), N("c")}) - }) -); - -ADD_CASE_TO_GROUP("simple doc, multi doc, map-seq, no term", -R"(--- -a: 0 -b: 1 -c: 2 ---- -- a -- b -- c -)", - N(STREAM, L{ - N(DOCMAP, L{N("a", "0"), N("b", "1"), N("c", "2")}), - N(DOCSEQ, L{N("a"), N("b"), N("c")}) - }) -); - -ADD_CASE_TO_GROUP("simple doc, multi doc, map-seq, no term, indented", -R"( - --- - a: 0 - b: 1 - c: 2 - --- - - a - - b - - c -)", - N(STREAM, L{ - N(DOCMAP, L{N("a", "0"), N("b", "1"), N("c", "2")}), - N(DOCSEQ, L{N("a"), N("b"), N("c")}) - }) -); - -ADD_CASE_TO_GROUP("simple doc, multi doc, impl seq-map", -R"(--- -[a, b, c] -... ---- -{a: 0, b: 1, c: 2} -... -)", - N(STREAM, L{ - N(DOCSEQ, L{N("a"), N("b"), N("c")}), - N(DOCMAP, L{N("a", "0"), N("b", "1"), N("c", "2")}) - }) -); - -ADD_CASE_TO_GROUP("simple doc, multi doc, impl seq-map, indented", -R"( - --- - [a, b, c] - ... - --- - {a: 0, b: 1, c: 2} - ... -)", - N(STREAM, L{ - N(DOCSEQ, L{N("a"), N("b"), N("c")}), - N(DOCMAP, L{N("a", "0"), N("b", "1"), N("c", "2")}) - }) -); - -ADD_CASE_TO_GROUP("simple doc, multi doc, impl seq-map, no term", -R"(--- -[a, b, c] ---- -{a: 0, b: 1, c: 2} -)", - N(STREAM, L{ - N(DOCSEQ, L{N("a"), N("b"), N("c")}), - N(DOCMAP, L{N("a", "0"), N("b", "1"), N("c", "2")}) - }) -); - -ADD_CASE_TO_GROUP("simple doc, multi doc, impl seq-map, no term, indented", -R"( - --- - [a, b, c] - --- - {a: 0, b: 1, c: 2} -)", - N(STREAM, L{ - N(DOCSEQ, L{N("a"), N("b"), N("c")}), - N(DOCMAP, L{N("a", "0"), N("b", "1"), N("c", "2")}) - }) -); - -ADD_CASE_TO_GROUP("simple doc, multi doc, impl map-seq", -R"(--- -{a: 0, b: 1, c: 2} -... ---- -[a, b, c] -... -)", - N(STREAM, L{ - N(DOCMAP, L{N("a", "0"), N("b", "1"), N("c", "2")}), - N(DOCSEQ, L{N("a"), N("b"), N("c")}) - }) -); - -ADD_CASE_TO_GROUP("simple doc, multi doc, impl map-seq, indented", -R"( - --- - {a: 0, b: 1, c: 2} - ... - --- - [a, b, c] - ... -)", - N(STREAM, L{ - N(DOCMAP, L{N("a", "0"), N("b", "1"), N("c", "2")}), - N(DOCSEQ, L{N("a"), N("b"), N("c")}) - }) -); - -ADD_CASE_TO_GROUP("simple doc, multi doc, impl map-seq, no term", -R"(--- -{a: 0, b: 1, c: 2} ---- -[a, b, c] -)", - N(STREAM, L{ - N(DOCMAP, L{N("a", "0"), N("b", "1"), N("c", "2")}), - N(DOCSEQ, L{N("a"), N("b"), N("c")}) - }) -); - -ADD_CASE_TO_GROUP("simple doc, multi doc, impl map-seq, no term, indented", -R"( - --- - {a: 0, b: 1, c: 2} - --- - [a, b, c] -)", - N(STREAM, L{ - N(DOCMAP, L{N("a", "0"), N("b", "1"), N("c", "2")}), - N(DOCSEQ, L{N("a"), N("b"), N("c")}) - }) -); - -ADD_CASE_TO_GROUP("simple doc, indented with empty lines", -R"( - --- - {a: 0, b: 1, c: 2, - - - - - - - - d: - some scalar - } - --- - a: 0 - b: 1 - c: 2 - - - - - - - - d: - some scalar -)", - N(STREAM, L{ - N(DOCMAP, L{N("a", "0"), N("b", "1"), N("c", "2"), N("d", "some scalar")}), - N(DOCMAP, L{N("a", "0"), N("b", "1"), N("c", "2"), N("d", "some scalar")}), - }) -); - - -ADD_CASE_TO_GROUP("simple doc, tags at global scope, 9WXW", -R"(# Private -!foo "bar" -... -# Global -%TAG ! tag:example.com,2000:app/ ---- -!foo "bar" -)", -N(STREAM, L{ - N(DOCVAL|VALQUO, TS("!foo", "bar")), - // strict YAML should result in this for the second doc: - //N(DOCVAL|VALQUO, TS("", "bar")), - // but since we don't do lookup, it should result in: - N(DOCVAL|VALQUO, TS("!foo", "bar")), -}) -); -} - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_simple_map.cpp b/thirdparty/ryml/test/test_simple_map.cpp deleted file mode 100644 index 3e814e279..000000000 --- a/thirdparty/ryml/test/test_simple_map.cpp +++ /dev/null @@ -1,1050 +0,0 @@ -#include "./test_group.hpp" - -namespace c4 { -namespace yml { - -TEST(simple_map, issue274) -{ - Tree tree = parse_in_arena(R"( -foo: -- bar -- -baz: qux -foo2: -- bar -- -baz2: qux -)"); - std::cout << tree; - ASSERT_EQ(tree.rootref().num_children(), 4u); - ASSERT_EQ(tree["foo"].num_children(), 2u); - EXPECT_EQ(tree["foo"][0].val(), "bar"); - EXPECT_EQ(tree["foo"][1].val(), ""); - EXPECT_EQ(tree["baz"].val(), "qux"); - ASSERT_EQ(tree["foo2"].num_children(), 2u); - EXPECT_EQ(tree["foo2"][0].val(), "bar"); - EXPECT_EQ(tree["foo2"][1].val(), ""); - EXPECT_EQ(tree["baz2"].val(), "qux"); -} - -TEST(simple_map, keys_with_leading_colon) -{ - Tree tree = parse_in_arena(R"( -:foo: - :bar: a - :barbar: b - :barbarbar: c -)"); - EXPECT_EQ(tree[":foo"][":bar"].val(), "a"); - EXPECT_EQ(tree[":foo"][":barbar"].val(), "b"); - EXPECT_EQ(tree[":foo"][":barbarbar"].val(), "c"); -} - -TEST(simple_map, open_on_new_doc_without_space) -{ - Tree tree = parse_in_arena(R"( -foo: bar ---- -foo: bar ---- -foo: bar ---- -foo: -... -foo: ---- -)"); - EXPECT_EQ(tree.docref(0)["foo"].val(), "bar"); - EXPECT_EQ(tree.docref(1)["foo"].val(), "bar"); - EXPECT_EQ(tree.docref(2)["foo"].val(), "bar"); - EXPECT_EQ(tree.docref(3)["foo"].val(), ""); - EXPECT_EQ(tree.docref(4)["foo"].val(), ""); -} - -TEST(simple_map, open_on_new_doc_with_space_before_colon) -{ - Tree tree = parse_in_arena(R"( -foo0 : bar ---- -foo1 : bar # the " :" was causing an assert ---- -foo2 : bar ---- -foo3 : bar ---- -foo4 : bar -)"); - EXPECT_EQ(tree.docref(0)["foo0"].val(), "bar"); - EXPECT_EQ(tree.docref(1)["foo1"].val(), "bar"); - EXPECT_EQ(tree.docref(2)["foo2"].val(), "bar"); - EXPECT_EQ(tree.docref(3)["foo3"].val(), "bar"); - EXPECT_EQ(tree.docref(4)["foo4"].val(), "bar"); -} - - -TEST(simple_map, test_suite_UT92) -{ - csubstr yaml = R"( -- { matches -% : 20 } -- { matches -%: 20 } -- { matches -%: - 20 } -)"; - test_check_emit_check(yaml, [](Tree const &t){ - ASSERT_TRUE(t[0].has_child("matches %")); - EXPECT_EQ(t[0]["matches %"].val(), "20"); - ASSERT_TRUE(t[0].has_child("matches %")); - ASSERT_TRUE(t[1].has_child("matches %")); - EXPECT_EQ(t[1]["matches %"].val(), "20"); - ASSERT_TRUE(t[1].has_child("matches %")); - ASSERT_TRUE(t[2].has_child("matches %")); - EXPECT_EQ(t[2]["matches %"].val(), "20"); - ASSERT_TRUE(t[2].has_child("matches %")); - }); -} - -TEST(simple_map, two_nested_flow_maps_not_accepted_because_of_container_key) -{ - Tree tree; - ExpectError::do_check(&tree, [&]{ - parse_in_arena("{{}}", &tree); - }); -} - -TEST(simple_map, many_unmatched_brackets) -{ - std::string src; - src.reserve(10000000u); - for(size_t num_brackets : {4u, 8u, 32u, 256u, 4096u, 1024u}) - { - SCOPED_TRACE(num_brackets); - for(size_t i = src.size(); i < num_brackets; ++i) - src += '{'; - Tree tree; - ExpectError::do_check(&tree, [&]{ - parse_in_place(to_substr(src), &tree); - }); - } -} - -TEST(simple_map, missing_quoted_key) -{ - csubstr yaml = R"( -"top1" : - "key1" : scalar1 -'top2' : - 'key2' : scalar2 ---- -"top1" : - "key1" : scalar1 -'top2' : - 'key2' : scalar2 ---- -'x2': {'y': z} ---- -'x3': - 'y': z ---- -x4: - 'y': z ---- -'x5': -'y': z ---- -x6: -'y': z ---- -'x7' : [ - 'y' : z, - ] ---- -"x8" : - "y" : value, - "x" : value -"y" : - "y" : value, - "x" : value -)"; - test_check_emit_check(yaml, [](Tree const &t){ - size_t doc = 0; - EXPECT_TRUE(t.docref(doc)["top1"].is_key_quoted()); - EXPECT_TRUE(t.docref(doc)["top2"].is_key_quoted()); - EXPECT_TRUE(t.docref(doc)["top1"]["key1"].is_key_quoted()); - EXPECT_TRUE(t.docref(doc)["top2"]["key2"].is_key_quoted()); - ++doc; - EXPECT_TRUE(t.docref(doc)["top1"].is_key_quoted()); - EXPECT_TRUE(t.docref(doc)["top2"].is_key_quoted()); - EXPECT_TRUE(t.docref(doc)["top1"]["key1"].is_key_quoted()); - EXPECT_TRUE(t.docref(doc)["top2"]["key2"].is_key_quoted()); - ++doc; - EXPECT_TRUE(t.docref(doc)["x2"].is_key_quoted()); - EXPECT_TRUE(t.docref(doc)["x2"]["y"].is_key_quoted()); - ++doc; - EXPECT_TRUE(t.docref(doc)["x3"].is_key_quoted()); - EXPECT_TRUE(t.docref(doc)["x3"]["y"].is_key_quoted()); - ++doc; - EXPECT_FALSE(t.docref(doc)["x4"].is_key_quoted()); - EXPECT_TRUE(t.docref(doc)["x4"]["y"].is_key_quoted()); - ++doc; - EXPECT_TRUE(t.docref(doc)["x5"].is_key_quoted()); - EXPECT_TRUE(t.docref(doc)["y"].is_key_quoted()); - ++doc; - EXPECT_FALSE(t.docref(doc)["x6"].is_key_quoted()); - EXPECT_TRUE(t.docref(doc)["y"].is_key_quoted()); - ++doc; - EXPECT_TRUE(t.docref(doc)["x7"].is_key_quoted()); - EXPECT_TRUE(t.docref(doc)["x7"][0]["y"].is_key_quoted()); - ++doc; - EXPECT_TRUE(t.docref(doc)["x8"].is_key_quoted()); - EXPECT_TRUE(t.docref(doc)["x8"]["y"].is_key_quoted()); - EXPECT_TRUE(t.docref(doc)["x8"]["x"].is_key_quoted()); - EXPECT_TRUE(t.docref(doc)["y"].is_key_quoted()); - EXPECT_TRUE(t.docref(doc)["y"]["y"].is_key_quoted()); - EXPECT_TRUE(t.docref(doc)["y"]["x"].is_key_quoted()); - }); -} - -#ifdef JAVAI -void verify_error_is_reported(csubstr case_name, csubstr yaml, size_t col={}) -{ - SCOPED_TRACE(case_name); - SCOPED_TRACE(yaml); - Tree tree; - Location loc = {}; - loc.col = col; - ExpectError::do_check(&tree, [&](){ - parse_in_arena(yaml, &tree); - }, loc); -} - -TEST(simple_map, no_map_key_flow) -{ - verify_error_is_reported("map key", R"({ first: Sammy, last: Sosa }: foo)", 28u); -} - -TEST(simple_map, no_map_key_block) -{ - verify_error_is_reported("map key", R"(? - first: Sammy - last: Sosa -: - foo -)"); -} - -TEST(simple_map, no_seq_key_flow) -{ - verify_error_is_reported("seq key", R"([Sammy, Sosa]: foo)", 28u); -} - -TEST(simple_map, no_seq_key_block) -{ - verify_error_is_reported("map key", R"(? - - Sammy - - Sosa -: - foo -)"); -} -#endif - -#ifdef RYML_WITH_TAB_TOKENS -TEST(simple_map, block_tab_tokens) -{ - Tree tree = parse_in_arena(R"( ---- # block, spaces only -a: 0 -b: 1 -c: 2 ---- # block, tabs after token -a: 0 -b: 1 -c: 2 ---- # block, tabs before and after token -a : 0 -b : 1 -c : 2 ---- # block, tabs before token -a : 0 -b : 1 -c : 2 ---- # block, tabs before newline -a : 0 -b : 1 -c : 2 -)"); - EXPECT_EQ(tree.docref(0)["a"].val(), csubstr("0")); - EXPECT_EQ(tree.docref(0)["b"].val(), csubstr("1")); - EXPECT_EQ(tree.docref(0)["c"].val(), csubstr("2")); - EXPECT_EQ(tree.docref(1)["a"].val(), csubstr("0")); - EXPECT_EQ(tree.docref(1)["b"].val(), csubstr("1")); - EXPECT_EQ(tree.docref(1)["c"].val(), csubstr("2")); - EXPECT_EQ(tree.docref(2)["a"].val(), csubstr("0")); - EXPECT_EQ(tree.docref(2)["b"].val(), csubstr("1")); - EXPECT_EQ(tree.docref(2)["c"].val(), csubstr("2")); - EXPECT_EQ(tree.docref(3)["a"].val(), csubstr("0")); - EXPECT_EQ(tree.docref(3)["b"].val(), csubstr("1")); - EXPECT_EQ(tree.docref(3)["c"].val(), csubstr("2")); - EXPECT_EQ(tree.docref(4)["a"].val(), csubstr("0")); - EXPECT_EQ(tree.docref(4)["b"].val(), csubstr("1")); - EXPECT_EQ(tree.docref(4)["c"].val(), csubstr("2")); -} - -TEST(simple_map, flow_tab_tokens) -{ - Tree tree = parse_in_arena(R"( ---- # flow, no tabs -{a: 0, b: 1, c: 2} ---- # flow, tabs after token -{a: 0, b: 1, c: 2} ---- # flow, tabs before and after token -{a : 0, b : 1, c : 2} ---- # flow, tabs before token -{a : 0, b : 1, c : 2} ---- # flow, tabs after val -{a : 0 , b : 1 , c : 2 } ---- # flow, tabs after val and comma -{a : 0 , b : 1 , c : 2 } ---- # flow, tabs everywhere - { - a : 0 , - b : 1 , - c : 2 - } - )"); - EXPECT_EQ(tree.docref(0)["a"].val(), csubstr("0")); - EXPECT_EQ(tree.docref(0)["b"].val(), csubstr("1")); - EXPECT_EQ(tree.docref(0)["c"].val(), csubstr("2")); - EXPECT_EQ(tree.docref(1)["a"].val(), csubstr("0")); - EXPECT_EQ(tree.docref(1)["b"].val(), csubstr("1")); - EXPECT_EQ(tree.docref(1)["c"].val(), csubstr("2")); - EXPECT_EQ(tree.docref(2)["a"].val(), csubstr("0")); - EXPECT_EQ(tree.docref(2)["b"].val(), csubstr("1")); - EXPECT_EQ(tree.docref(2)["c"].val(), csubstr("2")); - EXPECT_EQ(tree.docref(3)["a"].val(), csubstr("0")); - EXPECT_EQ(tree.docref(3)["b"].val(), csubstr("1")); - EXPECT_EQ(tree.docref(3)["c"].val(), csubstr("2")); - EXPECT_EQ(tree.docref(4)["a"].val(), csubstr("0")); - EXPECT_EQ(tree.docref(4)["b"].val(), csubstr("1")); - EXPECT_EQ(tree.docref(4)["c"].val(), csubstr("2")); - EXPECT_EQ(tree.docref(5)["a"].val(), csubstr("0")); - EXPECT_EQ(tree.docref(5)["b"].val(), csubstr("1")); - EXPECT_EQ(tree.docref(5)["c"].val(), csubstr("2")); - EXPECT_EQ(tree.docref(6)["a"].val(), csubstr("0")); - EXPECT_EQ(tree.docref(6)["b"].val(), csubstr("1")); - EXPECT_EQ(tree.docref(6)["c"].val(), csubstr("2")); -} -#endif // RYML_WITH_TAB_TOKENS - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - - -CASE_GROUP(SIMPLE_MAP) -{ -// -ADD_CASE_TO_GROUP("empty map", -"{}", - MAP -); - -ADD_CASE_TO_GROUP("empty map, multiline", -R"({ -} -)", - MAP -); - -ADD_CASE_TO_GROUP("empty map, multilines", -R"({ -# foo bar baz akjasdkj -} -)", - MAP -); - -ADD_CASE_TO_GROUP("simple map, explicit, single line", -"{foo: 0, bar: 1, baz: 2, bat: 3}", - L{N{"foo", "0"}, N{"bar", "1"}, N{"baz", "2"}, N{"bat", "3"}} -); - -ADD_CASE_TO_GROUP("simple map, explicit, multiline, unindented", -R"({ -foo: 0, -bar: 1, -baz: 2, -bat: 3 -})", - L{N{"foo", "0"}, N{"bar", "1"}, N{"baz", "2"}, N{"bat", "3"}} -); - -ADD_CASE_TO_GROUP("simple map, explicit, multiline, indented", -R"({ - foo: 0, - bar: 1, - baz: 2, - bat: 3 -})", - L{N{"foo", "0"}, N{"bar", "1"}, N{"baz", "2"}, N{"bat", "3"}} -); - -ADD_CASE_TO_GROUP("simple map", -R"( -foo: 0 -bar: 1 -baz: 2 -bat: 3 -)", - L{N{"foo", "0"}, N{"bar", "1"}, N{"baz", "2"}, N{"bat", "3"}} -); - -ADD_CASE_TO_GROUP("simple map, values on next line", -R"( -foo: - 0 -bar: - 1 -baz: - 2 -bat: - 3 -)", - L{N{"foo", "0"}, N{"bar", "1"}, N{"baz", "2"}, N{"bat", "3"}} -); - -ADD_CASE_TO_GROUP("simple map, with comments", -R"( -foo: 0 # this is a foo -bar: 1 # this is a bar -baz: 2 # this is a baz -bat: 3 # this is a bat -)", - L{N{"foo", "0"}, N{"bar", "1"}, N{"baz", "2"}, N{"bat", "3"}} -); - -ADD_CASE_TO_GROUP("simple map, with comments interspersed", -R"( -# this is a foo -foo: 0 -# this is a bar -bar: 1 -# this is a baz -baz: 2 -# this is a bat -bat: 3 -)", - L{N{"foo", "0"}, N{"bar", "1"}, N{"baz", "2"}, N{"bat", "3"}} -); - -ADD_CASE_TO_GROUP("simple map, with comments interspersed implicit key X8DW", -R"( -? key -# comment -: value -)", - L{N("key", "value")} -); - -ADD_CASE_TO_GROUP("simple map, with indented comments interspersed, before", -R"( - # this is a foo -foo: 0 - # this is a bar -bar: 1 - # this is a baz -baz: 2 - # this is a bat -bat: 3 -)", - L{N{"foo", "0"}, N{"bar", "1"}, N{"baz", "2"}, N{"bat", "3"}} -); - -ADD_CASE_TO_GROUP("simple map, with indented comments interspersed, after", -R"( -foo: 0 - # this is a foo -bar: 1 - # this is a bar -baz: 2 - # this is a baz -bat: 3 - # this is a bat -)", - L{N{"foo", "0"}, N{"bar", "1"}, N{"baz", "2"}, N{"bat", "3"}} -); - -ADD_CASE_TO_GROUP("simple map, null values", -R"( -key: val -a: -b: -c: -d: -e: -f: -g: -foo: bar -)", -L{N("key", "val"), N(KEYVAL, "a", /*"~"*/{}), N(KEYVAL, "b", /*"~"*/{}), N(KEYVAL, "c", /*"~"*/{}), N(KEYVAL, "d", /*"~"*/{}), N(KEYVAL, "e", /*"~"*/{}), N(KEYVAL, "f", /*"~"*/{}), N(KEYVAL, "g", /*"~"*/{}), N("foo", "bar"),} -); - -ADD_CASE_TO_GROUP("simple map expl, null values 1", -R"({key: val, a, b, c, d, e: , f: , g: , foo: bar})", -L{N("key", "val"), N(KEYVAL, "a", /*"~"*/{}), N(KEYVAL, "b", /*"~"*/{}), N(KEYVAL, "c", /*"~"*/{}), N(KEYVAL, "d", /*"~"*/{}), N(KEYVAL, "e", /*"~"*/{}), N(KEYVAL, "f", /*"~"*/{}), N(KEYVAL, "g", /*"~"*/{}), N("foo", "bar"),} -); - -ADD_CASE_TO_GROUP("simple map expl, null values 2", -R"( -- {a} -- {a, b, c} -- {a: 1, b: 2, c} -- {a: 1, b, c: 2} -- {a, b: 1, c: 2} -)", -L{ - N(L{N(KEYVAL, "a", /*"~"*/{})}), - N(L{N(KEYVAL, "a", /*"~"*/{}), N(KEYVAL, "b", /*"~"*/{}), N(KEYVAL, "c", /*"~"*/{})}), - N(L{N("a", "1"), N("b", "2"), N(KEYVAL, "c", /*"~"*/{})}), - N(L{N("a", "1"), N(KEYVAL, "b", /*"~"*/{}), N("c", "2")}), - N(L{N(KEYVAL, "a", /*"~"*/{}), N("b", "1"), N("c", "2")}), - } -); - -ADD_CASE_TO_GROUP("simple map expl, null values 3, 4ABK", -R"( -- {foo: , bar: , baz: } -- {foo:, bar:, baz:} -- {foo:foo: , bar:bar: , baz:baz: } -- {foo:foo:, bar:bar:, baz:baz:} -)", -L{ - N(L{N(KEYVAL, "foo", {}), N(KEYVAL, "bar", {}), N(KEYVAL, "baz", {})}), - N(L{N(KEYVAL, "foo", {}), N(KEYVAL, "bar", {}), N(KEYVAL, "baz", {})}), - N(L{N(KEYVAL, "foo:foo", {}), N(KEYVAL, "bar:bar", {}), N(KEYVAL, "baz:baz", {})}), - N(L{N(KEYVAL, "foo:foo", {}), N(KEYVAL, "bar:bar", {}), N(KEYVAL, "baz:baz", {})}), -}); - -ADD_CASE_TO_GROUP("simple map, scalars with special chars, comma", -R"( -a,b: val,000 -c,d: val, 000 -e,f: val , 000 -h,i: val ,000 -a, b: val,000 -c, d: val, 000 -e, f: val , 000 -h, i: val ,000 -a , b: val,000 -c , d: val, 000 -e , f: val , 000 -h , i: val ,000 -a ,b: val,000 -c ,d: val, 000 -e ,f: val , 000 -h ,i: val ,000 -)", - L{ - N{"a,b", "val,000"}, N{"c,d", "val, 000"}, N{"e,f", "val , 000"}, N{"h,i", "val ,000"}, - N{"a, b", "val,000"}, N{"c, d", "val, 000"}, N{"e, f", "val , 000"}, N{"h, i", "val ,000"}, - N{"a , b", "val,000"}, N{"c , d", "val, 000"}, N{"e , f", "val , 000"}, N{"h , i", "val ,000"}, - N{"a ,b", "val,000"}, N{"c ,d", "val, 000"}, N{"e ,f", "val , 000"}, N{"h ,i", "val ,000"}, -} -); - -ADD_CASE_TO_GROUP("simple map, scalars with special chars, semicolon", -R"( -a:b: val:000 -c:d: "val: 000" -e:f: "val : 000" -h:i: val :000 -"a: b": val:000 -"c: d": "val: 000" -"e: f": "val : 000" -"h: i": val :000 -"a : b": val:000 -"c : d": "val: 000" -"e : f": "val : 000" -"h : i": val :000 -a :b: val:000 -c :d: "val: 000" -e :f: "val : 000" -h :i: val :000 -)", - L{ - N{ "a:b", "val:000"}, N{QV, "c:d", "val: 000"}, N{QV, "e:f", "val : 000"}, N{ "h:i", "val :000"}, - N{QK, "a: b", "val:000"}, N{QKV, "c: d", "val: 000"}, N{QKV, "e: f", "val : 000"},N{QK, "h: i", "val :000"}, - N{QK, "a : b", "val:000"},N{QKV, "c : d", "val: 000"},N{QKV, "e : f", "val : 000"},N{QK, "h : i", "val :000"}, - N{ "a :b", "val:000"}, N{QV, "c :d", "val: 000"}, N{QV, "e :f", "val : 000"}, N{ "h :i", "val :000"}, -} -); - -ADD_CASE_TO_GROUP("simple map, scalars with special chars, cardinal", -R"( -a#b: val#000 -c#d: val# 000 -e#f: "val # 000" -h#i: "val #000" -a# b: val#000 -c# d: val# 000 -e# f: "val # 000" -h# i: "val #000" -"a # b": val#000 -"c # d": val# 000 -"e # f": "val # 000" -"h # i": "val #000" -"a #b": val#000 -"c #d": val# 000 -"e #f": "val # 000" -"h #i": "val #000" -)", - L{ - N{ "a#b", "val#000"}, N{ "c#d", "val# 000"}, N{QV, "e#f", "val # 000"}, N{QV, "h#i", "val #000"}, - N{ "a# b", "val#000"}, N{ "c# d", "val# 000"}, N{QV, "e# f", "val # 000"}, N{QV, "h# i", "val #000"}, - N{QK, "a # b", "val#000"}, N{QK, "c # d", "val# 000"}, N{QKV, "e # f", "val # 000"}, N{QKV, "h # i", "val #000"}, - N{QK, "a #b", "val#000"}, N{QK, "c #d", "val# 000"}, N{QKV, "e #f", "val # 000"}, N{QKV, "h #i", "val #000"}, -} -); - -ADD_CASE_TO_GROUP("simple map, scalars with special chars, dash", -R"( -a-b: val-000 -c-d: val- 000 -e-f: val - 000 -h-i: val -000 -a- b: val-000 -c- d: val- 000 -e- f: val - 000 -h- i: val -000 -a - b: val-000 -c - d: val- 000 -e - f: val - 000 -h - i: val -000 -a -b: val-000 -c -d: val- 000 -e -f: val - 000 -h -i: val -000 -)", - L{ - N{"a-b", "val-000"}, N{"c-d", "val- 000"}, N{"e-f", "val - 000"}, N{"h-i", "val -000"}, - N{"a- b", "val-000"}, N{"c- d", "val- 000"}, N{"e- f", "val - 000"}, N{"h- i", "val -000"}, - N{"a - b", "val-000"}, N{"c - d", "val- 000"}, N{"e - f", "val - 000"}, N{"h - i", "val -000"}, - N{"a -b", "val-000"}, N{"c -d", "val- 000"}, N{"e -f", "val - 000"}, N{"h -i", "val -000"}, -} -); - -ADD_CASE_TO_GROUP("simple map, scalars with special chars, left-bracket", -R"( -a[b: val[000 -c[d: val[ 000 -e[f: val [ 000 -h[i: val [000 -a[ b: val[000 -c[ d: val[ 000 -e[ f: val [ 000 -h[ i: val [000 -a [ b: val[000 -c [ d: val[ 000 -e [ f: val [ 000 -h [ i: val [000 -a [b: val[000 -c [d: val[ 000 -e [f: val [ 000 -h [i: val [000 -)", - L{ - N{"a[b", "val[000"}, N{"c[d", "val[ 000"}, N{"e[f", "val [ 000"}, N{"h[i", "val [000"}, - N{"a[ b", "val[000"}, N{"c[ d", "val[ 000"}, N{"e[ f", "val [ 000"}, N{"h[ i", "val [000"}, - N{"a [ b", "val[000"}, N{"c [ d", "val[ 000"}, N{"e [ f", "val [ 000"}, N{"h [ i", "val [000"}, - N{"a [b", "val[000"}, N{"c [d", "val[ 000"}, N{"e [f", "val [ 000"}, N{"h [i", "val [000"}, -} -); - -ADD_CASE_TO_GROUP("simple map, scalars with special chars, right-bracket", -R"( -a]b: val]000 -c]d: val] 000 -e]f: val ] 000 -h]i: val ]000 -a] b: val]000 -c] d: val] 000 -e] f: val ] 000 -h] i: val ]000 -a ] b: val]000 -c ] d: val] 000 -e ] f: val ] 000 -h ] i: val ]000 -a ]b: val]000 -c ]d: val] 000 -e ]f: val ] 000 -h ]i: val ]000 -)", - L{ - N{"a]b", "val]000"}, N{"c]d", "val] 000"}, N{"e]f", "val ] 000"}, N{"h]i", "val ]000"}, - N{"a] b", "val]000"}, N{"c] d", "val] 000"}, N{"e] f", "val ] 000"}, N{"h] i", "val ]000"}, - N{"a ] b", "val]000"}, N{"c ] d", "val] 000"}, N{"e ] f", "val ] 000"}, N{"h ] i", "val ]000"}, - N{"a ]b", "val]000"}, N{"c ]d", "val] 000"}, N{"e ]f", "val ] 000"}, N{"h ]i", "val ]000"}, -} -); - -ADD_CASE_TO_GROUP("simple map, scalars with special chars, left-curly", -R"( -a{b: val{000 -c{d: val{ 000 -e{f: val { 000 -h{i: val {000 -a{ b: val{000 -c{ d: val{ 000 -e{ f: val { 000 -h{ i: val {000 -a { b: val{000 -c { d: val{ 000 -e { f: val { 000 -h { i: val {000 -a {b: val{000 -c {d: val{ 000 -e {f: val { 000 -h {i: val {000 -)", - L{ - N{"a{b", "val{000"}, N{"c{d", "val{ 000"}, N{"e{f", "val { 000"}, N{"h{i", "val {000"}, - N{"a{ b", "val{000"}, N{"c{ d", "val{ 000"}, N{"e{ f", "val { 000"}, N{"h{ i", "val {000"}, - N{"a { b", "val{000"}, N{"c { d", "val{ 000"}, N{"e { f", "val { 000"}, N{"h { i", "val {000"}, - N{"a {b", "val{000"}, N{"c {d", "val{ 000"}, N{"e {f", "val { 000"}, N{"h {i", "val {000"}, -} -); - -ADD_CASE_TO_GROUP("simple map, scalars with special chars, right-curly", -R"( -a}b: val}000 -c}d: val} 000 -e}f: val } 000 -h}i: val }000 -a} b: val}000 -c} d: val} 000 -e} f: val } 000 -h} i: val }000 -a } b: val}000 -c } d: val} 000 -e } f: val } 000 -h } i: val }000 -a }b: val}000 -c }d: val} 000 -e }f: val } 000 -h }i: val }000 -)", - L{ - N{"a}b", "val}000"}, N{"c}d", "val} 000"}, N{"e}f", "val } 000"}, N{"h}i", "val }000"}, - N{"a} b", "val}000"}, N{"c} d", "val} 000"}, N{"e} f", "val } 000"}, N{"h} i", "val }000"}, - N{"a } b", "val}000"}, N{"c } d", "val} 000"}, N{"e } f", "val } 000"}, N{"h } i", "val }000"}, - N{"a }b", "val}000"}, N{"c }d", "val} 000"}, N{"e }f", "val } 000"}, N{"h }i", "val }000"}, -} -); - -ADD_CASE_TO_GROUP("simple map expl, scalars with special chars, comma", -R"({ -a0,b0: val0,0000 -c0,d0: val0, 0000 -e0,f0: val0 , 0000 -h0,i0: val0 ,0000 -a1, b1: val1,0001 -c1, d1: val1, 0001 -e1, f1: val1 , 0001 -h1, i1: val1 ,0001 -a2 , b2: val2,0002 -c2 , d2: val2, 0002 -e2 , f2: val2 , 0002 -h2 , i2: val2 ,0002 -a3 ,b3: val3,0003 -c3 ,d3: val3, 0003 -e3 ,f3: val3 , 0003 -h3 ,i3: val3 ,0003 -})", - L{ // this is crazy... - N(KEYVAL, "a0", /*"~"*/{}), - N("b0", "val0"), - N(KEYVAL, "0000 c0", /*"~"*/{}), - N("d0", "val0"), N(KEYVAL, "0000 e0", /*"~"*/{}), - N("f0", "val0"), N(KEYVAL, "0000 h0", /*"~"*/{}), - N("i0", "val0"), N(KEYVAL, "0000 a1", /*"~"*/{}), - N("b1", "val1"), N(KEYVAL, "0001 c1", /*"~"*/{}), - N("d1", "val1"), N(KEYVAL, "0001 e1", /*"~"*/{}), - N("f1", "val1"), N(KEYVAL, "0001 h1", /*"~"*/{}), - N("i1", "val1"), N(KEYVAL, "0001 a2", /*"~"*/{}), - N("b2", "val2"), N(KEYVAL, "0002 c2", /*"~"*/{}), - N("d2", "val2"), N(KEYVAL, "0002 e2", /*"~"*/{}), - N("f2", "val2"), N(KEYVAL, "0002 h2", /*"~"*/{}), - N("i2", "val2"), N(KEYVAL, "0002 a3", /*"~"*/{}), - N("b3", "val3"), N(KEYVAL, "0003 c3", /*"~"*/{}), - N("d3", "val3"), N(KEYVAL, "0003 e3", /*"~"*/{}), - N("f3", "val3"), N(KEYVAL, "0003 h3", /*"~"*/{}), - N("i3", "val3"), N(KEYVAL, "0003", /*"~"*/{}), -} -); - - -ADD_CASE_TO_GROUP("simple map, spaces before semicolon, issue54", -R"( -foo : crl -keyA : - keyA.B : test value -"key C" : val C -'key D' : val D -elm2 : - "key C" : val C - 'key D' : val D - key E : val E -elm3 : - 'key D' : val D - "key C" : val C - key E : val E -elm4 : - key E : val E - 'key D' : val D - "key C" : val C -)", -L{ - N("foo", "crl"), - N("keyA", L{N("keyA.B", "test value")}), - N(QK, "key C", "val C"), - N(QK, "key D", "val D"), - N("elm2", L{N(QK, "key C", "val C"), N(QK, "key D", "val D"), N("key E", "val E"),}), - N("elm3", L{N(QK, "key D", "val D"), N(QK, "key C", "val C"), N("key E", "val E"),}), - N("elm4", L{N("key E", "val E"), N(QK, "key D", "val D"), N(QK, "key C", "val C"),}), -} -); - -ADD_CASE_TO_GROUP("simple map, spaces before semicolon, issue65, v0", -R"({a : b})", -L{ - N("a", "b"), -} -); - -ADD_CASE_TO_GROUP("simple map, spaces before semicolon, issue65, v1", -R"(a : b)", -L{ - N("a", "b"), -} -); - -ADD_CASE_TO_GROUP("simple map, spaces before semicolon, issue65, v2", -R"( -is it ok : let's see -ok : {a : b, c : d, e : f,} -must be ok : - c0 : d - c1 : d - c2 : d -)", -L{ - N("is it ok", "let's see"), - N("ok", L{N("a", "b"), N("c", "d"), N("e", "f")}), - N("must be ok", L{N("c0", "d"), N("c1", "d"), N("c2", "d")}), -} -); - -ADD_CASE_TO_GROUP("simple map, spaces before semicolon, issue65, v3", -R"({ -oka: {a : b}, -is it ok : let's see, -okb: {a : b}, -ok : {a : b}, -must be ok : { - c0 : d, - c1 : d, - c2 : d, -} -})", -L{ - N("oka", L{N("a", "b")}), - N("is it ok", "let's see"), - N("okb", L{N("a", "b")}), - N("ok", L{N("a", "b")}), - N("must be ok", L{N("c0", "d"), N("c1", "d"), N("c2", "d")}), -}); - -ADD_CASE_TO_GROUP("simple map, empty keys 2JQS, v1", -R"( -: a -: b -)", -N(MAP, L{ - N("", "a"), - N("", "b"), -})); - -ADD_CASE_TO_GROUP("simple map, empty keys 2JQS, v2", -R"( -: - a -: - b -)", -N(MAP, L{ - N("", "a"), - N("", "b"), -})); - -ADD_CASE_TO_GROUP("simple map, empty keys 4ABK, v1", -R"({ -: a, -: b, -})", -N(MAP, L{ - N("", "a"), - N("", "b"), -})); - -ADD_CASE_TO_GROUP("simple map, empty keys 4ABK, v2", -R"({ -: - a, -: - b, -})", -N(MAP, L{ - N("", "a"), - N("", "b"), -})); - -ADD_CASE_TO_GROUP("simple map, values on next line 4MUZ, v1", -R"({foo -: bar, -baz -: bat -})", -N(MAP, L{ - N("foo", "bar"), - N("baz", "bat"), -})); - -ADD_CASE_TO_GROUP("simple map, values on next line 4MUZ, v2", -R"({foo -: - bar, -baz -: - bat -})", -N(MAP, L{ - N("foo", "bar"), - N("baz", "bat"), -})); - -/* this is not valid YAML: plain scalars can't have ':' as a token -ADD_CASE_TO_GROUP("simple map, values on next line 4MUZ, v3", -R"(foo -: bar -baz -: bat -)", -N(MAP, L{ - N("foo", "bar"), - N("baz", "bat"), -})); - -ADD_CASE_TO_GROUP("simple map, values on next line 4MUZ, v4", -R"(foo -: - bar -baz -: - bat -)", -N(MAP, L{ - N("foo", "bar"), - N("baz", "bat"), -})); -*/ - -ADD_CASE_TO_GROUP("json compact", -R"(--- -{ -"foo0":"bar", -"foo1":bar, -"foo3":{"a":map}, -"foo5":[a,seq], -} ---- {"foo0":"bar","foo1":bar,"foo3":{"a":map},"foo5":[a,seq],} -)", -N(STREAM, - L{ - N(DOCMAP, L{ - N(KEYVAL|KEYQUO|VALQUO,"foo0","bar"), - N(KEYVAL|KEYQUO,"foo1","bar"), - N(KEYMAP|KEYQUO,"foo3", L{N(KEYVAL|KEYQUO,"a","map")}), - N(KEYSEQ|KEYQUO,"foo5", L{N("a"),N("seq")}), - }), - N(DOCMAP, L{ - N(KEYVAL|KEYQUO|VALQUO,"foo0","bar"), - N(KEYVAL|KEYQUO,"foo1","bar"), - N(KEYMAP|KEYQUO,"foo3", L{N(KEYVAL|KEYQUO,"a","map")}), - N(KEYSEQ|KEYQUO,"foo5", L{N("a"),N("seq")}), - }), - }) -); - - -ADD_CASE_TO_GROUP("issue223 0 fails", -R"( - A: - - 1 - - 4 - B: - - 2 - - 3 - )", -N(L{ - N("A", L{N("1"), N("4")}), - N("B", L{N("2"), N("3")}), - }) -); - -ADD_CASE_TO_GROUP("issue223 1 passes", -R"(A: - - 1 - - 4 -B: - - 2 - - 3 -)", -N(L{ - N("A", L{N("1"), N("4")}), - N("B", L{N("2"), N("3")}), - }) -); - -ADD_CASE_TO_GROUP("issue223 2 passes", -R"(A: - - 1 - - 4 -B: - - 2 - - 3)", -N(L{ - N("A", L{N("1"), N("4")}), - N("B", L{N("2"), N("3")}), - }) -); -ADD_CASE_TO_GROUP("issue223 3 fails", -R"(A: - - 1 - - 4 -B: - - 2 - - 3 - )", -N(L{ - N("A", L{N("1"), N("4")}), - N("B", L{N("2"), N("3")}), - }) -); -} - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_simple_seq.cpp b/thirdparty/ryml/test/test_simple_seq.cpp deleted file mode 100644 index a24f5d4f7..000000000 --- a/thirdparty/ryml/test/test_simple_seq.cpp +++ /dev/null @@ -1,695 +0,0 @@ -#include "./test_group.hpp" - -namespace c4 { -namespace yml { - -TEST(simple_seq, bad_seq1) -{ - Tree tree; - ExpectError::do_check(&tree, [&]{ - parse_in_arena(R"( ---- -[ a, b, c ] ] -)", &tree); - }); -} - -TEST(simple_seq, bad_seq2) -{ - Tree tree; - ExpectError::do_check(&tree, [&]{ - parse_in_arena(R"( ---- -[ [ a, b, c ] -)", &tree); - }); -} - -TEST(simple_seq, two_nested_flow_seqs) -{ - Tree tree = parse_in_arena("[[]]"); - EXPECT_TRUE(tree.rootref().is_seq()); - ASSERT_TRUE(tree.rootref().has_children()); - EXPECT_TRUE(tree.rootref().first_child().is_seq()); - ASSERT_FALSE(tree.rootref().first_child().has_children()); -} - -TEST(simple_seq, many_unmatched_brackets) -{ - std::string src; - src.reserve(10000000u); - for(size_t num_brackets : {4u, 8u, 32u}) - { - SCOPED_TRACE(num_brackets); - for(size_t i = src.size(); i < num_brackets; ++i) - src += '['; - Tree tree; - Location loc = {}; - loc.line = 1; - loc.col = num_brackets + 1u; - ExpectError::do_check(&tree, [&]{ - parse_in_place(to_substr(src), &tree); - }, loc); - } -} - -TEST(simple_seq, missing_quoted_key) -{ - csubstr yaml = R"( -"top1" : - ["0", "1", ] -'top2' : - ["0", "1", ] ---- -"top1" : - - "0" - - "1" -'top2' : - - "0" - - "1" -)"; - test_check_emit_check(yaml, [](Tree const &t){ - size_t doc = 0; - EXPECT_TRUE(t.docref(doc)["top1"].is_key_quoted()); - EXPECT_TRUE(t.docref(doc)["top2"].is_key_quoted()); - EXPECT_TRUE(t.docref(doc)["top1"][0].is_val_quoted()); - EXPECT_TRUE(t.docref(doc)["top1"][1].is_val_quoted()); - EXPECT_TRUE(t.docref(doc)["top2"][0].is_val_quoted()); - EXPECT_TRUE(t.docref(doc)["top2"][1].is_val_quoted()); - ++doc; - EXPECT_TRUE(t.docref(doc)["top1"].is_key_quoted()); - EXPECT_TRUE(t.docref(doc)["top2"].is_key_quoted()); - EXPECT_TRUE(t.docref(doc)["top1"][0].is_val_quoted()); - EXPECT_TRUE(t.docref(doc)["top1"][1].is_val_quoted()); - EXPECT_TRUE(t.docref(doc)["top2"][0].is_val_quoted()); - EXPECT_TRUE(t.docref(doc)["top2"][1].is_val_quoted()); - }); -} - -TEST(simple_seq, deeply_nested_to_cover_parse_stack_resizes) -{ - csubstr yaml = R"( -[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[0, 1, 2, 3, 4, 5, 6, 7]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] -)"; - Tree t = parse_in_arena(yaml); - size_t id = t.root_id(); - while(t.has_children(id)) - id = t.first_child(id); - ASSERT_TRUE(t.ref(id).has_parent()); - NodeRef seq = t.ref(id).parent(); - ASSERT_TRUE(seq.is_seq()); - EXPECT_EQ(seq[0].val(), csubstr("0")); - EXPECT_EQ(seq[1].val(), csubstr("1")); - EXPECT_EQ(seq[2].val(), csubstr("2")); - EXPECT_EQ(seq[3].val(), csubstr("3")); - EXPECT_EQ(seq[4].val(), csubstr("4")); - EXPECT_EQ(seq[5].val(), csubstr("5")); - EXPECT_EQ(seq[6].val(), csubstr("6")); - EXPECT_EQ(seq[7].val(), csubstr("7")); -} - - -#ifdef RYML_WITH_TAB_TOKENS -TEST(simple_seq, block_tab_tokens) -{ - Tree tree = parse_in_arena(R"( ---- # block, spaces only -- 0 -- 1 -- 2 ---- # block, tabs after -- 0 -- 1 -- 2 ---- # block, tabs after token, and after val -- 0 -- 1 -- 2 -)"); - EXPECT_EQ(tree.docref(0)[0].val(), csubstr("0")); - EXPECT_EQ(tree.docref(0)[1].val(), csubstr("1")); - EXPECT_EQ(tree.docref(0)[2].val(), csubstr("2")); - EXPECT_EQ(tree.docref(1)[0].val(), csubstr("0")); - EXPECT_EQ(tree.docref(1)[1].val(), csubstr("1")); - EXPECT_EQ(tree.docref(1)[2].val(), csubstr("2")); -} - -TEST(simple_seq, flow_tab_tokens) -{ - Tree tree = parse_in_arena(R"( ---- # flow, no tabs -[0, 1, 2] ---- # flow, tabs after -[0, 1, 2] ---- # flow, tabs before and after -[0 , 1 , 2] ---- # flow, tabs everywhere - [ - 0 , - 1 , - 2 , - ] -)"); - EXPECT_EQ(tree.docref(0)[0].val(), csubstr("0")); - EXPECT_EQ(tree.docref(0)[1].val(), csubstr("1")); - EXPECT_EQ(tree.docref(0)[2].val(), csubstr("2")); - EXPECT_EQ(tree.docref(1)[0].val(), csubstr("0")); - EXPECT_EQ(tree.docref(1)[1].val(), csubstr("1")); - EXPECT_EQ(tree.docref(1)[2].val(), csubstr("2")); - EXPECT_EQ(tree.docref(2)[0].val(), csubstr("0")); - EXPECT_EQ(tree.docref(2)[1].val(), csubstr("1")); - EXPECT_EQ(tree.docref(2)[2].val(), csubstr("2")); - EXPECT_EQ(tree.docref(3)[0].val(), csubstr("0")); - EXPECT_EQ(tree.docref(3)[1].val(), csubstr("1")); - EXPECT_EQ(tree.docref(3)[2].val(), csubstr("2")); -} -#endif // RYML_WITH_TAB_TOKENS - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - - -CASE_GROUP(SIMPLE_SEQ) -{ - -ADD_CASE_TO_GROUP("simple seq", -R"(- 0 -- 1 -- 2 -- 3 -)", -L{N{"0"}, N{"1"}, N{"2"}, N{"3"}} -); - - -ADD_CASE_TO_GROUP("simple seq, explicit, single line", -"[0, 1, 2, 3]", -L{N{"0"}, N{"1"}, N{"2"}, N{"3"}} -); - -ADD_CASE_TO_GROUP("simple seq, explicit, single line, trailcomma", -"[0, 1, 2, 3,]", -L{N{"0"}, N{"1"}, N{"2"}, N{"3"},} -); - -ADD_CASE_TO_GROUP("simple seq, explicit, multiline, unindented", -R"([ -0, -1, -2, -3 -])", - L{N{"0"}, N{"1"}, N{"2"}, N{"3"}} -); - -ADD_CASE_TO_GROUP("simple seq, explicit, multiline, unindented, trailcomma", -R"([ -0, -1, -2, -3, -])", - L{N{"0"}, N{"1"}, N{"2"}, N{"3"}} -); - -ADD_CASE_TO_GROUP("simple seq, explicit, multiline, comments inline", -R"([ -0, # bla0 -1, # bla1 -2, # bla2 -3 # bla3 -])", - L{N{"0"}, N{"1"}, N{"2"}, N{"3"}} -); - -ADD_CASE_TO_GROUP("simple seq, explicit, multiline, comments prev line", -R"([ -# bla0 -0, -# bla1 -1, -# bla2 -2, -# bla3 -3 -])", - L{N{"0"}, N{"1"}, N{"2"}, N{"3"}} -); - -ADD_CASE_TO_GROUP("simple seq, explicit, multiline, indented", -R"([ - 0, - 1, - 2, - 3 -])", - L{N{"0"}, N{"1"}, N{"2"}, N{"3"}} -); - -ADD_CASE_TO_GROUP("simple seq, comments inline", -R"( -- 0 # this is a foo -- 1 # this is a bar -- 2 # this is a bar -- 3 # this is a bar -)", - L{N{"0"}, N{"1"}, N{"2"}, N{"3"}} -); - -ADD_CASE_TO_GROUP("simple seq, comments prev line", -R"( -# this is a foo -- 0 -# this is a bar -- 1 -# this is a baz -- 2 -# this is a bat -- 3 -)", - L{N{"0"}, N{"1"}, N{"2"}, N{"3"}} -); - -ADD_CASE_TO_GROUP("simple seq, scalars with special chars, comma", -R"( -- a,b -- c,d -- e,f -- a, b -- c, d -- e, f -- a , b -- c , d -- e , f -- a ,b -- c ,d -- e ,f -)", -L{N{"a,b"}, N{"c,d"}, N{"e,f"}, - N{"a, b"}, N{"c, d"}, N{"e, f"}, - N{"a , b"}, N{"c , d"}, N{"e , f"}, - N{"a ,b"}, N{"c ,d"}, N{"e ,f"}, - } -); - -ADD_CASE_TO_GROUP("simple seq, scalars with special chars, colon", -R"( -- a:b -- "c:d" -- 'e:f' -- a :b -- "c :d" -- 'e :f' -- a : b # THIS IS A KEY-VAL!!! -- "c : d" -- 'e : f' -- a: b # THIS IS A KEY-VAL!!! -- "c: d" -- 'e: f' -)", -L{ - N("a:b"), N(QV, "c:d"), N(QV, "e:f"), - N("a :b"), N(QV, "c :d"), N(QV, "e :f"), - N(L{N("a", "b")}), N(QV, "c : d"), N(QV, "e : f"), - N(L{N("a", "b")}), N(QV, "c: d"), N(QV, "e: f"), - } -); - -ADD_CASE_TO_GROUP("simple seq, scalars with special chars, cardinal", -R"( -- a#b -- "a#b" -- 'a#b' -- a# b -- "a# b" -- 'a# b' -- a # b -- "a # b" -- 'a # b' -- a #b -- "a #b" -- 'a #b' -)", -L{ - N{"a#b"}, N{QV, "a#b"}, N{QV, "a#b"}, - N{"a# b"}, N{QV, "a# b"}, N{QV, "a# b"}, - N{"a"}, N{QV, "a # b"}, N{QV, "a # b"}, - N{"a"}, N{QV, "a #b"}, N{QV, "a #b"}, - } -); - -ADD_CASE_TO_GROUP("simple seq, scalars with special chars, dash", -R"( -- a-b -- "a-b" -- 'a-b' -- a- b -- "a- b" -- 'a- b' -- a - b -- "a - b" -- 'a - b' -- a -b -- "a -b" -- 'a -b' -)", -L{ - N{"a-b"}, N{QV, "a-b"}, N{QV, "a-b"}, - N{"a- b"}, N{QV, "a- b"}, N{QV, "a- b"}, - N{"a - b"}, N{QV, "a - b"}, N{QV, "a - b"}, - N{"a -b"}, N{QV, "a -b"}, N{QV, "a -b"}, - } -); - -ADD_CASE_TO_GROUP("simple seq, scalars with special chars, left-curly", -R"( -- a{b -- "a{b" -- 'a{b' -- a{ b -- "a{ b" -- 'a{ b' -- a { b -- "a { b" -- 'a { b' -- a {b -- "a {b" -- 'a {b' -)", -L{ - N{"a{b"}, N{QV, "a{b"}, N{QV, "a{b"}, - N{"a{ b"}, N{QV, "a{ b"}, N{QV, "a{ b"}, - N{"a { b"}, N{QV, "a { b"}, N{QV, "a { b"}, - N{"a {b"}, N{QV, "a {b"}, N{QV, "a {b"}, - } -); - -ADD_CASE_TO_GROUP("simple seq, scalars with special chars, right-curly", -R"( -- a}b -- "a}b" -- 'a}b' -- a} b -- "a} b" -- 'a} b' -- a } b -- "a } b" -- 'a } b' -- a }b -- "a }b" -- 'a }b' -)", -L{ - N{"a}b"}, N{QV, "a}b"}, N{QV, "a}b"}, - N{"a} b"}, N{QV, "a} b"}, N{QV, "a} b"}, - N{"a } b"}, N{QV, "a } b"}, N{QV, "a } b"}, - N{"a }b"}, N{QV, "a }b"}, N{QV, "a }b"}, - } -); - -ADD_CASE_TO_GROUP("simple seq, scalars with special chars, left-bracket", -R"( -- a[b -- "a[b" -- 'a[b' -- a[ b -- "a[ b" -- 'a[ b' -- a [ b -- "a [ b" -- 'a [ b' -- a [b -- "a [b" -- 'a [b' -)", -L{ - N{"a[b"}, N{QV, "a[b"}, N{QV, "a[b"}, - N{"a[ b"}, N{QV, "a[ b"}, N{QV, "a[ b"}, - N{"a [ b"}, N{QV, "a [ b"}, N{QV, "a [ b"}, - N{"a [b"}, N{QV, "a [b"}, N{QV, "a [b"}, - } -); - -ADD_CASE_TO_GROUP("simple seq, scalars with special chars, right-bracket", -R"( -- a]b -- "a]b" -- 'a]b' -- a] b -- "a] b" -- 'a] b' -- a ] b -- "a ] b" -- 'a ] b' -- a ]b -- "a ]b" -- 'a ]b' -)", -L{ - N{"a]b"}, N{QV, "a]b"}, N{QV, "a]b"}, - N{"a] b"}, N{QV, "a] b"}, N{QV, "a] b"}, - N{"a ] b"}, N{QV, "a ] b"}, N{QV, "a ] b"}, - N{"a ]b"}, N{QV, "a ]b"}, N{QV, "a ]b"}, - } -); - -ADD_CASE_TO_GROUP("simple seq expl, scalars with special chars, comma", -R"([ - a,b, "c,d", 'e,f', - a, b, "c, d", 'e, f', - a , b, "c , d", 'e , f', - a ,b, "c ,d", 'e ,f', -])", -L{ - N{"a"}, N("b"), N(QV, "c,d"), N(QV, "e,f"), - N{"a"}, N("b"), N(QV, "c, d"), N(QV, "e, f"), - N{"a"}, N("b"), N(QV, "c , d"), N(QV, "e , f"), - N{"a"}, N("b"), N(QV, "c ,d"), N(QV, "e ,f"), - } -); - -#ifdef RYML_WITH_TAB_TOKENS -#define _ryml_with_or_without_tabs(with, without) with -#else -#define _ryml_with_or_without_tabs(with, without) without -#endif -ADD_CASE_TO_GROUP("simple seq expl, scalars with special chars, colon", -R"( -- [[], :@] -- [[], :%] -- [[], :^] -- [[], :$] -#- [[], ::] -- [[], : ] -- [[], :`] -)", -L{ - N(L{N(SEQ), N(":@")}), - N(L{N(SEQ), N(":%")}), - N(L{N(SEQ), N(":^")}), - N(L{N(SEQ), N(":$")}), - //N(L{N(SEQ), N("::")}), TODO: yaml playground - N(L{N(SEQ), _ryml_with_or_without_tabs(N(MAP, L{N("", "")}), N(": "))}), - N(L{N(SEQ), N(":`")}), -} -); - -ADD_CASE_TO_GROUP("simple seq expl, scalars with special chars, colon 2", -R"([ -# a:b, # not legal - "c:d", 'e:f', -# a: b, # not legal - "c: d", 'e: f', -# a : b, # not legal - "c : d", 'e : f', -# a :b, # not legal - "c :d", 'e :f', -])", -L{/*...not legal...*/ - /*N{"a"}, N("b"),*/ N(QV, "c:d"), N(QV, "e:f"), - /*N{"a"}, N("b"),*/ N(QV, "c: d"), N(QV, "e: f"), - /*N{"a"}, N("b"),*/ N(QV, "c : d"), N(QV, "e : f"), - /*N{"a"}, N("b"),*/ N(QV, "c :d"), N(QV, "e :f"), - } -); - -ADD_CASE_TO_GROUP("simple seq expl, scalars with special chars, cardinal", -R"([ - a#b, "c#d", 'e#f', - a# b, "c# d", 'e# f', - a # b, "c # d", 'e # f', -, # this is needed because of the comment above - a #b, "c #d", 'e #f', -])", -L{ - N{"a#b"}, N(QV, "c#d"), N(QV, "e#f"), - N{"a# b"}, N(QV, "c# d"), N(QV, "e# f"), - N{"a"}, - N{"a"}, - } -); - -ADD_CASE_TO_GROUP("simple seq expl, scalars with special chars, dash", -R"([ - a-b, "c-d", 'e-f', - a- b, "c- d", 'e- f', - a - b, "c - d", 'e - f', - a -b, "c -d", 'e -f', -])", -L{ - N{"a-b"}, N(QV, "c-d"), N(QV, "e-f"), - N{"a- b"}, N(QV, "c- d"), N(QV, "e- f"), - N{"a - b"}, N(QV, "c - d"), N(QV, "e - f"), - N{"a -b"}, N(QV, "c -d"), N(QV, "e -f"), - } -); - -ADD_CASE_TO_GROUP("simple seq expl, scalars with special chars, left-bracket", -R"([ -# a[b, - "c[d", 'e[f', -# a[ b, - "c[ d", 'e[ f', -# a [ b, - "c [ d", 'e [ f', -# a [b, - "c [d", 'e [f', -])", -L{ - /*N{"a[b"}, */ N(QV, "c[d"), N(QV, "e[f"), - /*N{"a[ b"}, */ N(QV, "c[ d"), N(QV, "e[ f"), - /*N{"a [ b"},*/ N(QV, "c [ d"), N(QV, "e [ f"), - /*N{"a [b"}, */ N(QV, "c [d"), N(QV, "e [f"), - } -); - -ADD_CASE_TO_GROUP("simple seq expl, scalars with special chars, right-bracket", -R"([ -# a]b, - "c]d", 'e]f', -# a] b, - "c] d", 'e] f', -# a ] b, - "c ] d", 'e ] f', -# a ]b, - "c ]d", 'e ]f', -])", -L{ - /*N{"a]b"}, */ N(QV, "c]d"), N(QV, "e]f"), - /*N{"a] b"}, */ N(QV, "c] d"), N(QV, "e] f"), - /*N{"a ] b"},*/ N(QV, "c ] d"), N(QV, "e ] f"), - /*N{"a ]b"}, */ N(QV, "c ]d"), N(QV, "e ]f"), - } -); - -ADD_CASE_TO_GROUP("simple seq expl, scalars with special chars, left-curly", -R"([ -# a{b, - "c{d", 'e{f', -# a{ b, - "c{ d", 'e{ f', -# a { b, - "c { d", 'e { f', -# a {b, - "c {d", 'e {f', -])", -L{ - /*N{"a{b"}, */ N(QV, "c{d"), N(QV, "e{f"), - /*N{"a{ b"}, */ N(QV, "c{ d"), N(QV, "e{ f"), - /*N{"a { b"},*/ N(QV, "c { d"), N(QV, "e { f"), - /*N{"a {b"}, */ N(QV, "c {d"), N(QV, "e {f"), - } -); - -ADD_CASE_TO_GROUP("simple seq expl, scalars with special chars, right-curly", -R"([ -# a}b, - "c}d", 'e}f', -# a} b, - "c} d", 'e} f', -# a } b, - "c } d", 'e } f', -# a }b, - "c }d", 'e }f', -])", -L{ - /*N{"a}b"}, */ N(QV, "c}d"), N(QV, "e}f"), - /*N{"a} b"}, */ N(QV, "c} d"), N(QV, "e} f"), - /*N{"a } b"},*/ N(QV, "c } d"), N(QV, "e } f"), - /*N{"a }b"}, */ N(QV, "c }d"), N(QV, "e }f"), - } -); - -ADD_CASE_TO_GROUP("simple seq, issue 28", -R"(# was failing on https://github.com/biojppm/rapidyaml/issues/28 -enemy: -- actors: - - {name: Enemy_Bokoblin_Junior, value: 4.0} - - {name: Enemy_Bokoblin_Middle, value: 16.0} - - {name: Enemy_Bokoblin_Senior, value: 32.0} - - {name: Enemy_Bokoblin_Dark, value: 48.0} - species: BokoblinSeries -enemy2: -- actors: - - {name: Enemy_Bokoblin_Junior, value: 4.0} - - {name: Enemy_Bokoblin_Middle, value: 16.0} - - {name: Enemy_Bokoblin_Senior, value: 32.0} - - {name: Enemy_Bokoblin_Dark, value: 48.0} - species: BokoblinSeries -)", -L{ - N("enemy", L{N(L{ - N("actors", L{ - N(L{N("name", "Enemy_Bokoblin_Junior"), N("value", "4.0"),}), - N(L{N("name", "Enemy_Bokoblin_Middle"), N("value", "16.0"),}), - N(L{N("name", "Enemy_Bokoblin_Senior"), N("value", "32.0"),}), - N(L{N("name", "Enemy_Bokoblin_Dark"), N("value", "48.0"),}), - }), - N("species", "BokoblinSeries"), - }) - }), - N("enemy2", L{N(L{ - N("actors", L{ - N(L{N("name", "Enemy_Bokoblin_Junior"), N("value", "4.0"),}), - N(L{N("name", "Enemy_Bokoblin_Middle"), N("value", "16.0"),}), - N(L{N("name", "Enemy_Bokoblin_Senior"), N("value", "32.0"),}), - N(L{N("name", "Enemy_Bokoblin_Dark"), N("value", "48.0"),}), - }), - N("species", "BokoblinSeries"), - }) - }), -}); - -ADD_CASE_TO_GROUP("simple seq, invalid character 1", EXPECT_PARSE_ERROR, -R"(- 0 # this is a foo -} -)", - LineCol(2, 1) -); - -ADD_CASE_TO_GROUP("simple seq, invalid character 2", EXPECT_PARSE_ERROR, -R"(- 0 # this is a foo -] -)", - LineCol(2, 1) -); - -ADD_CASE_TO_GROUP("simple seq, invalid character 3", EXPECT_PARSE_ERROR, -R"(- 0 # this is a foo -: -)", - LineCol(2, 1) -); - -ADD_CASE_TO_GROUP("simple seq, invalid character 4", EXPECT_PARSE_ERROR, -R"(- 0 # this is a foo -abcdef! -)", - LineCol(2, 1) -); -} - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_simple_set.cpp b/thirdparty/ryml/test/test_simple_set.cpp deleted file mode 100644 index f209c79c7..000000000 --- a/thirdparty/ryml/test/test_simple_set.cpp +++ /dev/null @@ -1,144 +0,0 @@ -#include "./test_group.hpp" - -namespace c4 { -namespace yml { - - -TEST(simple_set, emit) -{ - const char yaml[] = R"(!!set -? aa -? bb -? cc -)"; - std::string expected = R"(!!set -aa: -bb: -cc: -)"; - Tree t = parse_in_arena(yaml); - auto s = emitrs_yaml(t); - EXPECT_EQ(expected, s); -} - - -TEST(simple_set, emit_doc) -{ - const char yaml[] = R"(--- !!set -? aa -? bb -? cc -)"; - std::string expected = R"(--- !!set -aa: -bb: -cc: -)"; - Tree t = parse_in_arena(yaml); - auto s = emitrs_yaml(t); - EXPECT_EQ(expected, s); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -CASE_GROUP(SIMPLE_SET) -{ - -ADD_CASE_TO_GROUP("doc as set, missing value", -R"(!!set -? a -? b -? -)", -N(TL("!!set", L{N(KEYVAL, "a", {}), N(KEYVAL, "b", {}), N(KEYVAL, {}, "")})) -); - -ADD_CASE_TO_GROUP("doc as set, implicit", -R"(!!set -? a -? b -)", -N(TL("!!set", L{N(KEYVAL, "a", {}), N(KEYVAL, "b", {})})) -); - -ADD_CASE_TO_GROUP("doc as set", -R"(--- !!set -? aa -? bb -? cc -)", -N(STREAM, L{N(DOCMAP, TL("!!set", L{ - N(KEYVAL, "aa", /*"~"*/{}), - N(KEYVAL, "bb", /*"~"*/{}), - N(KEYVAL, "cc", /*"~"*/{})}) -)})); - -ADD_CASE_TO_GROUP("sets 2XXW", -R"( ---- !!set -? Mark McGwire -? Sammy Sosa -? Ken Griff -)", -N(STREAM, L{N(DOCMAP, TL("!!set", L{ - N(KEYVAL, "Mark McGwire", /*"~"*/{}), - N(KEYVAL, "Sammy Sosa", /*"~"*/{}), - N(KEYVAL, "Ken Griff", /*"~"*/{}),}) -)})); - -ADD_CASE_TO_GROUP("sets 2XXW, indented", -R"( - --- !!set - ? Mark McGwire - ? Sammy Sosa - ? Ken Griff -)", -N(STREAM, L{N(DOCMAP, TL("!!set", L{ - N(KEYVAL, "Mark McGwire", /*"~"*/{}), - N(KEYVAL, "Sammy Sosa", /*"~"*/{}), - N(KEYVAL, "Ken Griff", /*"~"*/{}),}) -)})); - -ADD_CASE_TO_GROUP("sets 2XXW, no set", -R"( ---- -? Mark McGwire -? Sammy Sosa -? Ken Griff -)", -N(STREAM, L{N(DOCMAP, L{ - N(KEYVAL, "Mark McGwire", /*"~"*/{}), - N(KEYVAL, "Sammy Sosa", /*"~"*/{}), - N(KEYVAL, "Ken Griff", /*"~"*/{}),} -)})); - -ADD_CASE_TO_GROUP("sets 2XXW, no doc", -R"(!!set -? Mark McGwire -? Sammy Sosa -? Ken Griff -)", -TL("!!set", L{ - N(KEYVAL, "Mark McGwire", /*"~"*/{}), - N(KEYVAL, "Sammy Sosa", /*"~"*/{}), - N(KEYVAL, "Ken Griff", /*"~"*/{}), -})); - -ADD_CASE_TO_GROUP("sets 2XXW, no doc, no set", -R"( -? Mark McGwire -? Sammy Sosa -? Ken Griff -)", -L{ - N(KEYVAL, "Mark McGwire", /*"~"*/{}), - N(KEYVAL, "Sammy Sosa", /*"~"*/{}), - N(KEYVAL, "Ken Griff", /*"~"*/{}), -}); -} - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_single_quoted.cpp b/thirdparty/ryml/test/test_single_quoted.cpp deleted file mode 100644 index d27fdb6e0..000000000 --- a/thirdparty/ryml/test/test_single_quoted.cpp +++ /dev/null @@ -1,356 +0,0 @@ -#include "./test_group.hpp" - -namespace c4 { -namespace yml { - -TEST(single_quoted, test_suite_KSS4) -{ - csubstr yaml = R"( ---- -'quoted -string' ---- 'quoted -string' ---- -- 'quoted - string' ---- -- 'quoted -string' ---- -'quoted - string': 'quoted - string' ---- -'quoted -string': 'quoted -string' -)"; - test_check_emit_check(yaml, [](Tree const &t){ - EXPECT_EQ(t.docref(0).val(), "quoted string"); - EXPECT_EQ(t.docref(1).val(), "quoted string"); - EXPECT_EQ(t.docref(2)[0].val(), "quoted string"); - EXPECT_EQ(t.docref(3)[0].val(), "quoted string"); - EXPECT_EQ(t.docref(4)["quoted string"].val(), "quoted string"); - EXPECT_EQ(t.docref(5)["quoted string"].val(), "quoted string"); - }); -} - - -TEST(single_quoted, test_suite_R4YG) -{ - csubstr yaml = R"( -- ' - -detected - -' - -)"; - test_check_emit_check(yaml, [](Tree const &t){ - EXPECT_EQ(t[0].val(), csubstr("\t\ndetected\n")); - }); -} - - -TEST(single_quoted, test_suite_PRH3) -{ - csubstr yaml = R"( -- ' 1st non-empty - - 2nd non-empty - 3rd non-empty ' -- ' 1st non-empty - - 2nd non-empty - 3rd non-empty ' -- ' 1st non-empty - - 2nd non-empty - 3rd non-empty ' -)"; - test_check_emit_check(yaml, [](Tree const &t){ - EXPECT_EQ(t[0].val(), csubstr(" 1st non-empty\n2nd non-empty 3rd non-empty ")); - EXPECT_EQ(t[1].val(), csubstr(" 1st non-empty\n2nd non-empty 3rd non-empty ")); - EXPECT_EQ(t[2].val(), csubstr(" 1st non-empty\n2nd non-empty 3rd non-empty ")); - }); -} - - -TEST(single_quoted, test_suite_T4YY) -{ - csubstr yaml = R"( ---- -' 1st non-empty - - 2nd non-empty - 3rd non-empty ' ---- -' - -detected - -' - -)"; - test_check_emit_check(yaml, [](Tree const &t){ - ASSERT_TRUE(t.rootref().is_stream()); - ASSERT_TRUE(t.rootref().first_child().is_doc()); - EXPECT_EQ(t.rootref().first_child().val(), csubstr(" 1st non-empty\n2nd non-empty 3rd non-empty ")); - }); -} - -TEST(single_quoted, test_suite_G4RS) -{ - csubstr yaml = R"( -single: '"Howdy!" he cried.' -quoted: ' # Not a ''comment''.' -tie-fighter: '|\-*-/|' -)"; - test_check_emit_check(yaml, [](Tree const &t){ - EXPECT_EQ(t["single"].val() , csubstr(R"("Howdy!" he cried.)")); - EXPECT_EQ(t["quoted"].val() , csubstr(R"( # Not a 'comment'.)")); - EXPECT_EQ(t["tie-fighter"].val(), csubstr(R"(|\-*-/|)")); - }); -} - -TEST(single_quoted, quotes_are_preserved) -{ - csubstr yaml = R"( -'%ROOT': '%VAL' -'%ROOT2': - - '%VAL' - - '%VAL' -)"; - test_check_emit_check(yaml, [](Tree const &t){ - ASSERT_TRUE(t.rootref().is_map()); - ASSERT_TRUE(t.rootref().has_child("%ROOT")); - ASSERT_TRUE(t.rootref().has_child("%ROOT2")); - ASSERT_EQ(t["%ROOT2"].num_children(), 2u); - EXPECT_TRUE(t["%ROOT"].is_key_quoted()); - EXPECT_TRUE(t["%ROOT"].is_val_quoted()); - EXPECT_TRUE(t["%ROOT2"].is_key_quoted()); - EXPECT_TRUE(t["%ROOT2"][0].is_val_quoted()); - EXPECT_TRUE(t["%ROOT2"][1].is_val_quoted()); - }); -} - - -//----------------------------------------------------------------------------- - -void verify_error_is_reported(csubstr case_name, csubstr yaml, Location loc={}) -{ - SCOPED_TRACE(case_name); - SCOPED_TRACE(yaml); - Tree tree; - ExpectError::do_check(&tree, [&](){ - parse_in_arena(yaml, &tree); - }, loc); -} - -TEST(single_quoted, error_on_unmatched_quotes) -{ - verify_error_is_reported("map block", R"(foo: '" -bar: '')"); - verify_error_is_reported("seq block", R"(- '" -- '')"); - verify_error_is_reported("map flow", R"({foo: '", bar: ''})"); - verify_error_is_reported("seq flow", R"(['", ''])"); -} - -TEST(single_quoted, error_on_unmatched_quotes_with_escapes) -{ - verify_error_is_reported("map block", R"(foo: '''" -bar: '')"); - verify_error_is_reported("seq block", R"(- '''" -- '')"); - verify_error_is_reported("map flow", R"({foo: '''", bar: ''})"); - verify_error_is_reported("seq flow", R"(['''", ''])"); -} - -TEST(single_quoted, error_on_unmatched_quotes_at_end) -{ - verify_error_is_reported("map block", R"(foo: '' -bar: '")"); - verify_error_is_reported("seq block", R"(- '' -- '")"); - verify_error_is_reported("map flow", R"({foo: '', bar: '"})"); - verify_error_is_reported("seq flow", R"(['', '"])"); -} - -TEST(single_quoted, error_on_unmatched_quotes_at_end_with_escapes) -{ - verify_error_is_reported("map block", R"(foo: '' -bar: '''")"); - verify_error_is_reported("seq block", R"(- '' -- '''")"); - verify_error_is_reported("map flow", R"({foo: '', bar: '''"})"); - verify_error_is_reported("seq flow", R"(['', '''"])"); -} - -TEST(single_quoted, error_on_unclosed_quotes) -{ - verify_error_is_reported("map block", R"(foo: ', -bar: what)"); - verify_error_is_reported("seq block", R"(- ' -- what)"); - verify_error_is_reported("map flow", R"({foo: ', bar: what})"); - verify_error_is_reported("seq flow", R"([', what])"); -} - -TEST(single_quoted, error_on_unclosed_quotes_with_escapes) -{ - verify_error_is_reported("map block", R"(foo: ''', -bar: what)"); - verify_error_is_reported("seq block", R"(- ''' -- what)"); - verify_error_is_reported("map flow", R"({foo: ''', bar: what})"); - verify_error_is_reported("seq flow", R"([''', what])"); -} - -TEST(single_quoted, error_on_unclosed_quotes_at_end) -{ - verify_error_is_reported("map block", R"(foo: what -bar: ')"); - verify_error_is_reported("seq block", R"(- what -- ')"); - verify_error_is_reported("map flow", R"({foo: what, bar: '})"); - verify_error_is_reported("seq flow", R"([what, '])"); -} - -TEST(single_quoted, error_on_unclosed_quotes_at_end_with_escapes) -{ - verify_error_is_reported("map block", R"(foo: what -bar: ''')"); - verify_error_is_reported("seq block", R"(- what -- ''')"); - verify_error_is_reported("map flow", R"({foo: what, bar: '''})"); - verify_error_is_reported("seq flow", R"([what, '''])"); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -CASE_GROUP(SINGLE_QUOTED) -{ - -ADD_CASE_TO_GROUP("squoted, only text", -R"('Some text without any quotes.' -)", - N(DOCVAL | VALQUO, "Some text without any quotes.") -); - -ADD_CASE_TO_GROUP("squoted, with double quotes", -R"('Some "text" "with double quotes"')", - N(DOCVAL | VALQUO, "Some \"text\" \"with double quotes\"") -); - -ADD_CASE_TO_GROUP("squoted, with single quotes", -R"('Some text ''with single quotes''')", - N(DOCVAL | VALQUO, "Some text 'with single quotes'") -); - -ADD_CASE_TO_GROUP("squoted, with single and double quotes", -R"('Some text ''with single quotes'' "and double quotes".')", - N(DOCVAL | VALQUO, "Some text 'with single quotes' \"and double quotes\".") -); - -ADD_CASE_TO_GROUP("squoted, with escapes", -R"('Some text with escapes \n \r \t')", - N(DOCVAL | VALQUO, "Some text with escapes \\n \\r \\t") -); - -ADD_CASE_TO_GROUP("squoted, all", -R"('Several lines of text, -containing ''single quotes'' and "double quotes". Escapes (like \n) don''t do anything. - -Newlines can be added by leaving a blank line. - Leading whitespace on lines is ignored.' -)", - N(DOCVAL | VALQUO, "Several lines of text, containing 'single quotes' and \"double quotes\". Escapes (like \\n) don't do anything.\nNewlines can be added by leaving a blank line. Leading whitespace on lines is ignored.") -); - -ADD_CASE_TO_GROUP("squoted, empty", -R"('')", - N(DOCVAL | VALQUO, "") -); - -ADD_CASE_TO_GROUP("squoted, blank", -R"( -- '' -- ' ' -- ' ' -- ' ' -- ' ' -)", - L{N(QV, ""), N(QV, " "), N(QV, " "), N(QV, " "), N(QV, " ")} -); - -ADD_CASE_TO_GROUP("squoted, numbers", // these should not be quoted when emitting -R"( -- -1 -- -1.0 -- +1.0 -- 1e-2 -- 1e+2 -)", - L{N("-1"), N("-1.0"), N("+1.0"), N("1e-2"), N("1e+2")} -); - -ADD_CASE_TO_GROUP("squoted, trailing space", -R"('a aaaa ')", - N(DOCVAL | VALQUO, "a aaaa ") -); - -ADD_CASE_TO_GROUP("squoted, leading space", -R"(' a aaaa')", - N(DOCVAL | VALQUO, " a aaaa") -); - -ADD_CASE_TO_GROUP("squoted, trailing and leading space", -R"(' 012345 ')", - N(DOCVAL | VALQUO, " 012345 ") -); - -ADD_CASE_TO_GROUP("squoted, 1 squote", -R"('''')", - N(DOCVAL | VALQUO, "'") -); - -ADD_CASE_TO_GROUP("squoted, 2 squotes", -R"('''''')", - N(DOCVAL | VALQUO, "''") -); - -ADD_CASE_TO_GROUP("squoted, 3 squotes", -R"('''''''')", - N(DOCVAL | VALQUO, "'''") -); - -ADD_CASE_TO_GROUP("squoted, 4 squotes", -R"('''''''''')", - N(DOCVAL | VALQUO, "''''") -); - -ADD_CASE_TO_GROUP("squoted, 5 squotes", -R"('''''''''''')", - N(DOCVAL | VALQUO, "'''''") -); - -/* -ADD_CASE_TO_GROUP("squoted, example 2", -R"('This is a key - -that has multiple lines - -': and this is its value -)", - L{N("This is a key\nthat has multiple lines\n", "and this is its value")} -); -*/ -} - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_singleheader/libryml_singleheader.cpp b/thirdparty/ryml/test/test_singleheader/libryml_singleheader.cpp deleted file mode 100644 index b5f27d1ed..000000000 --- a/thirdparty/ryml/test/test_singleheader/libryml_singleheader.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#define RYML_SINGLE_HDR_DEFINE_NOW -#define C4CORE_SINGLE_HDR_DEFINE_NOW -#include diff --git a/thirdparty/ryml/test/test_stack.cpp b/thirdparty/ryml/test/test_stack.cpp deleted file mode 100644 index 73d7b2cea..000000000 --- a/thirdparty/ryml/test/test_stack.cpp +++ /dev/null @@ -1,857 +0,0 @@ -#ifdef RYML_SINGLE_HEADER -#include "ryml_all.hpp" -#else -#include "c4/yml/detail/stack.hpp" -#endif -#include -#include "./callbacks_tester.hpp" - - -//------------------------------------------- - -namespace c4 { -namespace yml { - -namespace detail { - -template -using istack = stack; -using ip = int const*; - -template -void to_large(istack *s) -{ - size_t sz = 3u * N; - s->reserve(sz); - EXPECT_NE(s->m_stack, s->m_buf); -} - -template -void fill_to_large(istack *s) -{ - size_t sz = 3u * N; - s->reserve(sz); - for(int i = 0, e = (int)sz; i < e; ++i) - s->push(i); - EXPECT_NE(s->m_stack, s->m_buf); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -template -void test_stack_small_vs_large() -{ - istack s; - for(size_t i = 0; i < N; ++i) - { - s.push(static_cast(i)); - EXPECT_EQ(s.size(), i+1); - } - EXPECT_EQ(s.size(), N); - EXPECT_EQ(s.m_stack, s.m_buf); - for(size_t i = 0; i < N; ++i) - { - EXPECT_EQ(s.top(N-1-i), static_cast(i)); - } - s.push(N); - EXPECT_NE(s.m_stack, s.m_buf); - EXPECT_EQ(s.top(), static_cast(N)); - EXPECT_EQ(s.pop(), static_cast(N)); - EXPECT_NE(s.m_stack, s.m_buf); - for(size_t i = 0; i < N; ++i) - { - EXPECT_EQ(s.top(N-1-i), static_cast(i)); - } -} - -TEST(stack, small_vs_large) -{ - test_stack_small_vs_large<8>(); - test_stack_small_vs_large<16>(); - test_stack_small_vs_large<32>(); - test_stack_small_vs_large<128>(); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -template -void test_copy_ctor() -{ - istack src; - - // small - for(size_t i = 0; i < N; ++i) - { - src.push((int)i); - } - EXPECT_EQ(src.m_stack, src.m_buf); - ip b = src.begin(); - { - istack dst(src); - EXPECT_EQ(dst.size(), src.size()); - EXPECT_EQ(dst.m_stack, dst.m_buf); - EXPECT_EQ((ip)src.begin(), b); - EXPECT_NE((ip)dst.begin(), (ip)src.begin()); - } - - // large - for(size_t i = 0; i < 2*N; ++i) - { - src.push((int)i); // large - } - EXPECT_NE(src.m_stack, src.m_buf); - b = src.begin(); - { - istack dst(src); - EXPECT_EQ(dst.size(), src.size()); - EXPECT_NE(dst.m_stack, dst.m_buf); - EXPECT_EQ((ip)src.begin(), b); - EXPECT_NE((ip)dst.begin(), (ip)src.begin()); - } -} - -TEST(stack, copy_ctor) -{ - test_copy_ctor<4>(); - test_copy_ctor<8>(); - test_copy_ctor<64>(); - test_copy_ctor<128>(); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -template -void test_move_ctor() -{ - istack src; - - // small - for(size_t i = 0; i < N; ++i) - { - src.push((int)i); - } - EXPECT_EQ(src.m_stack, src.m_buf); - ip b = src.begin(); - size_t sz = src.size(); - { - istack dst(std::move(src)); - EXPECT_EQ(dst.size(), sz); - EXPECT_EQ(dst.m_stack, dst.m_buf); - EXPECT_NE(dst.m_stack, b); - EXPECT_EQ(src.size(), size_t(0)); - EXPECT_EQ((ip)src.begin(), src.m_buf); - EXPECT_NE((ip)dst.begin(), b); - } - EXPECT_EQ(src.size(), size_t(0)); - EXPECT_EQ(src.capacity(), N); - EXPECT_EQ(src.m_stack, src.m_buf); - - // redo - for(size_t i = 0; i < N; ++i) - { - src.push((int)i); - } - EXPECT_EQ(src.size(), N); - EXPECT_EQ(src.capacity(), N); - EXPECT_EQ(src.m_stack, src.m_buf); - // large - for(size_t i = 0; i < 2*N; ++i) - { - src.push((int)i); // large - } - EXPECT_EQ(src.size(), 3*N); - EXPECT_NE(src.m_stack, src.m_buf); - b = src.begin(); - sz = src.size(); - { - istack dst(std::move(src)); - EXPECT_EQ(dst.size(), sz); - EXPECT_NE(dst.m_stack, dst.m_buf); - EXPECT_EQ(dst.m_stack, b); - EXPECT_EQ(src.capacity(), N); - EXPECT_EQ(src.size(), size_t(0)); - EXPECT_EQ((ip)src.begin(), src.m_buf); - EXPECT_EQ((ip)dst.begin(), b); - } -} - -TEST(stack, move_ctor) -{ - test_move_ctor<4>(); - test_move_ctor<8>(); - test_move_ctor<64>(); - test_move_ctor<128>(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -template -void test_copy_assign() -{ - istack dst; - istack srcs; // small - istack srcl; // large - - for(size_t i = 0; i < N; ++i) - { - srcs.push((int)i); // small - srcl.push((int)i); // large - } - for(size_t i = 0; i < 2*N; ++i) - { - srcl.push((int)i); // large - } - EXPECT_EQ(srcs.m_stack, srcs.m_buf); - EXPECT_NE(srcl.m_stack, srcl.m_buf); - - ip bs = srcs.begin(), bl = srcl.begin(); - - { - dst = srcs; - EXPECT_EQ(dst.size(), srcs.size()); - EXPECT_EQ(dst.m_stack, dst.m_buf); - EXPECT_EQ((ip)srcs.begin(), bs); - EXPECT_NE((ip)dst.begin(), (ip)srcs.begin()); - } - - { - dst = srcl; - EXPECT_EQ(dst.size(), srcl.size()); - EXPECT_NE(dst.m_stack, dst.m_buf); - EXPECT_EQ((ip)srcl.begin(), bl); - EXPECT_NE((ip)dst.begin(), (ip)srcl.begin()); - } - - { - dst = srcs; - EXPECT_EQ(dst.size(), srcs.size()); - EXPECT_NE(dst.m_stack, dst.m_buf); // it stays in long mode (it's not trimmed when assigned from a short-mode stack) - EXPECT_EQ((ip)srcs.begin(), bs); - EXPECT_NE((ip)dst.begin(), (ip)srcs.begin()); - } -} - -TEST(stack, copy_assign) -{ - test_copy_assign<4>(); - test_copy_assign<8>(); - test_copy_assign<64>(); - test_copy_assign<128>(); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -template -void test_move_assign() -{ - istack srcs, srcl, dst; - - for(size_t i = 0; i < N; ++i) - { - srcs.push((int)i); // small - srcl.push((int)i); // large - } - for(size_t i = 0; i < 2*N; ++i) - { - srcl.push((int)i); // large - } - EXPECT_EQ(srcs.m_stack, srcs.m_buf); - EXPECT_NE(srcl.m_stack, srcl.m_buf); - - ip bs = srcs.begin()/*, bl = srcl.begin()*/; - size_t szs = srcs.size(), szl = srcl.size(); - - for(int i = 0; i < 10; ++i) - { - EXPECT_FALSE(srcs.empty()); - EXPECT_TRUE(dst.empty()); - EXPECT_EQ(dst.m_stack, dst.m_buf); - EXPECT_EQ(srcs.m_stack, srcs.m_buf); - - dst = std::move(srcs); - EXPECT_TRUE(srcs.empty()); - EXPECT_FALSE(dst.empty()); - EXPECT_EQ(srcs.size(), size_t(0)); - EXPECT_EQ(srcs.capacity(), N); - EXPECT_EQ(dst.size(), szs); - EXPECT_EQ(dst.m_stack, dst.m_buf); - EXPECT_EQ(srcs.m_stack, srcs.m_buf); - EXPECT_EQ((ip)srcs.begin(), bs); - EXPECT_NE((ip)dst.begin(), (ip)srcs.begin()); - - srcs = std::move(dst); - } - - for(int i = 0; i < 10; ++i) - { - EXPECT_EQ(srcl.size(), 3*N); - EXPECT_FALSE(srcl.empty()); - EXPECT_TRUE(dst.empty()); - EXPECT_EQ(dst.m_stack, dst.m_buf); - EXPECT_NE(srcl.m_stack, srcl.m_buf); - - dst = std::move(srcl); - EXPECT_TRUE(srcl.empty()); - EXPECT_FALSE(dst.empty()); - EXPECT_EQ(srcl.size(), size_t(0)); - EXPECT_EQ(srcl.capacity(), N); - EXPECT_EQ(dst.size(), szl); - EXPECT_NE(dst.m_stack, dst.m_buf); - EXPECT_EQ(srcl.m_stack, srcl.m_buf); - EXPECT_EQ((ip)srcl.begin(), srcl.m_buf); - EXPECT_NE((ip)dst.begin(), (ip)srcl.begin()); - - srcl = std::move(dst); - } -} - -TEST(stack, move_assign) -{ - test_move_assign<4>(); - test_move_assign<8>(); - test_move_assign<64>(); - test_move_assign<128>(); -} - - -//----------------------------------------------------------------------------- - -template -void test_callbacks_default_ctor() -{ - CallbacksTester td; - CallbacksTester ts; - istack dst; - EXPECT_EQ(dst.m_callbacks, get_callbacks()); -} - -TEST(stack, callbacks_default_ctor) -{ - test_callbacks_default_ctor<4>(); - test_callbacks_default_ctor<8>(); - test_callbacks_default_ctor<64>(); - test_callbacks_default_ctor<128>(); -} - -template -void test_callbacks_ctor() -{ - CallbacksTester td; - CallbacksTester ts; - istack dst(td.callbacks()); - ASSERT_EQ(dst.m_callbacks, td.callbacks()); -} - -TEST(stack, callbacks_ctor) -{ - test_callbacks_ctor<4>(); - test_callbacks_ctor<8>(); - test_callbacks_ctor<64>(); - test_callbacks_ctor<128>(); -} - - -//----------------------------------------------------------------------------- -// copy ctor - -template -void test_callbacks_copy_ctor_small() -{ - CallbacksTester ts("src"); - CallbacksTester td("dst"); - { - istack src(ts.callbacks()); - EXPECT_EQ(src.size(), 0u); - EXPECT_EQ(src.capacity(), N); - ASSERT_EQ(src.m_callbacks, ts.callbacks()); - EXPECT_EQ(src.m_stack, src.m_buf); - EXPECT_EQ(ts.num_allocs, 0u); - size_t nbefore = ts.num_allocs; - EXPECT_EQ(src.m_stack, src.m_buf); - EXPECT_EQ(ts.num_allocs, 0u); - istack dst(src); - EXPECT_EQ(dst.size(), 0u); - EXPECT_EQ(dst.capacity(), N); - ASSERT_EQ(src.m_callbacks, ts.callbacks()); - ASSERT_EQ(dst.m_callbacks, ts.callbacks()); - EXPECT_EQ(dst.m_stack, dst.m_buf); - EXPECT_EQ(src.m_stack, src.m_buf); - EXPECT_EQ(ts.num_allocs, nbefore); - EXPECT_EQ(td.num_allocs, 0u); - } -} - -template -void test_callbacks_copy_ctor_large_unfilled() -{ - CallbacksTester ts("src"); - CallbacksTester td("dst"); - { - istack src(ts.callbacks()); - ASSERT_EQ(src.m_callbacks, ts.callbacks()); - EXPECT_EQ(src.m_stack, src.m_buf); - EXPECT_EQ(ts.num_allocs, 0u); - to_large(&src); - ASSERT_GT(src.capacity(), N); - size_t nbefore = ts.num_allocs; - EXPECT_NE(src.m_stack, src.m_buf); - EXPECT_NE(ts.num_allocs, 0u); - istack dst(src); - ASSERT_EQ(dst.m_callbacks, ts.callbacks()); - ASSERT_NE(dst.m_callbacks, td.callbacks()); - EXPECT_EQ(dst.m_stack, dst.m_buf); - EXPECT_NE(src.m_stack, src.m_buf); - EXPECT_EQ(ts.num_allocs, nbefore); - EXPECT_EQ(td.num_allocs, 0u); - } -} - -template -void test_callbacks_copy_ctor_large_filled() -{ - CallbacksTester ts("src"); - CallbacksTester td("dst"); - { - istack src(ts.callbacks()); - ASSERT_EQ(src.m_callbacks, ts.callbacks()); - EXPECT_EQ(src.m_stack, src.m_buf); - EXPECT_EQ(ts.num_allocs, 0u); - fill_to_large(&src); - ASSERT_GT(src.capacity(), N); - size_t nbefore = ts.num_allocs; - EXPECT_NE(src.m_stack, src.m_buf); - EXPECT_NE(ts.num_allocs, 0u); - istack dst(src); - ASSERT_EQ(dst.m_callbacks, ts.callbacks()); - ASSERT_NE(dst.m_callbacks, td.callbacks()); - EXPECT_NE(dst.m_stack, dst.m_buf); - EXPECT_NE(src.m_stack, src.m_buf); - EXPECT_GT(ts.num_allocs, nbefore); - EXPECT_EQ(td.num_allocs, 0u); - } -} - -TEST(stack, callbacks_copy_ctor_small) -{ - test_callbacks_copy_ctor_small<4>(); - test_callbacks_copy_ctor_small<8>(); - test_callbacks_copy_ctor_small<64>(); - test_callbacks_copy_ctor_small<128>(); -} - -TEST(stack, callbacks_copy_ctor_large_unfilled) -{ - test_callbacks_copy_ctor_large_unfilled<4>(); - test_callbacks_copy_ctor_large_unfilled<8>(); - test_callbacks_copy_ctor_large_unfilled<64>(); - test_callbacks_copy_ctor_large_unfilled<128>(); -} - -TEST(stack, callbacks_copy_ctor_large_filled) -{ - test_callbacks_copy_ctor_large_filled<4>(); - test_callbacks_copy_ctor_large_filled<8>(); - test_callbacks_copy_ctor_large_filled<64>(); - test_callbacks_copy_ctor_large_filled<128>(); -} - - -//----------------------------------------------------------------------------- -// copy ctor - -template -void test_callbacks_move_ctor_small() -{ - CallbacksTester ts; - istack src(ts.callbacks()); - ASSERT_EQ(src.m_callbacks, ts.callbacks()); - EXPECT_EQ(src.m_stack, src.m_buf); - EXPECT_EQ(ts.num_allocs, 0u); - size_t nbefore = ts.num_allocs; - EXPECT_EQ(src.m_stack, src.m_buf); - EXPECT_EQ(ts.num_allocs, 0u); - istack dst(std::move(src)); - ASSERT_EQ(dst.m_callbacks, ts.callbacks()); - EXPECT_EQ(dst.m_stack, dst.m_buf); - EXPECT_EQ(src.m_stack, src.m_buf); - EXPECT_EQ(ts.num_allocs, nbefore); -} - -template -void test_callbacks_move_ctor_large_unfilled() -{ - CallbacksTester ts; - istack src(ts.callbacks()); - ASSERT_EQ(src.m_callbacks, ts.callbacks()); - EXPECT_EQ(src.m_stack, src.m_buf); - EXPECT_EQ(ts.num_allocs, 0u); - to_large(&src); - size_t nbefore = ts.num_allocs; - EXPECT_NE(src.m_stack, src.m_buf); - EXPECT_NE(ts.num_allocs, 0u); - istack dst(std::move(src)); - ASSERT_EQ(dst.m_callbacks, ts.callbacks()); - EXPECT_NE(dst.m_stack, dst.m_buf); - EXPECT_EQ(src.m_stack, src.m_buf); - EXPECT_EQ(ts.num_allocs, nbefore); -} - -template -void test_callbacks_move_ctor_large_filled() -{ - CallbacksTester ts; - istack src(ts.callbacks()); - ASSERT_EQ(src.m_callbacks, ts.callbacks()); - EXPECT_EQ(src.m_stack, src.m_buf); - EXPECT_EQ(ts.num_allocs, 0u); - fill_to_large(&src); - size_t nbefore = ts.num_allocs; - EXPECT_NE(src.m_stack, src.m_buf); - EXPECT_NE(ts.num_allocs, 0u); - istack dst(std::move(src)); - ASSERT_EQ(dst.m_callbacks, ts.callbacks()); - EXPECT_NE(dst.m_stack, dst.m_buf); - EXPECT_EQ(src.m_stack, src.m_buf); - EXPECT_EQ(ts.num_allocs, nbefore); -} - -TEST(stack, callbacks_move_ctor_small) -{ - test_callbacks_move_ctor_small<4>(); - test_callbacks_move_ctor_small<8>(); - test_callbacks_move_ctor_small<64>(); - test_callbacks_move_ctor_small<128>(); -} - -TEST(stack, callbacks_move_ctor_large_unfilled) -{ - test_callbacks_move_ctor_large_unfilled<4>(); - test_callbacks_move_ctor_large_unfilled<8>(); - test_callbacks_move_ctor_large_unfilled<64>(); - test_callbacks_move_ctor_large_unfilled<128>(); -} - -TEST(stack, callbacks_move_ctor_large_filled) -{ - test_callbacks_move_ctor_large_filled<4>(); - test_callbacks_move_ctor_large_filled<8>(); - test_callbacks_move_ctor_large_filled<64>(); - test_callbacks_move_ctor_large_filled<128>(); -} - - -//----------------------------------------------------------------------------- -// copy assign - -template -void test_callbacks_copy_assign_to_empty() -{ - CallbacksTester ts("src"); - CallbacksTester td("dst"); - istack src(ts.callbacks()); - istack dst(td.callbacks()); - ASSERT_EQ(src.m_callbacks, ts.callbacks()); - EXPECT_EQ(src.m_stack, src.m_buf); - EXPECT_EQ(ts.num_allocs, 0u); - fill_to_large(&src); - size_t nbefore = ts.num_allocs; - EXPECT_NE(src.m_stack, src.m_buf); - EXPECT_NE(ts.num_allocs, 0u); - dst = src; - ASSERT_EQ(dst.m_callbacks, ts.callbacks()); - ASSERT_NE(dst.m_callbacks, td.callbacks()); - EXPECT_NE(dst.m_stack, dst.m_buf); - EXPECT_NE(src.m_stack, src.m_buf); - EXPECT_GT(ts.num_allocs, nbefore); - EXPECT_EQ(td.num_allocs, 0u); -} - -TEST(stack, callbacks_copy_assign_to_empty) -{ - test_callbacks_copy_assign_to_empty<4>(); - test_callbacks_copy_assign_to_empty<8>(); - test_callbacks_copy_assign_to_empty<64>(); - test_callbacks_copy_assign_to_empty<128>(); -} - -template -void test_callbacks_copy_assign_to_nonempty() -{ - CallbacksTester ts("src"); - { - CallbacksTester td("dst"); - istack src(ts.callbacks()); - istack dst(td.callbacks()); - ASSERT_EQ(src.m_callbacks, ts.callbacks()); - ASSERT_EQ(dst.m_callbacks, td.callbacks()); - EXPECT_EQ(src.m_stack, src.m_buf); - EXPECT_EQ(src.m_stack, src.m_buf); - EXPECT_EQ(ts.num_allocs, 0u); - EXPECT_EQ(td.num_allocs, 0u); - EXPECT_EQ(ts.num_deallocs, 0u); - EXPECT_EQ(td.num_deallocs, 0u); - fill_to_large(&src); - fill_to_large(&dst); - EXPECT_NE(src.m_stack, src.m_buf); - EXPECT_NE(dst.m_stack, dst.m_buf); - EXPECT_EQ(ts.num_allocs, 1u); - EXPECT_EQ(td.num_allocs, 1u); - EXPECT_EQ(ts.num_deallocs, 0u); - EXPECT_EQ(td.num_deallocs, 0u); - dst = src; - ASSERT_EQ(src.m_callbacks, ts.callbacks()); - ASSERT_EQ(dst.m_callbacks, ts.callbacks()); // changed to ts - EXPECT_NE(dst.m_stack, dst.m_buf); - EXPECT_NE(src.m_stack, src.m_buf); - EXPECT_EQ(ts.num_allocs, 2u); - EXPECT_EQ(td.num_allocs, 1u); - EXPECT_EQ(ts.num_deallocs, 0u); - EXPECT_EQ(td.num_deallocs, 1u); - td.check(); - } - ts.check(); -} - -TEST(stack, callbacks_copy_assign_to_nonempty) -{ - test_callbacks_copy_assign_to_nonempty<4>(); - test_callbacks_copy_assign_to_nonempty<8>(); - test_callbacks_copy_assign_to_nonempty<64>(); - test_callbacks_copy_assign_to_nonempty<128>(); -} - -template -void test_callbacks_move_assign_to_empty() -{ - CallbacksTester ts("src"); - { - CallbacksTester td("dst"); - istack src(ts.callbacks()); - istack dst(td.callbacks()); - ASSERT_EQ(src.m_callbacks, ts.callbacks()); - ASSERT_EQ(dst.m_callbacks, td.callbacks()); - EXPECT_EQ(src.m_stack, src.m_buf); - EXPECT_EQ(dst.m_stack, dst.m_buf); - EXPECT_EQ(ts.num_allocs, 0u); - EXPECT_EQ(td.num_allocs, 0u); - fill_to_large(&src); - EXPECT_NE(src.m_stack, src.m_buf); - EXPECT_EQ(dst.m_stack, dst.m_buf); - EXPECT_EQ(ts.num_allocs, 1u); - EXPECT_EQ(td.num_allocs, 0u); - EXPECT_EQ(ts.num_deallocs, 0u); - EXPECT_EQ(td.num_deallocs, 0u); - dst = std::move(src); - ASSERT_EQ(src.m_callbacks, ts.callbacks()); - ASSERT_EQ(dst.m_callbacks, ts.callbacks()); // changed to ts - EXPECT_EQ(src.m_stack, src.m_buf); - EXPECT_NE(dst.m_stack, dst.m_buf); - EXPECT_EQ(ts.num_allocs, 1u); - EXPECT_EQ(td.num_allocs, 0u); - EXPECT_EQ(ts.num_deallocs, 0u); - EXPECT_EQ(td.num_deallocs, 0u); - td.check(); - } - EXPECT_EQ(ts.num_allocs, 1u); - EXPECT_EQ(ts.num_deallocs, 1u); - ts.check(); -} - -TEST(stack, callbacks_move_assign_to_empty) -{ - test_callbacks_move_assign_to_empty<4>(); - test_callbacks_move_assign_to_empty<8>(); - test_callbacks_move_assign_to_empty<64>(); - test_callbacks_move_assign_to_empty<128>(); -} - -template -void test_callbacks_move_assign_to_nonempty() -{ - CallbacksTester ts("src"); - { - CallbacksTester td("dst"); - istack src(ts.callbacks()); - istack dst(td.callbacks()); - ASSERT_EQ(src.m_callbacks, ts.callbacks()); - ASSERT_EQ(dst.m_callbacks, td.callbacks()); - EXPECT_EQ(src.m_stack, src.m_buf); - EXPECT_EQ(src.m_stack, src.m_buf); - EXPECT_EQ(ts.num_allocs, 0u); - EXPECT_EQ(td.num_allocs, 0u); - EXPECT_EQ(ts.num_deallocs, 0u); - EXPECT_EQ(td.num_deallocs, 0u); - fill_to_large(&src); - fill_to_large(&dst); - EXPECT_NE(src.m_stack, src.m_buf); - EXPECT_NE(dst.m_stack, dst.m_buf); - EXPECT_EQ(ts.num_allocs, 1u); - EXPECT_EQ(td.num_allocs, 1u); - EXPECT_EQ(ts.num_deallocs, 0u); - EXPECT_EQ(td.num_deallocs, 0u); - dst = std::move(src); - ASSERT_EQ(src.m_callbacks, ts.callbacks()); - ASSERT_EQ(dst.m_callbacks, ts.callbacks()); // changed to ts - EXPECT_NE(dst.m_stack, dst.m_buf); - EXPECT_EQ(src.m_stack, src.m_buf); - EXPECT_EQ(ts.num_allocs, 1u); - EXPECT_EQ(td.num_allocs, 1u); - EXPECT_EQ(ts.num_deallocs, 0u); - EXPECT_EQ(td.num_deallocs, 1u); - td.check(); - } - EXPECT_EQ(ts.num_allocs, 1u); - EXPECT_EQ(ts.num_deallocs, 1u); - ts.check(); -} - -TEST(stack, callbacks_move_assign_to_nonempty) -{ - test_callbacks_move_assign_to_nonempty<4>(); - test_callbacks_move_assign_to_nonempty<8>(); - test_callbacks_move_assign_to_nonempty<64>(); - test_callbacks_move_assign_to_nonempty<128>(); -} - - -//----------------------------------------------------------------------------- - -template -void test_reserve() -{ - { - CallbacksTester ts; - { - istack s(ts.callbacks()); - EXPECT_EQ(ts.num_allocs, 0u); - EXPECT_EQ(ts.num_deallocs, 0u); - EXPECT_EQ(s.capacity(), N); - s.reserve(4*N); - EXPECT_EQ(ts.num_allocs, 1u); - EXPECT_EQ(ts.num_deallocs, 0u); - EXPECT_EQ(s.capacity(), 4*N); - } - EXPECT_EQ(ts.num_allocs, 1u); - EXPECT_EQ(ts.num_deallocs, 1u); - ts.check(); - } - { - CallbacksTester ts; - { - istack s(ts.callbacks()); - EXPECT_EQ(ts.num_allocs, 0u); - EXPECT_EQ(ts.num_deallocs, 0u); - EXPECT_EQ(s.capacity(), N); - s.reserve(4*N); - EXPECT_EQ(ts.num_allocs, 1u); - EXPECT_EQ(ts.num_deallocs, 0u); - EXPECT_EQ(s.capacity(), 4*N); - s._free(); - } - EXPECT_EQ(ts.num_allocs, 1u); - EXPECT_EQ(ts.num_deallocs, 1u); - ts.check(); - } -} - -TEST(stack, reserve_capacity) -{ - test_reserve<10>(); - test_reserve<20>(); -} - - -template -void grow_to_large__push() -{ - istack s; - int ni = (int)N; - for(int i = 0; i < NumTimes * ni; ++i) - { - s.push(i); - if(i < ni) - EXPECT_EQ(s.m_stack, s.m_buf) << i; - else - EXPECT_NE(s.m_stack, s.m_buf) << i; - } - for(int i = 0; i < NumTimes * ni; ++i) - { - EXPECT_EQ(s.bottom((size_t)i), i); - } -} - -TEST(stack, push_to_large_twice) -{ - grow_to_large__push<10, 8>(); - grow_to_large__push<20, 8>(); - grow_to_large__push<32, 8>(); -} - -template -void grow_to_large__push_top() -{ - istack s; - int ni = (int)N; - s.push(0); - for(int i = 1; i < NumTimes * ni; ++i) - { - s.push_top(); - EXPECT_EQ(s.top(), i-1) << i; - s.top() = i; - if(i < ni) - EXPECT_EQ(s.m_stack, s.m_buf) << i; - else - EXPECT_NE(s.m_stack, s.m_buf) << i; - } - for(int i = 0; i < NumTimes * ni; ++i) - { - EXPECT_EQ(s.bottom((size_t)i), i); - } -} - -TEST(stack, push_top_to_large_twice) -{ - grow_to_large__push_top<10, 8>(); - grow_to_large__push_top<20, 8>(); - grow_to_large__push_top<32, 8>(); -} - -} // namespace detail -} // namespace yml -} // namespace c4 - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -// this is needed to use the test case library - -#ifndef RYML_SINGLE_HEADER -#include "c4/substr.hpp" -#endif - -namespace c4 { -namespace yml { -struct Case; -Case const* get_case(csubstr /*name*/) -{ - return nullptr; -} - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_style.cpp b/thirdparty/ryml/test/test_style.cpp deleted file mode 100644 index 5b46d075b..000000000 --- a/thirdparty/ryml/test/test_style.cpp +++ /dev/null @@ -1,616 +0,0 @@ -#ifndef RYML_SINGLE_HEADER -#include "c4/yml/std/std.hpp" -#include "c4/yml/parse.hpp" -#include "c4/yml/emit.hpp" -#include -#include -#include -#endif - -#include "./test_case.hpp" - -#include - -namespace c4 { -namespace yml { - -std::string emit2str(Tree const& t) -{ - return emitrs_yaml(t); -} - - -TEST(style, flags) -{ - Tree tree = parse_in_arena("foo: bar"); - EXPECT_TRUE(tree.rootref().type().default_block()); - EXPECT_FALSE(tree.rootref().type().marked_flow()); - EXPECT_FALSE(tree.rootref().type().marked_flow_sl()); - EXPECT_FALSE(tree.rootref().type().marked_flow_ml()); - tree._add_flags(tree.root_id(), _WIP_STYLE_FLOW_SL); - EXPECT_FALSE(tree.rootref().type().default_block()); - EXPECT_TRUE(tree.rootref().type().marked_flow()); - EXPECT_TRUE(tree.rootref().type().marked_flow_sl()); - EXPECT_FALSE(tree.rootref().type().marked_flow_ml()); - tree._rem_flags(tree.root_id(), _WIP_STYLE_FLOW_SL); - tree._add_flags(tree.root_id(), _WIP_STYLE_FLOW_ML); - EXPECT_FALSE(tree.rootref().type().default_block()); - EXPECT_TRUE(tree.rootref().type().marked_flow()); - EXPECT_FALSE(tree.rootref().type().marked_flow_sl()); - EXPECT_TRUE(tree.rootref().type().marked_flow_ml()); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -csubstr scalar_yaml = R"( -this is the key: >- - this is the multiline - "val" with - - 'empty' lines -)"; - -void check_same_emit(Tree const& expected) -{ - #if 0 - #define _showtrees(num) \ - std::cout << "--------\nEMITTED" #num "\n--------\n"; \ - std::cout << ws ## num; \ - std::cout << "--------\nACTUAL" #num "\n--------\n"; \ - print_tree(actual ## num); \ - std::cout << "--------\nEXPECTED" #num "\n--------\n"; \ - print_tree(expected) - #else - #define _showtrees(num) - #endif - - std::string ws1, ws2, ws3, ws4; - emitrs_yaml(expected, &ws1); - { - SCOPED_TRACE("actual1"); - Tree actual1 = parse_in_arena(to_csubstr(ws1)); - _showtrees(1); - test_compare(actual1, expected); - emitrs_yaml(actual1, &ws2); - } - { - SCOPED_TRACE("actual2"); - Tree actual2 = parse_in_arena(to_csubstr(ws2)); - _showtrees(2); - test_compare(actual2, expected); - emitrs_yaml(actual2, &ws3); - } - { - SCOPED_TRACE("actual3"); - Tree actual3 = parse_in_arena(to_csubstr(ws3)); - _showtrees(3); - test_compare(actual3, expected); - emitrs_yaml(actual3, &ws4); - } - { - SCOPED_TRACE("actual4"); - Tree actual4 = parse_in_arena(to_csubstr(ws4)); - _showtrees(4); - test_compare(actual4, expected); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - - -TEST(style, noflags) -{ - Tree expected = parse_in_arena("{}"); - NodeRef r = expected.rootref(); - r["normal"] |= MAP; - r["normal"]["singleline"] = "foo"; - r["normal"]["multiline"] |= MAP; - r["normal"]["multiline"]["____________"] = "foo"; - r["normal"]["multiline"]["____mid_____"] = "foo\nbar"; - r["normal"]["multiline"]["____mid_end1"] = "foo\nbar\n"; - r["normal"]["multiline"]["____mid_end2"] = "foo\nbar\n\n"; - r["normal"]["multiline"]["____mid_end3"] = "foo\nbar\n\n\n"; - r["normal"]["multiline"]["____________"] = "foo"; - r["normal"]["multiline"]["____________"] = "foo bar"; - r["normal"]["multiline"]["________end1"] = "foo bar\n"; - r["normal"]["multiline"]["________end2"] = "foo bar\n\n"; - r["normal"]["multiline"]["________end3"] = "foo bar\n\n\n"; - r["normal"]["multiline"]["beg_________"] = "\nfoo"; - r["normal"]["multiline"]["beg_mid_____"] = "\nfoo\nbar"; - r["normal"]["multiline"]["beg_mid_end1"] = "\nfoo\nbar\n"; - r["normal"]["multiline"]["beg_mid_end2"] = "\nfoo\nbar\n\n"; - r["normal"]["multiline"]["beg_mid_end3"] = "\nfoo\nbar\n\n\n"; - r["leading_ws"] |= MAP; - r["leading_ws"]["singleline"] |= MAP; - r["leading_ws"]["singleline"]["space"] = " foo"; - r["leading_ws"]["singleline"]["tab"] = "\tfoo"; - r["leading_ws"]["singleline"]["space_and_tab0"] = " \tfoo"; - r["leading_ws"]["singleline"]["space_and_tab1"] = "\t foo"; - r["leading_ws"]["multiline"] |= MAP; - r["leading_ws"]["multiline"]["beg_________"] = "\n \tfoo"; - r["leading_ws"]["multiline"]["beg_mid_____"] = "\n \tfoo\nbar"; - r["leading_ws"]["multiline"]["beg_mid_end1"] = "\n \tfoo\nbar\n"; - r["leading_ws"]["multiline"]["beg_mid_end2"] = "\n \tfoo\nbar\n\n"; - r["leading_ws"]["multiline"]["beg_mid_end3"] = "\n \tfoo\nbar\n\n\n"; - check_same_emit(expected); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -#ifdef WIP -TEST(style, scalar_retains_style_after_parse) -{ - { - Tree t = parse_in_arena("foo"); - EXPECT_TRUE(t.rootref().type().val_marked_plain()); - EXPECT_FALSE(t.rootref().type().val_marked_squo()); - EXPECT_FALSE(t.rootref().type().val_marked_dquo()); - EXPECT_FALSE(t.rootref().type().val_marked_literal()); - EXPECT_FALSE(t.rootref().type().val_marked_folded()); - EXPECT_EQ(emitrs(t), std::string("foo\n")); - } - { - Tree t = parse_in_arena("'foo'"); - EXPECT_FALSE(t.rootref().type().val_marked_plain()); - EXPECT_TRUE(t.rootref().type().val_marked_squo()); - EXPECT_FALSE(t.rootref().type().val_marked_dquo()); - EXPECT_FALSE(t.rootref().type().val_marked_literal()); - EXPECT_FALSE(t.rootref().type().val_marked_folded()); - EXPECT_EQ(emitrs(t), std::string("'foo'\n")); - } - { - Tree t = parse_in_arena("'foo'"); - EXPECT_FALSE(t.rootref().type().val_marked_plain()); - EXPECT_FALSE(t.rootref().type().val_marked_squo()); - EXPECT_TRUE(t.rootref().type().val_marked_dquo()); - EXPECT_FALSE(t.rootref().type().val_marked_literal()); - EXPECT_FALSE(t.rootref().type().val_marked_folded()); - EXPECT_EQ(emitrs(t), std::string("'foo'\n")); - } - { - Tree t = parse_in_arena("[foo, 'baz', \"bat\"]"); - EXPECT_TRUE(t.rootref().type().marked_flow()); - EXPECT_TRUE(t[0].type().val_marked_plain()); - EXPECT_FALSE(t[0].type().val_marked_squo()); - EXPECT_FALSE(t[0].type().val_marked_dquo()); - EXPECT_FALSE(t[0].type().val_marked_literal()); - EXPECT_FALSE(t[0].type().val_marked_folded()); - EXPECT_FALSE(t[1].type().val_marked_plain()); - EXPECT_TRUE(t[1].type().val_marked_squo()); - EXPECT_FALSE(t[1].type().val_marked_dquo()); - EXPECT_FALSE(t[1].type().val_marked_literal()); - EXPECT_FALSE(t[1].type().val_marked_folded()); - EXPECT_FALSE(t[2].type().val_marked_plain()); - EXPECT_FALSE(t[2].type().val_marked_squo()); - EXPECT_TRUE(t[2].type().val_marked_dquo()); - EXPECT_FALSE(t[2].type().val_marked_literal()); - EXPECT_FALSE(t[2].type().val_marked_folded()); - EXPECT_EQ(emitrs(t), std::string("foo")); - } -} -#endif - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -TEST(scalar, base) -{ - Tree tree = parse_in_arena(scalar_yaml); - EXPECT_EQ(tree[0].key(), csubstr("this is the key")); - EXPECT_EQ(tree[0].val(), csubstr("this is the multiline \"val\" with\n'empty' lines")); - EXPECT_EQ(emit2str(tree), R"(this is the key: |- - this is the multiline "val" with - 'empty' lines -)"); - check_same_emit(tree); -} - -TEST(scalar, block_literal) -{ - Tree tree = parse_in_arena(scalar_yaml); - { - SCOPED_TRACE("val only"); - EXPECT_FALSE(tree[0].type().key_marked_literal()); - EXPECT_FALSE(tree[0].type().val_marked_literal()); - tree._add_flags(tree[0].id(), _WIP_VAL_LITERAL); - EXPECT_FALSE(tree[0].type().key_marked_literal()); - EXPECT_TRUE(tree[0].type().val_marked_literal()); - EXPECT_EQ(emit2str(tree), R"(this is the key: |- - this is the multiline "val" with - 'empty' lines -)"); - check_same_emit(tree); - } - { - SCOPED_TRACE("key+val"); - tree._add_flags(tree[0].id(), _WIP_KEY_LITERAL); - EXPECT_TRUE(tree[0].type().key_marked_literal()); - EXPECT_TRUE(tree[0].type().val_marked_literal()); - EXPECT_EQ(emit2str(tree), R"(? |- - this is the key -: |- - this is the multiline "val" with - 'empty' lines -)"); - check_same_emit(tree); - } - { - SCOPED_TRACE("key only"); - tree._rem_flags(tree[0].id(), _WIP_VAL_LITERAL); - EXPECT_TRUE(tree[0].type().key_marked_literal()); - EXPECT_FALSE(tree[0].type().val_marked_literal()); - EXPECT_EQ(emit2str(tree), R"(? |- - this is the key -: |- - this is the multiline "val" with - 'empty' lines -)"); - check_same_emit(tree); - } -} - -TEST(scalar, block_folded) -{ - Tree tree = parse_in_arena(scalar_yaml); - { - SCOPED_TRACE("val only"); - EXPECT_FALSE(tree[0].type().key_marked_folded()); - EXPECT_FALSE(tree[0].type().val_marked_folded()); - tree._add_flags(tree[0].id(), _WIP_VAL_FOLDED); - EXPECT_FALSE(tree[0].type().key_marked_folded()); - EXPECT_TRUE(tree[0].type().val_marked_folded()); - EXPECT_EQ(emit2str(tree), R"(this is the key: >- - this is the multiline "val" with - - 'empty' lines -)"); - check_same_emit(tree); - } - { - SCOPED_TRACE("key+val"); - tree._add_flags(tree[0].id(), _WIP_KEY_FOLDED); - EXPECT_TRUE(tree[0].type().key_marked_folded()); - EXPECT_TRUE(tree[0].type().val_marked_folded()); - EXPECT_EQ(emit2str(tree), R"(? >- - this is the key -: >- - this is the multiline "val" with - - 'empty' lines -)"); - check_same_emit(tree); - } - { - SCOPED_TRACE("val only"); - tree._rem_flags(tree[0].id(), _WIP_VAL_FOLDED); - EXPECT_TRUE(tree[0].type().key_marked_folded()); - EXPECT_FALSE(tree[0].type().val_marked_folded()); - EXPECT_EQ(emit2str(tree), R"(? >- - this is the key -: |- - this is the multiline "val" with - 'empty' lines -)"); - check_same_emit(tree); - } -} - -TEST(scalar, squot) -{ - Tree tree = parse_in_arena(scalar_yaml); - EXPECT_FALSE(tree[0].type().key_marked_squo()); - EXPECT_FALSE(tree[0].type().val_marked_squo()); - { - SCOPED_TRACE("val only"); - tree._add_flags(tree[0].id(), _WIP_VAL_SQUO); - EXPECT_FALSE(tree[0].type().key_marked_squo()); - EXPECT_TRUE(tree[0].type().val_marked_squo()); - EXPECT_EQ(emit2str(tree), R"(this is the key: 'this is the multiline "val" with - - ''empty'' lines' -)"); - check_same_emit(tree); - } - { - SCOPED_TRACE("key+val"); - tree._add_flags(tree[0].id(), _WIP_KEY_SQUO); - EXPECT_TRUE(tree[0].type().key_marked_squo()); - EXPECT_TRUE(tree[0].type().val_marked_squo()); - EXPECT_EQ(emit2str(tree), R"('this is the key': 'this is the multiline "val" with - - ''empty'' lines' -)"); - check_same_emit(tree); - } - { - SCOPED_TRACE("key only"); - tree._rem_flags(tree[0].id(), _WIP_VAL_SQUO); - EXPECT_TRUE(tree[0].type().key_marked_squo()); - EXPECT_FALSE(tree[0].type().val_marked_squo()); - EXPECT_EQ(emit2str(tree), R"('this is the key': |- - this is the multiline "val" with - 'empty' lines -)"); - check_same_emit(tree); - } -} - -TEST(scalar, dquot) -{ - Tree tree = parse_in_arena(scalar_yaml); - EXPECT_FALSE(tree[0].type().key_marked_dquo()); - EXPECT_FALSE(tree[0].type().val_marked_dquo()); - { - SCOPED_TRACE("val only"); - tree._add_flags(tree[0].id(), _WIP_VAL_DQUO); - EXPECT_FALSE(tree[0].type().key_marked_dquo()); - EXPECT_TRUE(tree[0].type().val_marked_dquo()); - // visual studio fails to compile this string when used inside - // the EXPECT_EQ() macro below. So we declare it separately - // instead: - csubstr yaml = R"(this is the key: "this is the multiline \"val\" with - - 'empty' lines" -)"; - EXPECT_EQ(emit2str(tree), yaml); - check_same_emit(tree); - } - { - SCOPED_TRACE("key+val"); - tree._add_flags(tree[0].id(), _WIP_KEY_DQUO); - EXPECT_TRUE(tree[0].type().key_marked_dquo()); - EXPECT_TRUE(tree[0].type().val_marked_dquo()); - // visual studio fails to compile this string when used inside - // the EXPECT_EQ() macro below. So we declare it separately - // instead: - csubstr yaml = R"("this is the key": "this is the multiline \"val\" with - - 'empty' lines" -)"; - EXPECT_EQ(emit2str(tree), yaml); - check_same_emit(tree); - } - { - SCOPED_TRACE("key only"); - tree._rem_flags(tree[0].id(), _WIP_VAL_DQUO); - EXPECT_TRUE(tree[0].type().key_marked_dquo()); - EXPECT_FALSE(tree[0].type().val_marked_dquo()); - EXPECT_EQ(emit2str(tree), R"("this is the key": |- - this is the multiline "val" with - 'empty' lines -)"); - check_same_emit(tree); - } -} - -TEST(scalar, plain) -{ - Tree tree = parse_in_arena(scalar_yaml); - EXPECT_FALSE(tree[0].type().key_marked_plain()); - EXPECT_FALSE(tree[0].type().val_marked_plain()); - { - SCOPED_TRACE("val only"); - tree._add_flags(tree[0].id(), _WIP_VAL_PLAIN); - EXPECT_FALSE(tree[0].type().key_marked_plain()); - EXPECT_TRUE(tree[0].type().val_marked_plain()); - EXPECT_EQ(emit2str(tree), R"(this is the key: this is the multiline "val" with - - 'empty' lines -)"); - check_same_emit(tree); - } - { - SCOPED_TRACE("key+val"); - tree._add_flags(tree[0].id(), _WIP_KEY_PLAIN); - EXPECT_TRUE(tree[0].type().key_marked_plain()); - EXPECT_TRUE(tree[0].type().val_marked_plain()); - EXPECT_EQ(emit2str(tree), R"(this is the key: this is the multiline "val" with - - 'empty' lines -)"); - check_same_emit(tree); - } - { - SCOPED_TRACE("key only"); - tree._rem_flags(tree[0].id(), _WIP_VAL_PLAIN); - EXPECT_TRUE(tree[0].type().key_marked_plain()); - EXPECT_FALSE(tree[0].type().val_marked_plain()); - EXPECT_EQ(emit2str(tree), R"(this is the key: |- - this is the multiline "val" with - 'empty' lines -)"); - check_same_emit(tree); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -TEST(stream, block) -{ - Tree tree = parse_in_arena(R"( ---- -scalar -%YAML 1.2 ---- -foo ---- -bar -)"); - EXPECT_TRUE(tree.rootref().is_stream()); - EXPECT_TRUE(tree.docref(0).is_doc()); - EXPECT_TRUE(tree.docref(0).is_val()); - EXPECT_EQ(emit2str(tree), "--- scalar %YAML 1.2\n--- foo\n--- bar\n"); - tree._add_flags(tree.root_id(), _WIP_STYLE_FLOW_SL); - EXPECT_EQ(emit2str(tree), "--- scalar %YAML 1.2\n--- foo\n--- bar\n"); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -TEST(seq, block) -{ - Tree tree = parse_in_arena("[1, 2, 3, 4, 5, 6]"); - EXPECT_EQ(emit2str(tree), R"(- 1 -- 2 -- 3 -- 4 -- 5 -- 6 -)"); -} - -TEST(seq, flow_sl) -{ - Tree tree = parse_in_arena("[1, 2, 3, 4, 5, 6]"); - tree._add_flags(tree.root_id(), _WIP_STYLE_FLOW_SL); - EXPECT_EQ(emit2str(tree), R"([1,2,3,4,5,6])"); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -TEST(keyseq, block) -{ - Tree tree = parse_in_arena("{foo: [1, 2, 3, 4, 5, 6]}"); - EXPECT_TRUE(tree.rootref().type().default_block()); - EXPECT_EQ(emit2str(tree), R"(foo: - - 1 - - 2 - - 3 - - 4 - - 5 - - 6 -)"); - tree = parse_in_arena("{foo: [1, [2, 3], 4, [5, 6]]}"); - EXPECT_EQ(emit2str(tree), R"(foo: - - 1 - - - 2 - - 3 - - 4 - - - 5 - - 6 -)"); -} - -TEST(keyseq, flow_sl) -{ - Tree tree = parse_in_arena("{foo: [1, 2, 3, 4, 5, 6]}"); - EXPECT_TRUE(tree.rootref().type().default_block()); - tree._add_flags(tree.root_id(), _WIP_STYLE_FLOW_SL); - EXPECT_FALSE(tree.rootref().type().default_block()); - EXPECT_EQ(emit2str(tree), R"({foo: [1,2,3,4,5,6]})"); - // - tree = parse_in_arena("{foo: [1, [2, 3], 4, [5, 6]]}"); - tree._add_flags(tree.root_id(), _WIP_STYLE_FLOW_SL); - EXPECT_EQ(emit2str(tree), R"({foo: [1,[2,3],4,[5,6]]})"); - // - tree._rem_flags(tree.root_id(), _WIP_STYLE_FLOW_SL); - tree._add_flags(tree["foo"][1].id(), _WIP_STYLE_FLOW_SL); - tree._add_flags(tree["foo"][3].id(), _WIP_STYLE_FLOW_SL); - EXPECT_EQ(emit2str(tree), R"(foo: - - 1 - - [2,3] - - 4 - - [5,6] -)"); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -TEST(map, block) -{ - Tree tree = parse_in_arena("{1: 10, 2: 10, 3: 10, 4: 10, 5: 10, 6: 10}"); - EXPECT_EQ(emit2str(tree), R"(1: 10 -2: 10 -3: 10 -4: 10 -5: 10 -6: 10 -)"); -} - -TEST(map, flow_sl) -{ - Tree tree = parse_in_arena("{1: 10, 2: 10, 3: 10, 4: 10, 5: 10, 6: 10}"); - tree._add_flags(tree.root_id(), _WIP_STYLE_FLOW_SL); - EXPECT_EQ(emit2str(tree), R"({1: 10,2: 10,3: 10,4: 10,5: 10,6: 10})"); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -TEST(keymap, block) -{ - Tree tree = parse_in_arena("{foo: {1: 10, 2: 10, 3: 10, 4: 10, 5: 10, 6: 10}}"); - EXPECT_EQ(emit2str(tree), R"(foo: - 1: 10 - 2: 10 - 3: 10 - 4: 10 - 5: 10 - 6: 10 -)"); -} - - -TEST(keymap, flow_sl) -{ - Tree tree = parse_in_arena("{foo: {1: 10, 2: 10, 3: 10, 4: 10, 5: 10, 6: 10}}"); - tree._add_flags(tree.root_id(), _WIP_STYLE_FLOW_SL); - EXPECT_EQ(emit2str(tree), R"({foo: {1: 10,2: 10,3: 10,4: 10,5: 10,6: 10}})"); - // - tree = parse_in_arena("{foo: {1: 10, 2: {2: 10, 3: 10}, 4: 10, 5: {5: 10, 6: 10}}}"); - EXPECT_EQ(emit2str(tree), R"(foo: - 1: 10 - 2: - 2: 10 - 3: 10 - 4: 10 - 5: - 5: 10 - 6: 10 -)"); - tree._add_flags(tree.root_id(), _WIP_STYLE_FLOW_SL); - EXPECT_EQ(emit2str(tree), R"({foo: {1: 10,2: {2: 10,3: 10},4: 10,5: {5: 10,6: 10}}})"); - tree._rem_flags(tree.root_id(), _WIP_STYLE_FLOW_SL); - tree._add_flags(tree["foo"][1].id(), _WIP_STYLE_FLOW_SL); - tree._add_flags(tree["foo"][3].id(), _WIP_STYLE_FLOW_SL); - EXPECT_EQ(emit2str(tree), R"(foo: - 1: 10 - 2: {2: 10,3: 10} - 4: 10 - 5: {5: 10,6: 10} -)"); -} - - -//------------------------------------------- -// this is needed to use the test case library -Case const* get_case(csubstr /*name*/) -{ - return nullptr; -} - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_suite.cpp b/thirdparty/ryml/test/test_suite.cpp deleted file mode 100644 index 22dabf8c4..000000000 --- a/thirdparty/ryml/test/test_suite.cpp +++ /dev/null @@ -1,612 +0,0 @@ -#ifndef RYML_SINGLE_HEADER -#include -#include -#include -#include -#include -#include -#endif -#include "test_case.hpp" -#include "test_suite/test_suite_common.hpp" -#include "test_suite/test_suite_parts.hpp" -#include "test_suite/test_suite_events.hpp" -#include -#include -#include - - -/* Each case from the test suite contains: - * - * - (awkward) input yaml (in_yaml) - * - (somewhat standard) output equivalent (out_yaml) - * - (when meaningful/possible) json equivalent (in_json) - * - yaml parsing events (events) - * - * Running a test consists of parsing the contents above into a data - * structure, and then repeatedly parsing and emitting yaml in a sort - * of pipe. Ie, (eg for in_yaml) parse in_yaml, emit corresponding - * yaml, then parse this emitted yaml, and so on. Each parse/emit pair - * is named a processing level in this test. */ - - -C4_SUPPRESS_WARNING_MSVC_PUSH -C4_SUPPRESS_WARNING_MSVC(4702) // unreachable code - -#define NLEVELS 4 - -namespace c4 { -namespace yml { - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -struct Events -{ - csubstr filename = {}; - std::string src = {}; - std::string emitted_events = {}; - Tree tree = {}; - mutable Tree adjusted_tree = {}; - mutable Tree tree_from_emitted_events = {}; - bool was_parsed = false; - bool enabled = false; - - void init(csubstr filename_, csubstr src_) - { - filename = filename_; - src.assign(src_.begin(), src_.end()); - tree.clear(); - tree.clear_arena(); - tree.reserve(10); - was_parsed = false; - enabled = true; - } - - void compare_trees(csubstr actual_src, Tree const& actual_tree) const - { - if(actual_src.empty()) - GTEST_SKIP(); - _nfo_logf("SRC:\n{}", actual_src); - _nfo_print_tree("EXPECTED", tree); - _nfo_print_tree("ACTUAL", actual_tree); - test_compare(actual_tree, tree); - } - - void compare_emitted_events(csubstr actual_src, Tree const& tree_from_actual_src) - { - C4_UNUSED(actual_src); - emit_events(&emitted_events, tree_from_actual_src); - _nfo_logf("EXPECTED_EVENTS:\n{}", src); - _nfo_logf("ACTUAL_EVENTS:\n{}", emitted_events); - // we cannot directly compare the event strings, - // so we create a tree from the emitted events, - // and then compare the trees: - tree_from_emitted_events.clear(); - tree_from_emitted_events.reserve(16); - parser.parse(c4::to_csubstr(emitted_events), &tree_from_emitted_events); - _nfo_logf("SRC:\n{}", actual_src); - _nfo_print_tree("ACTUAL_FROM_SOURCE", tree_from_actual_src); - _nfo_print_tree("ACTUAL_FROM_EMITTED_EVENTS", tree_from_emitted_events); - _nfo_print_tree("EXPECTED_FROM_EVENTS", tree); - test_compare(tree_from_emitted_events, tree); - } - - EventsParser parser; - void parse_events(csubstr actual_src) - { - if(was_parsed) - return; - if(actual_src.empty()) - GTEST_SKIP(); - parser.parse(c4::to_csubstr(src), &tree); - if(tree.empty()) - tree.reserve(10); - _nfo_print_tree("EXPECTED", tree); - was_parsed = true; - } -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -/** a processing level */ -struct ProcLevel -{ - size_t level; - ProcLevel *prev; - csubstr filename; - std::string src; - c4::yml::Parser parser; - c4::yml::Tree tree; - std::string emitted; - - bool immutable = false; - bool reuse = false; - bool was_parsed = false; - bool was_emitted = false; - - void init(size_t level_, ProcLevel *prev_, csubstr filename_, csubstr src_, bool immutable_, bool reuse_) - { - level = level_; - prev = prev_; - filename = filename_; - src.assign(src_.begin(), src_.end()); - immutable = immutable_; - reuse = reuse_; - was_parsed = false; - was_emitted = false; - } - - void receive_src(ProcLevel & prev_) - { - RYML_ASSERT(&prev_ == prev); - if(!prev_.was_emitted) - { - _nfo_logf("level[{}] not emitted. emit!", prev_.level); - prev_.emit(); - } - if(src != prev_.emitted) - { - was_parsed = false; - was_emitted = false; - src = prev_.emitted; - } - } - - template - void log(const char* context, T const& v) - { - C4_UNUSED(context); - C4_UNUSED(v); - #if RYML_NFO - constexpr const char sep[] = "+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n"; - c4::log("{}:\n{}{}{}", context, sep, v, sep); - #endif - } - - void parse() - { - if(was_parsed) - return; - if(prev) - { - receive_src(*prev); - } - _nfo_logf("level[{}]: parsing source:\n{}", level, src); - if(reuse) - { - tree.clear(); - if(immutable) - parser.parse_in_arena(filename, c4::to_csubstr(src), &tree); - else - parser.parse_in_place(filename, c4::to_substr(src), &tree); - } - else - { - if(immutable) - tree = parse_in_arena(filename, c4::to_csubstr(src)); - else - tree = parse_in_place(filename, c4::to_substr(src)); - } - _nfo_print_tree("PARSED", tree); - tree.resolve_tags(); - _nfo_print_tree("RESOLVED TAGS", tree); - was_parsed = true; - //_resolve_if_needed(); - } - - void _resolve_if_needed() - { - ConstNodeRef root = tree.rootref(); - bool has_anchors_or_refs = root.visit([](ConstNodeRef const& node, size_t /*level*/){ - return (node.is_anchor() || node.is_ref()); - }); - if(has_anchors_or_refs) - { - tree.resolve(); - _nfo_print_tree("RESOLVED", tree); - } - } - - void emit() - { - if(was_emitted) - return; - if(!was_parsed) - { - _nfo_logf("level[{}] not parsed. parse!", level); - parse(); - } - emitrs_yaml(tree, &emitted); - csubstr ss = to_csubstr(emitted); - if(ss.ends_with("\n...\n")) - emitted.resize(emitted.size() - 4); - was_emitted = true; - _nfo_logf("EMITTED:\n{}", emitted); - } - - void compare_trees(ProcLevel & prev_) - { - RYML_ASSERT(&prev_ == prev); - if(!prev_.was_parsed) - { - _nfo_logf("level[{}] not parsed. parse!", prev_.level); - prev_.parse(); - } - if(!was_parsed) - { - _nfo_logf("level[{}] not parsed. parse!", level); - parse(); - } - _nfo_print_tree("PREV_", prev_.tree); - _nfo_print_tree("CURR", tree); - test_compare(prev_.tree, tree); - } - - void compare_emitted(ProcLevel & prev_) - { - RYML_ASSERT(&prev_ == prev); - if(!prev_.was_emitted) - { - _nfo_logf("level[{}] not emitted. emit!", prev_.level); - prev_.emit(); - } - if(!was_emitted) - { - _nfo_logf("level[{}] not emitted. emit!", level); - emit(); - } - _nfo_logf("level[{}]: EMITTED:\n{}", prev_.level, prev_.emitted); - _nfo_logf("level[{}]: EMITTED:\n{}", level, emitted); - if(emitted != prev_.emitted) - { - // workaround for lack of idempotency in tag normalization. - Tree from_prev = parse_in_arena(to_csubstr(prev_.emitted)); - Tree from_this = parse_in_arena(to_csubstr(emitted)); - from_prev.resolve_tags(); - from_this.resolve_tags(); - test_compare(from_prev, from_this); - } - } -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -/** holds data for one particular test suite approach. */ -struct Approach -{ - csubstr casename; - csubstr filename; - ProcLevel levels[NLEVELS] = {}; - AllowedFailure allowed_failure = {}; - bool enabled = false; - bool expect_error = false; - - void init(csubstr casename_, csubstr filename_, csubstr src_, bool immutable_, bool reuse_, bool expect_error_) - { - casename = casename_; - filename = filename_; - allowed_failure = is_failure_expected(casename); - size_t level_index = 0; - ProcLevel *prev = nullptr; - for(ProcLevel &l : levels) - { - l.init(level_index++, prev, filename, src_, immutable_, reuse_); - prev = &l; - } - expect_error = expect_error_; - } - - csubstr src() const { return c4::to_csubstr(levels[0].src); } - bool skip() const { return allowed_failure; } - - void parse(size_t num, bool emit) - { - if(allowed_failure) - GTEST_SKIP(); - for(size_t i = 0; i < num; ++i) - { - levels[i].parse(); - if(emit) - levels[i].emit(); - if(i + 1 < num) - levels[i+1].receive_src(levels[i]); - } - } - - void compare_trees(size_t num) - { - if(allowed_failure) - GTEST_SKIP(); - for(size_t i = 1; i < num; ++i) - levels[i].compare_trees(levels[i-1]); - } - void compare_trees(size_t num, Approach & other) - { - if(allowed_failure) - GTEST_SKIP(); - for(size_t i = 0; i < num; ++i) - levels[i].compare_trees(other.levels[i]); - } - - void compare_emitted(size_t num) - { - if(allowed_failure) - GTEST_SKIP(); - for(size_t i = 1; i < num; ++i) - levels[i].compare_emitted(levels[i-1]); - } - void compare_emitted(size_t num, Approach & other) - { - if(allowed_failure) - GTEST_SKIP(); - for(size_t i = 0; i < num; ++i) - levels[i].compare_emitted(other.levels[i]); - } - - void compare_events(Events *events) - { - if(allowed_failure || filename.ends_with(".json")) - GTEST_SKIP(); - events->parse_events(src()); - parse(1, /*emit*/false); - events->compare_trees(src(), levels[0].tree); - } - - void compare_emitted_events(Events *events) - { - if(allowed_failure || filename.ends_with(".json")) - GTEST_SKIP(); - events->parse_events(src()); - parse(1, /*emit*/false); - events->compare_emitted_events(src(), levels[0].tree); - } - - void check_expected_error() - { - if(allowed_failure) - GTEST_SKIP(); - ExpectError::do_check(&levels[0].tree, [this]{ - levels[0].parse(); - }); - } - -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -/** Each approach can be read from mutable/immutable yaml source and - * with/without reuse. */ -struct Subject -{ - Approach unix_arena; - Approach unix_arena_reuse; - Approach unix_inplace; - Approach unix_inplace_reuse; - - Approach windows_arena; - Approach windows_arena_reuse; - Approach windows_inplace; - Approach windows_inplace_reuse; - - std::string unix_src; - std::string windows_src; - - void init(csubstr casename, csubstr filename, csubstr src, bool expect_error) - { - src = replace_all("\r", "", src, &unix_src); - - unix_arena .init(casename, filename, src, /*immutable*/true , /*reuse*/false, expect_error); - unix_arena_reuse.init(casename, filename, src, /*immutable*/true , /*reuse*/true , expect_error); - unix_inplace .init(casename, filename, src, /*immutable*/false, /*reuse*/false, expect_error); - unix_inplace_reuse.init(casename, filename, src, /*immutable*/false, /*reuse*/true , expect_error); - - src = replace_all("\n", "\r\n", src, &windows_src); - - windows_arena .init(casename, filename, src, /*immutable*/true , /*reuse*/false, expect_error); - windows_arena_reuse.init(casename, filename, src, /*immutable*/true , /*reuse*/true , expect_error); - windows_inplace .init(casename, filename, src, /*immutable*/false, /*reuse*/false, expect_error); - windows_inplace_reuse.init(casename, filename, src, /*immutable*/false, /*reuse*/true , expect_error); - } -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -// some utility functions, used below - -/** all the ways to process a test case are available through this - * class. Tests are defined below and use only one of these. */ -struct SuiteCase -{ - csubstr case_title; - csubstr case_dir; - std::string filename; - std::string file_contents; - std::string events_filename; - std::string events_file_contents; - - Subject input; - Events events; - bool expect_error; - - /** loads the several types of tests from an input test suite file */ - SuiteCase(const char *case_title_, const char* case_dir_, const char *input_file) - { - using namespace c4; - using c4::to_csubstr; - - if(to_csubstr(input_file) == "error") - input_file = "in.yaml"; - - case_title = to_csubstr(case_title_); - - case_dir = to_csubstr(case_dir_); - RYML_CHECK(case_dir.find('\\') == yml::npos); - C4_CHECK_MSG(fs::dir_exists(case_dir.str), "dir not found: '%s'", case_dir); - - filename = catrs(case_dir, '/', to_csubstr(input_file)); - C4_CHECK_MSG(fs::file_exists(filename.c_str()), "file not found: '%s'", filename.c_str()); - log("testing suite case: {} {} ({})", case_title, filename, case_dir); - - std::string errfile = catrs(to_csubstr(case_dir_), "/error"); - expect_error = fs::file_exists(errfile.c_str()); - - fs::file_get_contents(filename.c_str(), &file_contents); - input.init(case_title, to_csubstr(filename), to_csubstr(file_contents), expect_error); - - events_filename = catrs(case_dir, "/test.event"); - C4_CHECK(fs::file_exists(events_filename.c_str())); - fs::file_get_contents(events_filename.c_str(), &events_file_contents); - events.init(to_csubstr(events_filename), to_csubstr(events_file_contents)); - - dump("~~~ case: " , case_title , "~~~\n", - "~~~ file: " , filename , "~~~\n", - "~~~ input:\n" , to_csubstr(input.unix_arena.levels[0].src), "~~~\n", - "~~~ events:\n" , events.src , "~~~\n"); - } - -}; - - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - - -// a global holding the test case data -SuiteCase* g_suite_case = nullptr; -bool g_do_subcases = true; - - - -#define DEFINE_TESTS(which) \ - \ - \ -struct which : public ::testing::TestWithParam \ -{ \ -}; \ - \ - \ -TEST_P(which, parse) \ -{ \ - RYML_CHECK(GetParam() < NLEVELS); \ - if(g_suite_case->expect_error) \ - GTEST_SKIP(); \ - g_suite_case->input.which.parse(1 + GetParam(), false); \ -} \ - \ - \ -TEST_P(which, compare_trees) \ -{ \ - RYML_CHECK(GetParam() < NLEVELS); \ - if(g_suite_case->expect_error) \ - GTEST_SKIP(); \ - g_suite_case->input.which.compare_trees(1 + GetParam()); \ -} \ - \ - \ -TEST_P(which, emit) \ -{ \ - RYML_CHECK(GetParam() < NLEVELS); \ - if(g_suite_case->expect_error) \ - GTEST_SKIP(); \ - g_suite_case->input.which.parse(1 + GetParam(), true); \ -} \ - \ - \ -TEST_P(which, compare_emitted) \ -{ \ - RYML_CHECK(GetParam() < NLEVELS); \ - if(g_suite_case->expect_error) \ - GTEST_SKIP(); \ - g_suite_case->input.which.compare_emitted(1 + GetParam()); \ -} \ - \ -/*-----------------------------------------------*/ \ - \ -TEST(which##_events, compare) \ -{ \ - if(g_suite_case->expect_error) \ - GTEST_SKIP(); \ - g_suite_case->input.which.compare_events(&g_suite_case->events); \ -} \ - \ -TEST(which##_events, emit_events) \ -{ \ - if(g_suite_case->expect_error) \ - GTEST_SKIP(); \ - g_suite_case->input.which.compare_emitted_events(&g_suite_case->events); \ -} \ - \ -/*-----------------------------------------------*/ \ - \ -TEST(which##_errors, check_expected_error) \ -{ \ - if(!g_suite_case->expect_error) \ - GTEST_SKIP(); \ - g_suite_case->input.which.check_expected_error(); \ -} \ - \ - \ -INSTANTIATE_TEST_SUITE_P(_, which, testing::Range(0, NLEVELS)) - - -DEFINE_TESTS(unix_arena); -DEFINE_TESTS(unix_inplace); -DEFINE_TESTS(unix_arena_reuse); -DEFINE_TESTS(unix_inplace_reuse); -DEFINE_TESTS(windows_arena); -DEFINE_TESTS(windows_inplace); -DEFINE_TESTS(windows_arena_reuse); -DEFINE_TESTS(windows_inplace_reuse); - - -//------------------------------------------- -// this is needed to use the test case library -Case const* get_case(csubstr /*name*/) { return nullptr; } - -} // namespace yml -} // namespace c4 - - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -int main(int argc, char* argv[]) -{ - c4::dump("$"); - for(int i = 0; i < argc; ++i) - c4::dump(' ', c4::to_csubstr(argv[i])); - c4::dump("\n"); - - // make gtest parse its args - testing::InitGoogleTest(&argc, argv); - - // now we have only our args to consider - if(argc != 4) - { - log("usage:\n{} ", c4::to_csubstr(argv[0])); - return 1; - } - - // load the test case from the suite file - c4::yml::SuiteCase suite_case(argv[1], argv[2], argv[3]); - c4::yml::g_suite_case = &suite_case; - - return RUN_ALL_TESTS(); -} - -C4_SUPPRESS_WARNING_MSVC_PUSH diff --git a/thirdparty/ryml/test/test_suite/test_suite_common.hpp b/thirdparty/ryml/test/test_suite/test_suite_common.hpp deleted file mode 100644 index 9cfd89f1f..000000000 --- a/thirdparty/ryml/test/test_suite/test_suite_common.hpp +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef C4_YML_TEST_SUITE_COMMON_HPP_ -#define C4_YML_TEST_SUITE_COMMON_HPP_ - -#ifndef RYML_SINGLE_HEADER -#include -#include -#include -#include -#include -#include -#endif - -#include -#include - -#include "test_case.hpp" -#include - -#define RYML_NFO (0 || RYML_DBG) - -#if RYML_NFO -#define _nfo_print_tree(title, tree) do { c4::log("{}:{}: " title ":", __FILE__, __LINE__); print_tree(tree); c4::yml::emit(tree, stdout); fflush(stdout); } while(0) -#define _nfo_logf(fmt, ...) do { c4::log("{}:{}: " fmt , __FILE__, __LINE__, __VA_ARGS__); fflush(stdout); } while(0) -#define _nfo_log(fmt) do { c4::log("{}:{}: " fmt , __FILE__, __LINE__); fflush(stdout); } while(0) -#define _nfo_printf(...) printf(__VA_ARGS__) -#else -#define _nfo_print_tree(title, tree) -#define _nfo_logf(fmt, ...) -#define _nfo_log(fmt) -#define _nfo_printf(...) -#endif -#define _nfo_llogf(fmt, ...) _nfo_logf("line[{}]: '{}': " fmt, linenum, line, __VA_ARGS__) -#define _nfo_llog(fmt) _nfo_logf("line[{}]: '{}': " fmt, linenum, line) - - -namespace c4 { -namespace yml { - - -} // namespace yml -} // namespace c4 - - -#endif /* C4_YML_TEST_SUITE_COMMON_HPP_ */ diff --git a/thirdparty/ryml/test/test_suite/test_suite_events.cpp b/thirdparty/ryml/test/test_suite/test_suite_events.cpp deleted file mode 100644 index b359421b5..000000000 --- a/thirdparty/ryml/test/test_suite/test_suite_events.cpp +++ /dev/null @@ -1,607 +0,0 @@ -#include "test_suite_events.hpp" -#include "test_suite_common.hpp" -#ifndef RYML_SINGLE_HEADER -#include -#endif - -namespace c4 { -namespace yml { - -namespace /*anon*/ { - -struct ScalarType -{ - typedef enum { - PLAIN = 0, - SQUOTED, - DQUOTED, - LITERAL, - FOLDED - } ScalarType_e; - - ScalarType_e val = PLAIN; - bool operator== (ScalarType_e v) const { return val == v; } - bool operator!= (ScalarType_e v) const { return val != v; } - ScalarType& operator= (ScalarType_e v) { val = v; return *this; } - - csubstr to_str() const - { - switch(val) - { - case ScalarType::PLAIN: return csubstr("PLAIN"); - case ScalarType::SQUOTED: return csubstr("SQUOTED"); - case ScalarType::DQUOTED: return csubstr("DQUOTED"); - case ScalarType::LITERAL: return csubstr("LITERAL"); - case ScalarType::FOLDED: return csubstr("FOLDED"); - } - C4_ERROR(""); - return csubstr(""); - } - - bool is_quoted() const { return val == ScalarType::SQUOTED || val == ScalarType::DQUOTED; } -}; - - -struct OptionalScalar -{ - csubstr val = {}; - bool was_set = false; - inline operator csubstr() const { return get(); } - inline operator bool() const { return was_set; } - void operator= (csubstr v) { val = v; was_set = true; } - csubstr get() const { RYML_ASSERT(was_set); return val; } -}; - -#if RYML_NFO -size_t to_chars(c4::substr buf, OptionalScalar const& s) -{ - if(!s) - return 0u; - if(s.val.len <= buf.len) - memcpy(buf.str, s.val.str, s.val.len); - return s.val.len; -} -#endif - -csubstr filtered_scalar(csubstr str, ScalarType scalar_type, Tree *tree) -{ - (void)scalar_type; - csubstr tokens[] = {R"(\n)", R"(\t)", R"(\\)"}; - if(!str.first_of_any_iter(std::begin(tokens), std::end(tokens))) - return str; - substr buf = tree->alloc_arena(str.len); // we are going to always replace with less characters - size_t strpos = 0; - size_t bufpos = 0; - auto append_str = [&](size_t pos){ - csubstr rng = str.range(strpos, pos); - memcpy(buf.str + bufpos, rng.str, rng.len); - bufpos += rng.len; - strpos = pos; - }; - size_t i; - auto append_chars = [&](csubstr s, size_t skipstr){ - memcpy(buf.str + bufpos, s.str, s.len); - bufpos += s.len; - i += skipstr - 1; // incremented at the loop - strpos += skipstr; - }; - for(i = 0; i < str.len; ++i) - { - char curr = str[i]; - char next1 = i+1 < str.len ? str[i+1] : '\0'; - if(curr == '\\') - { - if(next1 == '\\') - { - char next2 = i+2 < str.len ? str[i+2] : '\0'; - if(next2 == 'n') - { - append_str(i); - append_chars(R"(\n)", 3u); // '\\n' -> '\n' - } - else if(next2 == 't') - { - append_str(i); - append_chars(R"(\t)", 3u); // '\\t' -> '\t' - } - else - { - append_str(i); - append_chars(R"(\)", 2u); // '\\' -> '\' - } - } - else if(next1 == 'n') - { - append_str(i); - append_chars("\n", 2u); - } - else if(next1 == 't') - { - append_str(i); - append_chars("\t", 2u); - } - } - } - append_str(str.len); - buf = buf.first(bufpos); - _nfo_logf("filtering: result=~~~{}~~~", buf); - return buf; -} - -struct Scalar -{ - OptionalScalar scalar = {}; - OptionalScalar anchor = {}; - OptionalScalar ref = {}; - OptionalScalar tag = {}; - ScalarType type = {}; - inline operator bool() const { if(anchor || tag) { RYML_ASSERT(scalar); } return scalar.was_set; } - void add_key_props(Tree *tree, size_t node) const - { - if(ref) - { - _nfo_logf("node[{}]: set key ref: '{}'", node, ref); - tree->set_key_ref(node, ref); - } - if(anchor) - { - _nfo_logf("node[{}]: set key anchor: '{}'", node, anchor); - tree->set_key_anchor(node, anchor); - } - if(tag) - { - csubstr ntag = normalize_tag(tag); - _nfo_logf("node[{}]: set key tag: '{}' -> '{}'", node, tag, ntag); - tree->set_key_tag(node, ntag); - } - if(type.is_quoted()) - { - _nfo_logf("node[{}]: set key as quoted", node); - tree->_add_flags(node, KEYQUO); - } - } - void add_val_props(Tree *tree, size_t node) const - { - if(ref) - { - _nfo_logf("node[{}]: set val ref: '{}'", node, ref); - tree->set_val_ref(node, ref); - } - if(anchor) - { - _nfo_logf("node[{}]: set val anchor: '{}'", node, anchor); - tree->set_val_anchor(node, anchor); - } - if(tag) - { - csubstr ntag = normalize_tag(tag); - _nfo_logf("node[{}]: set val tag: '{}' -> '{}'", node, tag, ntag); - tree->set_val_tag(node, ntag); - } - if(type.is_quoted()) - { - _nfo_logf("node[{}]: set val as quoted", node); - tree->_add_flags(node, VALQUO); - } - } - csubstr filtered_scalar(Tree *tree) const - { - return ::c4::yml::filtered_scalar(scalar, type, tree); - } -}; - -csubstr parse_anchor_and_tag(csubstr tokens, OptionalScalar *anchor, OptionalScalar *tag) -{ - *anchor = OptionalScalar{}; - *tag = OptionalScalar{}; - if(tokens.begins_with('&')) - { - size_t pos = tokens.first_of(' '); - if(pos == (size_t)csubstr::npos) - { - *anchor = tokens.sub(1); - tokens = {}; - } - else - { - *anchor = tokens.first(pos).sub(1); - tokens = tokens.right_of(pos); - } - _nfo_logf("anchor: {}", *anchor); - } - if(tokens.begins_with('<')) - { - size_t pos = tokens.find('>'); - RYML_ASSERT(pos != (size_t)csubstr::npos); - *tag = tokens.first(pos + 1); - tokens = tokens.right_of(pos).triml(' '); - _nfo_logf("tag: {}", *tag); - } - return tokens; -} - -} // namespace /*anon*/ - -void EventsParser::parse(csubstr src, Tree *C4_RESTRICT tree_) -{ - struct ParseLevel { size_t tree_node; }; - detail::stack m_stack = {}; - Tree &C4_RESTRICT tree = *tree_; - size_t linenum = 0; - Scalar key = {}; - _nfo_logf("parsing events! src:\n{}", src); - for(csubstr line : src.split('\n')) - { - line = line.trimr('\r'); - line = line.triml(' '); - _nfo_printf("\n\n-----------------------\n"); - _nfo_llog(""); - _nfo_logf("line[{}]: top={} type={}", linenum, m_stack.empty() ? tree.root_id() : m_stack.top().tree_node, NodeType::type_str(tree.type(m_stack.empty() ? tree.root_id() : m_stack.top().tree_node))); - if(line.begins_with("=VAL ")) - { - line = line.stripl("=VAL "); - ASSERT_GE(m_stack.size(), 0u); - Scalar curr = {}; - line = parse_anchor_and_tag(line, &curr.anchor, &curr.tag); - if(line.begins_with('"')) - { - _nfo_llog("double-quoted scalar!"); - curr.scalar = line.sub(1); - curr.type = ScalarType::DQUOTED; - } - else if(line.begins_with('\'')) - { - _nfo_llog("single-quoted scalar!"); - curr.scalar = line.sub(1); - curr.type = ScalarType::SQUOTED; - } - else if(line.begins_with('|')) - { - _nfo_llog("block literal scalar!"); - curr.scalar = line.sub(1); - curr.type = ScalarType::LITERAL; - } - else if(line.begins_with('>')) - { - _nfo_llog("block folded scalar!"); - curr.scalar = line.sub(1); - curr.type = ScalarType::FOLDED; - } - else - { - _nfo_llog("plain scalar"); - ASSERT_TRUE(line.begins_with(':')); - curr.scalar = line.sub(1); - } - _nfo_logf("parsed scalar: '{}'", curr.scalar); - if(m_stack.empty()) - { - _nfo_log("stack was empty, pushing root as DOC..."); - //tree._p(tree.root_id())->m_type.add(DOC); - m_stack.push({tree.root_id()}); - } - ParseLevel &top = m_stack.top(); - if(tree.is_seq(top.tree_node)) - { - _nfo_logf("is seq! seq_id={}", top.tree_node); - ASSERT_FALSE(key); - ASSERT_TRUE(curr); - _nfo_logf("seq[{}]: adding child", top.tree_node); - size_t node = tree.append_child(top.tree_node); - NodeType_e as_doc = tree.is_stream(top.tree_node) ? DOC : NOTYPE; - _nfo_logf("seq[{}]: child={} val='{}' as_doc=", top.tree_node, node, curr.scalar, NodeType::type_str(as_doc)); - tree.to_val(node, curr.filtered_scalar(&tree), as_doc); - curr.add_val_props(&tree, node); - } - else if(tree.is_map(top.tree_node)) - { - _nfo_logf("is map! map_id={}", top.tree_node); - if(!key) - { - _nfo_logf("store key='{}' anchor='{}' tag='{}' type={}", curr.scalar, curr.anchor, curr.tag, curr.type.to_str()); - key = curr; - } - else - { - _nfo_logf("map[{}]: adding child", top.tree_node); - size_t node = tree.append_child(top.tree_node); - NodeType_e as_doc = tree.is_stream(top.tree_node) ? DOC : NOTYPE; - _nfo_logf("map[{}]: child={} key='{}' val='{}' as_doc={}", top.tree_node, node, key.scalar, curr.scalar, NodeType::type_str(as_doc)); - tree.to_keyval(node, key.filtered_scalar(&tree), curr.filtered_scalar(&tree), as_doc); - key.add_key_props(&tree, node); - curr.add_val_props(&tree, node); - _nfo_logf("clear key='{}'", key.scalar); - key = {}; - } - } - else - { - _nfo_logf("setting tree_node={} to DOCVAL...", top.tree_node); - tree.to_val(top.tree_node, curr.filtered_scalar(&tree), DOC); - curr.add_val_props(&tree, top.tree_node); - } - } - else if(line.begins_with("=ALI ")) - { - csubstr alias = line.stripl("=ALI "); - _nfo_logf("REF token: {}", alias); - ParseLevel top = m_stack.top(); - if(tree.is_seq(top.tree_node)) - { - _nfo_logf("node[{}] is seq: set {} as val ref", top.tree_node, alias); - ASSERT_FALSE(key); - size_t node = tree.append_child(top.tree_node); - tree.to_val(node, alias); - tree.set_val_ref(node, alias); - } - else if(tree.is_map(top.tree_node)) - { - if(key) - { - _nfo_logf("node[{}] is map and key '{}' is pending: set {} as val ref", top.tree_node, key.scalar, alias); - size_t node = tree.append_child(top.tree_node); - tree.to_keyval(node, key.filtered_scalar(&tree), alias); - key.add_key_props(&tree, node); - tree.set_val_ref(node, alias); - _nfo_logf("clear key='{}'", key); - key = {}; - } - else - { - _nfo_logf("node[{}] is map and no key is pending: save {} as key ref", top.tree_node, alias); - key.scalar = alias; - key.ref = alias; - } - } - else - { - C4_ERROR("ALI event requires map or seq"); - } - } - else if(line.begins_with("+SEQ")) - { - _nfo_log("pushing SEQ"); - OptionalScalar anchor = {}; - OptionalScalar tag = {}; - csubstr more_tokens = line.stripl("+SEQ").triml(' '); - if(more_tokens.begins_with('[')) - { - ASSERT_TRUE(more_tokens.begins_with("[]")); - more_tokens = more_tokens.offs(2, 0).triml(' '); - } - parse_anchor_and_tag(more_tokens, &anchor, &tag); - size_t node = tree.root_id(); - if(m_stack.empty()) - { - _nfo_log("stack was empty, set root to SEQ"); - tree._add_flags(node, SEQ); - m_stack.push({node}); - ASSERT_FALSE(key); // for the key to exist, the parent must exist and be a map - } - else - { - size_t parent = m_stack.top().tree_node; - _nfo_logf("stack was not empty. parent={}", parent); - ASSERT_NE(parent, (size_t)NONE); - NodeType more_flags = NOTYPE; - if(tree.is_doc(parent) && !(tree.is_seq(parent) || tree.is_map(parent))) - { - _nfo_logf("set node to parent={}, add DOC", parent); - node = parent; - more_flags.add(DOC); - } - else - { - _nfo_logf("add child to parent={}", parent); - node = tree.append_child(parent); - m_stack.push({node}); - _nfo_logf("add child to parent={}: child={}", parent, node); - } - if(key) - { - _nfo_logf("has key, set to keyseq: parent={} child={} key='{}'", parent, node, key); - ASSERT_EQ(tree.is_map(parent) || node == parent, true); - tree.to_seq(node, key.filtered_scalar(&tree), more_flags); - key.add_key_props(&tree, node); - _nfo_logf("clear key='{}'", key.scalar); - key = {}; - } - else - { - if(tree.is_map(parent)) - { - _nfo_logf("has null key, set to keyseq: parent={} child={}", parent, node); - ASSERT_EQ(tree.is_map(parent) || node == parent, true); - tree.to_seq(node, csubstr{}, more_flags); - } - else - { - _nfo_logf("no key, set to seq: parent={} child={}", parent, node); - tree.to_seq(node, more_flags); - } - } - } - if(tag) - tree.set_val_tag(node, normalize_tag(tag)); - if(anchor) - tree.set_val_anchor(node, anchor); - } - else if(line.begins_with("+MAP")) - { - _nfo_log("pushing MAP"); - OptionalScalar anchor = {}; - OptionalScalar tag = {}; - csubstr more_tokens = line.stripl("+MAP").triml(' '); - if(more_tokens.begins_with('{')) - { - ASSERT_TRUE(more_tokens.begins_with("{}")); - more_tokens = more_tokens.offs(2, 0).triml(' '); - } - parse_anchor_and_tag(more_tokens, &anchor, &tag); - size_t node = tree.root_id(); - if(m_stack.empty()) - { - _nfo_log("stack was empty, set root to MAP"); - tree._add_flags(node, MAP); - m_stack.push({node}); - ASSERT_FALSE(key); // for the key to exist, the parent must exist and be a map - } - else - { - size_t parent = m_stack.top().tree_node; - _nfo_logf("stack was not empty. parent={}", parent); - ASSERT_NE(parent, (size_t)NONE); - NodeType more_flags = NOTYPE; - if(tree.is_doc(parent) && !(tree.is_seq(parent) || tree.is_map(parent))) - { - _nfo_logf("set node to parent={}, add DOC", parent); - node = parent; - more_flags.add(DOC); - } - else - { - _nfo_logf("add child to parent={}", parent); - node = tree.append_child(parent); - m_stack.push({node}); - _nfo_logf("add child to parent={}: child={}", parent, node); - } - if(key) - { - _nfo_logf("has key, set to keymap: parent={} child={} key='{}'", parent, node, key); - ASSERT_EQ(tree.is_map(parent) || node == parent, true); - tree.to_map(node, key.filtered_scalar(&tree), more_flags); - key.add_key_props(&tree, node); - _nfo_logf("clear key='{}'", key.scalar); - key = {}; - } - else - { - if(tree.is_map(parent)) - { - _nfo_logf("has null key, set to keymap: parent={} child={}", parent, node); - ASSERT_EQ(tree.is_map(parent) || node == parent, true); - tree.to_map(node, csubstr{}, more_flags); - } - else - { - _nfo_logf("no key, set to map: parent={} child={}", parent, node); - tree.to_map(node, more_flags); - } - } - } - if(tag) - tree.set_val_tag(node, normalize_tag(tag)); - if(anchor) - tree.set_val_anchor(node, anchor); - } - else if(line.begins_with("-SEQ")) - { - _nfo_logf("popping SEQ, empty={}", m_stack.empty()); - size_t node; - if(m_stack.empty()) - node = tree.root_id(); - else - node = m_stack.pop().tree_node; - ASSERT_TRUE(tree.is_seq(node)) << "node=" << node; - } - else if(line.begins_with("-MAP")) - { - _nfo_logf("popping MAP, empty={}", m_stack.empty()); - size_t node; - if(m_stack.empty()) - node = tree.root_id(); - else - node = m_stack.pop().tree_node; - ASSERT_TRUE(tree.is_map(node)) << "node=" << node; - } - else if(line.begins_with("+DOC")) - { - csubstr rem = line.stripl("+DOC").triml(' '); - _nfo_logf("pushing DOC: {}", rem); - size_t node = tree.root_id(); - auto is_sep = rem.first_of_any("---\n", "--- ", "---\r") || rem.ends_with("---"); - ASSERT_EQ(key, false); // for the key to exist, the parent must exist and be a map - if(m_stack.empty()) - { - _nfo_log("stack was empty"); - ASSERT_EQ(node, tree.root_id()); - if(tree.is_stream(node)) - { - _nfo_log("there is already a stream, append a DOC"); - node = tree.append_child(node); - tree.to_doc(node); - m_stack.push({node}); - } - else if(is_sep) - { - _nfo_logf("separator was specified: {}", rem); - if((!tree.is_container(node)) && (!tree.is_doc(node))) - { - tree._add_flags(node, STREAM); - node = tree.append_child(node); - _nfo_logf("create STREAM at {} and add DOC child={}", tree.root_id(), node); - tree.to_doc(node); - m_stack.push({node}); - } - else - { - _nfo_log("rearrange root as STREAM"); - tree.set_root_as_stream(); - node = tree.append_child(tree.root_id()); - _nfo_logf("added doc as STREAM child: {}", node); - tree.to_doc(node); - m_stack.push({node}); - } - } - else - { - if(tree.is_doc(node)) - { - _nfo_log("rearrange root as STREAM"); - tree.set_root_as_stream(); - m_stack.push({node}); - } - } - } - else - { - size_t parent = m_stack.top().tree_node; - _nfo_logf("add DOC to parent={}", parent); - ASSERT_NE(parent, (size_t)NONE); - node = tree.append_child(parent); - _nfo_logf("child DOC={}", node); - tree.to_doc(node); - m_stack.push({node}); - } - } - else if(line.begins_with("-DOC")) - { - _nfo_log("popping DOC"); - if(!m_stack.empty()) - m_stack.pop(); - } - else if(line.begins_with("+STR")) - { - ASSERT_EQ(m_stack.size(), 0u); - } - else if(line.begins_with("-STR")) - { - ASSERT_LE(m_stack.size(), 1u); - if(!m_stack.empty()) - m_stack.pop(); - } - else if(line.empty()) - { - // nothing to do - } - else - { - C4_ERROR("unknown event: '%.*s'", (int)line.len, line.str); - } - linenum++; - } -} - - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_suite/test_suite_events.hpp b/thirdparty/ryml/test/test_suite/test_suite_events.hpp deleted file mode 100644 index 3b3cdbffb..000000000 --- a/thirdparty/ryml/test/test_suite/test_suite_events.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef C4_YML_TEST_SUITE_EVENTS_HPP_ -#define C4_YML_TEST_SUITE_EVENTS_HPP_ - -#ifdef RYML_SINGLE_HEADER -#include -#else -#include -#endif - -namespace c4 { -namespace yml { - -struct EventsParser -{ - void parse(csubstr src, Tree *C4_RESTRICT tree); -}; - -size_t emit_events(substr buf, Tree const& C4_RESTRICT tree); - -template -void emit_events(CharContainer *container, Tree const& C4_RESTRICT tree) -{ - size_t ret = emit_events(to_substr(*container), tree); - if(ret > container->size()) - { - container->resize(ret); - ret = emit_events(to_substr(*container), tree); - C4_CHECK(ret == container->size()); - } - container->resize(ret); -} - -template -CharContainer emit_events(Tree const& C4_RESTRICT tree) -{ - CharContainer result; - emit_events(&result, tree); - return result; -} - -} // namespace yml -} // namespace c4 - - -#endif /* C4_YML_TEST_SUITE_EVENTS_HPP_ */ diff --git a/thirdparty/ryml/test/test_suite/test_suite_events_emitter.cpp b/thirdparty/ryml/test/test_suite/test_suite_events_emitter.cpp deleted file mode 100644 index 6c22b1e6e..000000000 --- a/thirdparty/ryml/test/test_suite/test_suite_events_emitter.cpp +++ /dev/null @@ -1,289 +0,0 @@ -#ifndef RYML_SINGLE_HEADER -#include -#endif -#include "test_suite_events.hpp" - -namespace c4 { -namespace yml { - -struct EventsEmitter -{ - substr buf; - size_t pos; - std::string tagbuf; - Tree const* C4_RESTRICT m_tree; - EventsEmitter(Tree const& tree, substr buf_) : buf(buf_), pos(), m_tree(&tree) {} - void emit_tag(csubstr tag, size_t node); - void emit_scalar(csubstr val, bool quoted); - void emit_key_anchor_tag(size_t node); - void emit_val_anchor_tag(size_t node); - void emit_events(size_t node); - void emit_doc(size_t node); - void emit_events(); - template - C4_ALWAYS_INLINE void pr(const char (&s)[N]) - { - if(pos + N-1 <= buf.len) - memcpy(buf.str + pos, s, N-1); - pos += N-1; - } - C4_ALWAYS_INLINE void pr(csubstr s) - { - if(pos + s.len <= buf.len) - memcpy(buf.str + pos, s.str, s.len); - pos += s.len; - } - C4_ALWAYS_INLINE void pr(char c) - { - if(pos + 1 <= buf.len) - buf[pos] = c; - ++pos; - } - C4_ALWAYS_INLINE size_t emit_to_esc(csubstr val, size_t prev, size_t i, char c) - { - pr(val.range(prev, i)); - pr('\\'); - pr(c); - return i+1; - } - C4_ALWAYS_INLINE size_t emit_to_esc(csubstr val, size_t prev, size_t i, csubstr repl) - { - pr(val.range(prev, i)); - pr(repl); - return i+1; - } -}; - -void EventsEmitter::emit_scalar(csubstr val, bool quoted) -{ - constexpr const char openchar[] = {':', '\''}; - pr(openchar[quoted]); - size_t prev = 0; - uint8_t const* C4_RESTRICT s = (uint8_t const* C4_RESTRICT) val.str; - for(size_t i = 0; i < val.len; ++i) - { - switch(s[i]) - { - case UINT8_C(0x0a): // \n - prev = emit_to_esc(val, prev, i, 'n'); break; - case UINT8_C(0x5c): // '\\' - prev = emit_to_esc(val, prev, i, '\\'); break; - case UINT8_C(0x09): // \t - prev = emit_to_esc(val, prev, i, 't'); break; - case UINT8_C(0x0d): // \r - prev = emit_to_esc(val, prev, i, 'r'); break; - case UINT8_C(0x00): // \0 - prev = emit_to_esc(val, prev, i, '0'); break; - case UINT8_C(0x0c): // \f (form feed) - prev = emit_to_esc(val, prev, i, 'f'); break; - case UINT8_C(0x08): // \b (backspace) - prev = emit_to_esc(val, prev, i, 'b'); break; - case UINT8_C(0x07): // \a (bell) - prev = emit_to_esc(val, prev, i, 'a'); break; - case UINT8_C(0x0b): // \v (vertical tab) - prev = emit_to_esc(val, prev, i, 'v'); break; - case UINT8_C(0x1b): // \e (escape) - prev = emit_to_esc(val, prev, i, "\\e"); break; - case UINT8_C(0xc2): - if(i+1 < val.len) - { - uint8_t np1 = s[i+1]; - if(np1 == UINT8_C(0xa0)) - prev = 1u + emit_to_esc(val, prev, i++, "\\_"); - else if(np1 == UINT8_C(0x85)) - prev = 1u + emit_to_esc(val, prev, i++, "\\N"); - } - break; - case UINT8_C(0xe2): - if(i+2 < val.len) - { - if(s[i+1] == UINT8_C(0x80)) - { - if(s[i+2] == UINT8_C(0xa8)) - { - prev = 2u + emit_to_esc(val, prev, i, "\\L"); - i += 2u; - } - else if(s[i+2] == UINT8_C(0xa9)) - { - prev = 2u + emit_to_esc(val, prev, i, "\\P"); - i += 2u; - } - } - } - break; - } - } - pr(val.sub(prev)); // print remaining portion -} - -void EventsEmitter::emit_tag(csubstr tag, size_t node) -{ - size_t tagsize = m_tree->resolve_tag(to_substr(tagbuf), tag, node); - if(tagsize) - { - if(tagsize > tagbuf.size()) - { - tagbuf.resize(tagsize); - tagsize = m_tree->resolve_tag(to_substr(tagbuf), tag, node); - } - pr(to_substr(tagbuf).first(tagsize)); - } - else - { - csubstr ntag = normalize_tag_long(tag); - if(ntag.begins_with('<')) - { - pr(ntag); - } - else - { - pr('<'); - pr(ntag); - pr('>'); - } - } -} - -void EventsEmitter::emit_key_anchor_tag(size_t node) -{ - if(m_tree->has_key_anchor(node)) - { - pr(" &"); - pr(m_tree->key_anchor(node)); - } - if(m_tree->has_key_tag(node)) - { - pr(' '); - emit_tag(m_tree->key_tag(node), node); - } -} - -void EventsEmitter::emit_val_anchor_tag(size_t node) -{ - if(m_tree->has_val_anchor(node)) - { - pr(" &"); - pr(m_tree->val_anchor(node)); - } - if(m_tree->has_val_tag(node)) - { - pr(' '); - emit_tag(m_tree->val_tag(node), node); - } -} - -void EventsEmitter::emit_events(size_t node) -{ - if(m_tree->has_key(node)) - { - if(m_tree->is_key_ref(node)) - { - csubstr k = m_tree->key(node); - if(k != "<<") - { - pr("=ALI "); - pr(k); - pr('\n'); - } - else - { - pr("=VAL :"); - pr(k); - pr('\n'); - } - } - else - { - pr("=VAL"); - emit_key_anchor_tag(node); - pr(' '); - emit_scalar(m_tree->key(node), m_tree->is_key_quoted(node)); - pr('\n'); - } - } - if(m_tree->has_val(node)) - { - if(m_tree->is_val_ref(node)) - { - pr("=ALI "); - pr(m_tree->val(node)); - pr('\n'); - } - else - { - pr("=VAL"); - emit_val_anchor_tag(node); - pr(' '); - emit_scalar(m_tree->val(node), m_tree->is_val_quoted(node)); - pr('\n'); - } - } - else if(m_tree->is_map(node)) - { - pr("+MAP"); - emit_val_anchor_tag(node); - pr('\n'); - for(size_t child = m_tree->first_child(node); child != NONE; child = m_tree->next_sibling(child)) - emit_events(child); - pr("-MAP\n"); - } - else if(m_tree->is_seq(node)) - { - pr("+SEQ"); - emit_val_anchor_tag(node); - pr('\n'); - for(size_t child = m_tree->first_child(node); child != NONE; child = m_tree->next_sibling(child)) - emit_events(child); - pr("-SEQ\n"); - } -} - -void EventsEmitter::emit_doc(size_t node) -{ - if(m_tree->type(node) == NOTYPE) - return; - if(m_tree->has_parent(node)) - pr("+DOC ---"); // parent must be a stream - else - pr("+DOC"); - if(m_tree->is_val(node)) - { - pr("\n=VAL"); - emit_val_anchor_tag(node); - pr(' '); - emit_scalar(m_tree->val(node), m_tree->is_val_quoted(node)); - pr('\n'); - } - else - { - pr('\n'); - emit_events(node); - } - pr("-DOC\n"); -} - -void EventsEmitter::emit_events() -{ - pr("+STR\n"); - if(!m_tree->empty()) - { - size_t root = m_tree->root_id(); - if(m_tree->is_stream(root)) - for(size_t node = m_tree->first_child(root); node != NONE; node = m_tree->next_sibling(node)) - emit_doc(node); - else - emit_doc(root); - } - pr("-STR\n"); -} - -size_t emit_events(substr buf, Tree const& C4_RESTRICT tree) -{ - EventsEmitter e(tree, buf); - e.emit_events(); - return e.pos; -} - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_suite/test_suite_parts.cpp b/thirdparty/ryml/test/test_suite/test_suite_parts.cpp deleted file mode 100644 index 5caaafeab..000000000 --- a/thirdparty/ryml/test/test_suite/test_suite_parts.cpp +++ /dev/null @@ -1,220 +0,0 @@ -#include "./test_suite_parts.hpp" - -namespace c4 { -namespace yml { - - -// To see the test case contents, refer to this URL: -// https://github.com/yaml/yaml-test-suite/tree/master/src -constexpr const AllowedFailure allowed_failures[] = { - - // g++-5 does not like creating a csubstr directly from the literal. - // so we use this macro to remove cruft from the code: - #define _(testcase, reason) AllowedFailure{csubstr(testcase), csubstr(reason)} - - //------------------------------------------------------------------------- - // SECTION 1. Known issues, TODO - // - // These tests are temporarily skipped, and cover issues that must be fixed. - - // double quoted scalars - _("G4RS-in_json" , "special characters must be emitted in double quoted style"), - _("G4RS-in_yaml" , "special characters must be emitted in double quoted style"), - _("G4RS-out_yaml" , "special characters must be emitted in double quoted style"), - // other - _("UKK6_01-in_yaml" , "fails to parse double :: in UNK state"), - - - //------------------------------------------------------------------------- - // SECTION 2. Expected errors that fail to materialize. - - // maps - _("236B-error" , "should not accept final scalar in a map"), - _("7MNF-error" , "should not accept final scalar in a map"), - _("62EZ-error" , "should not accept invalid block mapping key on same line as previous key"), - _("9CWY-error" , "should not accept final scalar in a map"), - _("CXX2-error" , "should not accept mapping with anchor on document start line"), - _("DK95_06-error" , "should not accept tab indentation"), - _("GDY7-error" , "should not accept comment that looks like a mapping key"), - _("D49Q-error" , "should not accept multiline single quoted implicit keys"), - _("DK4H-error" , "should not accept implicit key followed by newline"), - _("JY7Z-error" , "should not accept trailing content that looks like a mapping"), - _("SU74-error" , "should not accept anchor and alias as mapping key"), - _("T833-error" , "should not accept flow mapping missing a separating comma"), - _("VJP3_00-error" , "should not accept flow collections over many lines"), - _("Y79Y_006-error", "should not accept tab after ?"), - _("Y79Y_007-error", "should not accept tab after :"), - _("Y79Y_008-error", "should not accept tab after ?"), - _("Y79Y_009-error", "should not accept tab after ?"), - _("ZCZ6-error" , "should not accept invalid mapping in plain single line value"), - // seqs - _("5U3A-error" , "should not accept opening a sequence on same line as map key"), - _("6JTT-error" , "should not accept flow sequence without terminating ]"), - _("9C9N-error" , "should not accept non-indented flow sequence"), - _("9JBA-error" , "should not accept comment after flow seq terminating ]"), - _("9MAG-error" , "should not accept flow sequence with invalid comma at the beginning"), - _("CTN5-error" , "should not accept flow sequence with missing elements"), - _("CVW2-error" , "should not accept flow sequence with comment after ,"), - _("G5U8-error" , "should not accept [-, -]"), - _("KS4U-error" , "should not accept item after end of flow sequence"), - _("P2EQ-error" , "should not accept sequence item on same line as previous item"), - _("YJV2-error" , "should not accept [-]"), - _("Y79Y_003-error", "should not accept leading tabs in seq elmt"), - _("Y79Y_004-error", "should not accept tab after -"), - _("Y79Y_005-error", "should not accept tab after -"), - // block scalars - _("2G84_00-error" , "should not accept the block literal spec"), - _("2G84_01-error" , "should not accept the block literal spec"), - _("5LLU-error" , "should not accept folded scalar with wrong indented line after spaces only"), - _("S4GJ-error" , "should not accept text after block scalar indicator"), - _("S98Z-error" , "should not accept block scalar with more spaces than first content line"), - _("X4QW-error" , "should not accept comment without whitespace after block scalar indicator"), - _("Y79Y_000-error", "should not accept leading tabs in the block scalar"), - // quoted scalars - _("55WF-error" , "should not accept invalid escape in double quoted scalar"), - _("7LBH-error" , "should not accept multiline double quoted implicit keys"), - _("DK95_01-error", "should not accept leading tabs in double quoted multiline scalar"), - _("HRE5-error" , "should not accept double quoted scalar with escaped single quote"), - _("JKF3-error" , "should not accept multiline unindented double quoted scalar"), - _("QB6E-error" , "should not accept indented multiline quoted scalar"), - _("RXY3-error" , "should not accept document-end marker in single quoted string"), - _("SU5Z-error" , "should not accept comment without whitespace after double quoted scalar"), - // plain scalars - _("8XDJ-error" , "should not accept comment in multiline scalar"), - _("CML9-error" , "should not accept comment inside flow scalar"), - // documents/streams - _("3HFZ-error" , "should not accept scalar after ..."), - _("5TRB-error" , "should not accept document-end marker in double quoted string"), - _("9MMA-error" , "should not accept empty doc after %YAML directive"), - _("9MQT_01-error", "should not accept scalars after ..."), - _("B63P-error" , "should not accept directive without doc"), - _("EB22-error" , "should not accept missing document-end marker before directive"), - _("H7TQ-error" , "should not accept extra words after directive"), - _("MUS6_00-error", "should not accept #... at the end of %YAML directive"), - _("MUS6_01-error", "should not accept #... at the end of %YAML directive"), - _("N782-error" , "should not accept document markers in flow style"), - _("RHX7-error" , "should not accept directive without document end marker"), - _("SF5V-error" , "should not accept duplicate YAML directive"), - // anchors - _("4EJS-error" , "should not accept double anchor for scalar"), - _("4JVG-error" , "should not accept double anchor for scalar"), - _("SY6V-error" , "should not accept anchor before sequence entry on same line"), - // tags - _("9HCY-error" , "should not accept tag directive in non-doc scope"), - _("BU8L-error" , "should not accept node properties spread over multiple lines"), - _("LHL4-error" , "should not accept tag"), - _("U99R-error" , "should not accept comma in a tag"), - _("QLJ7-error" , "tag directives should apply only to the next doc (?)"), - - - //------------------------------------------------------------------------- - // SECTION 3. Deliberate ryml limitations. - // - // These tests are skipped because they cover parts of YAML that - // are deliberately not implemented by ryml. - - #ifndef RYML_WITH_TAB_TOKENS // - or : are supported only when the above macro is defined - _("A2M4-in_yaml-events" , "tabs tokens"), - _("6BCT-in_yaml" , "tabs tokens"), - _("J3BT-in_yaml-events" , "tabs tokens"), - _("Y79Y_010-in_yaml-events", "tabs tokens"), - #endif - // container keys are not supported - _("4FJ6-in_yaml" , "only scalar keys allowed (keys cannot be maps or seqs)"), - _("4FJ6-out_yaml" , "only scalar keys allowed (keys cannot be maps or seqs)"), - _("6BFJ-in_yaml" , "only scalar keys allowed (keys cannot be maps or seqs)"), - _("6BFJ-out_yaml" , "only scalar keys allowed (keys cannot be maps or seqs)"), - _("6PBE-in_yaml" , "only scalar keys allowed (keys cannot be maps or seqs)"), - _("6PBE-out_yaml" , "only scalar keys allowed (keys cannot be maps or seqs)"), - _("6PBE-emit_yaml" , "only scalar keys allowed (keys cannot be maps or seqs)"), - _("9MMW-in_yaml" , "only scalar keys allowed (keys cannot be maps or seqs)"), - _("9MMW-out_yaml" , "only scalar keys allowed (keys cannot be maps or seqs)"), - _("KK5P-in_yaml" , "only scalar keys allowed (keys cannot be maps or seqs)"), - _("KK5P-out_yaml" , "only scalar keys allowed (keys cannot be maps or seqs)"), - _("KZN9-in_yaml" , "only scalar keys allowed (keys cannot be maps or seqs)"), - _("KZN9-out_yaml" , "only scalar keys allowed (keys cannot be maps or seqs)"), - _("LX3P-in_yaml" , "only scalar keys allowed (keys cannot be maps or seqs)"), - _("LX3P-out_yaml" , "only scalar keys allowed (keys cannot be maps or seqs)"), - _("M2N8_00-in_yaml" , "only scalar keys allowed (keys cannot be maps or seqs)"), - _("M2N8_00-out_yaml" , "only scalar keys allowed (keys cannot be maps or seqs)"), - _("M2N8_01-in_yaml-events" , "only scalar keys allowed (keys cannot be maps or seqs)"), - _("M2N8_01-out_yaml-events", "only scalar keys allowed (keys cannot be maps or seqs)"), - _("M5DY-in_yaml" , "only scalar keys allowed (keys cannot be maps or seqs)"), - _("M5DY-out_yaml" , "only scalar keys allowed (keys cannot be maps or seqs)"), - _("Q9WF-in_yaml" , "only scalar keys allowed (keys cannot be maps or seqs)"), - _("Q9WF-out_yaml" , "only scalar keys allowed (keys cannot be maps or seqs)"), - _("RZP5-in_yaml" , "only scalar keys allowed (keys cannot be maps or seqs)"), - _("RZP5-out_yaml" , "only scalar keys allowed (keys cannot be maps or seqs)"), - _("SBG9-in_yaml" , "only scalar keys allowed (keys cannot be maps or seqs)"), - _("SBG9-out_yaml" , "only scalar keys allowed (keys cannot be maps or seqs)"), - _("V9D5-in_yaml" , "only scalar keys allowed (keys cannot be maps or seqs)"), - _("V9D5-out_yaml" , "only scalar keys allowed (keys cannot be maps or seqs)"), - _("X38W-in_yaml" , "only scalar keys allowed (keys cannot be maps or seqs)"), - _("X38W-out_yaml" , "only scalar keys allowed (keys cannot be maps or seqs)"), - _("XW4D-in_yaml" , "only scalar keys allowed (keys cannot be maps or seqs)"), - _("XW4D-out_yaml" , "only scalar keys allowed (keys cannot be maps or seqs)"), - // anchors with : are not supported - _("2SXE-in_yaml-events" , "weird characters in anchors, anchors must not end with :"), - // malformed json in the test spec - _("35KP-in_json" , "malformed JSON from multiple documents"), - _("5TYM-in_json" , "malformed JSON from multiple documents"), - _("6XDY-in_json" , "malformed JSON from multiple documents"), - _("6WLZ-in_json" , "malformed JSON from multiple documents"), - _("6ZKB-in_json" , "malformed JSON from multiple documents"), - _("7Z25-in_json" , "malformed JSON from multiple documents"), - _("9DXL-in_json" , "malformed JSON from multiple documents"), - _("9KAX-in_json" , "malformed JSON from multiple documents"), - _("9WXW-in_json" , "malformed JSON from multiple documents"), - _("JHB9-in_json" , "malformed JSON from multiple documents"), - _("KSS4-in_json" , "malformed JSON from multiple documents"), - _("L383-in_json" , "malformed JSON from multiple documents"), - _("M7A3-in_json" , "malformed JSON from multiple documents"), - _("RZT7-in_json" , "malformed JSON from multiple documents"), - _("U9NS-in_json" , "malformed JSON from multiple documents"), - _("W4TN-in_json" , "malformed JSON from multiple documents"), - // malformed test spec? - _("4ABK-out_yaml-events" , "out-yaml contains null, while in-yaml and events contain empty scalars"), - _("4WA9-out_yaml-events" , "out-yaml test spec is missing a --- document token, which is required in the events"), - _("652Z-out_yaml-events" , "out-yaml test spec is missing a --- document token, which is required in the events"), - _("6CA3-emit_yaml" , "out-yaml test spec is missing a --- document token, which is required in the events"), - _("6FWR-out_yaml-events" , "out-yaml test spec is missing a --- document token, which is required in the events"), - _("6WPF-out_yaml-events" , "out-yaml test spec is missing a --- document token, which is required in the events"), - _("9TFX-out_yaml-events" , "out-yaml test spec is missing a --- document token, which is required in the events"), - _("B3HG-out_yaml-events" , "out-yaml test spec is missing a --- document token, which is required in the events"), - _("DK95_00-emit_yaml-events", "out-yaml test spec is missing a --- document token, which is required in the events"), - _("DK95_02-emit_yaml-events", "out-yaml test spec is missing a --- document token, which is required in the events"), - _("DK95_03-emit_yaml-events", "out-yaml test spec is missing a --- document token, which is required in the events"), - _("DK95_04-emit_yaml-events", "out-yaml test spec is missing a --- document token, which is required in the events"), - _("DK95_05-emit_yaml-events", "out-yaml test spec is missing a --- document token, which is required in the events"), - _("DK95_06-emit_yaml-events", "out-yaml test spec is missing a --- document token, which is required in the events"), - _("DK95_07-emit_yaml-events", "out-yaml test spec is missing a --- document token, which is required in the events"), - _("DK95_08-emit_yaml-events", "out-yaml test spec is missing a --- document token, which is required in the events"), - _("EX5H-out_yaml-events" , "out-yaml test spec is missing a --- document token, which is required in the events"), - _("EXG3-out_yaml-events" , "out-yaml test spec is missing a --- document token, which is required in the events"), - _("L24T_00-emit_yaml-events", "out-yaml test spec is missing a --- document token, which is required in the events"), - _("L24T_01-emit_yaml-events", "out-yaml test spec is missing a --- document token, which is required in the events"), - _("M6YH-out_yaml-events" , "out-yaml test spec is missing a --- document token, which is required in the events"), - _("Q8AD-out_yaml-events" , "out-yaml test spec is missing a --- document token, which is required in the events"), - _("T26H-out_yaml-events" , "out-yaml test spec is missing a --- document token, which is required in the events"), - _("T4YY-out_yaml-events" , "out-yaml test spec is missing a --- document token, which is required in the events"), - _("T5N4-out_yaml-events" , "out-yaml test spec is missing a --- document token, which is required in the events"), - _("VJP3_01-out_yaml-events" , "out-yaml test spec is missing a --- document token, which is required in the events"), - - #undef _ -}; - - -cspan g_allowed_failures = allowed_failures; - -AllowedFailure is_failure_expected(csubstr casename) -{ - RYML_CHECK(casename.not_empty()); - for(AllowedFailure const& af : g_allowed_failures) - if(af.test_name == casename || casename.begins_with(af.test_name)) - return af; - return {}; -} - - -} // namespace c4 -} // namespace yml diff --git a/thirdparty/ryml/test/test_suite/test_suite_parts.hpp b/thirdparty/ryml/test/test_suite/test_suite_parts.hpp deleted file mode 100644 index 9092313ba..000000000 --- a/thirdparty/ryml/test/test_suite/test_suite_parts.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef C4_YML_TEST_SUITE_PARTS_HPP_ -#define C4_YML_TEST_SUITE_PARTS_HPP_ - -#ifdef RYML_SINGLE_HEADER -#include -#else -#include -#include -#endif -#include - -namespace c4 { -namespace yml { - -struct AllowedFailure -{ - csubstr test_name; - csubstr reason; - operator bool() const { return !test_name.empty(); } -}; - -AllowedFailure is_failure_expected(csubstr casename); - -} // namespace c4 -} // namespace yml - - -#endif /* C4_YML_TEST_SUITE_PARTS_HPP_ */ diff --git a/thirdparty/ryml/test/test_tag_property.cpp b/thirdparty/ryml/test/test_tag_property.cpp deleted file mode 100644 index e56fef994..000000000 --- a/thirdparty/ryml/test/test_tag_property.cpp +++ /dev/null @@ -1,1149 +0,0 @@ -#include "./test_group.hpp" -#include "test_case.hpp" - -namespace c4 { -namespace yml { - -TEST(tag_directives, basic) -{ - Tree t = parse_in_arena(R"( -%TAG !m! !my- ---- # Bulb here -!m!light fluorescent -... -%TAG !m! !meta- ---- # Color here -!m!light green -)"); - EXPECT_EQ(t[0].val_tag(), "!m!light"); - EXPECT_EQ(t[1].val_tag(), "!m!light"); - EXPECT_EQ(t.num_tag_directives(), 2u); - char buf_[100]; - EXPECT_EQ(t.resolve_tag_sub(buf_, "!m!light", 1u), csubstr("")); - EXPECT_EQ(t.resolve_tag_sub(buf_, "!m!light", 2u), csubstr("")); - EXPECT_EQ(emitrs_yaml(t), std::string(R"(%TAG !m! !my- ---- !m!light fluorescent -... -%TAG !m! !meta- ---- !m!light green -)")); -} - -TEST(tag_directives, accepts_comment) -{ - Tree t = parse_in_arena(R"( -%TAG !m! !my- # comment ---- # Bulb here -!m!light fluorescent -... -%TAG !m! !meta- # comment ---- # Color here -!m!light green -)"); - EXPECT_EQ(t[0].val_tag(), "!m!light"); - EXPECT_EQ(t[1].val_tag(), "!m!light"); - EXPECT_EQ(t.num_tag_directives(), 2u); - char buf_[100]; - EXPECT_EQ(t.resolve_tag_sub(buf_, "!m!light", 1u), csubstr("")); - EXPECT_EQ(t.resolve_tag_sub(buf_, "!m!light", 2u), csubstr("")); - EXPECT_EQ(emitrs_yaml(t), std::string(R"(%TAG !m! !my- ---- !m!light fluorescent -... -%TAG !m! !meta- ---- !m!light green -)")); -} - -TEST(tag_directives, accepts_multiple_spaces) -{ - Tree t = parse_in_arena(R"( -%TAG !m! !my- # comment ---- # Bulb here -!m!light fluorescent -... -%TAG !m! !meta- # comment ---- # Color here -!m!light green -)"); - EXPECT_EQ(t[0].val_tag(), "!m!light"); - EXPECT_EQ(t[1].val_tag(), "!m!light"); - EXPECT_EQ(t.num_tag_directives(), 2u); - char buf_[100]; - EXPECT_EQ(t.resolve_tag_sub(buf_, "!m!light", 1u), csubstr("")); - EXPECT_EQ(t.resolve_tag_sub(buf_, "!m!light", 2u), csubstr("")); - EXPECT_EQ(emitrs_yaml(t), std::string(R"(%TAG !m! !my- ---- !m!light fluorescent -... -%TAG !m! !meta- ---- !m!light green -)")); -} - -TEST(tag_directives, errors) -{ - { - Tree t; - ExpectError::do_check(&t, [&]{ - t = parse_in_arena(R"( -%TAG ---- # Bulb here -!m!light fluorescent)"); - }); - } - { - Tree t; - ExpectError::do_check(&t, [&]{ - t = parse_in_arena(R"( -%TAG !m! ---- # Bulb here -!m!light fluorescent)"); - }); - } -} - -TEST(tag_directives, resolve_tags) -{ - Tree t = parse_in_arena(R"( -%TAG !m! !my- # comment ---- # Bulb here -!m!light fluorescent: !m!light bulb -... -%TAG !m! !meta- # comment ---- # Color here -!m!light green: !m!light color -)"); - EXPECT_EQ(t.docref(0)[0].key_tag(), "!m!light"); - EXPECT_EQ(t.docref(0)[0].val_tag(), "!m!light"); - EXPECT_EQ(t.num_tag_directives(), 2u); - t.resolve_tags(); - EXPECT_EQ(t.docref(0)[0].key_tag(), ""); - EXPECT_EQ(t.docref(0)[0].val_tag(), ""); - EXPECT_EQ(emitrs_yaml(t), std::string(R"(%TAG !m! !my- ---- -! fluorescent: ! bulb -... -%TAG !m! !meta- ---- -! green: ! color -)")); -} - -TEST(tag_directives, safe_with_empty_tree) -{ - Tree t; - t.resolve_tags(); - EXPECT_TRUE(t.empty()); -} - -TEST(tag_directives, decode_uri_chars) -{ - { - Tree t = parse_in_arena(R"( -%TAG !e! tag:example.com,2000:app/ ---- -- !e!%61%62%63%21 baz -)"); - t.resolve_tags(); - EXPECT_EQ(t.docref(0)[0].val_tag(), csubstr("")); - } - { - Tree t; - auto checkerr = [&t](csubstr yaml){ - ExpectError::do_check(&t, [&]{ - t.clear(); - t = parse_in_arena(yaml); - t.resolve_tags(); - }); - }; - { - SCOPED_TRACE("without numbers at begin"); - checkerr(R"( -%TAG !e! tag:example.com,2000:app/ ---- -- !e!%%62%63 baz -)"); - } - { - SCOPED_TRACE("without numbers in the middle"); - checkerr(R"( -%TAG !e! tag:example.com,2000:app/ ---- -- !e!%61%%63 baz -)"); - } - { - SCOPED_TRACE("without numbers in the end"); - checkerr(R"( -%TAG !e! tag:example.com,2000:app/ ---- -- !e!%61%62% baz -)"); - } - { - SCOPED_TRACE("with wrong characters numbers at begin"); - checkerr(R"( -%TAG !e! tag:example.com,2000:app/ ---- -- !e!%h%62%63 baz -)"); - } - { - SCOPED_TRACE("with wrong characters in the middle"); - checkerr(R"( -%TAG !e! tag:example.com,2000:app/ ---- -- !e!%61%hh%63 baz -)"); - } - { - SCOPED_TRACE("with wrong characters in the end"); - checkerr(R"( -%TAG !e! tag:example.com,2000:app/ ---- -- !e!%61%62%hh baz -)"); - } - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -TEST(tags, test_suite_735Y) -{ - csubstr yaml_without_seq = R"( -!!map # Block collection -foo : bar -)"; - test_check_emit_check(yaml_without_seq, [](Tree const &t){ - EXPECT_TRUE(t.rootref().is_map()); - EXPECT_TRUE(t.rootref().has_val_tag()); - EXPECT_EQ(t.rootref()["foo"].val(), csubstr("bar")); - }); - - csubstr yaml = R"( -- - foo : bar -- #!!map - foo : bar -- #!!map # Block collection - foo : bar -- !!map - foo : bar -- !!map # Block collection - foo : bar -)"; - test_check_emit_check(yaml, [](Tree const &t){ - ASSERT_TRUE(t.rootref().is_seq()); - ASSERT_EQ(t.rootref().num_children(), 5u); - // - EXPECT_TRUE(t[0].is_map()); - EXPECT_TRUE(!t[0].has_val_tag()); - EXPECT_EQ(t[0]["foo"].val(), csubstr("bar")); - // - EXPECT_TRUE(t[1].is_map()); - EXPECT_TRUE(!t[1].has_val_tag()); - EXPECT_EQ(t[1]["foo"].val(), csubstr("bar")); - // - EXPECT_TRUE(t[2].is_map()); - EXPECT_TRUE(!t[2].has_val_tag()); - EXPECT_EQ(t[2]["foo"].val(), csubstr("bar")); - // - EXPECT_TRUE(t[3].is_map()); - ASSERT_TRUE(t[3].has_val_tag()); - EXPECT_EQ(t[3].val_tag(), csubstr("!!map")); - EXPECT_EQ(t[3]["foo"].val(), csubstr("bar")); - // - EXPECT_TRUE(t[4].is_map()); - ASSERT_TRUE(t[4].has_val_tag()); - EXPECT_EQ(t[4].val_tag(), csubstr("!!map")); - EXPECT_EQ(t[4]["foo"].val(), csubstr("bar")); - }); -} - - -TEST(tags, parsing) -{ - Tree t = parse_in_arena(R"( -!!seq -- !!map - !key key1: !val val1 - ! key2: ! val2 - ! key3: ! val3 - key4: val4 # there are NOT parsed as tags -- ! - !key key1: !val val1 -- ! - - !val val - - !str val - - val - - ! val - - ! val - - ! val -)"); - EXPECT_EQ(t.rootref().val_tag(), csubstr("!!seq")); - EXPECT_EQ(t[0].val_tag(), csubstr("!!map")); - EXPECT_EQ(t[1].val_tag(), csubstr("!!map")); - EXPECT_EQ(t[2].val_tag(), csubstr("!!seq")); - EXPECT_EQ(t[0]["key1"].key_tag(), csubstr("!key")); - EXPECT_EQ(t[0]["key1"].val_tag(), csubstr("!val")); - EXPECT_EQ(t[0]["key2"].key_tag(), csubstr("")); - EXPECT_EQ(t[0]["key2"].val_tag(), csubstr("")); - EXPECT_EQ(t[0]["key3"].key_tag(), csubstr("")); - EXPECT_EQ(t[0]["key3"].val_tag(), csubstr("")); - EXPECT_EQ(t[0][" key4"].has_key_tag(), false); - EXPECT_EQ(t[0][" key4"].has_val_tag(), false); - EXPECT_EQ(t[0][" key4"].key(), csubstr(" key4")); - EXPECT_EQ(t[0][" key4"].val(), csubstr(" val4")); - EXPECT_EQ(t[2][5].val_tag(), csubstr("!!str")); - - EXPECT_EQ(emitrs_yaml(t), R"(!!seq -- !!map - !key key1: !val val1 - ! key2: ! val2 - ! key3: ! val3 - key4: val4 -- !!map - !key key1: !val val1 -- !!seq - - !val val - - !str val - - val - - ! val - - ! val - - !!str val -)"); -} - - -TEST(tags, setting) -{ - Tree t; - size_t rid = t.root_id(); - t.to_map(rid); - t.set_val_tag(rid, "!valtag"); - EXPECT_EQ(t.val_tag(rid), "!valtag"); - - // a keymap - { - size_t child = t.append_child(rid); - t.to_seq(child, "key2"); - t.set_key_tag(child, "!keytag"); - t.set_val_tag(child, "!valtag2"); - EXPECT_TRUE(t.has_key(child)); - EXPECT_FALSE(t.has_val(child)); - EXPECT_EQ(t.key(child), "key2"); - EXPECT_EQ(t.key_tag(child), "!keytag"); - EXPECT_EQ(t.val_tag(child), "!valtag2"); - } - - // a keyseq - { - size_t child = t.append_child(rid); - t.to_seq(child, "key2"); - t.set_key_tag(child, "!keytag"); - t.set_val_tag(child, "!valtag2"); - EXPECT_TRUE(t.has_key(child)); - EXPECT_FALSE(t.has_val(child)); - EXPECT_EQ(t.key(child), "key2"); - EXPECT_EQ(t.key_tag(child), "!keytag"); - EXPECT_EQ(t.val_tag(child), "!valtag2"); - } - - // a keyval - { - size_t child = t.append_child(rid); - t.to_keyval(child, "key", "val"); - t.set_key_tag(child, "!keytag"); - t.set_val_tag(child, "!valtag"); - EXPECT_TRUE(t.has_key(child)); - EXPECT_TRUE(t.has_val(child)); - EXPECT_EQ(t.key(child), "key"); - EXPECT_EQ(t.val(child), "val"); - EXPECT_EQ(t.key_tag(child), "!keytag"); - EXPECT_EQ(t.val_tag(child), "!valtag"); - } - - // a val - { - size_t seqid = t[1].id(); - ASSERT_TRUE(t.is_seq(seqid)); - size_t child = t.append_child(seqid); - t.to_val(child, "val"); - t.set_val_tag(child, "!valtag"); - EXPECT_FALSE(t.has_key(child)); - EXPECT_TRUE(t.has_val(child)); - EXPECT_EQ(t.val(child), "val"); - EXPECT_EQ(t.val_tag(child), "!valtag"); - } -} - -TEST(tags, errors) -{ - Tree t = parse_in_arena("{key: val, keymap: {}, keyseq: [val]}"); - size_t keyval = t["keyval"].id(); - size_t keymap = t["keymap"].id(); - size_t keyseq = t["keyseq"].id(); - size_t val = t["keyseq"][0].id(); - size_t empty_keyval = t.append_child(keymap); - size_t empty_val = t.append_child(keyseq); - - ASSERT_NE(keyval, (size_t)npos); - ASSERT_NE(keymap, (size_t)npos); - ASSERT_NE(keyseq, (size_t)npos); - ASSERT_NE(val, (size_t)npos); - - // cannot get key tag in a node that does not have a key tag - EXPECT_FALSE(t.has_key_tag(empty_keyval)); - ExpectError::check_assertion(&t, [&](){ - EXPECT_EQ(t.key_tag(empty_keyval), ""); - }); - ExpectError::check_assertion(&t, [&](){ - EXPECT_EQ(t.key_tag(keyval), ""); - }); - ExpectError::check_assertion(&t, [&](){ - EXPECT_EQ(t.key_tag(keymap), ""); - }); - ExpectError::check_assertion(&t, [&](){ - EXPECT_EQ(t.key_tag(keyseq), ""); - }); - ExpectError::check_assertion(&t, [&](){ - EXPECT_EQ(t.key_tag(val), ""); - }); - // cannot get val tag in a node that does not have a val tag - EXPECT_FALSE(t.has_val_tag(empty_val)); - ExpectError::check_assertion(&t, [&](){ - EXPECT_EQ(t.val_tag(empty_val), ""); - }); - EXPECT_FALSE(t.has_val_tag(empty_keyval)); - ExpectError::check_assertion(&t, [&](){ - EXPECT_EQ(t.val_tag(empty_keyval), ""); - }); - ExpectError::check_assertion(&t, [&](){ - EXPECT_EQ(t.val_tag(keyval), ""); - }); - ExpectError::check_assertion(&t, [&](){ - EXPECT_EQ(t.val_tag(keymap), ""); - }); - ExpectError::check_assertion(&t, [&](){ - EXPECT_EQ(t.val_tag(keyseq), ""); - }); - ExpectError::check_assertion(&t, [&](){ - EXPECT_EQ(t.val_tag(val), ""); - }); - // cannot set key tag in a node that does not have a key - EXPECT_FALSE(t.has_key(empty_keyval)); - ExpectError::check_assertion(&t, [&](){ - t.set_key_tag(empty_keyval, "!keytag"); - }); - EXPECT_FALSE(t.has_key_tag(val)); // must stay the same - ExpectError::check_assertion(&t, [&](){ - t.set_key_tag(val, "!valtag"); - }); - EXPECT_FALSE(t.has_key_tag(val)); // must stay the same - // cannot set val tag in a node that does not have a val - EXPECT_FALSE(t.has_val(empty_val)); - ExpectError::check_assertion(&t, [&](){ - t.set_val_tag(empty_val, "!valtag"); - }); - EXPECT_FALSE(t.has_val_tag(empty_val)); // must stay the same - EXPECT_FALSE(t.has_val(empty_keyval)); - ExpectError::check_assertion(&t, [&](){ - t.set_val_tag(empty_keyval, "!valtag"); - }); - EXPECT_FALSE(t.has_val_tag(empty_keyval)); // must stay the same -} - - -TEST(tags, setting_user_tags_do_not_require_leading_mark) -{ - Tree t = parse_in_arena("{key: val, keymap: {}, keyseq: [val]}"); - size_t keyval = t["keyval"].id(); - size_t keymap = t["keymap"].id(); - size_t keyseq = t["keyseq"].id(); - size_t val = t["keyseq"][0].id(); - ASSERT_NE(keyval, (size_t)npos); - ASSERT_NE(keymap, (size_t)npos); - ASSERT_NE(keyseq, (size_t)npos); - ASSERT_NE(val, (size_t)npos); - - // without leading mark - t.set_key_tag(keyseq, "keytag"); - t.set_val_tag(keyseq, "valtag"); - t.set_val_tag(val, "valtag2"); - EXPECT_EQ(t.key_tag(keyseq), "keytag"); - EXPECT_EQ(t.val_tag(keyseq), "valtag"); - EXPECT_EQ(t.val_tag(val), "valtag2"); - - EXPECT_EQ(emitrs_yaml(t), R"(key: val -keymap: {} -!keytag keyseq: !valtag - - !valtag2 val -)"); - - // with leading mark - t.set_key_tag(keyseq, "!keytag"); - t.set_val_tag(keyseq, "!valtag"); - t.set_val_tag(val, "!valtag2"); - EXPECT_EQ(t.key_tag(keyseq), "!keytag"); - EXPECT_EQ(t.val_tag(keyseq), "!valtag"); - EXPECT_EQ(t.val_tag(val), "!valtag2"); - - EXPECT_EQ(emitrs_yaml(t), R"(key: val -keymap: {} -!keytag keyseq: !valtag - - !valtag2 val -)"); -} - - -TEST(tags, valid_chars) -{ - Tree t = parse_in_arena(R"( -- ! val -- ! bar> val -- ! val -)"); - EXPECT_EQ(t[0].val_tag(), ""); - EXPECT_EQ(t[0].val(), "val"); - EXPECT_EQ(t[1].val_tag(), ""); - EXPECT_EQ(t[1].val(), "bar> val"); - EXPECT_EQ(t[2].val_tag(), ""); - EXPECT_EQ(t[2].val(), " val"); -} - - -TEST(tags, EHF6) -{ - { - Tree t = parse_in_arena(R"(!!map { - k: !!seq [ a, !!str b], - j: !!seq - [ a, !!str b] -})"); - ASSERT_TRUE(t.rootref().has_val_tag()); - EXPECT_EQ(t.rootref().val_tag(), "!!map"); - ASSERT_TRUE(t["k"].has_val_tag()); - ASSERT_TRUE(t["j"].has_val_tag()); - EXPECT_EQ(t["k"].val_tag(), "!!seq"); - EXPECT_EQ(t["j"].val_tag(), "!!seq"); - } - { - Tree t = parse_in_arena(R"(!!seq [ - !!map { !!str k: v}, - !!map { !!str ? k: v} -])"); - ASSERT_TRUE(t.rootref().has_val_tag()); - EXPECT_EQ(t.rootref().val_tag(), "!!seq"); - ASSERT_TRUE(t[0].has_val_tag()); - ASSERT_TRUE(t[1].has_val_tag()); - EXPECT_EQ(t[0].val_tag(), "!!map"); - EXPECT_EQ(t[1].val_tag(), "!!map"); - ASSERT_TRUE(t[0]["k"].has_key_tag()); - ASSERT_TRUE(t[1]["k"].has_key_tag()); - EXPECT_EQ(t[0]["k"].key_tag(), "!!str"); - EXPECT_EQ(t[1]["k"].key_tag(), "!!str"); - } -} - - -//----------------------------------------------------------------------------- - -TEST(to_tag, user) -{ - EXPECT_EQ(to_tag("!"), TAG_NONE); - EXPECT_EQ(to_tag("!."), TAG_NONE); - EXPECT_EQ(to_tag("!good_type"), TAG_NONE); -} - -TEST(to_tag, double_exc_mark) -{ - EXPECT_EQ(to_tag("!!" ), TAG_NONE); - EXPECT_EQ(to_tag("!!." ), TAG_NONE); - - EXPECT_EQ(to_tag("!!map" ), TAG_MAP); - EXPECT_EQ(to_tag("!!omap" ), TAG_OMAP); - EXPECT_EQ(to_tag("!!pairs" ), TAG_PAIRS); - EXPECT_EQ(to_tag("!!set" ), TAG_SET); - EXPECT_EQ(to_tag("!!seq" ), TAG_SEQ); - EXPECT_EQ(to_tag("!!binary" ), TAG_BINARY); - EXPECT_EQ(to_tag("!!bool" ), TAG_BOOL); - EXPECT_EQ(to_tag("!!float" ), TAG_FLOAT); - EXPECT_EQ(to_tag("!!int" ), TAG_INT); - EXPECT_EQ(to_tag("!!merge" ), TAG_MERGE); - EXPECT_EQ(to_tag("!!null" ), TAG_NULL); - EXPECT_EQ(to_tag("!!str" ), TAG_STR); - EXPECT_EQ(to_tag("!!timestamp" ), TAG_TIMESTAMP); - EXPECT_EQ(to_tag("!!value" ), TAG_VALUE); - - EXPECT_EQ(to_tag("!!map." ), TAG_NONE); - EXPECT_EQ(to_tag("!!omap." ), TAG_NONE); - EXPECT_EQ(to_tag("!!pairs." ), TAG_NONE); - EXPECT_EQ(to_tag("!!set." ), TAG_NONE); - EXPECT_EQ(to_tag("!!seq." ), TAG_NONE); - EXPECT_EQ(to_tag("!!binary." ), TAG_NONE); - EXPECT_EQ(to_tag("!!bool." ), TAG_NONE); - EXPECT_EQ(to_tag("!!float." ), TAG_NONE); - EXPECT_EQ(to_tag("!!int." ), TAG_NONE); - EXPECT_EQ(to_tag("!!merge." ), TAG_NONE); - EXPECT_EQ(to_tag("!!null." ), TAG_NONE); - EXPECT_EQ(to_tag("!!str." ), TAG_NONE); - EXPECT_EQ(to_tag("!!timestamp."), TAG_NONE); - EXPECT_EQ(to_tag("!!value." ), TAG_NONE); -} - -TEST(to_tag, with_namespace) -{ - EXPECT_EQ(to_tag("tag:yaml.org,2002:" ), TAG_NONE); - EXPECT_EQ(to_tag("tag:yaml.org,2002:." ), TAG_NONE); - - EXPECT_EQ(to_tag("tag:yaml.org,2002:map" ), TAG_MAP); - EXPECT_EQ(to_tag("tag:yaml.org,2002:omap" ), TAG_OMAP); - EXPECT_EQ(to_tag("tag:yaml.org,2002:pairs" ), TAG_PAIRS); - EXPECT_EQ(to_tag("tag:yaml.org,2002:set" ), TAG_SET); - EXPECT_EQ(to_tag("tag:yaml.org,2002:seq" ), TAG_SEQ); - EXPECT_EQ(to_tag("tag:yaml.org,2002:binary" ), TAG_BINARY); - EXPECT_EQ(to_tag("tag:yaml.org,2002:bool" ), TAG_BOOL); - EXPECT_EQ(to_tag("tag:yaml.org,2002:float" ), TAG_FLOAT); - EXPECT_EQ(to_tag("tag:yaml.org,2002:int" ), TAG_INT); - EXPECT_EQ(to_tag("tag:yaml.org,2002:merge" ), TAG_MERGE); - EXPECT_EQ(to_tag("tag:yaml.org,2002:null" ), TAG_NULL); - EXPECT_EQ(to_tag("tag:yaml.org,2002:str" ), TAG_STR); - EXPECT_EQ(to_tag("tag:yaml.org,2002:timestamp" ), TAG_TIMESTAMP); - EXPECT_EQ(to_tag("tag:yaml.org,2002:value" ), TAG_VALUE); - - EXPECT_EQ(to_tag("tag:yaml.org,2002:map." ), TAG_NONE); - EXPECT_EQ(to_tag("tag:yaml.org,2002:omap." ), TAG_NONE); - EXPECT_EQ(to_tag("tag:yaml.org,2002:pairs." ), TAG_NONE); - EXPECT_EQ(to_tag("tag:yaml.org,2002:set." ), TAG_NONE); - EXPECT_EQ(to_tag("tag:yaml.org,2002:seq." ), TAG_NONE); - EXPECT_EQ(to_tag("tag:yaml.org,2002:binary." ), TAG_NONE); - EXPECT_EQ(to_tag("tag:yaml.org,2002:bool." ), TAG_NONE); - EXPECT_EQ(to_tag("tag:yaml.org,2002:float." ), TAG_NONE); - EXPECT_EQ(to_tag("tag:yaml.org,2002:int." ), TAG_NONE); - EXPECT_EQ(to_tag("tag:yaml.org,2002:merge." ), TAG_NONE); - EXPECT_EQ(to_tag("tag:yaml.org,2002:null." ), TAG_NONE); - EXPECT_EQ(to_tag("tag:yaml.org,2002:str." ), TAG_NONE); - EXPECT_EQ(to_tag("tag:yaml.org,2002:timestamp."), TAG_NONE); - EXPECT_EQ(to_tag("tag:yaml.org,2002:value." ), TAG_NONE); -} - -TEST(to_tag, with_namespace_bracket) -{ - EXPECT_EQ(to_tag("" ), TAG_MAP); - EXPECT_EQ(to_tag("" ), TAG_OMAP); - EXPECT_EQ(to_tag("" ), TAG_PAIRS); - EXPECT_EQ(to_tag("" ), TAG_SET); - EXPECT_EQ(to_tag("" ), TAG_SEQ); - EXPECT_EQ(to_tag("" ), TAG_BINARY); - EXPECT_EQ(to_tag("" ), TAG_BOOL); - EXPECT_EQ(to_tag("" ), TAG_FLOAT); - EXPECT_EQ(to_tag("" ), TAG_INT); - EXPECT_EQ(to_tag("" ), TAG_MERGE); - EXPECT_EQ(to_tag("" ), TAG_NULL); - EXPECT_EQ(to_tag("" ), TAG_STR); - EXPECT_EQ(to_tag("" ), TAG_TIMESTAMP); - EXPECT_EQ(to_tag("" ), TAG_VALUE); - - EXPECT_EQ(to_tag("" ), TAG_NONE); - EXPECT_EQ(to_tag("" ), TAG_NONE); - EXPECT_EQ(to_tag("" ), TAG_NONE); - EXPECT_EQ(to_tag("" ), TAG_NONE); - EXPECT_EQ(to_tag("" ), TAG_NONE); - EXPECT_EQ(to_tag("" ), TAG_NONE); - EXPECT_EQ(to_tag("" ), TAG_NONE); - EXPECT_EQ(to_tag("" ), TAG_NONE); - EXPECT_EQ(to_tag("" ), TAG_NONE); - EXPECT_EQ(to_tag("" ), TAG_NONE); - EXPECT_EQ(to_tag("" ), TAG_NONE); - EXPECT_EQ(to_tag("" ), TAG_NONE); - EXPECT_EQ(to_tag(""), TAG_NONE); - EXPECT_EQ(to_tag("" ), TAG_NONE); -} - -TEST(from_tag, basic) -{ - EXPECT_EQ("", from_tag(TAG_NONE)); - - EXPECT_EQ("!!map" , from_tag(TAG_MAP)); - EXPECT_EQ("!!omap" , from_tag(TAG_OMAP)); - EXPECT_EQ("!!pairs" , from_tag(TAG_PAIRS)); - EXPECT_EQ("!!set" , from_tag(TAG_SET)); - EXPECT_EQ("!!seq" , from_tag(TAG_SEQ)); - EXPECT_EQ("!!binary" , from_tag(TAG_BINARY)); - EXPECT_EQ("!!bool" , from_tag(TAG_BOOL)); - EXPECT_EQ("!!float" , from_tag(TAG_FLOAT)); - EXPECT_EQ("!!int" , from_tag(TAG_INT)); - EXPECT_EQ("!!merge" , from_tag(TAG_MERGE)); - EXPECT_EQ("!!null" , from_tag(TAG_NULL)); - EXPECT_EQ("!!str" , from_tag(TAG_STR)); - EXPECT_EQ("!!timestamp" , from_tag(TAG_TIMESTAMP)); - EXPECT_EQ("!!value" , from_tag(TAG_VALUE)); -} - -TEST(normalize_tag, basic) -{ - EXPECT_EQ(normalize_tag("" ), "!!map"); - EXPECT_EQ(normalize_tag("" ), "!!omap"); - EXPECT_EQ(normalize_tag("" ), "!!pairs"); - EXPECT_EQ(normalize_tag("" ), "!!set"); - EXPECT_EQ(normalize_tag("" ), "!!seq"); - EXPECT_EQ(normalize_tag("" ), "!!binary"); - EXPECT_EQ(normalize_tag("" ), "!!bool"); - EXPECT_EQ(normalize_tag("" ), "!!float"); - EXPECT_EQ(normalize_tag("" ), "!!int"); - EXPECT_EQ(normalize_tag("" ), "!!merge"); - EXPECT_EQ(normalize_tag("" ), "!!null"); - EXPECT_EQ(normalize_tag("" ), "!!str"); - EXPECT_EQ(normalize_tag("" ), "!!timestamp"); - EXPECT_EQ(normalize_tag("" ), "!!value"); - - EXPECT_EQ(normalize_tag("!" ), "!!map"); - EXPECT_EQ(normalize_tag("!" ), "!!omap"); - EXPECT_EQ(normalize_tag("!" ), "!!pairs"); - EXPECT_EQ(normalize_tag("!" ), "!!set"); - EXPECT_EQ(normalize_tag("!" ), "!!seq"); - EXPECT_EQ(normalize_tag("!" ), "!!binary"); - EXPECT_EQ(normalize_tag("!" ), "!!bool"); - EXPECT_EQ(normalize_tag("!" ), "!!float"); - EXPECT_EQ(normalize_tag("!" ), "!!int"); - EXPECT_EQ(normalize_tag("!" ), "!!merge"); - EXPECT_EQ(normalize_tag("!" ), "!!null"); - EXPECT_EQ(normalize_tag("!" ), "!!str"); - EXPECT_EQ(normalize_tag("!"), "!!timestamp"); - EXPECT_EQ(normalize_tag("!" ), "!!value"); - - EXPECT_EQ(normalize_tag("!!map" ), "!!map"); - EXPECT_EQ(normalize_tag("!!omap" ), "!!omap"); - EXPECT_EQ(normalize_tag("!!pairs" ), "!!pairs"); - EXPECT_EQ(normalize_tag("!!set" ), "!!set"); - EXPECT_EQ(normalize_tag("!!seq" ), "!!seq"); - EXPECT_EQ(normalize_tag("!!binary" ), "!!binary"); - EXPECT_EQ(normalize_tag("!!bool" ), "!!bool"); - EXPECT_EQ(normalize_tag("!!float" ), "!!float"); - EXPECT_EQ(normalize_tag("!!int" ), "!!int"); - EXPECT_EQ(normalize_tag("!!merge" ), "!!merge"); - EXPECT_EQ(normalize_tag("!!null" ), "!!null"); - EXPECT_EQ(normalize_tag("!!str" ), "!!str"); - EXPECT_EQ(normalize_tag("!!timestamp"), "!!timestamp"); - EXPECT_EQ(normalize_tag("!!value" ), "!!value"); - - EXPECT_EQ(normalize_tag("!!foo" ), "!!foo"); - - EXPECT_EQ(normalize_tag("!my-light"), "!my-light"); - EXPECT_EQ(normalize_tag("!foo"), "!foo"); - EXPECT_EQ(normalize_tag(""), ""); - EXPECT_EQ(normalize_tag(""), ""); - EXPECT_EQ(normalize_tag(""), ""); - - EXPECT_EQ(normalize_tag("!"), ""); - EXPECT_EQ(normalize_tag("!"), ""); - EXPECT_EQ(normalize_tag("!"), ""); -} - -TEST(normalize_tag_long, basic) -{ - EXPECT_EQ(normalize_tag_long("" ), ""); - EXPECT_EQ(normalize_tag_long("" ), ""); - EXPECT_EQ(normalize_tag_long("" ), ""); - EXPECT_EQ(normalize_tag_long("" ), ""); - EXPECT_EQ(normalize_tag_long("" ), ""); - EXPECT_EQ(normalize_tag_long("" ), ""); - EXPECT_EQ(normalize_tag_long("" ), ""); - EXPECT_EQ(normalize_tag_long("" ), ""); - EXPECT_EQ(normalize_tag_long("" ), ""); - EXPECT_EQ(normalize_tag_long("" ), ""); - EXPECT_EQ(normalize_tag_long("" ), ""); - EXPECT_EQ(normalize_tag_long("" ), ""); - EXPECT_EQ(normalize_tag_long("" ), ""); - EXPECT_EQ(normalize_tag_long("" ), ""); - - EXPECT_EQ(normalize_tag_long("!" ), ""); - EXPECT_EQ(normalize_tag_long("!" ), ""); - EXPECT_EQ(normalize_tag_long("!" ), ""); - EXPECT_EQ(normalize_tag_long("!" ), ""); - EXPECT_EQ(normalize_tag_long("!" ), ""); - EXPECT_EQ(normalize_tag_long("!" ), ""); - EXPECT_EQ(normalize_tag_long("!" ), ""); - EXPECT_EQ(normalize_tag_long("!" ), ""); - EXPECT_EQ(normalize_tag_long("!" ), ""); - EXPECT_EQ(normalize_tag_long("!" ), ""); - EXPECT_EQ(normalize_tag_long("!" ), ""); - EXPECT_EQ(normalize_tag_long("!" ), ""); - EXPECT_EQ(normalize_tag_long("!"), ""); - EXPECT_EQ(normalize_tag_long("!" ), ""); - - EXPECT_EQ(normalize_tag_long("!!map" ), ""); - EXPECT_EQ(normalize_tag_long("!!omap" ), ""); - EXPECT_EQ(normalize_tag_long("!!pairs" ), ""); - EXPECT_EQ(normalize_tag_long("!!set" ), ""); - EXPECT_EQ(normalize_tag_long("!!seq" ), ""); - EXPECT_EQ(normalize_tag_long("!!binary" ), ""); - EXPECT_EQ(normalize_tag_long("!!bool" ), ""); - EXPECT_EQ(normalize_tag_long("!!float" ), ""); - EXPECT_EQ(normalize_tag_long("!!int" ), ""); - EXPECT_EQ(normalize_tag_long("!!merge" ), ""); - EXPECT_EQ(normalize_tag_long("!!null" ), ""); - EXPECT_EQ(normalize_tag_long("!!str" ), ""); - EXPECT_EQ(normalize_tag_long("!!timestamp"), ""); - EXPECT_EQ(normalize_tag_long("!!value" ), ""); - - EXPECT_EQ(normalize_tag_long("!!foo" ), "!!foo"); - - EXPECT_EQ(normalize_tag_long("!my-light"), "!my-light"); - EXPECT_EQ(normalize_tag_long("!foo"), "!foo"); - EXPECT_EQ(normalize_tag_long(""), ""); - EXPECT_EQ(normalize_tag_long(""), ""); - EXPECT_EQ(normalize_tag_long(""), ""); - - EXPECT_EQ(normalize_tag_long("!"), ""); - EXPECT_EQ(normalize_tag_long("!"), ""); - EXPECT_EQ(normalize_tag_long("!"), ""); - EXPECT_EQ(normalize_tag_long("!"), ""); - EXPECT_EQ(normalize_tag_long("!"), ""); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -CASE_GROUP(TAG_PROPERTY) -{ - -ADD_CASE_TO_GROUP("user tag, empty, test suite 52DL", -R"(! a)", -N(DOCVAL, TS("!", "a")) -); - -ADD_CASE_TO_GROUP("tag property in implicit map, std tags", -R"(ivar: !!int 0 -svar: !!str 0 -fvar: !!float 0.1 -!!int 2: !!float 3 -!!float 3: !!int 3.4 -!!str key: !!int val -myObject: !myClass { name: Joe, age: 15 } -picture: !!binary >- - R0lGODdhDQAIAIAAAAAAANn - Z2SwAAAAADQAIAAACF4SDGQ - ar3xxbJ9p0qa7R0YxwzaFME - 1IAADs= -)", - L{ - N("ivar", TS("!!int", "0")), - N("svar", TS("!!str", "0")), - N("fvar", TS("!!float", "0.1")), - N(TS("!!int", "2"), TS("!!float", "3")), - N(TS("!!float", "3"), TS("!!int", "3.4")), - N(TS("!!str", "key"), TS("!!int", "val")), - N("myObject", TL("!myClass", L{N("name", "Joe"), N("age", "15")})), - N(QV, "picture", TS("!!binary", R"(R0lGODdhDQAIAIAAAAAAANn Z2SwAAAAADQAIAAACF4SDGQ ar3xxbJ9p0qa7R0YxwzaFME 1IAADs=)")), - } -); - -ADD_CASE_TO_GROUP("tag property in implicit map, usr tags", -R"(ivar: !int 0 -svar: !str 0 -fvar: !float 0.1 -!int 2: !float 3 -!float 3: !int 3.4 -!str key: !int val -myObject: !myClass { name: Joe, age: 15 } -picture: !binary >- - R0lGODdhDQAIAIAAAAAAANn - Z2SwAAAAADQAIAAACF4SDGQ - ar3xxbJ9p0qa7R0YxwzaFME - 1IAADs= -)", - L{ - N("ivar", TS("!int", "0")), - N("svar", TS("!str", "0")), - N("fvar", TS("!float", "0.1")), - N(TS("!int", "2"), TS("!float", "3")), - N(TS("!float", "3"), TS("!int", "3.4")), - N(TS("!str", "key"), TS("!int", "val")), - N("myObject", TL("!myClass", L{N("name", "Joe"), N("age", "15")})), - N(QV, "picture", TS("!binary", R"(R0lGODdhDQAIAIAAAAAAANn Z2SwAAAAADQAIAAACF4SDGQ ar3xxbJ9p0qa7R0YxwzaFME 1IAADs=)")), - } -); - -ADD_CASE_TO_GROUP("tag property in explicit map, std tags", -R"({ -ivar: !!int 0, -svar: !!str 0, -!!str key: !!int val -})", - L{ - N("ivar", TS("!!int", "0")), - N("svar", TS("!!str", "0")), - N(TS("!!str", "key"), TS("!!int", "val")) - } -); - -ADD_CASE_TO_GROUP("tag property in explicit map, usr tags", -R"({ -ivar: !int 0, -svar: !str 0, -!str key: !int val -} -)", - L{ - N("ivar", TS("!int", "0")), - N("svar", TS("!str", "0")), - N(TS("!str", "key"), TS("!int", "val")) - } -); - -ADD_CASE_TO_GROUP("tag property in implicit seq, std tags", -R"(- !!int 0 -- !!str 0 -)", - L{ - N(TS("!!int", "0")), - N(TS("!!str", "0")), - } -); - -ADD_CASE_TO_GROUP("tag property in implicit seq, usr tags", -R"(- !int 0 -- !str 0 -)", - L{ - N(TS("!int", "0")), - N(TS("!str", "0")), - } -); - -ADD_CASE_TO_GROUP("tag property in explicit seq, std tags", -R"([ -!!int 0, -!!str 0 -] -)", - L{ - N(TS("!!int", "0")), - N(TS("!!str", "0")), - } -); - -ADD_CASE_TO_GROUP("tag property in explicit seq, usr tags", -R"([ -!int 0, -!str 0 -] -)", - L{ - N(TS("!int", "0")), - N(TS("!str", "0")), - } -); - -ADD_CASE_TO_GROUP("tagged explicit sequence in map, std tags", -R"(some_seq: !!its_type [ -!!int 0, -!!str 0 -] -)", - L{N("some_seq", TL("!!its_type", L{ - N(TS("!!int", "0")), - N(TS("!!str", "0")), - })) - } -); - -ADD_CASE_TO_GROUP("tagged explicit sequence in map, usr tags", -R"(some_seq: !its_type [ -!int 0, -!str 0 -] -)", - L{N("some_seq", TL("!its_type", L{ - N(TS("!int", "0")), - N(TS("!str", "0")), - })) - } -); - -ADD_CASE_TO_GROUP("tagged doc", -R"( ---- !!map -a: 0 -b: 1 ---- !map -? a -: b ---- !!seq -- a -- b ---- !!str -a - b -... ---- !!str a b -... ---- !!str a b ---- !!str -a: b ---- !!str a: b ---- -!!str a: b ---- -!!str a - b ---- -!!set -? a -? b ---- !!set -? a -? b -)", -N(STREAM, L{ - N(DOCMAP, TL("!!map", L{N("a", "0"), N("b", "1")})), - N(DOCMAP, TL("!map", L{N("a", "b")})), - N(DOCSEQ, TL("!!seq", L{N("a"), N("b")})), - N(DOCVAL, TS("!!str", "a b")), - N(DOCVAL, TS("!!str", "a b")), - N(DOCVAL, TS("!!str", "a b")), - N(DOCVAL, TS("!!str", "a: b")), - N(DOCVAL, TS("!!str", "a: b")), - N(DOCMAP, L{N(TS("!!str", "a"), "b")}), - N(DOCVAL, TS("!!str", "a b")), - N(DOCMAP, TL("!!set", L{N(KEYVAL, "a", /*"~"*/{}), N(KEYVAL, "b", /*"~"*/{})})), - N(DOCMAP, TL("!!set", L{N(KEYVAL, "a", /*"~"*/{}), N(KEYVAL, "b", /*"~"*/{})})), -})); - - -ADD_CASE_TO_GROUP("ambiguous tag in map, std tag", -R"(!!map -!!str a0: !!xxx b0 -!!str fooz: !!map - k1: !!float 1.0 - k3: !!float 2.0 -!!str foo: !!map - !!int 1: !!float 20.0 - !!int 3: !!float 40.0 -bar: !!map - 10: !!str 2 - 30: !!str 4 -!!str baz: - !!int 10: !!float 20 - !!int 30: !!float 40 -)", -TL("!!map", L{ - N(TS("!!str", "a0"), TS("!!xxx", "b0")), - N(TS("!!str", "fooz"), TL("!!map", L{N("k1", TS("!!float", "1.0")), N("k3", TS("!!float", "2.0"))})), - N(TS("!!str", "foo"), TL("!!map", L{N(TS("!!int", "1"), TS("!!float", "20.0")), N(TS("!!int", "3"), TS("!!float", "40.0"))})), - N("bar", TL("!!map", L{N("10", TS("!!str", "2")), N("30", TS("!!str", "4"))})), - N(TS("!!str", "baz"), L{N(TS("!!int", "10"), TS("!!float", "20")), N(TS("!!int", "30"), TS("!!float", "40"))}), -})); - -ADD_CASE_TO_GROUP("ambiguous tag in map, usr tag", -R"(!map -!str a0: !xxx b0 -!str fooz: !map - k1: !float 1.0 - k3: !float 2.0 -!str foo: !map - !int 1: !float 20.0 - !int 3: !float 40.0 -bar: !map - 10: !str 2 - 30: !str 4 -!str baz: - !int 10: !float 20 - !int 30: !float 40 -)", -TL("!map", L{ - N(TS("!str", "a0"), TS("!xxx", "b0")), - N(TS("!str", "fooz"), TL("!map", L{N("k1", TS("!float", "1.0")), N("k3", TS("!float", "2.0"))})), - N(TS("!str", "foo"), TL("!map", L{N(TS("!int", "1"), TS("!float", "20.0")), N(TS("!int", "3"), TS("!float", "40.0"))})), - N("bar", TL("!map", L{N("10", TS("!str", "2")), N("30", TS("!str", "4"))})), - N(TS("!str", "baz"), L{N(TS("!int", "10"), TS("!float", "20")), N(TS("!int", "30"), TS("!float", "40"))}), -})); - - -ADD_CASE_TO_GROUP("ambiguous tag in seq, std tag", -R"(!!seq -- !!str k1: v1 - !!str k2: v2 - !!str k3: v3 -- !!map - !!str k4: v4 - !!str k5: v5 - !!str k6: v6 -- !!map - k7: v7 - k8: v8 - k9: v9 -- - !!str v10 - - !!str v20 - - !!str v30 -- !!seq - - !!str v40 - - !!str v50 - - !!str v60 -- !!seq - - v70 - - v80 - - v90 -)", -TL("!!seq", L{ - N(L{N(TS("!!str", "k1"), "v1"), N(TS("!!str", "k2"), "v2"), N(TS("!!str", "k3"), "v3"), }), - N(TL("!!map", L{N(TS("!!str", "k4"), "v4"), N(TS("!!str", "k5"), "v5"), N(TS("!!str", "k6"), "v6"), })), - N(TL("!!map", L{N("k7", "v7"), N("k8", "v8"), N("k9", "v9"), })), - N(L{N(TS("!!str", "v10")), N(TS("!!str", "v20")), N(TS("!!str", "v30"))}), - N(TL("!!seq", L{N(TS("!!str", "v40")), N(TS("!!str", "v50")), N(TS("!!str", "v60"))})), - N(TL("!!seq", L{N("v70"), N("v80"), N("v90")})), -})); - -ADD_CASE_TO_GROUP("ambiguous tag in seq, usr tag", -R"(!seq -- !str k1: v1 - !str k2: v2 - !str k3: v3 -- !map - !str k4: v4 - !str k5: v5 - !str k6: v6 -- !map - k7: v7 - k8: v8 - k9: v9 -- - !str v10 - - !str v20 - - !str v30 -- !seq - - !str v40 - - !str v50 - - !str v60 -- !seq - - v70 - - v80 - - v90 -)", -TL("!seq", L{ - N(L{N(TS("!str", "k1"), "v1"), N(TS("!str", "k2"), "v2"), N(TS("!str", "k3"), "v3"), }), - N(TL("!map", L{N(TS("!str", "k4"), "v4"), N(TS("!str", "k5"), "v5"), N(TS("!str", "k6"), "v6"), })), - N(TL("!map", L{N("k7", "v7"), N("k8", "v8"), N("k9", "v9"), })), - N(L{N(TS("!str", "v10")), N(TS("!str", "v20")), N(TS("!str", "v30"))}), - N(TL("!seq", L{N(TS("!str", "v40")), N(TS("!str", "v50")), N(TS("!str", "v60"))})), - N(TL("!seq", L{N("v70"), N("v80"), N("v90")})), -})); -} - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/test/test_tree.cpp b/thirdparty/ryml/test/test_tree.cpp deleted file mode 100644 index b6aad0435..000000000 --- a/thirdparty/ryml/test/test_tree.cpp +++ /dev/null @@ -1,3924 +0,0 @@ -#ifndef RYML_SINGLE_HEADER -#include "c4/yml/std/std.hpp" -#include "c4/yml/parse.hpp" -#include "c4/yml/emit.hpp" -#include -#include -#include -#endif -#include "./test_case.hpp" -#include "./callbacks_tester.hpp" - -#include - -#if defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable: 4389) // signed/unsigned mismatch -#elif defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdollar-in-identifier-extension" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -#endif - -namespace c4 { -namespace yml { - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -void node_scalar_test_empty(NodeScalar const& s) -{ - EXPECT_TRUE(s.empty()); - EXPECT_EQ(s.tag, ""); - EXPECT_EQ(s.tag.len, 0u); - EXPECT_TRUE(s.tag.empty()); - EXPECT_EQ(s.scalar, ""); - EXPECT_EQ(s.scalar.len, 0u); - EXPECT_TRUE(s.scalar.empty()); -} - -void node_scalar_test_foo(NodeScalar const& s, bool with_tag=false) -{ - EXPECT_FALSE(s.empty()); - if(with_tag) - { - EXPECT_EQ(s.tag, "!!str"); - EXPECT_EQ(s.tag.len, 5u); - EXPECT_FALSE(s.tag.empty()); - } - else - { - EXPECT_EQ(s.tag, ""); - EXPECT_EQ(s.tag.len, 0u); - EXPECT_TRUE(s.tag.empty()); - } - EXPECT_EQ(s.scalar, "foo"); - EXPECT_EQ(s.scalar.len, 3u); - EXPECT_FALSE(s.scalar.empty()); -} - -void node_scalar_test_foo3(NodeScalar const& s, bool with_tag=false) -{ - EXPECT_FALSE(s.empty()); - if(with_tag) - { - EXPECT_EQ(s.tag, "!!str+++"); - EXPECT_EQ(s.tag.len, 8u); - EXPECT_FALSE(s.tag.empty()); - } - else - { - EXPECT_EQ(s.tag, ""); - EXPECT_EQ(s.tag.len, 0u); - EXPECT_TRUE(s.tag.empty()); - } - EXPECT_EQ(s.scalar, "foo3"); - EXPECT_EQ(s.scalar.len, 4u); - EXPECT_FALSE(s.scalar.empty()); -} - -TEST(NodeScalar, ctor_empty) -{ - NodeScalar s; - node_scalar_test_empty(s); -} - -TEST(NodeScalar, ctor__untagged) -{ - { - const char sarr[] = "foo"; - const char *sptr = "foo"; - csubstr ssp = "foo"; - - for(auto s : {NodeScalar(sarr), NodeScalar(to_csubstr(sptr)), NodeScalar(ssp)}) - { - node_scalar_test_foo(s); - } - - NodeScalar s; - s = {sarr}; - node_scalar_test_foo(s); - s = to_csubstr(sptr); - node_scalar_test_foo(s); - s = {ssp}; - node_scalar_test_foo(s); - } - - { - const char sarr[] = "foo3"; - const char *sptr = "foo3"; - csubstr ssp = "foo3"; - - for(auto s : {NodeScalar(sarr), NodeScalar(to_csubstr(sptr)), NodeScalar(ssp)}) - { - node_scalar_test_foo3(s); - } - - NodeScalar s; - { - SCOPED_TRACE("here 1"); - s = {sarr}; - node_scalar_test_foo3(s); - } - { - SCOPED_TRACE("here 2"); - s = to_csubstr(sptr); - node_scalar_test_foo3(s); - } - { - SCOPED_TRACE("here 3"); - s = ssp; - node_scalar_test_foo3(s); - } - } -} - -TEST(NodeScalar, ctor__tagged) -{ - { - const char sarr[] = "foo", tarr[] = "!!str"; - const char *sptr = "foo"; - const char *tptr = "!!str"; - csubstr ssp = "foo", tsp = "!!str"; - - for(NodeScalar s : { - NodeScalar(tsp, ssp), - NodeScalar(tsp, to_csubstr(sptr)), - NodeScalar(tsp, sarr), - NodeScalar(to_csubstr(tptr), ssp), - NodeScalar(to_csubstr(tptr), to_csubstr(sptr)), - NodeScalar(to_csubstr(tptr), sarr), - NodeScalar(tarr, ssp), - NodeScalar(tarr, to_csubstr(sptr)), - NodeScalar(tarr, sarr), - }) - { - node_scalar_test_foo(s, true); - } - - NodeScalar s; - - { - SCOPED_TRACE("here 0.0"); - s = {tsp, ssp}; - node_scalar_test_foo(s, true); - } - { - SCOPED_TRACE("here 0.1"); - s = {tsp, to_csubstr(sptr)}; - node_scalar_test_foo(s, true); - } - { - SCOPED_TRACE("here 0.2"); - s = {tsp, sarr}; - node_scalar_test_foo(s, true); - } - - { - SCOPED_TRACE("here 1.0"); - s = {to_csubstr(tptr), ssp}; - node_scalar_test_foo(s, true); - } - { - SCOPED_TRACE("here 1.1"); - s = {to_csubstr(tptr), to_csubstr(sptr)}; - node_scalar_test_foo(s, true); - } - { - SCOPED_TRACE("here 1.3"); - s = {to_csubstr(tptr), sarr}; - node_scalar_test_foo(s, true); - } - - { - SCOPED_TRACE("here 3.0"); - s = {tarr, ssp}; - node_scalar_test_foo(s, true); - } - { - SCOPED_TRACE("here 3.1"); - s = {tarr, to_csubstr(sptr)}; - node_scalar_test_foo(s, true); - } - { - SCOPED_TRACE("here 3.3"); - s = {tarr, sarr}; - node_scalar_test_foo(s, true); - } - - } - - { - const char sarr[] = "foo3", tarr[] = "!!str+++"; - const char *sptr = "foo3"; - const char *tptr = "!!str+++"; - csubstr ssp = "foo3", tsp = "!!str+++"; - - NodeScalar wtf = {tsp, ssp}; - EXPECT_EQ(wtf.tag, tsp); - EXPECT_EQ(wtf.scalar, ssp); - for(auto s : { - NodeScalar(tsp, ssp), - NodeScalar(tsp, to_csubstr(sptr)), - NodeScalar(tsp, sarr), - NodeScalar(to_csubstr(tptr), ssp), - NodeScalar(to_csubstr(tptr), to_csubstr(sptr)), - NodeScalar(to_csubstr(tptr), sarr), - NodeScalar(tarr, ssp), - NodeScalar(tarr, to_csubstr(sptr)), - NodeScalar(tarr, sarr), - }) - { - node_scalar_test_foo3(s, true); - } - - NodeScalar s; - - { - SCOPED_TRACE("here 0.0"); - s = {tsp, ssp}; - node_scalar_test_foo3(s, true); - } - { - SCOPED_TRACE("here 0.1"); - s = {tsp, to_csubstr(sptr)}; - node_scalar_test_foo3(s, true); - } - { - SCOPED_TRACE("here 0.3"); - s = {tsp, sarr}; - node_scalar_test_foo3(s, true); - } - - { - SCOPED_TRACE("here 1.0"); - s = {to_csubstr(tptr), ssp}; - node_scalar_test_foo3(s, true); - } - { - SCOPED_TRACE("here 1.1"); - s = {to_csubstr(tptr), to_csubstr(sptr)}; - node_scalar_test_foo3(s, true); - } - { - SCOPED_TRACE("here 1.3"); - s = {to_csubstr(tptr), sarr}; - node_scalar_test_foo3(s, true); - } - - { - SCOPED_TRACE("here 3.0"); - s = {tarr, ssp}; - node_scalar_test_foo3(s, true); - } - { - SCOPED_TRACE("here 3.1"); - s = {tarr, to_csubstr(sptr)}; - node_scalar_test_foo3(s, true); - } - { - SCOPED_TRACE("here 3.3"); - s = {tarr, sarr}; - node_scalar_test_foo3(s, true); - } - - } - -} - - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -TEST(NodeInit, ctor__empty) -{ - NodeInit n; - EXPECT_EQ((type_bits)n.type, (type_bits)NOTYPE); - EXPECT_EQ(n.key.scalar, ""); - EXPECT_EQ(n.key.tag, ""); - EXPECT_EQ(n.val.scalar, ""); - EXPECT_EQ(n.val.tag, ""); -} - -TEST(NodeInit, ctor__type_only) -{ - for(auto k : {KEY, KEYVAL, MAP, KEYMAP, SEQ, KEYSEQ}) - { - SCOPED_TRACE(NodeType::type_str(k)); - NodeInit n(k); - EXPECT_EQ((type_bits)n.type, (type_bits)k); - EXPECT_EQ(n.key.scalar, ""); - EXPECT_EQ(n.key.tag, ""); - EXPECT_EQ(n.val.scalar, ""); - EXPECT_EQ(n.val.tag, ""); - } -} - -TEST(NodeInit, ctor__val_only) -{ - { - const char sarr[] = "foo"; - const char *sptr = "foo"; size_t sptrlen = 3; - csubstr ssp = "foo"; - - { - SCOPED_TRACE("here 0"); - { - NodeInit s(sarr); - node_scalar_test_foo(s.val); - node_scalar_test_empty(s.key); - s.clear(); - } - { - NodeInit s{to_csubstr(sptr)}; - node_scalar_test_foo(s.val); - node_scalar_test_empty(s.key); - s.clear(); - } - { - NodeInit s{sarr}; - node_scalar_test_foo(s.val); - node_scalar_test_empty(s.key); - s.clear(); - } - } - - { - SCOPED_TRACE("here 1"); - { - NodeInit s(sarr); - node_scalar_test_foo(s.val); - node_scalar_test_empty(s.key); - s.clear(); - } - { - NodeInit s(to_csubstr(sptr)); - node_scalar_test_foo(s.val); - node_scalar_test_empty(s.key); - s.clear(); - } - { - NodeInit s(sarr); - node_scalar_test_foo(s.val); - node_scalar_test_empty(s.key); - s.clear(); - } - } - - { - SCOPED_TRACE("here 2"); - NodeInit s; - s = {sarr}; - node_scalar_test_foo(s.val); - node_scalar_test_empty(s.key); - s.clear(); - s = {to_csubstr(sptr)}; - node_scalar_test_foo(s.val); - node_scalar_test_empty(s.key); - s.clear(); - //s = {sptr, sptrlen}; // fails to compile - //node_scalar_test_foo(s.val); - //node_scalar_test_empty(s.key); - //s.clear(); - s = {ssp}; - node_scalar_test_foo(s.val); - node_scalar_test_empty(s.key); - s.clear(); - } - - for(auto s : { - NodeInit(sarr), - NodeInit(to_csubstr(sptr)), - NodeInit(csubstr{sptr, sptrlen}), - NodeInit(ssp)}) - { - SCOPED_TRACE("here LOOP"); - node_scalar_test_foo(s.val); - node_scalar_test_empty(s.key); - } - } - - { - const char sarr[] = "foo3"; - const char *sptr = "foo3"; size_t sptrlen = 4; - csubstr ssp = "foo3"; - - { - SCOPED_TRACE("here 0"); - NodeInit s = {sarr}; - node_scalar_test_foo3(s.val); - node_scalar_test_empty(s.key); - } - { // FAILS - SCOPED_TRACE("here 1"); - //NodeInit s = sarr; - //node_scalar_test_foo3(s.val); - //node_scalar_test_empty(s.key); - } - { - SCOPED_TRACE("here 2"); - NodeInit s{sarr}; - node_scalar_test_foo3(s.val); - node_scalar_test_empty(s.key); - } - { - SCOPED_TRACE("here 3"); - NodeInit s(sarr); - node_scalar_test_foo3(s.val); - node_scalar_test_empty(s.key); - } - - for(auto s : { - NodeInit(sarr), - NodeInit(to_csubstr(sptr)), - NodeInit(csubstr{sptr, sptrlen}), - NodeInit(ssp)}) - { - SCOPED_TRACE("here LOOP"); - node_scalar_test_foo3(s.val); - node_scalar_test_empty(s.key); - } - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -TEST(Tree, empty_ctor) -{ - Tree tree; - EXPECT_EQ(tree.callbacks(), get_callbacks()); - EXPECT_EQ(tree.empty(), true); - EXPECT_EQ(tree.capacity(), 0u); - EXPECT_EQ(tree.arena_capacity(), 0u); - EXPECT_EQ(tree.arena_slack(), 0u); - EXPECT_EQ(tree.size(), 0u); - EXPECT_EQ(tree.slack(), 0u); - EXPECT_EQ(tree.arena().empty(), true); -} - -TEST(Tree, node_cap_ctor) -{ - { - Tree tree(10u); - EXPECT_EQ(tree.callbacks(), get_callbacks()); - EXPECT_EQ(tree.empty(), false); // we have the root - EXPECT_EQ(tree.capacity(), 10u); - EXPECT_EQ(tree.arena_capacity(), 0u); - EXPECT_EQ(tree.arena_slack(), 0u); - EXPECT_EQ(tree.arena().empty(), true); - EXPECT_EQ(tree.size(), 1u); // we have the root - EXPECT_EQ(tree.slack(), 9u); - } - { - Tree tree(10u, 20u); - EXPECT_EQ(tree.callbacks(), get_callbacks()); - EXPECT_EQ(tree.empty(), false); // we have the root - EXPECT_EQ(tree.capacity(), 10u); - EXPECT_EQ(tree.arena_capacity(), 20u); - EXPECT_EQ(tree.arena().empty(), true); - EXPECT_EQ(tree.size(), 1u); // we have the root - EXPECT_EQ(tree.slack(), 9u); - } - { - Tree tree(0u, 20u); - EXPECT_EQ(tree.callbacks(), get_callbacks()); - EXPECT_EQ(tree.empty(), true); - EXPECT_EQ(tree.capacity(), 0u); - EXPECT_EQ(tree.arena_capacity(), 20u); - EXPECT_EQ(tree.arena_slack(), 20u); - EXPECT_EQ(tree.arena().empty(), true); - EXPECT_EQ(tree.size(), 0u); - EXPECT_EQ(tree.slack(), 0u); - } -} - -Tree get_test_tree(CallbacksTester *cbt=nullptr) -{ - Parser parser(cbt ? cbt->callbacks() : get_callbacks()); - Tree t = parser.parse_in_arena("", "{a: b, c: d, e: [0, 1, 2, 3]}"); - // make sure the tree has strings in its arena - NodeRef n = t.rootref(); - NodeRef ch = n.append_child(); - ch << key("serialized_key"); - ch << 89; - return t; -} - -TEST(Tree, test_tree_has_arena) -{ - { - Tree t = get_test_tree(); - ASSERT_GT(t.arena().size(), 0u); - } - { - CallbacksTester cbt; - Tree t = get_test_tree(&cbt); - ASSERT_GT(t.arena().size(), 0u); - } -} - -//------------------------------------------- -TEST(Tree, copy_ctor) -{ - CallbacksTester cbt; - { - Tree src = get_test_tree(&cbt); - test_invariants(src); - { - Tree dst(src); - test_invariants(dst); - test_compare(dst, src); - test_arena_not_shared(dst, src); - EXPECT_EQ(dst.callbacks(), src.callbacks()); - } - } -} - -//------------------------------------------- -TEST(Tree, move_ctor) -{ - CallbacksTester cbt; - Tree src = get_test_tree(&cbt); - test_invariants(src); - Tree save(src); - test_invariants(save); - test_compare(save, src); - { - Tree dst(std::move(src)); - EXPECT_EQ(src.empty(), true); - EXPECT_EQ(src.size(), 0u); - EXPECT_EQ(src.arena().empty(), true); - EXPECT_EQ(dst.size(), save.size()); - EXPECT_EQ(dst.arena(), save.arena()); - test_invariants(src); - test_invariants(dst); - test_compare(dst, save); - test_arena_not_shared(src, dst); - test_arena_not_shared(save, dst); - } -} - -//------------------------------------------- -TEST(Tree, copy_assign_same_callbacks) -{ - CallbacksTester cbt; - { - Tree src = get_test_tree(&cbt); - test_invariants(src); - { - Tree dst(cbt.callbacks()); - EXPECT_EQ(dst.callbacks(), src.callbacks()); - test_invariants(dst); - dst = src; - test_invariants(dst); - test_compare(dst, src); - test_arena_not_shared(dst, src); - EXPECT_EQ(dst.callbacks(), src.callbacks()); - } - } -} - -TEST(Tree, copy_assign_diff_callbacks) -{ - CallbacksTester cbsrc("src"); - CallbacksTester cbdst("dst"); - { - Tree src = get_test_tree(&cbsrc); - EXPECT_EQ(src.callbacks(), cbsrc.callbacks()); - test_invariants(src); - { - Tree dst = get_test_tree(&cbdst); - EXPECT_EQ(dst.callbacks(), cbdst.callbacks()); - test_invariants(dst); - dst = src; - test_invariants(dst); - test_compare(dst, src); - test_arena_not_shared(dst, src); - EXPECT_EQ(dst.callbacks(), src.callbacks()); - } - } -} - -//------------------------------------------- -TEST(Tree, move_assign_same_callbacks) -{ - CallbacksTester cbt; - Tree src = get_test_tree(&cbt); - test_invariants(src); - Tree save(src); - EXPECT_EQ(save.callbacks(), src.callbacks()); - test_invariants(save); - test_compare(save, src); - { - Tree dst = get_test_tree(&cbt); - EXPECT_NE(dst.empty(), true); - EXPECT_NE(dst.size(), 0u); - EXPECT_NE(dst.arena().empty(), true); - dst = std::move(src); - EXPECT_EQ(src.empty(), true); - EXPECT_EQ(src.size(), 0u); - EXPECT_EQ(src.arena().empty(), true); - EXPECT_EQ(src.callbacks(), cbt.callbacks()); - EXPECT_EQ(dst.size(), save.size()); - EXPECT_EQ(dst.arena(), save.arena()); - EXPECT_EQ(dst.callbacks(), save.callbacks()); - test_invariants(src); - test_invariants(dst); - test_compare(dst, save); - test_arena_not_shared(src, dst); - test_arena_not_shared(save, dst); - } -} - -TEST(Tree, move_assign_diff_callbacks) -{ - CallbacksTester cbsrc("src"); - CallbacksTester cbdst("dst"); - Tree src = get_test_tree(&cbsrc); - test_invariants(src); - Tree save(src); - test_invariants(save); - test_compare(save, src); - { - Tree dst = get_test_tree(&cbdst); - EXPECT_NE(dst.empty(), true); - EXPECT_NE(dst.size(), 0u); - EXPECT_NE(dst.arena().empty(), true); - EXPECT_EQ(dst.callbacks(), cbdst.callbacks()); - dst = std::move(src); - EXPECT_EQ(src.empty(), true); - EXPECT_EQ(src.size(), 0u); - EXPECT_EQ(src.arena().empty(), true); - EXPECT_EQ(src.callbacks(), cbsrc.callbacks()); - EXPECT_EQ(dst.size(), save.size()); - EXPECT_EQ(dst.arena(), save.arena()); - EXPECT_NE(dst.callbacks(), cbdst.callbacks()); - EXPECT_EQ(dst.callbacks(), save.callbacks()); - test_invariants(src); - test_invariants(dst); - test_compare(dst, save); - test_arena_not_shared(src, dst); - test_arena_not_shared(save, dst); - } -} - -TEST(Tree, std_interop) -{ - CallbacksTester cbt; - std::vector forest; - for(size_t i = 0; i < 3; ++i) - { - forest.emplace_back(cbt.callbacks()); - parse_in_arena("{foo: bar}", &forest.back()); - } -} - - -//------------------------------------------- -TEST(Tree, reserve) -{ - Tree t(16, 64); - EXPECT_EQ(t.capacity(), 16); - EXPECT_EQ(t.slack(), 15); - EXPECT_EQ(t.size(), 1); - EXPECT_EQ(t.arena_capacity(), 64); - EXPECT_EQ(t.arena_slack(), 64); - EXPECT_EQ(t.arena_size(), 0); - test_invariants(t); - - auto buf = t.m_buf; - t.reserve(16); - t.reserve_arena(64); - EXPECT_EQ(t.m_buf, buf); - EXPECT_EQ(t.capacity(), 16); - EXPECT_EQ(t.slack(), 15); - EXPECT_EQ(t.size(), 1); - EXPECT_EQ(t.arena_capacity(), 64); - EXPECT_EQ(t.arena_slack(), 64); - EXPECT_EQ(t.arena_size(), 0); - test_invariants(t); - - t.reserve(32); - t.reserve_arena(128); - EXPECT_EQ(t.capacity(), 32); - EXPECT_EQ(t.slack(), 31); - EXPECT_EQ(t.size(), 1); - EXPECT_EQ(t.arena_capacity(), 128); - EXPECT_EQ(t.arena_slack(), 128); - EXPECT_EQ(t.arena_size(), 0); - test_invariants(t); - - buf = t.m_buf; - parse_in_arena("[a, b, c, d, e, f]", &t); - EXPECT_EQ(t.m_buf, buf); - EXPECT_EQ(t.capacity(), 32); - EXPECT_EQ(t.slack(), 25); - EXPECT_EQ(t.size(), 7); - EXPECT_EQ(t.arena_capacity(), 128); - EXPECT_EQ(t.arena_slack(), 110); - EXPECT_EQ(t.arena_size(), 18); - test_invariants(t); - - t.reserve(64); - t.reserve_arena(256); - EXPECT_EQ(t.capacity(), 64); - EXPECT_EQ(t.slack(), 57); - EXPECT_EQ(t.size(), 7); - EXPECT_EQ(t.arena_capacity(), 256); - EXPECT_EQ(t.arena_slack(), 238); - EXPECT_EQ(t.arena_size(), 18); - test_invariants(t); -} - -// https://github.com/biojppm/rapidyaml/issues/288 -TEST(Tree, reserve_arena_issue288) -{ - Tree t; - EXPECT_EQ(t.arena_slack(), 0u); - EXPECT_EQ(t.arena_capacity(), 0u); - EXPECT_EQ(t.arena_size(), 0u); - t.reserve_arena(3u); - EXPECT_EQ(t.arena_slack(), 3u); - EXPECT_GE(t.arena_capacity(), 3u); - EXPECT_EQ(t.arena_size(), 0u); - // longer than the slack to cause another call to _grow_arena() - std::string stars(2 * t.arena_slack(), '*'); - t.copy_to_arena(to_csubstr(stars)); - EXPECT_GE(t.arena_capacity(), stars.size()); - EXPECT_EQ(t.arena_size(), stars.size()); - EXPECT_EQ(t.arena(), to_csubstr(stars)); - // again - std::string pluses(2 * t.arena_slack(), '+'); - t.copy_to_arena(to_csubstr(pluses)); - EXPECT_GE(t.arena_capacity(), stars.size() + pluses.size()); - EXPECT_EQ(t.arena_size(), stars.size() + pluses.size()); - EXPECT_EQ(t.arena().first(stars.size()), to_csubstr(stars)); - EXPECT_EQ(t.arena().last(pluses.size()), to_csubstr(pluses)); -} - -TEST(Tree, clear) -{ - Tree t(16, 64); - EXPECT_EQ(t.capacity(), 16); - EXPECT_EQ(t.slack(), 15); - EXPECT_EQ(t.size(), 1); - EXPECT_EQ(t.arena_capacity(), 64); - EXPECT_EQ(t.arena_slack(), 64); - EXPECT_EQ(t.arena_size(), 0); - test_invariants(t); - - t.clear(); - t.clear_arena(); - EXPECT_EQ(t.capacity(), 16); - EXPECT_EQ(t.slack(), 15); - EXPECT_EQ(t.size(), 1); - EXPECT_EQ(t.arena_capacity(), 64); - EXPECT_EQ(t.arena_slack(), 64); - EXPECT_EQ(t.arena_size(), 0); - test_invariants(t); - - auto buf = t.m_buf; - t.reserve(16); - t.reserve_arena(64); - EXPECT_EQ(t.m_buf, buf); - EXPECT_EQ(t.capacity(), 16); - EXPECT_EQ(t.slack(), 15); - EXPECT_EQ(t.size(), 1); - EXPECT_EQ(t.arena_capacity(), 64); - EXPECT_EQ(t.arena_slack(), 64); - EXPECT_EQ(t.arena_size(), 0); - test_invariants(t); - - t.reserve(32); - t.reserve_arena(128); - EXPECT_EQ(t.capacity(), 32); - EXPECT_EQ(t.slack(), 31); - EXPECT_EQ(t.size(), 1); - EXPECT_EQ(t.arena_capacity(), 128); - EXPECT_EQ(t.arena_slack(), 128); - EXPECT_EQ(t.arena_size(), 0); - test_invariants(t); - - buf = t.m_buf; - parse_in_arena("[a, b, c, d, e, f]", &t); - EXPECT_EQ(t.m_buf, buf); - EXPECT_EQ(t.capacity(), 32); - EXPECT_EQ(t.slack(), 25); - EXPECT_EQ(t.size(), 7); - EXPECT_EQ(t.arena_capacity(), 128); - EXPECT_EQ(t.arena_slack(), 110); - EXPECT_EQ(t.arena_size(), 18); - test_invariants(t); - - t.clear(); - t.clear_arena(); - EXPECT_EQ(t.capacity(), 32); - EXPECT_EQ(t.slack(), 31); - EXPECT_EQ(t.size(), 1); - EXPECT_EQ(t.arena_capacity(), 128); - EXPECT_EQ(t.arena_slack(), 128); - EXPECT_EQ(t.arena_size(), 0); - test_invariants(t); -} - - -//------------------------------------------- - -TEST(Tree, ref) -{ - Tree t = parse_in_arena("[0, 1, 2, 3]"); - EXPECT_EQ(t.ref(0).id(), 0); - EXPECT_EQ(t.ref(1).id(), 1); - EXPECT_EQ(t.ref(2).id(), 2); - EXPECT_EQ(t.ref(3).id(), 3); - EXPECT_EQ(t.ref(4).id(), 4); - EXPECT_TRUE(t.ref(0).is_seq()); - EXPECT_TRUE(t.ref(1).is_val()); - EXPECT_TRUE(t.ref(2).is_val()); - EXPECT_TRUE(t.ref(3).is_val()); - EXPECT_TRUE(t.ref(4).is_val()); -} - -TEST(Tree, ref_const) -{ - const Tree t = parse_in_arena("[0, 1, 2, 3]"); - EXPECT_EQ(t.ref(0).id(), 0); - EXPECT_EQ(t.ref(1).id(), 1); - EXPECT_EQ(t.ref(2).id(), 2); - EXPECT_EQ(t.ref(3).id(), 3); - EXPECT_EQ(t.ref(4).id(), 4); - EXPECT_TRUE(t.ref(0).is_seq()); - EXPECT_TRUE(t.ref(1).is_val()); - EXPECT_TRUE(t.ref(2).is_val()); - EXPECT_TRUE(t.ref(3).is_val()); - EXPECT_TRUE(t.ref(4).is_val()); -} - - -TEST(Tree, operator_square_brackets) -{ - { - Tree t = parse_in_arena("[0, 1, 2, 3, 4]"); - Tree &m = t; - Tree const& cm = t; - EXPECT_EQ(m[0].val(), "0"); - EXPECT_EQ(m[1].val(), "1"); - EXPECT_EQ(m[2].val(), "2"); - EXPECT_EQ(m[3].val(), "3"); - EXPECT_EQ(m[4].val(), "4"); - EXPECT_EQ(cm[0].val(), "0"); - EXPECT_EQ(cm[1].val(), "1"); - EXPECT_EQ(cm[2].val(), "2"); - EXPECT_EQ(cm[3].val(), "3"); - EXPECT_EQ(cm[4].val(), "4"); - // - EXPECT_TRUE(m[0] == "0"); - EXPECT_TRUE(m[1] == "1"); - EXPECT_TRUE(m[2] == "2"); - EXPECT_TRUE(m[3] == "3"); - EXPECT_TRUE(m[4] == "4"); - EXPECT_TRUE(cm[0] == "0"); - EXPECT_TRUE(cm[1] == "1"); - EXPECT_TRUE(cm[2] == "2"); - EXPECT_TRUE(cm[3] == "3"); - EXPECT_TRUE(cm[4] == "4"); - // - EXPECT_FALSE(m[0] != "0"); - EXPECT_FALSE(m[1] != "1"); - EXPECT_FALSE(m[2] != "2"); - EXPECT_FALSE(m[3] != "3"); - EXPECT_FALSE(m[4] != "4"); - EXPECT_FALSE(cm[0] != "0"); - EXPECT_FALSE(cm[1] != "1"); - EXPECT_FALSE(cm[2] != "2"); - EXPECT_FALSE(cm[3] != "3"); - EXPECT_FALSE(cm[4] != "4"); - } - { - Tree t = parse_in_arena("{a: 0, b: 1, c: 2, d: 3, e: 4}"); - Tree &m = t; - Tree const& cm = t; - EXPECT_EQ(m["a"].val(), "0"); - EXPECT_EQ(m["b"].val(), "1"); - EXPECT_EQ(m["c"].val(), "2"); - EXPECT_EQ(m["d"].val(), "3"); - EXPECT_EQ(m["e"].val(), "4"); - EXPECT_EQ(cm["a"].val(), "0"); - EXPECT_EQ(cm["b"].val(), "1"); - EXPECT_EQ(cm["c"].val(), "2"); - EXPECT_EQ(cm["d"].val(), "3"); - EXPECT_EQ(cm["e"].val(), "4"); - // - EXPECT_TRUE(m["a"] == "0"); - EXPECT_TRUE(m["b"] == "1"); - EXPECT_TRUE(m["c"] == "2"); - EXPECT_TRUE(m["d"] == "3"); - EXPECT_TRUE(m["e"] == "4"); - EXPECT_TRUE(cm["a"] == "0"); - EXPECT_TRUE(cm["b"] == "1"); - EXPECT_TRUE(cm["c"] == "2"); - EXPECT_TRUE(cm["d"] == "3"); - EXPECT_TRUE(cm["e"] == "4"); - // - EXPECT_FALSE(m["a"] != "0"); - EXPECT_FALSE(m["b"] != "1"); - EXPECT_FALSE(m["c"] != "2"); - EXPECT_FALSE(m["d"] != "3"); - EXPECT_FALSE(m["e"] != "4"); - EXPECT_FALSE(cm["a"] != "0"); - EXPECT_FALSE(cm["b"] != "1"); - EXPECT_FALSE(cm["c"] != "2"); - EXPECT_FALSE(cm["d"] != "3"); - EXPECT_FALSE(cm["e"] != "4"); - } -} - -TEST(Tree, relocate) -{ - // create a tree with anchors and refs, and copy it to ensure the - // relocation also applies to the anchors and refs. Ensure to put - // the source in the arena so that it gets relocated. - Tree tree = parse_in_arena(R"(&keyanchor key: val -key2: &valanchor val2 -keyref: *keyanchor -*valanchor: was val anchor -!!int 0: !!str foo -!!str doe: !!str a deer a female deer -ray: a drop of golden sun -me: a name I call myself -far: a long long way to run -)"); - Tree copy = tree; - EXPECT_EQ(copy.size(), tree.size()); - EXPECT_EQ(emitrs_yaml(copy), R"(&keyanchor key: val -key2: &valanchor val2 -keyref: *keyanchor -*valanchor: was val anchor -!!int 0: !!str foo -!!str doe: !!str a deer a female deer -ray: a drop of golden sun -me: a name I call myself -far: a long long way to run -)"); - // - Tree copy2 = copy; - EXPECT_EQ(copy.size(), tree.size()); - copy2.resolve(); - EXPECT_EQ(emitrs_yaml(copy2), R"(key: val -key2: val2 -keyref: key -val2: was val anchor -!!int 0: !!str foo -!!str doe: !!str a deer a female deer -ray: a drop of golden sun -me: a name I call myself -far: a long long way to run -)"); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -TEST(NodeType, type_str) -{ - // avoid coverage misses - EXPECT_EQ(to_csubstr(NodeType(KEYVAL).type_str()), "KEYVAL"); - EXPECT_EQ(to_csubstr(NodeType(KEY).type_str()), "KEY"); - EXPECT_EQ(to_csubstr(NodeType(VAL).type_str()), "VAL"); - EXPECT_EQ(to_csubstr(NodeType(MAP).type_str()), "MAP"); - EXPECT_EQ(to_csubstr(NodeType(SEQ).type_str()), "SEQ"); - EXPECT_EQ(to_csubstr(NodeType(KEYMAP).type_str()), "KEYMAP"); - EXPECT_EQ(to_csubstr(NodeType(KEYSEQ).type_str()), "KEYSEQ"); - EXPECT_EQ(to_csubstr(NodeType(DOCSEQ).type_str()), "DOCSEQ"); - EXPECT_EQ(to_csubstr(NodeType(DOCMAP).type_str()), "DOCMAP"); - EXPECT_EQ(to_csubstr(NodeType(DOCVAL).type_str()), "DOCVAL"); - EXPECT_EQ(to_csubstr(NodeType(DOC).type_str()), "DOC"); - EXPECT_EQ(to_csubstr(NodeType(STREAM).type_str()), "STREAM"); - EXPECT_EQ(to_csubstr(NodeType(NOTYPE).type_str()), "NOTYPE"); - EXPECT_EQ(to_csubstr(NodeType(KEYVAL|KEYREF).type_str()), "KEYVAL***"); - EXPECT_EQ(to_csubstr(NodeType(KEYVAL|VALREF).type_str()), "KEYVAL***"); - EXPECT_EQ(to_csubstr(NodeType(KEYVAL|KEYANCH).type_str()), "KEYVAL***"); - EXPECT_EQ(to_csubstr(NodeType(KEYVAL|VALANCH).type_str()), "KEYVAL***"); - EXPECT_EQ(to_csubstr(NodeType(KEYVAL|KEYREF|VALANCH).type_str()), "KEYVAL***"); - EXPECT_EQ(to_csubstr(NodeType(KEYVAL|KEYANCH|VALREF).type_str()), "KEYVAL***"); - EXPECT_EQ(to_csubstr(NodeType(KEYMAP|KEYREF).type_str()), "KEYMAP***"); - EXPECT_EQ(to_csubstr(NodeType(KEYMAP|VALREF).type_str()), "KEYMAP***"); - EXPECT_EQ(to_csubstr(NodeType(KEYMAP|KEYANCH).type_str()), "KEYMAP***"); - EXPECT_EQ(to_csubstr(NodeType(KEYMAP|VALANCH).type_str()), "KEYMAP***"); - EXPECT_EQ(to_csubstr(NodeType(KEYMAP|KEYREF|VALANCH).type_str()), "KEYMAP***"); - EXPECT_EQ(to_csubstr(NodeType(KEYMAP|KEYANCH|VALREF).type_str()), "KEYMAP***"); - EXPECT_EQ(to_csubstr(NodeType(KEYSEQ|KEYREF).type_str()), "KEYSEQ***"); - EXPECT_EQ(to_csubstr(NodeType(KEYSEQ|VALREF).type_str()), "KEYSEQ***"); - EXPECT_EQ(to_csubstr(NodeType(KEYSEQ|KEYANCH).type_str()), "KEYSEQ***"); - EXPECT_EQ(to_csubstr(NodeType(KEYSEQ|VALANCH).type_str()), "KEYSEQ***"); - EXPECT_EQ(to_csubstr(NodeType(KEYSEQ|KEYREF|VALANCH).type_str()), "KEYSEQ***"); - EXPECT_EQ(to_csubstr(NodeType(KEYSEQ|KEYANCH|VALREF).type_str()), "KEYSEQ***"); - EXPECT_EQ(to_csubstr(NodeType(DOCSEQ|VALANCH).type_str()), "DOCSEQ***"); - EXPECT_EQ(to_csubstr(NodeType(DOCSEQ|VALREF).type_str()), "DOCSEQ***"); - EXPECT_EQ(to_csubstr(NodeType(DOCMAP|VALANCH).type_str()), "DOCMAP***"); - EXPECT_EQ(to_csubstr(NodeType(DOCMAP|VALREF).type_str()), "DOCMAP***"); - EXPECT_EQ(to_csubstr(NodeType(DOCVAL|VALANCH).type_str()), "DOCVAL***"); - EXPECT_EQ(to_csubstr(NodeType(DOCVAL|VALREF).type_str()), "DOCVAL***"); - EXPECT_EQ(to_csubstr(NodeType(KEY|KEYREF).type_str()), "KEY***"); - EXPECT_EQ(to_csubstr(NodeType(KEY|KEYANCH).type_str()), "KEY***"); - EXPECT_EQ(to_csubstr(NodeType(VAL|VALREF).type_str()), "VAL***"); - EXPECT_EQ(to_csubstr(NodeType(VAL|VALANCH).type_str()), "VAL***"); - EXPECT_EQ(to_csubstr(NodeType(MAP|VALREF).type_str()), "MAP***"); - EXPECT_EQ(to_csubstr(NodeType(MAP|VALANCH).type_str()), "MAP***"); - EXPECT_EQ(to_csubstr(NodeType(SEQ|VALREF).type_str()), "SEQ***"); - EXPECT_EQ(to_csubstr(NodeType(SEQ|VALANCH).type_str()), "SEQ***"); - EXPECT_EQ(to_csubstr(NodeType(DOC|VALREF).type_str()), "DOC***"); - EXPECT_EQ(to_csubstr(NodeType(DOC|VALANCH).type_str()), "DOC***"); - EXPECT_EQ(to_csubstr(NodeType(KEYREF).type_str()), "(unk)"); - EXPECT_EQ(to_csubstr(NodeType(VALREF).type_str()), "(unk)"); - EXPECT_EQ(to_csubstr(NodeType(KEYANCH).type_str()), "(unk)"); - EXPECT_EQ(to_csubstr(NodeType(VALANCH).type_str()), "(unk)"); -} - -TEST(NodeType, is_stream) -{ - EXPECT_FALSE(NodeType(NOTYPE).is_stream()); - EXPECT_TRUE(NodeType(STREAM).is_stream()); -} - -TEST(Tree, is_stream) -{ - Tree t = parse_in_arena(R"(--- -foo: bar -...)"); - const size_t stream_id = t.root_id(); - const size_t doc_id = t.first_child(stream_id); - const size_t keyval_id = t.first_child(doc_id); - ConstNodeRef stream = t.ref(stream_id); - ConstNodeRef doc = t.ref(doc_id); - ConstNodeRef keyval = t.ref(keyval_id); - EXPECT_TRUE(t.is_stream(stream_id)); - EXPECT_FALSE(t.is_stream(doc_id)); - EXPECT_FALSE(t.is_stream(keyval_id)); - EXPECT_TRUE(stream.is_stream()); - EXPECT_FALSE(doc.is_stream()); - EXPECT_FALSE(keyval.is_stream()); - EXPECT_EQ(t.is_stream(stream_id), t._p(stream_id)->m_type.is_stream()); - EXPECT_EQ(t.is_stream(doc_id), t._p(doc_id)->m_type.is_stream()); - EXPECT_EQ(t.is_stream(keyval_id), t._p(keyval_id)->m_type.is_stream()); - EXPECT_EQ(stream.is_stream(), stream.get()->m_type.is_stream()); - EXPECT_EQ(doc.is_stream(), doc.get()->m_type.is_stream()); - EXPECT_EQ(keyval.is_stream(), keyval.get()->m_type.is_stream()); -} - -TEST(NodeType, is_doc) -{ - EXPECT_FALSE(NodeType(NOTYPE).is_doc()); - EXPECT_TRUE(NodeType(DOC).is_doc()); -} - -TEST(Tree, is_doc) -{ - Tree t = parse_in_arena(R"(--- -foo: bar ---- -a scalar -...)"); - const size_t stream_id = t.root_id(); - const size_t doc_id = t.first_child(stream_id); - const size_t keyval_id = t.first_child(doc_id); - const size_t docval_id = t.last_child(stream_id); - ConstNodeRef stream = t.ref(stream_id); - ConstNodeRef doc = t.ref(doc_id); - ConstNodeRef keyval = t.ref(keyval_id); - ConstNodeRef docval = t.ref(docval_id); - NodeRef mstream = t.ref(stream_id); - NodeRef mdoc = t.ref(doc_id); - NodeRef mkeyval = t.ref(keyval_id); - NodeRef mdocval = t.ref(docval_id); - EXPECT_FALSE(t.is_doc(stream_id)); - EXPECT_TRUE(t.is_doc(doc_id)); - EXPECT_FALSE(t.is_doc(keyval_id)); - EXPECT_TRUE(t.is_doc(docval_id)); - EXPECT_FALSE(stream.is_doc()); - EXPECT_TRUE(doc.is_doc()); - EXPECT_FALSE(keyval.is_doc()); - EXPECT_TRUE(docval.is_doc()); - EXPECT_FALSE(mstream.is_doc()); - EXPECT_TRUE(mdoc.is_doc()); - EXPECT_FALSE(mkeyval.is_doc()); - EXPECT_TRUE(mdocval.is_doc()); - EXPECT_EQ(t.is_doc(stream_id), t._p(stream_id)->m_type.is_doc()); - EXPECT_EQ(t.is_doc(doc_id), t._p(doc_id)->m_type.is_doc()); - EXPECT_EQ(t.is_doc(keyval_id), t._p(keyval_id)->m_type.is_doc()); - EXPECT_EQ(t.is_doc(docval_id), t._p(docval_id)->m_type.is_doc()); - EXPECT_EQ(stream.is_doc(), stream.get()->m_type.is_doc()); - EXPECT_EQ(doc.is_doc(), doc.get()->m_type.is_doc()); - EXPECT_EQ(keyval.is_doc(), keyval.get()->m_type.is_doc()); - EXPECT_EQ(docval.is_doc(), docval.get()->m_type.is_doc()); - EXPECT_EQ(mstream.is_doc(), mstream.get()->m_type.is_doc()); - EXPECT_EQ(mdoc.is_doc(), mdoc.get()->m_type.is_doc()); - EXPECT_EQ(mkeyval.is_doc(), mkeyval.get()->m_type.is_doc()); - EXPECT_EQ(mdocval.is_doc(), mdocval.get()->m_type.is_doc()); -} - -TEST(NodeType, is_container) -{ - EXPECT_FALSE(NodeType(NOTYPE).is_container()); - EXPECT_FALSE(NodeType(VAL).is_container()); - EXPECT_FALSE(NodeType(KEY).is_container()); - EXPECT_FALSE(NodeType(KEYVAL).is_container()); - EXPECT_TRUE(NodeType(MAP).is_container()); - EXPECT_TRUE(NodeType(SEQ).is_container()); - EXPECT_TRUE(NodeType(KEYMAP).is_container()); - EXPECT_TRUE(NodeType(KEYSEQ).is_container()); - EXPECT_TRUE(NodeType(DOCMAP).is_container()); - EXPECT_TRUE(NodeType(DOCSEQ).is_container()); -} - -TEST(Tree, is_container) -{ - Tree t = parse_in_arena(R"(--- -map: {foo: bar} -seq: [foo, bar] ---- -a scalar -...)"); - const size_t stream_id = t.root_id(); - const size_t doc_id = t.first_child(stream_id); - const size_t map_id = t.first_child(doc_id); - const size_t keyval_id = t.first_child(map_id); - const size_t seq_id = t.last_child(doc_id); - const size_t val_id = t.first_child(seq_id); - const size_t docval_id = t.last_child(stream_id); - ConstNodeRef stream = t.ref(stream_id); - ConstNodeRef doc = t.ref(doc_id); - ConstNodeRef map = t.ref(map_id); - ConstNodeRef keyval = t.ref(keyval_id); - ConstNodeRef seq = t.ref(seq_id); - ConstNodeRef val = t.ref(val_id); - ConstNodeRef docval = t.ref(docval_id); - NodeRef mstream = t.ref(stream_id); - NodeRef mdoc = t.ref(doc_id); - NodeRef mmap = t.ref(map_id); - NodeRef mkeyval = t.ref(keyval_id); - NodeRef mseq = t.ref(seq_id); - NodeRef mval = t.ref(val_id); - NodeRef mdocval = t.ref(docval_id); - EXPECT_TRUE(t.is_container(stream_id)); - EXPECT_TRUE(t.is_container(doc_id)); - EXPECT_TRUE(t.is_container(map_id)); - EXPECT_FALSE(t.is_container(keyval_id)); - EXPECT_TRUE(t.is_container(seq_id)); - EXPECT_FALSE(t.is_container(val_id)); - EXPECT_FALSE(t.is_container(docval_id)); - EXPECT_TRUE(stream.is_container()); - EXPECT_TRUE(doc.is_container()); - EXPECT_TRUE(map.is_container()); - EXPECT_FALSE(keyval.is_container()); - EXPECT_TRUE(seq.is_container()); - EXPECT_FALSE(val.is_container()); - EXPECT_FALSE(docval.is_container()); - EXPECT_TRUE(mstream.is_container()); - EXPECT_TRUE(mdoc.is_container()); - EXPECT_TRUE(mmap.is_container()); - EXPECT_FALSE(mkeyval.is_container()); - EXPECT_TRUE(mseq.is_container()); - EXPECT_FALSE(mval.is_container()); - EXPECT_FALSE(mdocval.is_container()); - EXPECT_EQ(t.is_container(stream_id), t._p(stream_id)->m_type.is_container()); - EXPECT_EQ(t.is_container(doc_id), t._p(doc_id)->m_type.is_container()); - EXPECT_EQ(t.is_container(map_id), t._p(map_id)->m_type.is_container()); - EXPECT_EQ(t.is_container(keyval_id), t._p(keyval_id)->m_type.is_container()); - EXPECT_EQ(t.is_container(seq_id), t._p(seq_id)->m_type.is_container()); - EXPECT_EQ(t.is_container(val_id), t._p(val_id)->m_type.is_container()); - EXPECT_EQ(t.is_container(docval_id), t._p(docval_id)->m_type.is_container()); - EXPECT_EQ(stream.is_container(), stream.get()->m_type.is_container()); - EXPECT_EQ(doc.is_container(), doc.get()->m_type.is_container()); - EXPECT_EQ(map.is_container(), map.get()->m_type.is_container()); - EXPECT_EQ(keyval.is_container(), keyval.get()->m_type.is_container()); - EXPECT_EQ(seq.is_container(), seq.get()->m_type.is_container()); - EXPECT_EQ(val.is_container(), val.get()->m_type.is_container()); - EXPECT_EQ(docval.is_container(), docval.get()->m_type.is_container()); - EXPECT_EQ(mstream.is_container(), mstream.get()->m_type.is_container()); - EXPECT_EQ(mdoc.is_container(), mdoc.get()->m_type.is_container()); - EXPECT_EQ(mmap.is_container(), mmap.get()->m_type.is_container()); - EXPECT_EQ(mkeyval.is_container(), mkeyval.get()->m_type.is_container()); - EXPECT_EQ(mseq.is_container(), mseq.get()->m_type.is_container()); - EXPECT_EQ(mval.is_container(), mval.get()->m_type.is_container()); - EXPECT_EQ(mdocval.is_container(), mdocval.get()->m_type.is_container()); -} - -TEST(NodeType, is_map) -{ - EXPECT_FALSE(NodeType(NOTYPE).is_map()); - EXPECT_FALSE(NodeType(VAL).is_map()); - EXPECT_FALSE(NodeType(KEY).is_map()); - EXPECT_TRUE(NodeType(MAP).is_map()); - EXPECT_TRUE(NodeType(KEYMAP).is_map()); - EXPECT_FALSE(NodeType(SEQ).is_map()); - EXPECT_FALSE(NodeType(KEYSEQ).is_map()); -} - -TEST(Tree, is_map) -{ - Tree t = parse_in_arena(R"(--- -map: {foo: bar} -seq: [foo, bar] ---- -a scalar -...)"); - const size_t stream_id = t.root_id(); - const size_t doc_id = t.first_child(stream_id); - const size_t map_id = t.first_child(doc_id); - const size_t keyval_id = t.first_child(map_id); - const size_t seq_id = t.last_child(doc_id); - const size_t val_id = t.first_child(seq_id); - const size_t docval_id = t.last_child(stream_id); - ConstNodeRef stream = t.ref(stream_id); - ConstNodeRef doc = t.ref(doc_id); - ConstNodeRef map = t.ref(map_id); - ConstNodeRef keyval = t.ref(keyval_id); - ConstNodeRef seq = t.ref(seq_id); - ConstNodeRef val = t.ref(val_id); - ConstNodeRef docval = t.ref(docval_id); - NodeRef mstream = t.ref(stream_id); - NodeRef mdoc = t.ref(doc_id); - NodeRef mmap = t.ref(map_id); - NodeRef mkeyval = t.ref(keyval_id); - NodeRef mseq = t.ref(seq_id); - NodeRef mval = t.ref(val_id); - NodeRef mdocval = t.ref(docval_id); - EXPECT_FALSE(t.is_map(stream_id)); - EXPECT_TRUE(t.is_map(doc_id)); - EXPECT_TRUE(t.is_map(map_id)); - EXPECT_FALSE(t.is_map(keyval_id)); - EXPECT_FALSE(t.is_map(seq_id)); - EXPECT_FALSE(t.is_map(val_id)); - EXPECT_FALSE(t.is_map(docval_id)); - EXPECT_FALSE(stream.is_map()); - EXPECT_TRUE(doc.is_map()); - EXPECT_TRUE(map.is_map()); - EXPECT_FALSE(keyval.is_map()); - EXPECT_FALSE(seq.is_map()); - EXPECT_FALSE(val.is_map()); - EXPECT_FALSE(docval.is_map()); - EXPECT_FALSE(mstream.is_map()); - EXPECT_TRUE(mdoc.is_map()); - EXPECT_TRUE(mmap.is_map()); - EXPECT_FALSE(mkeyval.is_map()); - EXPECT_FALSE(mseq.is_map()); - EXPECT_FALSE(mval.is_map()); - EXPECT_FALSE(mdocval.is_map()); - EXPECT_EQ(t.is_map(stream_id), t._p(stream_id)->m_type.is_map()); - EXPECT_EQ(t.is_map(doc_id), t._p(doc_id)->m_type.is_map()); - EXPECT_EQ(t.is_map(map_id), t._p(map_id)->m_type.is_map()); - EXPECT_EQ(t.is_map(keyval_id), t._p(keyval_id)->m_type.is_map()); - EXPECT_EQ(t.is_map(seq_id), t._p(seq_id)->m_type.is_map()); - EXPECT_EQ(t.is_map(val_id), t._p(val_id)->m_type.is_map()); - EXPECT_EQ(t.is_map(docval_id), t._p(docval_id)->m_type.is_map()); - EXPECT_EQ(stream.is_map(), stream.get()->m_type.is_map()); - EXPECT_EQ(doc.is_map(), doc.get()->m_type.is_map()); - EXPECT_EQ(map.is_map(), map.get()->m_type.is_map()); - EXPECT_EQ(keyval.is_map(), keyval.get()->m_type.is_map()); - EXPECT_EQ(seq.is_map(), seq.get()->m_type.is_map()); - EXPECT_EQ(val.is_map(), val.get()->m_type.is_map()); - EXPECT_EQ(docval.is_map(), docval.get()->m_type.is_map()); - EXPECT_EQ(mstream.is_map(), mstream.get()->m_type.is_map()); - EXPECT_EQ(mdoc.is_map(), mdoc.get()->m_type.is_map()); - EXPECT_EQ(mmap.is_map(), mmap.get()->m_type.is_map()); - EXPECT_EQ(mkeyval.is_map(), mkeyval.get()->m_type.is_map()); - EXPECT_EQ(mseq.is_map(), mseq.get()->m_type.is_map()); - EXPECT_EQ(mval.is_map(), mval.get()->m_type.is_map()); - EXPECT_EQ(mdocval.is_map(), mdocval.get()->m_type.is_map()); -} - -TEST(NodeType, is_seq) -{ - EXPECT_FALSE(NodeType(NOTYPE).is_seq()); - EXPECT_FALSE(NodeType(VAL).is_seq()); - EXPECT_FALSE(NodeType(KEY).is_seq()); - EXPECT_FALSE(NodeType(MAP).is_seq()); - EXPECT_FALSE(NodeType(KEYMAP).is_seq()); - EXPECT_TRUE(NodeType(SEQ).is_seq()); - EXPECT_TRUE(NodeType(KEYSEQ).is_seq()); -} - -TEST(Tree, is_seq) -{ - Tree t = parse_in_arena(R"(--- -map: {foo: bar} -seq: [foo, bar] ---- -a scalar -...)"); - const size_t stream_id = t.root_id(); - const size_t doc_id = t.first_child(stream_id); - const size_t map_id = t.first_child(doc_id); - const size_t keyval_id = t.first_child(map_id); - const size_t seq_id = t.last_child(doc_id); - const size_t val_id = t.first_child(seq_id); - const size_t docval_id = t.last_child(stream_id); - ConstNodeRef stream = t.ref(stream_id); - ConstNodeRef doc = t.ref(doc_id); - ConstNodeRef map = t.ref(map_id); - ConstNodeRef keyval = t.ref(keyval_id); - ConstNodeRef seq = t.ref(seq_id); - ConstNodeRef val = t.ref(val_id); - ConstNodeRef docval = t.ref(docval_id); - NodeRef mstream = t.ref(stream_id); - NodeRef mdoc = t.ref(doc_id); - NodeRef mmap = t.ref(map_id); - NodeRef mkeyval = t.ref(keyval_id); - NodeRef mseq = t.ref(seq_id); - NodeRef mval = t.ref(val_id); - NodeRef mdocval = t.ref(docval_id); - EXPECT_TRUE(t.is_seq(stream_id)); - EXPECT_FALSE(t.is_seq(doc_id)); - EXPECT_FALSE(t.is_seq(map_id)); - EXPECT_FALSE(t.is_seq(keyval_id)); - EXPECT_TRUE(t.is_seq(seq_id)); - EXPECT_FALSE(t.is_seq(val_id)); - EXPECT_FALSE(t.is_seq(docval_id)); - EXPECT_TRUE(stream.is_seq()); - EXPECT_FALSE(doc.is_seq()); - EXPECT_FALSE(map.is_seq()); - EXPECT_FALSE(keyval.is_seq()); - EXPECT_TRUE(seq.is_seq()); - EXPECT_FALSE(val.is_seq()); - EXPECT_FALSE(docval.is_seq()); - EXPECT_TRUE(mstream.is_seq()); - EXPECT_FALSE(mdoc.is_seq()); - EXPECT_FALSE(mmap.is_seq()); - EXPECT_FALSE(mkeyval.is_seq()); - EXPECT_TRUE(mseq.is_seq()); - EXPECT_FALSE(mval.is_seq()); - EXPECT_FALSE(mdocval.is_seq()); - EXPECT_EQ(t.is_seq(stream_id), t._p(stream_id)->m_type.is_seq()); - EXPECT_EQ(t.is_seq(doc_id), t._p(doc_id)->m_type.is_seq()); - EXPECT_EQ(t.is_seq(map_id), t._p(map_id)->m_type.is_seq()); - EXPECT_EQ(t.is_seq(keyval_id), t._p(keyval_id)->m_type.is_seq()); - EXPECT_EQ(t.is_seq(seq_id), t._p(seq_id)->m_type.is_seq()); - EXPECT_EQ(t.is_seq(val_id), t._p(val_id)->m_type.is_seq()); - EXPECT_EQ(t.is_seq(docval_id), t._p(docval_id)->m_type.is_seq()); - EXPECT_EQ(stream.is_seq(), stream.get()->m_type.is_seq()); - EXPECT_EQ(doc.is_seq(), doc.get()->m_type.is_seq()); - EXPECT_EQ(map.is_seq(), map.get()->m_type.is_seq()); - EXPECT_EQ(keyval.is_seq(), keyval.get()->m_type.is_seq()); - EXPECT_EQ(seq.is_seq(), seq.get()->m_type.is_seq()); - EXPECT_EQ(val.is_seq(), val.get()->m_type.is_seq()); - EXPECT_EQ(docval.is_seq(), docval.get()->m_type.is_seq()); - EXPECT_EQ(mstream.is_seq(), mstream.get()->m_type.is_seq()); - EXPECT_EQ(mdoc.is_seq(), mdoc.get()->m_type.is_seq()); - EXPECT_EQ(mmap.is_seq(), mmap.get()->m_type.is_seq()); - EXPECT_EQ(mkeyval.is_seq(), mkeyval.get()->m_type.is_seq()); - EXPECT_EQ(mseq.is_seq(), mseq.get()->m_type.is_seq()); - EXPECT_EQ(mval.is_seq(), mval.get()->m_type.is_seq()); - EXPECT_EQ(mdocval.is_seq(), mdocval.get()->m_type.is_seq()); -} - -TEST(NodeType, has_val) -{ - EXPECT_FALSE(NodeType(NOTYPE).has_val()); - EXPECT_FALSE(NodeType(KEY).has_val()); - EXPECT_TRUE(NodeType(VAL).has_val()); - EXPECT_TRUE(NodeType(DOCVAL).has_val()); - EXPECT_TRUE(NodeType(KEYVAL).has_val()); - EXPECT_FALSE(NodeType(KEYMAP).has_val()); - EXPECT_FALSE(NodeType(KEYSEQ).has_val()); -} - -TEST(Tree, has_val) -{ - Tree t = parse_in_arena(R"(--- -map: {foo: bar} -seq: [foo, bar] ---- -a scalar -...)"); - const size_t stream_id = t.root_id(); - const size_t doc_id = t.first_child(stream_id); - const size_t map_id = t.first_child(doc_id); - const size_t keyval_id = t.first_child(map_id); - const size_t seq_id = t.last_child(doc_id); - const size_t val_id = t.first_child(seq_id); - const size_t docval_id = t.last_child(stream_id); - ConstNodeRef stream = t.ref(stream_id); - ConstNodeRef doc = t.ref(doc_id); - ConstNodeRef map = t.ref(map_id); - ConstNodeRef keyval = t.ref(keyval_id); - ConstNodeRef seq = t.ref(seq_id); - ConstNodeRef val = t.ref(val_id); - ConstNodeRef docval = t.ref(docval_id); - NodeRef mstream = t.ref(stream_id); - NodeRef mdoc = t.ref(doc_id); - NodeRef mmap = t.ref(map_id); - NodeRef mkeyval = t.ref(keyval_id); - NodeRef mseq = t.ref(seq_id); - NodeRef mval = t.ref(val_id); - NodeRef mdocval = t.ref(docval_id); - EXPECT_FALSE(t.has_val(stream_id)); - EXPECT_FALSE(t.has_val(doc_id)); - EXPECT_FALSE(t.has_val(map_id)); - EXPECT_TRUE(t.has_val(keyval_id)); - EXPECT_FALSE(t.has_val(seq_id)); - EXPECT_TRUE(t.has_val(val_id)); - EXPECT_TRUE(t.has_val(docval_id)); - EXPECT_FALSE(stream.has_val()); - EXPECT_FALSE(doc.has_val()); - EXPECT_FALSE(map.has_val()); - EXPECT_TRUE(keyval.has_val()); - EXPECT_FALSE(seq.has_val()); - EXPECT_TRUE(val.has_val()); - EXPECT_TRUE(docval.has_val()); - EXPECT_FALSE(mstream.has_val()); - EXPECT_FALSE(mdoc.has_val()); - EXPECT_FALSE(mmap.has_val()); - EXPECT_TRUE(mkeyval.has_val()); - EXPECT_FALSE(mseq.has_val()); - EXPECT_TRUE(mval.has_val()); - EXPECT_TRUE(mdocval.has_val()); - EXPECT_EQ(t.has_val(stream_id), t._p(stream_id)->m_type.has_val()); - EXPECT_EQ(t.has_val(doc_id), t._p(doc_id)->m_type.has_val()); - EXPECT_EQ(t.has_val(map_id), t._p(map_id)->m_type.has_val()); - EXPECT_EQ(t.has_val(keyval_id), t._p(keyval_id)->m_type.has_val()); - EXPECT_EQ(t.has_val(seq_id), t._p(seq_id)->m_type.has_val()); - EXPECT_EQ(t.has_val(val_id), t._p(val_id)->m_type.has_val()); - EXPECT_EQ(t.has_val(docval_id), t._p(docval_id)->m_type.has_val()); - EXPECT_EQ(stream.has_val(), stream.get()->m_type.has_val()); - EXPECT_EQ(doc.has_val(), doc.get()->m_type.has_val()); - EXPECT_EQ(map.has_val(), map.get()->m_type.has_val()); - EXPECT_EQ(keyval.has_val(), keyval.get()->m_type.has_val()); - EXPECT_EQ(seq.has_val(), seq.get()->m_type.has_val()); - EXPECT_EQ(val.has_val(), val.get()->m_type.has_val()); - EXPECT_EQ(docval.has_val(), docval.get()->m_type.has_val()); - EXPECT_EQ(mstream.has_val(), mstream.get()->m_type.has_val()); - EXPECT_EQ(mdoc.has_val(), mdoc.get()->m_type.has_val()); - EXPECT_EQ(mmap.has_val(), mmap.get()->m_type.has_val()); - EXPECT_EQ(mkeyval.has_val(), mkeyval.get()->m_type.has_val()); - EXPECT_EQ(mseq.has_val(), mseq.get()->m_type.has_val()); - EXPECT_EQ(mval.has_val(), mval.get()->m_type.has_val()); - EXPECT_EQ(mdocval.has_val(), mdocval.get()->m_type.has_val()); -} - -TEST(NodeType, is_val) -{ - EXPECT_FALSE(NodeType(NOTYPE).is_val()); - EXPECT_FALSE(NodeType(KEY).is_val()); - EXPECT_TRUE(NodeType(VAL).is_val()); - EXPECT_TRUE(NodeType(DOCVAL).is_val()); - EXPECT_FALSE(NodeType(KEYVAL).is_val()); - EXPECT_FALSE(NodeType(KEYMAP).is_val()); - EXPECT_FALSE(NodeType(KEYSEQ).is_val()); -} - -TEST(Tree, is_val) -{ - Tree t = parse_in_arena(R"(--- -map: {foo: bar} -seq: [foo, bar] ---- -a scalar -...)"); - const size_t stream_id = t.root_id(); - const size_t doc_id = t.first_child(stream_id); - const size_t map_id = t.first_child(doc_id); - const size_t keyval_id = t.first_child(map_id); - const size_t seq_id = t.last_child(doc_id); - const size_t val_id = t.first_child(seq_id); - const size_t docval_id = t.last_child(stream_id); - ConstNodeRef stream = t.ref(stream_id); - ConstNodeRef doc = t.ref(doc_id); - ConstNodeRef map = t.ref(map_id); - ConstNodeRef keyval = t.ref(keyval_id); - ConstNodeRef seq = t.ref(seq_id); - ConstNodeRef val = t.ref(val_id); - ConstNodeRef docval = t.ref(docval_id); - NodeRef mstream = t.ref(stream_id); - NodeRef mdoc = t.ref(doc_id); - NodeRef mmap = t.ref(map_id); - NodeRef mkeyval = t.ref(keyval_id); - NodeRef mseq = t.ref(seq_id); - NodeRef mval = t.ref(val_id); - NodeRef mdocval = t.ref(docval_id); - EXPECT_FALSE(t.is_val(stream_id)); - EXPECT_FALSE(t.is_val(doc_id)); - EXPECT_FALSE(t.is_val(map_id)); - EXPECT_FALSE(t.is_val(keyval_id)); - EXPECT_FALSE(t.is_val(seq_id)); - EXPECT_TRUE(t.is_val(val_id)); - EXPECT_TRUE(t.is_val(docval_id)); - EXPECT_FALSE(stream.is_val()); - EXPECT_FALSE(doc.is_val()); - EXPECT_FALSE(map.is_val()); - EXPECT_FALSE(keyval.is_val()); - EXPECT_FALSE(seq.is_val()); - EXPECT_TRUE(val.is_val()); - EXPECT_TRUE(docval.is_val()); - EXPECT_FALSE(mstream.is_val()); - EXPECT_FALSE(mdoc.is_val()); - EXPECT_FALSE(mmap.is_val()); - EXPECT_FALSE(mkeyval.is_val()); - EXPECT_FALSE(mseq.is_val()); - EXPECT_TRUE(mval.is_val()); - EXPECT_TRUE(mdocval.is_val()); - EXPECT_EQ(t.is_val(stream_id), t._p(stream_id)->m_type.is_val()); - EXPECT_EQ(t.is_val(doc_id), t._p(doc_id)->m_type.is_val()); - EXPECT_EQ(t.is_val(map_id), t._p(map_id)->m_type.is_val()); - EXPECT_EQ(t.is_val(keyval_id), t._p(keyval_id)->m_type.is_val()); - EXPECT_EQ(t.is_val(seq_id), t._p(seq_id)->m_type.is_val()); - EXPECT_EQ(t.is_val(val_id), t._p(val_id)->m_type.is_val()); - EXPECT_EQ(t.is_val(docval_id), t._p(docval_id)->m_type.is_val()); - EXPECT_EQ(stream.is_val(), stream.get()->m_type.is_val()); - EXPECT_EQ(doc.is_val(), doc.get()->m_type.is_val()); - EXPECT_EQ(map.is_val(), map.get()->m_type.is_val()); - EXPECT_EQ(keyval.is_val(), keyval.get()->m_type.is_val()); - EXPECT_EQ(seq.is_val(), seq.get()->m_type.is_val()); - EXPECT_EQ(val.is_val(), val.get()->m_type.is_val()); - EXPECT_EQ(docval.is_val(), docval.get()->m_type.is_val()); - EXPECT_EQ(mstream.is_val(), mstream.get()->m_type.is_val()); - EXPECT_EQ(mdoc.is_val(), mdoc.get()->m_type.is_val()); - EXPECT_EQ(mmap.is_val(), mmap.get()->m_type.is_val()); - EXPECT_EQ(mkeyval.is_val(), mkeyval.get()->m_type.is_val()); - EXPECT_EQ(mseq.is_val(), mseq.get()->m_type.is_val()); - EXPECT_EQ(mval.is_val(), mval.get()->m_type.is_val()); - EXPECT_EQ(mdocval.is_val(), mdocval.get()->m_type.is_val()); -} - -TEST(NodeType, has_key) -{ - EXPECT_FALSE(NodeType(NOTYPE).has_key()); - EXPECT_TRUE(NodeType(KEY).has_key()); - EXPECT_FALSE(NodeType(VAL).has_key()); - EXPECT_TRUE(NodeType(KEYVAL).has_key()); - EXPECT_TRUE(NodeType(KEYMAP).has_key()); - EXPECT_TRUE(NodeType(KEYSEQ).has_key()); -} - -TEST(Tree, has_key) -{ - Tree t = parse_in_arena(R"(--- -map: {foo: bar} -seq: [foo, bar] ---- -a scalar -...)"); - const size_t stream_id = t.root_id(); - const size_t doc_id = t.first_child(stream_id); - const size_t map_id = t.first_child(doc_id); - const size_t keyval_id = t.first_child(map_id); - const size_t seq_id = t.last_child(doc_id); - const size_t val_id = t.first_child(seq_id); - const size_t docval_id = t.last_child(stream_id); - ConstNodeRef stream = t.ref(stream_id); - ConstNodeRef doc = t.ref(doc_id); - ConstNodeRef map = t.ref(map_id); - ConstNodeRef keyval = t.ref(keyval_id); - ConstNodeRef seq = t.ref(seq_id); - ConstNodeRef val = t.ref(val_id); - ConstNodeRef docval = t.ref(docval_id); - NodeRef mstream = t.ref(stream_id); - NodeRef mdoc = t.ref(doc_id); - NodeRef mmap = t.ref(map_id); - NodeRef mkeyval = t.ref(keyval_id); - NodeRef mseq = t.ref(seq_id); - NodeRef mval = t.ref(val_id); - NodeRef mdocval = t.ref(docval_id); - EXPECT_FALSE(t.has_key(stream_id)); - EXPECT_FALSE(t.has_key(doc_id)); - EXPECT_TRUE(t.has_key(map_id)); - EXPECT_TRUE(t.has_key(keyval_id)); - EXPECT_TRUE(t.has_key(seq_id)); - EXPECT_FALSE(t.has_key(val_id)); - EXPECT_FALSE(t.has_key(docval_id)); - EXPECT_FALSE(stream.has_key()); - EXPECT_FALSE(doc.has_key()); - EXPECT_TRUE(map.has_key()); - EXPECT_TRUE(keyval.has_key()); - EXPECT_TRUE(seq.has_key()); - EXPECT_FALSE(val.has_key()); - EXPECT_FALSE(docval.has_key()); - EXPECT_FALSE(mstream.has_key()); - EXPECT_FALSE(mdoc.has_key()); - EXPECT_TRUE(mmap.has_key()); - EXPECT_TRUE(mkeyval.has_key()); - EXPECT_TRUE(mseq.has_key()); - EXPECT_FALSE(mval.has_key()); - EXPECT_FALSE(mdocval.has_key()); - EXPECT_EQ(t.has_key(stream_id), t._p(stream_id)->m_type.has_key()); - EXPECT_EQ(t.has_key(doc_id), t._p(doc_id)->m_type.has_key()); - EXPECT_EQ(t.has_key(map_id), t._p(map_id)->m_type.has_key()); - EXPECT_EQ(t.has_key(keyval_id), t._p(keyval_id)->m_type.has_key()); - EXPECT_EQ(t.has_key(seq_id), t._p(seq_id)->m_type.has_key()); - EXPECT_EQ(t.has_key(val_id), t._p(val_id)->m_type.has_key()); - EXPECT_EQ(t.has_key(docval_id), t._p(docval_id)->m_type.has_key()); - EXPECT_EQ(stream.has_key(), stream.get()->m_type.has_key()); - EXPECT_EQ(doc.has_key(), doc.get()->m_type.has_key()); - EXPECT_EQ(map.has_key(), map.get()->m_type.has_key()); - EXPECT_EQ(keyval.has_key(), keyval.get()->m_type.has_key()); - EXPECT_EQ(seq.has_key(), seq.get()->m_type.has_key()); - EXPECT_EQ(val.has_key(), val.get()->m_type.has_key()); - EXPECT_EQ(docval.has_key(), docval.get()->m_type.has_key()); - EXPECT_EQ(mstream.has_key(), mstream.get()->m_type.has_key()); - EXPECT_EQ(mdoc.has_key(), mdoc.get()->m_type.has_key()); - EXPECT_EQ(mmap.has_key(), mmap.get()->m_type.has_key()); - EXPECT_EQ(mkeyval.has_key(), mkeyval.get()->m_type.has_key()); - EXPECT_EQ(mseq.has_key(), mseq.get()->m_type.has_key()); - EXPECT_EQ(mval.has_key(), mval.get()->m_type.has_key()); - EXPECT_EQ(mdocval.has_key(), mdocval.get()->m_type.has_key()); -} - -TEST(NodeType, is_keyval) -{ - EXPECT_FALSE(NodeType(NOTYPE).is_keyval()); - EXPECT_FALSE(NodeType(KEY).is_keyval()); - EXPECT_FALSE(NodeType(VAL).is_keyval()); - EXPECT_TRUE(NodeType(KEYVAL).is_keyval()); - EXPECT_FALSE(NodeType(DOCVAL).is_keyval()); - EXPECT_FALSE(NodeType(KEYMAP).is_keyval()); - EXPECT_FALSE(NodeType(KEYSEQ).is_keyval()); -} - -TEST(Tree, is_keyval) -{ - Tree t = parse_in_arena(R"(--- -map: {foo: bar} -seq: [foo, bar] ---- -a scalar -...)"); - const size_t stream_id = t.root_id(); - const size_t doc_id = t.first_child(stream_id); - const size_t map_id = t.first_child(doc_id); - const size_t keyval_id = t.first_child(map_id); - const size_t seq_id = t.last_child(doc_id); - const size_t val_id = t.first_child(seq_id); - const size_t docval_id = t.last_child(stream_id); - ConstNodeRef stream = t.ref(stream_id); - ConstNodeRef doc = t.ref(doc_id); - ConstNodeRef map = t.ref(map_id); - ConstNodeRef keyval = t.ref(keyval_id); - ConstNodeRef seq = t.ref(seq_id); - ConstNodeRef val = t.ref(val_id); - ConstNodeRef docval = t.ref(docval_id); - NodeRef mstream = t.ref(stream_id); - NodeRef mdoc = t.ref(doc_id); - NodeRef mmap = t.ref(map_id); - NodeRef mkeyval = t.ref(keyval_id); - NodeRef mseq = t.ref(seq_id); - NodeRef mval = t.ref(val_id); - NodeRef mdocval = t.ref(docval_id); - EXPECT_FALSE(t.is_keyval(stream_id)); - EXPECT_FALSE(t.is_keyval(doc_id)); - EXPECT_FALSE(t.is_keyval(map_id)); - EXPECT_TRUE(t.is_keyval(keyval_id)); - EXPECT_FALSE(t.is_keyval(seq_id)); - EXPECT_FALSE(t.is_keyval(val_id)); - EXPECT_FALSE(t.is_keyval(docval_id)); - EXPECT_FALSE(stream.is_keyval()); - EXPECT_FALSE(doc.is_keyval()); - EXPECT_FALSE(map.is_keyval()); - EXPECT_TRUE(keyval.is_keyval()); - EXPECT_FALSE(seq.is_keyval()); - EXPECT_FALSE(val.is_keyval()); - EXPECT_FALSE(docval.is_keyval()); - EXPECT_FALSE(mstream.is_keyval()); - EXPECT_FALSE(mdoc.is_keyval()); - EXPECT_FALSE(mmap.is_keyval()); - EXPECT_TRUE(mkeyval.is_keyval()); - EXPECT_FALSE(mseq.is_keyval()); - EXPECT_FALSE(mval.is_keyval()); - EXPECT_FALSE(mdocval.is_keyval()); - EXPECT_EQ(t.is_keyval(stream_id), t._p(stream_id)->m_type.is_keyval()); - EXPECT_EQ(t.is_keyval(doc_id), t._p(doc_id)->m_type.is_keyval()); - EXPECT_EQ(t.is_keyval(map_id), t._p(map_id)->m_type.is_keyval()); - EXPECT_EQ(t.is_keyval(keyval_id), t._p(keyval_id)->m_type.is_keyval()); - EXPECT_EQ(t.is_keyval(seq_id), t._p(seq_id)->m_type.is_keyval()); - EXPECT_EQ(t.is_keyval(val_id), t._p(val_id)->m_type.is_keyval()); - EXPECT_EQ(t.is_keyval(docval_id), t._p(docval_id)->m_type.is_keyval()); - EXPECT_EQ(stream.is_keyval(), stream.get()->m_type.is_keyval()); - EXPECT_EQ(doc.is_keyval(), doc.get()->m_type.is_keyval()); - EXPECT_EQ(map.is_keyval(), map.get()->m_type.is_keyval()); - EXPECT_EQ(keyval.is_keyval(), keyval.get()->m_type.is_keyval()); - EXPECT_EQ(seq.is_keyval(), seq.get()->m_type.is_keyval()); - EXPECT_EQ(val.is_keyval(), val.get()->m_type.is_keyval()); - EXPECT_EQ(docval.is_keyval(), docval.get()->m_type.is_keyval()); - EXPECT_EQ(mstream.is_keyval(), mstream.get()->m_type.is_keyval()); - EXPECT_EQ(mdoc.is_keyval(), mdoc.get()->m_type.is_keyval()); - EXPECT_EQ(mmap.is_keyval(), mmap.get()->m_type.is_keyval()); - EXPECT_EQ(mkeyval.is_keyval(), mkeyval.get()->m_type.is_keyval()); - EXPECT_EQ(mseq.is_keyval(), mseq.get()->m_type.is_keyval()); - EXPECT_EQ(mval.is_keyval(), mval.get()->m_type.is_keyval()); - EXPECT_EQ(mdocval.is_keyval(), mdocval.get()->m_type.is_keyval()); -} - -TEST(NodeType, has_key_tag) -{ - EXPECT_FALSE(NodeType().has_key_tag()); - EXPECT_FALSE(NodeType(KEYTAG).has_key_tag()); - EXPECT_TRUE(NodeType(KEY|KEYTAG).has_key_tag()); -} - -TEST(Tree, has_key_tag) -{ - Tree t = parse_in_arena(R"(--- !docmaptag -!maptag map: {!footag foo: bar, notag: none} -!seqtag seq: [!footag foo, bar] ---- -a scalar -...)"); - const size_t stream_id = t.root_id(); - const size_t doc_id = t.first_child(stream_id); - const size_t map_id = t.first_child(doc_id); - const size_t keyval_id = t.first_child(map_id); - const size_t keyvalnotag_id = t.last_child(map_id); - const size_t seq_id = t.last_child(doc_id); - const size_t val_id = t.first_child(seq_id); - const size_t valnotag_id = t.last_child(seq_id); - const size_t docval_id = t.last_child(stream_id); - ConstNodeRef stream = t.ref(stream_id); - ConstNodeRef doc = t.ref(doc_id); - ConstNodeRef map = t.ref(map_id); - ConstNodeRef keyval = t.ref(keyval_id); - ConstNodeRef keyvalnotag = t.ref(keyvalnotag_id); - ConstNodeRef seq = t.ref(seq_id); - ConstNodeRef val = t.ref(val_id); - ConstNodeRef valnotag = t.ref(val_id); - ConstNodeRef docval = t.ref(docval_id); - NodeRef mstream = t.ref(stream_id); - NodeRef mdoc = t.ref(doc_id); - NodeRef mmap = t.ref(map_id); - NodeRef mkeyval = t.ref(keyval_id); - NodeRef mkeyvalnotag = t.ref(keyvalnotag_id); - NodeRef mseq = t.ref(seq_id); - NodeRef mval = t.ref(val_id); - NodeRef mvalnotag = t.ref(val_id); - NodeRef mdocval = t.ref(docval_id); - EXPECT_FALSE(t.has_key_tag(stream_id)); - EXPECT_FALSE(t.has_key_tag(doc_id)); - EXPECT_TRUE(t.has_key_tag(map_id)); - EXPECT_TRUE(t.has_key_tag(keyval_id)); - EXPECT_FALSE(t.has_key_tag(keyvalnotag_id)); - EXPECT_TRUE(t.has_key_tag(seq_id)); - EXPECT_FALSE(t.has_key_tag(val_id)); - EXPECT_FALSE(t.has_key_tag(valnotag_id)); - EXPECT_FALSE(t.has_key_tag(docval_id)); - EXPECT_FALSE(stream.has_key_tag()); - EXPECT_FALSE(doc.has_key_tag()); - EXPECT_TRUE(map.has_key_tag()); - EXPECT_TRUE(keyval.has_key_tag()); - EXPECT_FALSE(keyvalnotag.has_key_tag()); - EXPECT_TRUE(seq.has_key_tag()); - EXPECT_FALSE(val.has_key_tag()); - EXPECT_FALSE(valnotag.has_key_tag()); - EXPECT_FALSE(docval.has_key_tag()); - EXPECT_FALSE(mstream.has_key_tag()); - EXPECT_FALSE(mdoc.has_key_tag()); - EXPECT_TRUE(mmap.has_key_tag()); - EXPECT_TRUE(mkeyval.has_key_tag()); - EXPECT_FALSE(mkeyvalnotag.has_key_tag()); - EXPECT_TRUE(mseq.has_key_tag()); - EXPECT_FALSE(mval.has_key_tag()); - EXPECT_FALSE(mvalnotag.has_key_tag()); - EXPECT_FALSE(mdocval.has_key_tag()); - EXPECT_EQ(t.has_key_tag(stream_id), t._p(stream_id)->m_type.has_key_tag()); - EXPECT_EQ(t.has_key_tag(doc_id), t._p(doc_id)->m_type.has_key_tag()); - EXPECT_EQ(t.has_key_tag(map_id), t._p(map_id)->m_type.has_key_tag()); - EXPECT_EQ(t.has_key_tag(keyval_id), t._p(keyval_id)->m_type.has_key_tag()); - EXPECT_EQ(t.has_key_tag(keyvalnotag_id), t._p(keyvalnotag_id)->m_type.has_key_tag()); - EXPECT_EQ(t.has_key_tag(seq_id), t._p(seq_id)->m_type.has_key_tag()); - EXPECT_EQ(t.has_key_tag(val_id), t._p(val_id)->m_type.has_key_tag()); - EXPECT_EQ(t.has_key_tag(valnotag_id), t._p(valnotag_id)->m_type.has_key_tag()); - EXPECT_EQ(t.has_key_tag(docval_id), t._p(docval_id)->m_type.has_key_tag()); - EXPECT_EQ(stream.has_key_tag(), stream.get()->m_type.has_key_tag()); - EXPECT_EQ(doc.has_key_tag(), doc.get()->m_type.has_key_tag()); - EXPECT_EQ(map.has_key_tag(), map.get()->m_type.has_key_tag()); - EXPECT_EQ(keyval.has_key_tag(), keyval.get()->m_type.has_key_tag()); - EXPECT_EQ(keyvalnotag.has_key_tag(), keyvalnotag.get()->m_type.has_key_tag()); - EXPECT_EQ(seq.has_key_tag(), seq.get()->m_type.has_key_tag()); - EXPECT_EQ(val.has_key_tag(), val.get()->m_type.has_key_tag()); - EXPECT_EQ(valnotag.has_key_tag(), valnotag.get()->m_type.has_key_tag()); - EXPECT_EQ(docval.has_key_tag(), docval.get()->m_type.has_key_tag()); - EXPECT_EQ(mstream.has_key_tag(), mstream.get()->m_type.has_key_tag()); - EXPECT_EQ(mdoc.has_key_tag(), mdoc.get()->m_type.has_key_tag()); - EXPECT_EQ(mmap.has_key_tag(), mmap.get()->m_type.has_key_tag()); - EXPECT_EQ(mkeyval.has_key_tag(), mkeyval.get()->m_type.has_key_tag()); - EXPECT_EQ(mkeyvalnotag.has_key_tag(), mkeyvalnotag.get()->m_type.has_key_tag()); - EXPECT_EQ(mseq.has_key_tag(), mseq.get()->m_type.has_key_tag()); - EXPECT_EQ(mval.has_key_tag(), mval.get()->m_type.has_key_tag()); - EXPECT_EQ(mvalnotag.has_key_tag(), mvalnotag.get()->m_type.has_key_tag()); - EXPECT_EQ(mdocval.has_key_tag(), mdocval.get()->m_type.has_key_tag()); -} - -TEST(NodeType, has_val_tag) -{ - EXPECT_FALSE(NodeType().has_val_tag()); - EXPECT_FALSE(NodeType(VALTAG).has_val_tag()); - EXPECT_TRUE(NodeType(VAL|VALTAG).has_val_tag()); -} - -TEST(Tree, has_val_tag) -{ - Tree t = parse_in_arena(R"(--- !docmaptag -map: !maptag {foo: !bartag bar, notag: none} -seq: !seqtag [!footag foo, bar] ---- -a scalar -...)"); - const size_t stream_id = t.root_id(); - const size_t doc_id = t.first_child(stream_id); - const size_t map_id = t.first_child(doc_id); - const size_t keyval_id = t.first_child(map_id); - const size_t keyvalnotag_id = t.last_child(map_id); - const size_t seq_id = t.last_child(doc_id); - const size_t val_id = t.first_child(seq_id); - const size_t valnotag_id = t.last_child(seq_id); - const size_t docval_id = t.last_child(stream_id); - ConstNodeRef stream = t.ref(stream_id); - ConstNodeRef doc = t.ref(doc_id); - ConstNodeRef map = t.ref(map_id); - ConstNodeRef keyval = t.ref(keyval_id); - ConstNodeRef keyvalnotag = t.ref(keyvalnotag_id); - ConstNodeRef seq = t.ref(seq_id); - ConstNodeRef val = t.ref(val_id); - ConstNodeRef valnotag = t.ref(valnotag_id); - ConstNodeRef docval = t.ref(docval_id); - NodeRef mstream = t.ref(stream_id); - NodeRef mdoc = t.ref(doc_id); - NodeRef mmap = t.ref(map_id); - NodeRef mkeyval = t.ref(keyval_id); - NodeRef mkeyvalnotag = t.ref(keyvalnotag_id); - NodeRef mseq = t.ref(seq_id); - NodeRef mval = t.ref(val_id); - NodeRef mvalnotag = t.ref(valnotag_id); - NodeRef mdocval = t.ref(docval_id); - EXPECT_FALSE(t.has_val_tag(stream_id)); - EXPECT_TRUE(t.has_val_tag(doc_id)); - EXPECT_TRUE(t.has_val_tag(map_id)); - EXPECT_TRUE(t.has_val_tag(keyval_id)); - EXPECT_FALSE(t.has_val_tag(keyvalnotag_id)); - EXPECT_TRUE(t.has_val_tag(seq_id)); - EXPECT_TRUE(t.has_val_tag(val_id)); - EXPECT_FALSE(t.has_val_tag(valnotag_id)); - EXPECT_FALSE(t.has_val_tag(docval_id)); - EXPECT_FALSE(stream.has_val_tag()); - EXPECT_TRUE(doc.has_val_tag()); - EXPECT_TRUE(map.has_val_tag()); - EXPECT_TRUE(keyval.has_val_tag()); - EXPECT_FALSE(keyvalnotag.has_val_tag()); - EXPECT_TRUE(seq.has_val_tag()); - EXPECT_TRUE(val.has_val_tag()); - EXPECT_FALSE(valnotag.has_val_tag()); - EXPECT_FALSE(docval.has_val_tag()); - EXPECT_FALSE(mstream.has_val_tag()); - EXPECT_TRUE(mdoc.has_val_tag()); - EXPECT_TRUE(mmap.has_val_tag()); - EXPECT_TRUE(mkeyval.has_val_tag()); - EXPECT_FALSE(mkeyvalnotag.has_val_tag()); - EXPECT_TRUE(mseq.has_val_tag()); - EXPECT_TRUE(mval.has_val_tag()); - EXPECT_FALSE(mvalnotag.has_val_tag()); - EXPECT_FALSE(mdocval.has_val_tag()); - EXPECT_EQ(t.has_val_tag(stream_id), t._p(stream_id)->m_type.has_val_tag()); - EXPECT_EQ(t.has_val_tag(doc_id), t._p(doc_id)->m_type.has_val_tag()); - EXPECT_EQ(t.has_val_tag(map_id), t._p(map_id)->m_type.has_val_tag()); - EXPECT_EQ(t.has_val_tag(keyval_id), t._p(keyval_id)->m_type.has_val_tag()); - EXPECT_EQ(t.has_val_tag(keyvalnotag_id), t._p(keyvalnotag_id)->m_type.has_val_tag()); - EXPECT_EQ(t.has_val_tag(seq_id), t._p(seq_id)->m_type.has_val_tag()); - EXPECT_EQ(t.has_val_tag(val_id), t._p(val_id)->m_type.has_val_tag()); - EXPECT_EQ(t.has_val_tag(valnotag_id), t._p(valnotag_id)->m_type.has_val_tag()); - EXPECT_EQ(t.has_val_tag(docval_id), t._p(docval_id)->m_type.has_val_tag()); - EXPECT_EQ(stream.has_val_tag(), stream.get()->m_type.has_val_tag()); - EXPECT_EQ(doc.has_val_tag(), doc.get()->m_type.has_val_tag()); - EXPECT_EQ(map.has_val_tag(), map.get()->m_type.has_val_tag()); - EXPECT_EQ(keyval.has_val_tag(), keyval.get()->m_type.has_val_tag()); - EXPECT_EQ(keyvalnotag.has_val_tag(), keyvalnotag.get()->m_type.has_val_tag()); - EXPECT_EQ(seq.has_val_tag(), seq.get()->m_type.has_val_tag()); - EXPECT_EQ(val.has_val_tag(), val.get()->m_type.has_val_tag()); - EXPECT_EQ(valnotag.has_val_tag(), valnotag.get()->m_type.has_val_tag()); - EXPECT_EQ(docval.has_val_tag(), docval.get()->m_type.has_val_tag()); - EXPECT_EQ(mstream.has_val_tag(), mstream.get()->m_type.has_val_tag()); - EXPECT_EQ(mdoc.has_val_tag(), mdoc.get()->m_type.has_val_tag()); - EXPECT_EQ(mmap.has_val_tag(), mmap.get()->m_type.has_val_tag()); - EXPECT_EQ(mkeyval.has_val_tag(), mkeyval.get()->m_type.has_val_tag()); - EXPECT_EQ(mkeyvalnotag.has_val_tag(), mkeyvalnotag.get()->m_type.has_val_tag()); - EXPECT_EQ(mseq.has_val_tag(), mseq.get()->m_type.has_val_tag()); - EXPECT_EQ(mval.has_val_tag(), mval.get()->m_type.has_val_tag()); - EXPECT_EQ(mvalnotag.has_val_tag(), mvalnotag.get()->m_type.has_val_tag()); - EXPECT_EQ(mdocval.has_val_tag(), mdocval.get()->m_type.has_val_tag()); -} - -TEST(NodeType, has_key_anchor) -{ - EXPECT_FALSE(NodeType().has_key_anchor()); - EXPECT_FALSE(NodeType(KEYANCH).has_key_anchor()); - EXPECT_TRUE(NodeType(KEY|KEYANCH).has_key_anchor()); -} - -TEST(Tree, has_key_anchor) -{ - Tree t = parse_in_arena(R"(--- &docanchor -&mapanchor map: {&keyvalanchor foo: bar, anchor: none} -&seqanchor seq: [&valanchor foo, bar] -...)"); - const size_t stream_id = t.root_id(); - const size_t doc_id = t.first_child(stream_id); - const size_t map_id = t.first_child(doc_id); - const size_t keyval_id = t.first_child(map_id); - const size_t keyvalnoanchor_id = t.last_child(map_id); - const size_t seq_id = t.last_child(doc_id); - const size_t val_id = t.first_child(seq_id); - const size_t valnoanchor_id = t.last_child(seq_id); - ConstNodeRef stream = t.ref(stream_id); - ConstNodeRef doc = t.ref(doc_id); - ConstNodeRef map = t.ref(map_id); - ConstNodeRef keyval = t.ref(keyval_id); - ConstNodeRef keyvalnoanchor = t.ref(keyvalnoanchor_id); - ConstNodeRef seq = t.ref(seq_id); - ConstNodeRef val = t.ref(val_id); - ConstNodeRef valnoanchor = t.ref(valnoanchor_id); - NodeRef mstream = t.ref(stream_id); - NodeRef mdoc = t.ref(doc_id); - NodeRef mmap = t.ref(map_id); - NodeRef mkeyval = t.ref(keyval_id); - NodeRef mkeyvalnoanchor = t.ref(keyvalnoanchor_id); - NodeRef mseq = t.ref(seq_id); - NodeRef mval = t.ref(val_id); - NodeRef mvalnoanchor = t.ref(valnoanchor_id); - EXPECT_FALSE(t.has_key_anchor(stream_id)); - EXPECT_FALSE(t.has_key_anchor(doc_id)); - EXPECT_TRUE(t.has_key_anchor(map_id)); - EXPECT_TRUE(t.has_key_anchor(keyval_id)); - EXPECT_FALSE(t.has_key_anchor(keyvalnoanchor_id)); - EXPECT_TRUE(t.has_key_anchor(seq_id)); - EXPECT_FALSE(t.has_key_anchor(val_id)); - EXPECT_FALSE(t.has_key_anchor(valnoanchor_id)); - EXPECT_FALSE(stream.has_key_anchor()); - EXPECT_FALSE(doc.has_key_anchor()); - EXPECT_TRUE(map.has_key_anchor()); - EXPECT_TRUE(keyval.has_key_anchor()); - EXPECT_FALSE(keyvalnoanchor.has_key_anchor()); - EXPECT_TRUE(seq.has_key_anchor()); - EXPECT_FALSE(val.has_key_anchor()); - EXPECT_FALSE(valnoanchor.has_key_anchor()); - EXPECT_FALSE(mstream.has_key_anchor()); - EXPECT_FALSE(mdoc.has_key_anchor()); - EXPECT_TRUE(mmap.has_key_anchor()); - EXPECT_TRUE(mkeyval.has_key_anchor()); - EXPECT_FALSE(mkeyvalnoanchor.has_key_anchor()); - EXPECT_TRUE(mseq.has_key_anchor()); - EXPECT_FALSE(mval.has_key_anchor()); - EXPECT_FALSE(mvalnoanchor.has_key_anchor()); - EXPECT_EQ(t.has_key_anchor(stream_id), t._p(stream_id)->m_type.has_key_anchor()); - EXPECT_EQ(t.has_key_anchor(doc_id), t._p(doc_id)->m_type.has_key_anchor()); - EXPECT_EQ(t.has_key_anchor(map_id), t._p(map_id)->m_type.has_key_anchor()); - EXPECT_EQ(t.has_key_anchor(keyval_id), t._p(keyval_id)->m_type.has_key_anchor()); - EXPECT_EQ(t.has_key_anchor(keyvalnoanchor_id), t._p(keyvalnoanchor_id)->m_type.has_key_anchor()); - EXPECT_EQ(t.has_key_anchor(seq_id), t._p(seq_id)->m_type.has_key_anchor()); - EXPECT_EQ(t.has_key_anchor(val_id), t._p(val_id)->m_type.has_key_anchor()); - EXPECT_EQ(t.has_key_anchor(valnoanchor_id), t._p(valnoanchor_id)->m_type.has_key_anchor()); - EXPECT_EQ(stream.has_key_anchor(), stream.get()->m_type.has_key_anchor()); - EXPECT_EQ(doc.has_key_anchor(), doc.get()->m_type.has_key_anchor()); - EXPECT_EQ(map.has_key_anchor(), map.get()->m_type.has_key_anchor()); - EXPECT_EQ(keyval.has_key_anchor(), keyval.get()->m_type.has_key_anchor()); - EXPECT_EQ(keyvalnoanchor.has_key_anchor(), keyvalnoanchor.get()->m_type.has_key_anchor()); - EXPECT_EQ(seq.has_key_anchor(), seq.get()->m_type.has_key_anchor()); - EXPECT_EQ(val.has_key_anchor(), val.get()->m_type.has_key_anchor()); - EXPECT_EQ(valnoanchor.has_key_anchor(), valnoanchor.get()->m_type.has_key_anchor()); - EXPECT_EQ(mstream.has_key_anchor(), mstream.get()->m_type.has_key_anchor()); - EXPECT_EQ(mdoc.has_key_anchor(), mdoc.get()->m_type.has_key_anchor()); - EXPECT_EQ(mmap.has_key_anchor(), mmap.get()->m_type.has_key_anchor()); - EXPECT_EQ(mkeyval.has_key_anchor(), mkeyval.get()->m_type.has_key_anchor()); - EXPECT_EQ(mkeyvalnoanchor.has_key_anchor(), mkeyvalnoanchor.get()->m_type.has_key_anchor()); - EXPECT_EQ(mseq.has_key_anchor(), mseq.get()->m_type.has_key_anchor()); - EXPECT_EQ(mval.has_key_anchor(), mval.get()->m_type.has_key_anchor()); - EXPECT_EQ(mvalnoanchor.has_key_anchor(), mvalnoanchor.get()->m_type.has_key_anchor()); -} - -TEST(NodeType, is_key_anchor) -{ - EXPECT_FALSE(NodeType().is_key_anchor()); - EXPECT_FALSE(NodeType(KEYANCH).is_key_anchor()); - EXPECT_TRUE(NodeType(KEY|KEYANCH).is_key_anchor()); -} - -TEST(Tree, is_key_anchor) -{ - Tree t = parse_in_arena(R"(--- &docanchor -&mapanchor map: {&keyvalanchor foo: bar, anchor: none} -&seqanchor seq: [&valanchor foo, bar] -...)"); - const size_t stream_id = t.root_id(); - const size_t doc_id = t.first_child(stream_id); - const size_t map_id = t.first_child(doc_id); - const size_t keyval_id = t.first_child(map_id); - const size_t keyvalnoanchor_id = t.last_child(map_id); - const size_t seq_id = t.last_child(doc_id); - const size_t val_id = t.first_child(seq_id); - const size_t valnoanchor_id = t.last_child(seq_id); - ConstNodeRef stream = t.ref(stream_id); - ConstNodeRef doc = t.ref(doc_id); - ConstNodeRef map = t.ref(map_id); - ConstNodeRef keyval = t.ref(keyval_id); - ConstNodeRef keyvalnoanchor = t.ref(keyvalnoanchor_id); - ConstNodeRef seq = t.ref(seq_id); - ConstNodeRef val = t.ref(val_id); - ConstNodeRef valnoanchor = t.ref(valnoanchor_id); - NodeRef mstream = t.ref(stream_id); - NodeRef mdoc = t.ref(doc_id); - NodeRef mmap = t.ref(map_id); - NodeRef mkeyval = t.ref(keyval_id); - NodeRef mkeyvalnoanchor = t.ref(keyvalnoanchor_id); - NodeRef mseq = t.ref(seq_id); - NodeRef mval = t.ref(val_id); - NodeRef mvalnoanchor = t.ref(valnoanchor_id); - EXPECT_FALSE(t.is_key_anchor(stream_id)); - EXPECT_FALSE(t.is_key_anchor(doc_id)); - EXPECT_TRUE(t.is_key_anchor(map_id)); - EXPECT_TRUE(t.is_key_anchor(keyval_id)); - EXPECT_FALSE(t.is_key_anchor(keyvalnoanchor_id)); - EXPECT_TRUE(t.is_key_anchor(seq_id)); - EXPECT_FALSE(t.is_key_anchor(val_id)); - EXPECT_FALSE(t.is_key_anchor(valnoanchor_id)); - EXPECT_FALSE(stream.is_key_anchor()); - EXPECT_FALSE(doc.is_key_anchor()); - EXPECT_TRUE(map.is_key_anchor()); - EXPECT_TRUE(keyval.is_key_anchor()); - EXPECT_FALSE(keyvalnoanchor.is_key_anchor()); - EXPECT_TRUE(seq.is_key_anchor()); - EXPECT_FALSE(val.is_key_anchor()); - EXPECT_FALSE(valnoanchor.is_key_anchor()); - EXPECT_FALSE(mstream.is_key_anchor()); - EXPECT_FALSE(mdoc.is_key_anchor()); - EXPECT_TRUE(mmap.is_key_anchor()); - EXPECT_TRUE(mkeyval.is_key_anchor()); - EXPECT_FALSE(mkeyvalnoanchor.is_key_anchor()); - EXPECT_TRUE(mseq.is_key_anchor()); - EXPECT_FALSE(mval.is_key_anchor()); - EXPECT_FALSE(mvalnoanchor.is_key_anchor()); - EXPECT_EQ(t.is_key_anchor(stream_id), t._p(stream_id)->m_type.is_key_anchor()); - EXPECT_EQ(t.is_key_anchor(doc_id), t._p(doc_id)->m_type.is_key_anchor()); - EXPECT_EQ(t.is_key_anchor(map_id), t._p(map_id)->m_type.is_key_anchor()); - EXPECT_EQ(t.is_key_anchor(keyval_id), t._p(keyval_id)->m_type.is_key_anchor()); - EXPECT_EQ(t.is_key_anchor(keyvalnoanchor_id), t._p(keyvalnoanchor_id)->m_type.is_key_anchor()); - EXPECT_EQ(t.is_key_anchor(seq_id), t._p(seq_id)->m_type.is_key_anchor()); - EXPECT_EQ(t.is_key_anchor(val_id), t._p(val_id)->m_type.is_key_anchor()); - EXPECT_EQ(t.is_key_anchor(valnoanchor_id), t._p(valnoanchor_id)->m_type.is_key_anchor()); - EXPECT_EQ(stream.is_key_anchor(), stream.get()->m_type.is_key_anchor()); - EXPECT_EQ(doc.is_key_anchor(), doc.get()->m_type.is_key_anchor()); - EXPECT_EQ(map.is_key_anchor(), map.get()->m_type.is_key_anchor()); - EXPECT_EQ(keyval.is_key_anchor(), keyval.get()->m_type.is_key_anchor()); - EXPECT_EQ(keyvalnoanchor.is_key_anchor(), keyvalnoanchor.get()->m_type.is_key_anchor()); - EXPECT_EQ(seq.is_key_anchor(), seq.get()->m_type.is_key_anchor()); - EXPECT_EQ(val.is_key_anchor(), val.get()->m_type.is_key_anchor()); - EXPECT_EQ(valnoanchor.is_key_anchor(), valnoanchor.get()->m_type.is_key_anchor()); - EXPECT_EQ(mstream.is_key_anchor(), mstream.get()->m_type.is_key_anchor()); - EXPECT_EQ(mdoc.is_key_anchor(), mdoc.get()->m_type.is_key_anchor()); - EXPECT_EQ(mmap.is_key_anchor(), mmap.get()->m_type.is_key_anchor()); - EXPECT_EQ(mkeyval.is_key_anchor(), mkeyval.get()->m_type.is_key_anchor()); - EXPECT_EQ(mkeyvalnoanchor.is_key_anchor(), mkeyvalnoanchor.get()->m_type.is_key_anchor()); - EXPECT_EQ(mseq.is_key_anchor(), mseq.get()->m_type.is_key_anchor()); - EXPECT_EQ(mval.is_key_anchor(), mval.get()->m_type.is_key_anchor()); - EXPECT_EQ(mvalnoanchor.is_key_anchor(), mvalnoanchor.get()->m_type.is_key_anchor()); -} - -TEST(NodeType, has_val_anchor) -{ - EXPECT_FALSE(NodeType().has_val_anchor()); - EXPECT_FALSE(NodeType(VALANCH).has_val_anchor()); - EXPECT_TRUE(NodeType(VAL|VALANCH).has_val_anchor()); -} - -TEST(Tree, has_val_anchor) -{ - Tree t = parse_in_arena(R"(--- &docanchor -map: &mapanchor {foo: &keyvalanchor bar, anchor: none} -seq: &seqanchor [&valanchor foo, bar] -...)"); - const size_t stream_id = t.root_id(); - const size_t doc_id = t.first_child(stream_id); - const size_t map_id = t.first_child(doc_id); - const size_t keyval_id = t.first_child(map_id); - const size_t keyvalnoanchor_id = t.last_child(map_id); - const size_t seq_id = t.last_child(doc_id); - const size_t val_id = t.first_child(seq_id); - const size_t valnoanchor_id = t.last_child(seq_id); - ConstNodeRef stream = t.ref(stream_id); - ConstNodeRef doc = t.ref(doc_id); - ConstNodeRef map = t.ref(map_id); - ConstNodeRef keyval = t.ref(keyval_id); - ConstNodeRef keyvalnoanchor = t.ref(keyvalnoanchor_id); - ConstNodeRef seq = t.ref(seq_id); - ConstNodeRef val = t.ref(val_id); - ConstNodeRef valnoanchor = t.ref(valnoanchor_id); - NodeRef mstream = t.ref(stream_id); - NodeRef mdoc = t.ref(doc_id); - NodeRef mmap = t.ref(map_id); - NodeRef mkeyval = t.ref(keyval_id); - NodeRef mkeyvalnoanchor = t.ref(keyvalnoanchor_id); - NodeRef mseq = t.ref(seq_id); - NodeRef mval = t.ref(val_id); - NodeRef mvalnoanchor = t.ref(valnoanchor_id); - EXPECT_FALSE(t.has_val_anchor(stream_id)); - EXPECT_FALSE(t.has_val_anchor(doc_id)); - EXPECT_TRUE(t.has_val_anchor(map_id)); - EXPECT_TRUE(t.has_val_anchor(keyval_id)); - EXPECT_FALSE(t.has_val_anchor(keyvalnoanchor_id)); - EXPECT_TRUE(t.has_val_anchor(seq_id)); - EXPECT_TRUE(t.has_val_anchor(val_id)); - EXPECT_FALSE(t.has_val_anchor(valnoanchor_id)); - EXPECT_FALSE(stream.has_val_anchor()); - EXPECT_FALSE(doc.has_val_anchor()); - EXPECT_TRUE(map.has_val_anchor()); - EXPECT_TRUE(keyval.has_val_anchor()); - EXPECT_FALSE(keyvalnoanchor.has_val_anchor()); - EXPECT_TRUE(seq.has_val_anchor()); - EXPECT_TRUE(val.has_val_anchor()); - EXPECT_FALSE(valnoanchor.has_val_anchor()); - EXPECT_FALSE(mstream.has_val_anchor()); - EXPECT_FALSE(mdoc.has_val_anchor()); - EXPECT_TRUE(mmap.has_val_anchor()); - EXPECT_TRUE(mkeyval.has_val_anchor()); - EXPECT_FALSE(mkeyvalnoanchor.has_val_anchor()); - EXPECT_TRUE(mseq.has_val_anchor()); - EXPECT_TRUE(mval.has_val_anchor()); - EXPECT_FALSE(mvalnoanchor.has_val_anchor()); - EXPECT_EQ(t.has_val_anchor(stream_id), t._p(stream_id)->m_type.has_val_anchor()); - EXPECT_EQ(t.has_val_anchor(doc_id), t._p(doc_id)->m_type.has_val_anchor()); - EXPECT_EQ(t.has_val_anchor(map_id), t._p(map_id)->m_type.has_val_anchor()); - EXPECT_EQ(t.has_val_anchor(keyval_id), t._p(keyval_id)->m_type.has_val_anchor()); - EXPECT_EQ(t.has_val_anchor(keyvalnoanchor_id), t._p(keyvalnoanchor_id)->m_type.has_val_anchor()); - EXPECT_EQ(t.has_val_anchor(seq_id), t._p(seq_id)->m_type.has_val_anchor()); - EXPECT_EQ(t.has_val_anchor(val_id), t._p(val_id)->m_type.has_val_anchor()); - EXPECT_EQ(t.has_val_anchor(valnoanchor_id), t._p(valnoanchor_id)->m_type.has_val_anchor()); - EXPECT_EQ(stream.has_val_anchor(), stream.get()->m_type.has_val_anchor()); - EXPECT_EQ(doc.has_val_anchor(), doc.get()->m_type.has_val_anchor()); - EXPECT_EQ(map.has_val_anchor(), map.get()->m_type.has_val_anchor()); - EXPECT_EQ(keyval.has_val_anchor(), keyval.get()->m_type.has_val_anchor()); - EXPECT_EQ(keyvalnoanchor.has_val_anchor(), keyvalnoanchor.get()->m_type.has_val_anchor()); - EXPECT_EQ(seq.has_val_anchor(), seq.get()->m_type.has_val_anchor()); - EXPECT_EQ(val.has_val_anchor(), val.get()->m_type.has_val_anchor()); - EXPECT_EQ(valnoanchor.has_val_anchor(), valnoanchor.get()->m_type.has_val_anchor()); - EXPECT_EQ(mstream.has_val_anchor(), mstream.get()->m_type.has_val_anchor()); - EXPECT_EQ(mdoc.has_val_anchor(), mdoc.get()->m_type.has_val_anchor()); - EXPECT_EQ(mmap.has_val_anchor(), mmap.get()->m_type.has_val_anchor()); - EXPECT_EQ(mkeyval.has_val_anchor(), mkeyval.get()->m_type.has_val_anchor()); - EXPECT_EQ(mkeyvalnoanchor.has_val_anchor(), mkeyvalnoanchor.get()->m_type.has_val_anchor()); - EXPECT_EQ(mseq.has_val_anchor(), mseq.get()->m_type.has_val_anchor()); - EXPECT_EQ(mval.has_val_anchor(), mval.get()->m_type.has_val_anchor()); - EXPECT_EQ(mvalnoanchor.has_val_anchor(), mvalnoanchor.get()->m_type.has_val_anchor()); -} - -TEST(NodeType, is_val_anchor) -{ - EXPECT_FALSE(NodeType().is_val_anchor()); - EXPECT_FALSE(NodeType(VALANCH).is_val_anchor()); - EXPECT_TRUE(NodeType(VAL|VALANCH).is_val_anchor()); -} - -TEST(Tree, is_val_anchor) -{ - Tree t = parse_in_arena(R"(--- &docanchor -map: &mapanchor {foo: &keyvalanchor bar, anchor: none} -seq: &seqanchor [&valanchor foo, bar] -...)"); - const size_t stream_id = t.root_id(); - const size_t doc_id = t.first_child(stream_id); - const size_t map_id = t.first_child(doc_id); - const size_t keyval_id = t.first_child(map_id); - const size_t keyvalnoanchor_id = t.last_child(map_id); - const size_t seq_id = t.last_child(doc_id); - const size_t val_id = t.first_child(seq_id); - const size_t valnoanchor_id = t.last_child(seq_id); - ConstNodeRef stream = t.ref(stream_id); - ConstNodeRef doc = t.ref(doc_id); - ConstNodeRef map = t.ref(map_id); - ConstNodeRef keyval = t.ref(keyval_id); - ConstNodeRef keyvalnoanchor = t.ref(keyvalnoanchor_id); - ConstNodeRef seq = t.ref(seq_id); - ConstNodeRef val = t.ref(val_id); - ConstNodeRef valnoanchor = t.ref(valnoanchor_id); - NodeRef mstream = t.ref(stream_id); - NodeRef mdoc = t.ref(doc_id); - NodeRef mmap = t.ref(map_id); - NodeRef mkeyval = t.ref(keyval_id); - NodeRef mkeyvalnoanchor = t.ref(keyvalnoanchor_id); - NodeRef mseq = t.ref(seq_id); - NodeRef mval = t.ref(val_id); - NodeRef mvalnoanchor = t.ref(valnoanchor_id); - EXPECT_FALSE(t.is_val_anchor(stream_id)); - EXPECT_FALSE(t.is_val_anchor(doc_id)); - EXPECT_TRUE(t.is_val_anchor(map_id)); - EXPECT_TRUE(t.is_val_anchor(keyval_id)); - EXPECT_FALSE(t.is_val_anchor(keyvalnoanchor_id)); - EXPECT_TRUE(t.is_val_anchor(seq_id)); - EXPECT_TRUE(t.is_val_anchor(val_id)); - EXPECT_FALSE(t.is_val_anchor(valnoanchor_id)); - EXPECT_FALSE(stream.is_val_anchor()); - EXPECT_FALSE(doc.is_val_anchor()); - EXPECT_TRUE(map.is_val_anchor()); - EXPECT_TRUE(keyval.is_val_anchor()); - EXPECT_FALSE(keyvalnoanchor.is_val_anchor()); - EXPECT_TRUE(seq.is_val_anchor()); - EXPECT_TRUE(val.is_val_anchor()); - EXPECT_FALSE(valnoanchor.is_val_anchor()); - EXPECT_FALSE(mstream.is_val_anchor()); - EXPECT_FALSE(mdoc.is_val_anchor()); - EXPECT_TRUE(mmap.is_val_anchor()); - EXPECT_TRUE(mkeyval.is_val_anchor()); - EXPECT_FALSE(mkeyvalnoanchor.is_val_anchor()); - EXPECT_TRUE(mseq.is_val_anchor()); - EXPECT_TRUE(mval.is_val_anchor()); - EXPECT_FALSE(mvalnoanchor.is_val_anchor()); - EXPECT_EQ(t.is_val_anchor(stream_id), t._p(stream_id)->m_type.is_val_anchor()); - EXPECT_EQ(t.is_val_anchor(doc_id), t._p(doc_id)->m_type.is_val_anchor()); - EXPECT_EQ(t.is_val_anchor(map_id), t._p(map_id)->m_type.is_val_anchor()); - EXPECT_EQ(t.is_val_anchor(keyval_id), t._p(keyval_id)->m_type.is_val_anchor()); - EXPECT_EQ(t.is_val_anchor(keyvalnoanchor_id), t._p(keyvalnoanchor_id)->m_type.is_val_anchor()); - EXPECT_EQ(t.is_val_anchor(seq_id), t._p(seq_id)->m_type.is_val_anchor()); - EXPECT_EQ(t.is_val_anchor(val_id), t._p(val_id)->m_type.is_val_anchor()); - EXPECT_EQ(t.is_val_anchor(valnoanchor_id), t._p(valnoanchor_id)->m_type.is_val_anchor()); - EXPECT_EQ(stream.is_val_anchor(), stream.get()->m_type.is_val_anchor()); - EXPECT_EQ(doc.is_val_anchor(), doc.get()->m_type.is_val_anchor()); - EXPECT_EQ(map.is_val_anchor(), map.get()->m_type.is_val_anchor()); - EXPECT_EQ(keyval.is_val_anchor(), keyval.get()->m_type.is_val_anchor()); - EXPECT_EQ(keyvalnoanchor.is_val_anchor(), keyvalnoanchor.get()->m_type.is_val_anchor()); - EXPECT_EQ(seq.is_val_anchor(), seq.get()->m_type.is_val_anchor()); - EXPECT_EQ(val.is_val_anchor(), val.get()->m_type.is_val_anchor()); - EXPECT_EQ(valnoanchor.is_val_anchor(), valnoanchor.get()->m_type.is_val_anchor()); - EXPECT_EQ(mstream.is_val_anchor(), mstream.get()->m_type.is_val_anchor()); - EXPECT_EQ(mdoc.is_val_anchor(), mdoc.get()->m_type.is_val_anchor()); - EXPECT_EQ(mmap.is_val_anchor(), mmap.get()->m_type.is_val_anchor()); - EXPECT_EQ(mkeyval.is_val_anchor(), mkeyval.get()->m_type.is_val_anchor()); - EXPECT_EQ(mkeyvalnoanchor.is_val_anchor(), mkeyvalnoanchor.get()->m_type.is_val_anchor()); - EXPECT_EQ(mseq.is_val_anchor(), mseq.get()->m_type.is_val_anchor()); - EXPECT_EQ(mval.is_val_anchor(), mval.get()->m_type.is_val_anchor()); - EXPECT_EQ(mvalnoanchor.is_val_anchor(), mvalnoanchor.get()->m_type.is_val_anchor()); -} - -TEST(NodeType, has_anchor) -{ - EXPECT_FALSE(NodeType().has_anchor()); - EXPECT_TRUE(NodeType(VALANCH).has_anchor()); - EXPECT_TRUE(NodeType(KEYANCH).has_anchor()); - EXPECT_TRUE(NodeType(KEYANCH|VALANCH).has_anchor()); - EXPECT_TRUE(NodeType(KEY|VALANCH).has_anchor()); - EXPECT_TRUE(NodeType(VAL|KEYANCH).has_anchor()); - EXPECT_TRUE(NodeType(KEY|KEYANCH).has_anchor()); - EXPECT_TRUE(NodeType(VAL|VALANCH).has_anchor()); -} - -TEST(Tree, has_anchor) -{ - Tree t = parse_in_arena(R"(--- &docanchor -map: &mapanchor {foo: &keyvalanchor bar, anchor: none} -&seqanchor seq: [&valanchor foo, bar] -...)"); - const size_t stream_id = t.root_id(); - const size_t doc_id = t.first_child(stream_id); - const size_t map_id = t.first_child(doc_id); - const size_t keyval_id = t.first_child(map_id); - const size_t keyvalnoanchor_id = t.last_child(map_id); - const size_t seq_id = t.last_child(doc_id); - const size_t val_id = t.first_child(seq_id); - const size_t valnoanchor_id = t.last_child(seq_id); - ConstNodeRef stream = t.ref(stream_id); - ConstNodeRef doc = t.ref(doc_id); - ConstNodeRef map = t.ref(map_id); - ConstNodeRef keyval = t.ref(keyval_id); - ConstNodeRef keyvalnoanchor = t.ref(keyvalnoanchor_id); - ConstNodeRef seq = t.ref(seq_id); - ConstNodeRef val = t.ref(val_id); - ConstNodeRef valnoanchor = t.ref(valnoanchor_id); - NodeRef mstream = t.ref(stream_id); - NodeRef mdoc = t.ref(doc_id); - NodeRef mmap = t.ref(map_id); - NodeRef mkeyval = t.ref(keyval_id); - NodeRef mkeyvalnoanchor = t.ref(keyvalnoanchor_id); - NodeRef mseq = t.ref(seq_id); - NodeRef mval = t.ref(val_id); - NodeRef mvalnoanchor = t.ref(valnoanchor_id); - EXPECT_FALSE(t.has_anchor(stream_id)); - EXPECT_FALSE(t.has_anchor(doc_id)); - EXPECT_TRUE(t.has_anchor(map_id)); - EXPECT_TRUE(t.has_anchor(keyval_id)); - EXPECT_FALSE(t.has_anchor(keyvalnoanchor_id)); - EXPECT_TRUE(t.has_anchor(seq_id)); - EXPECT_TRUE(t.has_anchor(val_id)); - EXPECT_FALSE(t.has_anchor(valnoanchor_id)); - EXPECT_FALSE(stream.has_anchor()); - EXPECT_FALSE(doc.has_anchor()); - EXPECT_TRUE(map.has_anchor()); - EXPECT_TRUE(keyval.has_anchor()); - EXPECT_FALSE(keyvalnoanchor.has_anchor()); - EXPECT_TRUE(seq.has_anchor()); - EXPECT_TRUE(val.has_anchor()); - EXPECT_FALSE(valnoanchor.has_anchor()); - EXPECT_FALSE(mstream.has_anchor()); - EXPECT_FALSE(mdoc.has_anchor()); - EXPECT_TRUE(mmap.has_anchor()); - EXPECT_TRUE(mkeyval.has_anchor()); - EXPECT_FALSE(mkeyvalnoanchor.has_anchor()); - EXPECT_TRUE(mseq.has_anchor()); - EXPECT_TRUE(mval.has_anchor()); - EXPECT_FALSE(mvalnoanchor.has_anchor()); - EXPECT_EQ(t.has_anchor(stream_id), t._p(stream_id)->m_type.has_anchor()); - EXPECT_EQ(t.has_anchor(doc_id), t._p(doc_id)->m_type.has_anchor()); - EXPECT_EQ(t.has_anchor(map_id), t._p(map_id)->m_type.has_anchor()); - EXPECT_EQ(t.has_anchor(keyval_id), t._p(keyval_id)->m_type.has_anchor()); - EXPECT_EQ(t.has_anchor(keyvalnoanchor_id), t._p(keyvalnoanchor_id)->m_type.has_anchor()); - EXPECT_EQ(t.has_anchor(seq_id), t._p(seq_id)->m_type.has_anchor()); - EXPECT_EQ(t.has_anchor(val_id), t._p(val_id)->m_type.has_anchor()); - EXPECT_EQ(t.has_anchor(valnoanchor_id), t._p(valnoanchor_id)->m_type.has_anchor()); - EXPECT_EQ(stream.has_anchor(), stream.get()->m_type.has_anchor()); - EXPECT_EQ(doc.has_anchor(), doc.get()->m_type.has_anchor()); - EXPECT_EQ(map.has_anchor(), map.get()->m_type.has_anchor()); - EXPECT_EQ(keyval.has_anchor(), keyval.get()->m_type.has_anchor()); - EXPECT_EQ(keyvalnoanchor.has_anchor(), keyvalnoanchor.get()->m_type.has_anchor()); - EXPECT_EQ(seq.has_anchor(), seq.get()->m_type.has_anchor()); - EXPECT_EQ(val.has_anchor(), val.get()->m_type.has_anchor()); - EXPECT_EQ(valnoanchor.has_anchor(), valnoanchor.get()->m_type.has_anchor()); - EXPECT_EQ(mstream.has_anchor(), mstream.get()->m_type.has_anchor()); - EXPECT_EQ(mdoc.has_anchor(), mdoc.get()->m_type.has_anchor()); - EXPECT_EQ(mmap.has_anchor(), mmap.get()->m_type.has_anchor()); - EXPECT_EQ(mkeyval.has_anchor(), mkeyval.get()->m_type.has_anchor()); - EXPECT_EQ(mkeyvalnoanchor.has_anchor(), mkeyvalnoanchor.get()->m_type.has_anchor()); - EXPECT_EQ(mseq.has_anchor(), mseq.get()->m_type.has_anchor()); - EXPECT_EQ(mval.has_anchor(), mval.get()->m_type.has_anchor()); - EXPECT_EQ(mvalnoanchor.has_anchor(), mvalnoanchor.get()->m_type.has_anchor()); -} - -TEST(NodeType, is_anchor) -{ - EXPECT_FALSE(NodeType().is_anchor()); - EXPECT_TRUE(NodeType(VALANCH).is_anchor()); - EXPECT_TRUE(NodeType(KEYANCH).is_anchor()); - EXPECT_TRUE(NodeType(KEYANCH|VALANCH).is_anchor()); - EXPECT_TRUE(NodeType(KEY|VALANCH).is_anchor()); - EXPECT_TRUE(NodeType(VAL|KEYANCH).is_anchor()); - EXPECT_TRUE(NodeType(KEY|KEYANCH).is_anchor()); - EXPECT_TRUE(NodeType(VAL|VALANCH).is_anchor()); -} - -TEST(Tree, is_anchor) -{ - Tree t = parse_in_arena(R"(--- &docanchor -map: &mapanchor {foo: &keyvalanchor bar, anchor: none} -&seqanchor seq: [&valanchor foo, bar] -...)"); - const size_t stream_id = t.root_id(); - const size_t doc_id = t.first_child(stream_id); - const size_t map_id = t.first_child(doc_id); - const size_t keyval_id = t.first_child(map_id); - const size_t keyvalnoanchor_id = t.last_child(map_id); - const size_t seq_id = t.last_child(doc_id); - const size_t val_id = t.first_child(seq_id); - const size_t valnoanchor_id = t.last_child(seq_id); - ConstNodeRef stream = t.ref(stream_id); - ConstNodeRef doc = t.ref(doc_id); - ConstNodeRef map = t.ref(map_id); - ConstNodeRef keyval = t.ref(keyval_id); - ConstNodeRef keyvalnoanchor = t.ref(keyvalnoanchor_id); - ConstNodeRef seq = t.ref(seq_id); - ConstNodeRef val = t.ref(val_id); - ConstNodeRef valnoanchor = t.ref(valnoanchor_id); - NodeRef mstream = t.ref(stream_id); - NodeRef mdoc = t.ref(doc_id); - NodeRef mmap = t.ref(map_id); - NodeRef mkeyval = t.ref(keyval_id); - NodeRef mkeyvalnoanchor = t.ref(keyvalnoanchor_id); - NodeRef mseq = t.ref(seq_id); - NodeRef mval = t.ref(val_id); - NodeRef mvalnoanchor = t.ref(valnoanchor_id); - EXPECT_FALSE(t.is_anchor(stream_id)); - EXPECT_FALSE(t.is_anchor(doc_id)); - EXPECT_TRUE(t.is_anchor(map_id)); - EXPECT_TRUE(t.is_anchor(keyval_id)); - EXPECT_FALSE(t.is_anchor(keyvalnoanchor_id)); - EXPECT_TRUE(t.is_anchor(seq_id)); - EXPECT_TRUE(t.is_anchor(val_id)); - EXPECT_FALSE(t.is_anchor(valnoanchor_id)); - EXPECT_FALSE(stream.is_anchor()); - EXPECT_FALSE(doc.is_anchor()); - EXPECT_TRUE(map.is_anchor()); - EXPECT_TRUE(keyval.is_anchor()); - EXPECT_FALSE(keyvalnoanchor.is_anchor()); - EXPECT_TRUE(seq.is_anchor()); - EXPECT_TRUE(val.is_anchor()); - EXPECT_FALSE(valnoanchor.is_anchor()); - EXPECT_FALSE(mstream.is_anchor()); - EXPECT_FALSE(mdoc.is_anchor()); - EXPECT_TRUE(mmap.is_anchor()); - EXPECT_TRUE(mkeyval.is_anchor()); - EXPECT_FALSE(mkeyvalnoanchor.is_anchor()); - EXPECT_TRUE(mseq.is_anchor()); - EXPECT_TRUE(mval.is_anchor()); - EXPECT_FALSE(mvalnoanchor.is_anchor()); - EXPECT_EQ(t.is_anchor(stream_id), t._p(stream_id)->m_type.is_anchor()); - EXPECT_EQ(t.is_anchor(doc_id), t._p(doc_id)->m_type.is_anchor()); - EXPECT_EQ(t.is_anchor(map_id), t._p(map_id)->m_type.is_anchor()); - EXPECT_EQ(t.is_anchor(keyval_id), t._p(keyval_id)->m_type.is_anchor()); - EXPECT_EQ(t.is_anchor(keyvalnoanchor_id), t._p(keyvalnoanchor_id)->m_type.is_anchor()); - EXPECT_EQ(t.is_anchor(seq_id), t._p(seq_id)->m_type.is_anchor()); - EXPECT_EQ(t.is_anchor(val_id), t._p(val_id)->m_type.is_anchor()); - EXPECT_EQ(t.is_anchor(valnoanchor_id), t._p(valnoanchor_id)->m_type.is_anchor()); - EXPECT_EQ(stream.is_anchor(), stream.get()->m_type.is_anchor()); - EXPECT_EQ(doc.is_anchor(), doc.get()->m_type.is_anchor()); - EXPECT_EQ(map.is_anchor(), map.get()->m_type.is_anchor()); - EXPECT_EQ(keyval.is_anchor(), keyval.get()->m_type.is_anchor()); - EXPECT_EQ(keyvalnoanchor.is_anchor(), keyvalnoanchor.get()->m_type.is_anchor()); - EXPECT_EQ(seq.is_anchor(), seq.get()->m_type.is_anchor()); - EXPECT_EQ(val.is_anchor(), val.get()->m_type.is_anchor()); - EXPECT_EQ(valnoanchor.is_anchor(), valnoanchor.get()->m_type.is_anchor()); - EXPECT_EQ(mstream.is_anchor(), mstream.get()->m_type.is_anchor()); - EXPECT_EQ(mdoc.is_anchor(), mdoc.get()->m_type.is_anchor()); - EXPECT_EQ(mmap.is_anchor(), mmap.get()->m_type.is_anchor()); - EXPECT_EQ(mkeyval.is_anchor(), mkeyval.get()->m_type.is_anchor()); - EXPECT_EQ(mkeyvalnoanchor.is_anchor(), mkeyvalnoanchor.get()->m_type.is_anchor()); - EXPECT_EQ(mseq.is_anchor(), mseq.get()->m_type.is_anchor()); - EXPECT_EQ(mval.is_anchor(), mval.get()->m_type.is_anchor()); - EXPECT_EQ(mvalnoanchor.is_anchor(), mvalnoanchor.get()->m_type.is_anchor()); -} - -TEST(NodeType, is_key_ref) -{ - EXPECT_FALSE(NodeType().is_key_ref()); - EXPECT_TRUE(NodeType(KEYREF).is_key_ref()); - EXPECT_TRUE(NodeType(KEY|KEYREF).is_key_ref()); -} - -TEST(Tree, is_key_ref) -{ - Tree t = parse_in_arena(R"(--- -*mapref: {foo: bar, notag: none} -*seqref: [foo, bar] -...)"); - const size_t stream_id = t.root_id(); - const size_t doc_id = t.first_child(stream_id); - const size_t map_id = t.first_child(doc_id); - const size_t keyval_id = t.first_child(map_id); - const size_t seq_id = t.last_child(doc_id); - const size_t val_id = t.first_child(seq_id); - ConstNodeRef stream = t.ref(stream_id); - ConstNodeRef doc = t.ref(doc_id); - ConstNodeRef map = t.ref(map_id); - ConstNodeRef keyval = t.ref(keyval_id); - ConstNodeRef seq = t.ref(seq_id); - ConstNodeRef val = t.ref(val_id); - NodeRef mstream = t.ref(stream_id); - NodeRef mdoc = t.ref(doc_id); - NodeRef mmap = t.ref(map_id); - NodeRef mkeyval = t.ref(keyval_id); - NodeRef mseq = t.ref(seq_id); - NodeRef mval = t.ref(val_id); - EXPECT_FALSE(t.is_key_ref(stream_id)); - EXPECT_FALSE(t.is_key_ref(doc_id)); - EXPECT_TRUE(t.is_key_ref(map_id)); - EXPECT_FALSE(t.is_key_ref(keyval_id)); - EXPECT_TRUE(t.is_key_ref(seq_id)); - EXPECT_FALSE(t.is_key_ref(val_id)); - EXPECT_FALSE(stream.is_key_ref()); - EXPECT_FALSE(doc.is_key_ref()); - EXPECT_TRUE(map.is_key_ref()); - EXPECT_FALSE(keyval.is_key_ref()); - EXPECT_TRUE(seq.is_key_ref()); - EXPECT_FALSE(val.is_key_ref()); - EXPECT_FALSE(mstream.is_key_ref()); - EXPECT_FALSE(mdoc.is_key_ref()); - EXPECT_TRUE(mmap.is_key_ref()); - EXPECT_FALSE(mkeyval.is_key_ref()); - EXPECT_TRUE(mseq.is_key_ref()); - EXPECT_FALSE(mval.is_key_ref()); - EXPECT_EQ(t.is_key_ref(stream_id), t._p(stream_id)->m_type.is_key_ref()); - EXPECT_EQ(t.is_key_ref(doc_id), t._p(doc_id)->m_type.is_key_ref()); - EXPECT_EQ(t.is_key_ref(map_id), t._p(map_id)->m_type.is_key_ref()); - EXPECT_EQ(t.is_key_ref(keyval_id), t._p(keyval_id)->m_type.is_key_ref()); - EXPECT_EQ(t.is_key_ref(seq_id), t._p(seq_id)->m_type.is_key_ref()); - EXPECT_EQ(t.is_key_ref(val_id), t._p(val_id)->m_type.is_key_ref()); - EXPECT_EQ(stream.is_key_ref(), stream.get()->m_type.is_key_ref()); - EXPECT_EQ(doc.is_key_ref(), doc.get()->m_type.is_key_ref()); - EXPECT_EQ(map.is_key_ref(), map.get()->m_type.is_key_ref()); - EXPECT_EQ(keyval.is_key_ref(), keyval.get()->m_type.is_key_ref()); - EXPECT_EQ(seq.is_key_ref(), seq.get()->m_type.is_key_ref()); - EXPECT_EQ(val.is_key_ref(), val.get()->m_type.is_key_ref()); - EXPECT_EQ(mstream.is_key_ref(), mstream.get()->m_type.is_key_ref()); - EXPECT_EQ(mdoc.is_key_ref(), mdoc.get()->m_type.is_key_ref()); - EXPECT_EQ(mmap.is_key_ref(), mmap.get()->m_type.is_key_ref()); - EXPECT_EQ(mkeyval.is_key_ref(), mkeyval.get()->m_type.is_key_ref()); - EXPECT_EQ(mseq.is_key_ref(), mseq.get()->m_type.is_key_ref()); - EXPECT_EQ(mval.is_key_ref(), mval.get()->m_type.is_key_ref()); -} - -TEST(NodeType, is_val_ref) -{ - EXPECT_FALSE(NodeType().is_val_ref()); - EXPECT_TRUE(NodeType(VALREF).is_val_ref()); - EXPECT_TRUE(NodeType(VAL|VALREF).is_val_ref()); -} - -TEST(Tree, is_val_ref) -{ - Tree t = parse_in_arena(R"(--- -map: {foo: *keyvalref, notag: none} -seq: [*valref, bar] -...)"); - const size_t stream_id = t.root_id(); - const size_t doc_id = t.first_child(stream_id); - const size_t map_id = t.first_child(doc_id); - const size_t keyval_id = t.first_child(map_id); - const size_t seq_id = t.last_child(doc_id); - const size_t val_id = t.first_child(seq_id); - ConstNodeRef stream = t.ref(stream_id); - ConstNodeRef doc = t.ref(doc_id); - ConstNodeRef map = t.ref(map_id); - ConstNodeRef keyval = t.ref(keyval_id); - ConstNodeRef seq = t.ref(seq_id); - ConstNodeRef val = t.ref(val_id); - NodeRef mstream = t.ref(stream_id); - NodeRef mdoc = t.ref(doc_id); - NodeRef mmap = t.ref(map_id); - NodeRef mkeyval = t.ref(keyval_id); - NodeRef mseq = t.ref(seq_id); - NodeRef mval = t.ref(val_id); - EXPECT_FALSE(t.is_val_ref(stream_id)); - EXPECT_FALSE(t.is_val_ref(doc_id)); - EXPECT_FALSE(t.is_val_ref(map_id)); - EXPECT_TRUE(t.is_val_ref(keyval_id)); - EXPECT_FALSE(t.is_val_ref(seq_id)); - EXPECT_TRUE(t.is_val_ref(val_id)); - EXPECT_FALSE(stream.is_val_ref()); - EXPECT_FALSE(doc.is_val_ref()); - EXPECT_FALSE(map.is_val_ref()); - EXPECT_TRUE(keyval.is_val_ref()); - EXPECT_FALSE(seq.is_val_ref()); - EXPECT_TRUE(val.is_val_ref()); - EXPECT_FALSE(mstream.is_val_ref()); - EXPECT_FALSE(mdoc.is_val_ref()); - EXPECT_FALSE(mmap.is_val_ref()); - EXPECT_TRUE(mkeyval.is_val_ref()); - EXPECT_FALSE(mseq.is_val_ref()); - EXPECT_TRUE(mval.is_val_ref()); - EXPECT_EQ(t.is_val_ref(stream_id), t._p(stream_id)->m_type.is_val_ref()); - EXPECT_EQ(t.is_val_ref(doc_id), t._p(doc_id)->m_type.is_val_ref()); - EXPECT_EQ(t.is_val_ref(map_id), t._p(map_id)->m_type.is_val_ref()); - EXPECT_EQ(t.is_val_ref(keyval_id), t._p(keyval_id)->m_type.is_val_ref()); - EXPECT_EQ(t.is_val_ref(seq_id), t._p(seq_id)->m_type.is_val_ref()); - EXPECT_EQ(t.is_val_ref(val_id), t._p(val_id)->m_type.is_val_ref()); - EXPECT_EQ(stream.is_val_ref(), stream.get()->m_type.is_val_ref()); - EXPECT_EQ(doc.is_val_ref(), doc.get()->m_type.is_val_ref()); - EXPECT_EQ(map.is_val_ref(), map.get()->m_type.is_val_ref()); - EXPECT_EQ(keyval.is_val_ref(), keyval.get()->m_type.is_val_ref()); - EXPECT_EQ(seq.is_val_ref(), seq.get()->m_type.is_val_ref()); - EXPECT_EQ(val.is_val_ref(), val.get()->m_type.is_val_ref()); - EXPECT_EQ(mstream.is_val_ref(), mstream.get()->m_type.is_val_ref()); - EXPECT_EQ(mdoc.is_val_ref(), mdoc.get()->m_type.is_val_ref()); - EXPECT_EQ(mmap.is_val_ref(), mmap.get()->m_type.is_val_ref()); - EXPECT_EQ(mkeyval.is_val_ref(), mkeyval.get()->m_type.is_val_ref()); - EXPECT_EQ(mseq.is_val_ref(), mseq.get()->m_type.is_val_ref()); - EXPECT_EQ(mval.is_val_ref(), mval.get()->m_type.is_val_ref()); -} - -TEST(NodeType, is_ref) -{ - EXPECT_FALSE(NodeType().is_ref()); - EXPECT_FALSE(NodeType(KEYVAL).is_ref()); - EXPECT_TRUE(NodeType(KEYREF).is_ref()); - EXPECT_TRUE(NodeType(VALREF).is_ref()); - EXPECT_TRUE(NodeType(KEY|VALREF).is_ref()); - EXPECT_TRUE(NodeType(VAL|KEYREF).is_ref()); - EXPECT_TRUE(NodeType(KEYREF|VALREF).is_ref()); -} - -TEST(Tree, is_ref) -{ - Tree t = parse_in_arena(R"(--- -map: {foo: *keyvalref, notag: none} -seq: [*valref, bar] -...)"); - const size_t stream_id = t.root_id(); - const size_t doc_id = t.first_child(stream_id); - const size_t map_id = t.first_child(doc_id); - const size_t keyval_id = t.first_child(map_id); - const size_t seq_id = t.last_child(doc_id); - const size_t val_id = t.first_child(seq_id); - ConstNodeRef stream = t.ref(stream_id); - ConstNodeRef doc = t.ref(doc_id); - ConstNodeRef map = t.ref(map_id); - ConstNodeRef keyval = t.ref(keyval_id); - ConstNodeRef seq = t.ref(seq_id); - ConstNodeRef val = t.ref(val_id); - NodeRef mstream = t.ref(stream_id); - NodeRef mdoc = t.ref(doc_id); - NodeRef mmap = t.ref(map_id); - NodeRef mkeyval = t.ref(keyval_id); - NodeRef mseq = t.ref(seq_id); - NodeRef mval = t.ref(val_id); - EXPECT_FALSE(t.is_ref(stream_id)); - EXPECT_FALSE(t.is_ref(doc_id)); - EXPECT_FALSE(t.is_ref(map_id)); - EXPECT_TRUE(t.is_ref(keyval_id)); - EXPECT_FALSE(t.is_ref(seq_id)); - EXPECT_TRUE(t.is_ref(val_id)); - EXPECT_FALSE(stream.is_ref()); - EXPECT_FALSE(doc.is_ref()); - EXPECT_FALSE(map.is_ref()); - EXPECT_TRUE(keyval.is_ref()); - EXPECT_FALSE(seq.is_ref()); - EXPECT_TRUE(val.is_ref()); - EXPECT_FALSE(mstream.is_ref()); - EXPECT_FALSE(mdoc.is_ref()); - EXPECT_FALSE(mmap.is_ref()); - EXPECT_TRUE(mkeyval.is_ref()); - EXPECT_FALSE(mseq.is_ref()); - EXPECT_TRUE(mval.is_ref()); - EXPECT_EQ(t.is_ref(stream_id), t._p(stream_id)->m_type.is_ref()); - EXPECT_EQ(t.is_ref(doc_id), t._p(doc_id)->m_type.is_ref()); - EXPECT_EQ(t.is_ref(map_id), t._p(map_id)->m_type.is_ref()); - EXPECT_EQ(t.is_ref(keyval_id), t._p(keyval_id)->m_type.is_ref()); - EXPECT_EQ(t.is_ref(seq_id), t._p(seq_id)->m_type.is_ref()); - EXPECT_EQ(t.is_ref(val_id), t._p(val_id)->m_type.is_ref()); - EXPECT_EQ(stream.is_ref(), stream.get()->m_type.is_ref()); - EXPECT_EQ(doc.is_ref(), doc.get()->m_type.is_ref()); - EXPECT_EQ(map.is_ref(), map.get()->m_type.is_ref()); - EXPECT_EQ(keyval.is_ref(), keyval.get()->m_type.is_ref()); - EXPECT_EQ(seq.is_ref(), seq.get()->m_type.is_ref()); - EXPECT_EQ(val.is_ref(), val.get()->m_type.is_ref()); - EXPECT_EQ(mstream.is_ref(), mstream.get()->m_type.is_ref()); - EXPECT_EQ(mdoc.is_ref(), mdoc.get()->m_type.is_ref()); - EXPECT_EQ(mmap.is_ref(), mmap.get()->m_type.is_ref()); - EXPECT_EQ(mkeyval.is_ref(), mkeyval.get()->m_type.is_ref()); - EXPECT_EQ(mseq.is_ref(), mseq.get()->m_type.is_ref()); - EXPECT_EQ(mval.is_ref(), mval.get()->m_type.is_ref()); -} - -TEST(NodeType, is_anchor_or_ref) -{ - EXPECT_FALSE(NodeType().is_anchor_or_ref()); - EXPECT_FALSE(NodeType(KEYVAL).is_anchor_or_ref()); - EXPECT_TRUE(NodeType(KEYREF).is_anchor_or_ref()); - EXPECT_TRUE(NodeType(KEYANCH).is_anchor_or_ref()); - EXPECT_TRUE(NodeType(VALREF).is_anchor_or_ref()); - EXPECT_TRUE(NodeType(VALANCH).is_anchor_or_ref()); - EXPECT_TRUE(NodeType(KEY|VALREF).is_anchor_or_ref()); - EXPECT_TRUE(NodeType(KEY|VALANCH).is_anchor_or_ref()); - EXPECT_TRUE(NodeType(VAL|KEYREF).is_anchor_or_ref()); - EXPECT_TRUE(NodeType(VAL|VALANCH).is_anchor_or_ref()); - EXPECT_TRUE(NodeType(KEY|VALANCH).is_anchor_or_ref()); - EXPECT_TRUE(NodeType(KEYREF|VALREF).is_anchor_or_ref()); - EXPECT_TRUE(NodeType(KEYANCH|VALANCH).is_anchor_or_ref()); -} - -TEST(Tree, is_anchor_or_ref) -{ - Tree t = parse_in_arena(R"(--- -&map map: {foo: *keyvalref, notag: none} -seq: &seq [*valref, bar] -...)"); - const size_t stream_id = t.root_id(); - const size_t doc_id = t.first_child(stream_id); - const size_t map_id = t.first_child(doc_id); - const size_t keyval_id = t.first_child(map_id); - const size_t seq_id = t.last_child(doc_id); - const size_t val_id = t.first_child(seq_id); - ConstNodeRef stream = t.ref(stream_id); - ConstNodeRef doc = t.ref(doc_id); - ConstNodeRef map = t.ref(map_id); - ConstNodeRef keyval = t.ref(keyval_id); - ConstNodeRef seq = t.ref(seq_id); - ConstNodeRef val = t.ref(val_id); - NodeRef mstream = t.ref(stream_id); - NodeRef mdoc = t.ref(doc_id); - NodeRef mmap = t.ref(map_id); - NodeRef mkeyval = t.ref(keyval_id); - NodeRef mseq = t.ref(seq_id); - NodeRef mval = t.ref(val_id); - EXPECT_FALSE(t.is_anchor_or_ref(stream_id)); - EXPECT_FALSE(t.is_anchor_or_ref(doc_id)); - EXPECT_TRUE(t.is_anchor_or_ref(map_id)); - EXPECT_TRUE(t.is_anchor_or_ref(keyval_id)); - EXPECT_TRUE(t.is_anchor_or_ref(seq_id)); - EXPECT_TRUE(t.is_anchor_or_ref(val_id)); - EXPECT_FALSE(stream.is_anchor_or_ref()); - EXPECT_FALSE(doc.is_anchor_or_ref()); - EXPECT_TRUE(map.is_anchor_or_ref()); - EXPECT_TRUE(keyval.is_anchor_or_ref()); - EXPECT_TRUE(seq.is_anchor_or_ref()); - EXPECT_TRUE(val.is_anchor_or_ref()); - EXPECT_FALSE(mstream.is_anchor_or_ref()); - EXPECT_FALSE(mdoc.is_anchor_or_ref()); - EXPECT_TRUE(mmap.is_anchor_or_ref()); - EXPECT_TRUE(mkeyval.is_anchor_or_ref()); - EXPECT_TRUE(mseq.is_anchor_or_ref()); - EXPECT_TRUE(mval.is_anchor_or_ref()); - EXPECT_EQ(t.is_anchor_or_ref(stream_id), t._p(stream_id)->m_type.is_anchor_or_ref()); - EXPECT_EQ(t.is_anchor_or_ref(doc_id), t._p(doc_id)->m_type.is_anchor_or_ref()); - EXPECT_EQ(t.is_anchor_or_ref(map_id), t._p(map_id)->m_type.is_anchor_or_ref()); - EXPECT_EQ(t.is_anchor_or_ref(keyval_id), t._p(keyval_id)->m_type.is_anchor_or_ref()); - EXPECT_EQ(t.is_anchor_or_ref(seq_id), t._p(seq_id)->m_type.is_anchor_or_ref()); - EXPECT_EQ(t.is_anchor_or_ref(val_id), t._p(val_id)->m_type.is_anchor_or_ref()); - EXPECT_EQ(stream.is_anchor_or_ref(), stream.get()->m_type.is_anchor_or_ref()); - EXPECT_EQ(doc.is_anchor_or_ref(), doc.get()->m_type.is_anchor_or_ref()); - EXPECT_EQ(map.is_anchor_or_ref(), map.get()->m_type.is_anchor_or_ref()); - EXPECT_EQ(keyval.is_anchor_or_ref(), keyval.get()->m_type.is_anchor_or_ref()); - EXPECT_EQ(seq.is_anchor_or_ref(), seq.get()->m_type.is_anchor_or_ref()); - EXPECT_EQ(val.is_anchor_or_ref(), val.get()->m_type.is_anchor_or_ref()); - EXPECT_EQ(mstream.is_anchor_or_ref(), mstream.get()->m_type.is_anchor_or_ref()); - EXPECT_EQ(mdoc.is_anchor_or_ref(), mdoc.get()->m_type.is_anchor_or_ref()); - EXPECT_EQ(mmap.is_anchor_or_ref(), mmap.get()->m_type.is_anchor_or_ref()); - EXPECT_EQ(mkeyval.is_anchor_or_ref(), mkeyval.get()->m_type.is_anchor_or_ref()); - EXPECT_EQ(mseq.is_anchor_or_ref(), mseq.get()->m_type.is_anchor_or_ref()); - EXPECT_EQ(mval.is_anchor_or_ref(), mval.get()->m_type.is_anchor_or_ref()); -} - -TEST(NodeType, is_key_quoted) -{ - EXPECT_FALSE(NodeType().is_key_quoted()); - EXPECT_FALSE(NodeType(KEYQUO).is_key_quoted()); - EXPECT_TRUE(NodeType(KEY|KEYQUO).is_key_quoted()); -} - -TEST(Tree, is_key_quoted) -{ - Tree t = parse_in_arena(R"(--- -"quoted": foo -notquoted: bar -...)"); - const size_t map_id = t.first_child(t.root_id()); - const size_t quoted_id = t.first_child(map_id); - const size_t notquoted_id = t.last_child(map_id); - ConstNodeRef map = t.ref(map_id); - ConstNodeRef quoted = t.ref(quoted_id); - ConstNodeRef notquoted = t.ref(notquoted_id); - NodeRef mmap = t.ref(map_id); - NodeRef mquoted = t.ref(quoted_id); - NodeRef mnotquoted = t.ref(notquoted_id); - EXPECT_FALSE(t.is_key_quoted(map_id)); - EXPECT_TRUE(t.is_key_quoted(quoted_id)); - EXPECT_FALSE(t.is_key_quoted(notquoted_id)); - EXPECT_FALSE(map.is_key_quoted()); - EXPECT_TRUE(quoted.is_key_quoted()); - EXPECT_FALSE(notquoted.is_key_quoted()); - EXPECT_FALSE(mmap.is_key_quoted()); - EXPECT_TRUE(mquoted.is_key_quoted()); - EXPECT_FALSE(mnotquoted.is_key_quoted()); - EXPECT_EQ(t.is_key_quoted(map_id), t._p(map_id)->m_type.is_key_quoted()); - EXPECT_EQ(t.is_key_quoted(quoted_id), t._p(quoted_id)->m_type.is_key_quoted()); - EXPECT_EQ(t.is_key_quoted(notquoted_id), t._p(notquoted_id)->m_type.is_key_quoted()); - EXPECT_EQ(map.is_key_quoted(), map.get()->m_type.is_key_quoted()); - EXPECT_EQ(quoted.is_key_quoted(), quoted.get()->m_type.is_key_quoted()); - EXPECT_EQ(notquoted.is_key_quoted(), notquoted.get()->m_type.is_key_quoted()); - EXPECT_EQ(mmap.is_key_quoted(), mmap.get()->m_type.is_key_quoted()); - EXPECT_EQ(mquoted.is_key_quoted(), mquoted.get()->m_type.is_key_quoted()); - EXPECT_EQ(mnotquoted.is_key_quoted(), mnotquoted.get()->m_type.is_key_quoted()); -} - -TEST(NodeType, is_val_quoted) -{ - EXPECT_FALSE(NodeType().is_val_quoted()); - EXPECT_FALSE(NodeType(VALQUO).is_val_quoted()); - EXPECT_TRUE(NodeType(VAL|VALQUO).is_val_quoted()); -} - -TEST(Tree, is_val_quoted) -{ - Tree t = parse_in_arena(R"(--- -"quoted": "foo" -notquoted: bar -...)"); - const size_t map_id = t.first_child(t.root_id()); - const size_t quoted_id = t.first_child(map_id); - const size_t notquoted_id = t.last_child(map_id); - ConstNodeRef map = t.ref(map_id); - ConstNodeRef quoted = t.ref(quoted_id); - ConstNodeRef notquoted = t.ref(notquoted_id); - NodeRef mmap = t.ref(map_id); - NodeRef mquoted = t.ref(quoted_id); - NodeRef mnotquoted = t.ref(notquoted_id); - EXPECT_FALSE(t.is_val_quoted(map_id)); - EXPECT_TRUE(t.is_val_quoted(quoted_id)); - EXPECT_FALSE(t.is_val_quoted(notquoted_id)); - EXPECT_FALSE(map.is_val_quoted()); - EXPECT_TRUE(quoted.is_val_quoted()); - EXPECT_FALSE(notquoted.is_val_quoted()); - EXPECT_FALSE(mmap.is_val_quoted()); - EXPECT_TRUE(mquoted.is_val_quoted()); - EXPECT_FALSE(mnotquoted.is_val_quoted()); - EXPECT_EQ(t.is_val_quoted(map_id), t._p(map_id)->m_type.is_val_quoted()); - EXPECT_EQ(t.is_val_quoted(quoted_id), t._p(quoted_id)->m_type.is_val_quoted()); - EXPECT_EQ(t.is_val_quoted(notquoted_id), t._p(notquoted_id)->m_type.is_val_quoted()); - EXPECT_EQ(map.is_val_quoted(), map.get()->m_type.is_val_quoted()); - EXPECT_EQ(quoted.is_val_quoted(), quoted.get()->m_type.is_val_quoted()); - EXPECT_EQ(notquoted.is_val_quoted(), notquoted.get()->m_type.is_val_quoted()); - EXPECT_EQ(mmap.is_val_quoted(), mmap.get()->m_type.is_val_quoted()); - EXPECT_EQ(mquoted.is_val_quoted(), mquoted.get()->m_type.is_val_quoted()); - EXPECT_EQ(mnotquoted.is_val_quoted(), mnotquoted.get()->m_type.is_val_quoted()); -} - -TEST(NodeType, is_quoted) -{ - EXPECT_FALSE(NodeType().is_quoted()); - EXPECT_FALSE(NodeType(KEYQUO).is_quoted()); - EXPECT_FALSE(NodeType(VALQUO).is_quoted()); - EXPECT_FALSE(NodeType(KEYQUO|VALQUO).is_quoted()); - EXPECT_TRUE(NodeType(KEY|KEYQUO).is_quoted()); - EXPECT_TRUE(NodeType(VAL|VALQUO).is_quoted()); - EXPECT_FALSE(NodeType(KEY|VALQUO).is_quoted()); - EXPECT_FALSE(NodeType(VAL|KEYQUO).is_quoted()); -} - -TEST(Tree, is_quoted) -{ - Tree t = parse_in_arena(R"(--- -"quoted1": foo -quoted2: "foo" -"quoted3": "foo" -'quoted4': foo -quoted5: 'foo' -'quoted6': 'foo' -notquoted: bar -...)"); - const size_t map_id = t.first_child(t.root_id()); - const size_t quoted1_id = t.find_child(map_id, "quoted1"); - const size_t quoted2_id = t.find_child(map_id, "quoted2"); - const size_t quoted3_id = t.find_child(map_id, "quoted3"); - const size_t quoted4_id = t.find_child(map_id, "quoted4"); - const size_t quoted5_id = t.find_child(map_id, "quoted5"); - const size_t quoted6_id = t.find_child(map_id, "quoted6"); - const size_t notquoted_id = t.last_child(map_id); - ConstNodeRef map = t.ref(map_id); - ConstNodeRef quoted1 = t.ref(quoted1_id); - ConstNodeRef quoted2 = t.ref(quoted2_id); - ConstNodeRef quoted3 = t.ref(quoted3_id); - ConstNodeRef quoted4 = t.ref(quoted4_id); - ConstNodeRef quoted5 = t.ref(quoted5_id); - ConstNodeRef quoted6 = t.ref(quoted6_id); - ConstNodeRef notquoted = t.ref(notquoted_id); - NodeRef mmap = t.ref(map_id); - NodeRef mquoted1 = t.ref(quoted1_id); - NodeRef mquoted2 = t.ref(quoted2_id); - NodeRef mquoted3 = t.ref(quoted3_id); - NodeRef mquoted4 = t.ref(quoted4_id); - NodeRef mquoted5 = t.ref(quoted5_id); - NodeRef mquoted6 = t.ref(quoted6_id); - NodeRef mnotquoted = t.ref(notquoted_id); - EXPECT_FALSE(t.is_quoted(map_id)); - EXPECT_TRUE(t.is_quoted(quoted1_id)); - EXPECT_TRUE(t.is_quoted(quoted2_id)); - EXPECT_TRUE(t.is_quoted(quoted3_id)); - EXPECT_TRUE(t.is_quoted(quoted4_id)); - EXPECT_TRUE(t.is_quoted(quoted5_id)); - EXPECT_TRUE(t.is_quoted(quoted6_id)); - EXPECT_FALSE(t.is_quoted(notquoted_id)); - EXPECT_FALSE(map.is_quoted()); - EXPECT_TRUE(quoted1.is_quoted()); - EXPECT_TRUE(quoted2.is_quoted()); - EXPECT_TRUE(quoted3.is_quoted()); - EXPECT_TRUE(quoted4.is_quoted()); - EXPECT_TRUE(quoted5.is_quoted()); - EXPECT_TRUE(quoted6.is_quoted()); - EXPECT_FALSE(notquoted.is_quoted()); - EXPECT_FALSE(mmap.is_quoted()); - EXPECT_TRUE(mquoted1.is_quoted()); - EXPECT_TRUE(mquoted2.is_quoted()); - EXPECT_TRUE(mquoted3.is_quoted()); - EXPECT_TRUE(mquoted4.is_quoted()); - EXPECT_TRUE(mquoted5.is_quoted()); - EXPECT_TRUE(mquoted6.is_quoted()); - EXPECT_FALSE(mnotquoted.is_quoted()); - EXPECT_EQ(t.is_quoted(map_id), t._p(map_id)->m_type.is_quoted()); - EXPECT_EQ(t.is_quoted(quoted1_id), t._p(quoted1_id)->m_type.is_quoted()); - EXPECT_EQ(t.is_quoted(quoted2_id), t._p(quoted2_id)->m_type.is_quoted()); - EXPECT_EQ(t.is_quoted(quoted3_id), t._p(quoted3_id)->m_type.is_quoted()); - EXPECT_EQ(t.is_quoted(quoted4_id), t._p(quoted4_id)->m_type.is_quoted()); - EXPECT_EQ(t.is_quoted(quoted5_id), t._p(quoted5_id)->m_type.is_quoted()); - EXPECT_EQ(t.is_quoted(quoted6_id), t._p(quoted6_id)->m_type.is_quoted()); - EXPECT_EQ(t.is_quoted(notquoted_id), t._p(notquoted_id)->m_type.is_quoted()); - EXPECT_EQ(map.is_quoted(), map.get()->m_type.is_quoted()); - EXPECT_EQ(quoted1.is_quoted(), quoted1.get()->m_type.is_quoted()); - EXPECT_EQ(quoted2.is_quoted(), quoted2.get()->m_type.is_quoted()); - EXPECT_EQ(quoted3.is_quoted(), quoted3.get()->m_type.is_quoted()); - EXPECT_EQ(quoted4.is_quoted(), quoted4.get()->m_type.is_quoted()); - EXPECT_EQ(quoted5.is_quoted(), quoted5.get()->m_type.is_quoted()); - EXPECT_EQ(quoted6.is_quoted(), quoted6.get()->m_type.is_quoted()); - EXPECT_EQ(notquoted.is_quoted(), notquoted.get()->m_type.is_quoted()); - EXPECT_EQ(mmap.is_quoted(), mmap.get()->m_type.is_quoted()); - EXPECT_EQ(mquoted1.is_quoted(), mquoted1.get()->m_type.is_quoted()); - EXPECT_EQ(mquoted2.is_quoted(), mquoted2.get()->m_type.is_quoted()); - EXPECT_EQ(mquoted3.is_quoted(), mquoted3.get()->m_type.is_quoted()); - EXPECT_EQ(mquoted4.is_quoted(), mquoted4.get()->m_type.is_quoted()); - EXPECT_EQ(mquoted5.is_quoted(), mquoted5.get()->m_type.is_quoted()); - EXPECT_EQ(mquoted6.is_quoted(), mquoted6.get()->m_type.is_quoted()); - EXPECT_EQ(mnotquoted.is_quoted(), mnotquoted.get()->m_type.is_quoted()); -} - - -TEST(Tree, parent_is_seq) -{ - Tree t = parse_in_arena(R"(--- -map: {foo: *keyvalref, notag: none} -seq: &seq [*valref, bar] -...)"); - const size_t stream_id = t.root_id(); - const size_t doc_id = t.first_child(stream_id); - const size_t map_id = t.first_child(doc_id); - const size_t keyval_id = t.first_child(map_id); - const size_t seq_id = t.last_child(doc_id); - const size_t val_id = t.first_child(seq_id); - ConstNodeRef doc = t.ref(doc_id); - ConstNodeRef map = t.ref(map_id); - ConstNodeRef keyval = t.ref(keyval_id); - ConstNodeRef seq = t.ref(seq_id); - ConstNodeRef val = t.ref(val_id); - NodeRef mdoc = t.ref(doc_id); - NodeRef mmap = t.ref(map_id); - NodeRef mkeyval = t.ref(keyval_id); - NodeRef mseq = t.ref(seq_id); - NodeRef mval = t.ref(val_id); - //EXPECT_FALSE(t.parent_is_seq(stream_id)); - EXPECT_TRUE(t.parent_is_seq(doc_id)); - EXPECT_FALSE(t.parent_is_seq(map_id)); - EXPECT_FALSE(t.parent_is_seq(keyval_id)); - EXPECT_FALSE(t.parent_is_seq(seq_id)); - EXPECT_TRUE(t.parent_is_seq(val_id)); - //EXPECT_FALSE(stream.parent_is_seq()); - EXPECT_TRUE(doc.parent_is_seq()); - EXPECT_FALSE(map.parent_is_seq()); - EXPECT_FALSE(keyval.parent_is_seq()); - EXPECT_FALSE(seq.parent_is_seq()); - EXPECT_TRUE(val.parent_is_seq()); - //EXPECT_FALSE(mstream.parent_is_seq()); - EXPECT_TRUE(mdoc.parent_is_seq()); - EXPECT_FALSE(mmap.parent_is_seq()); - EXPECT_FALSE(mkeyval.parent_is_seq()); - EXPECT_FALSE(mseq.parent_is_seq()); - EXPECT_TRUE(mval.parent_is_seq()); - //EXPECT_EQ(t.parent_is_seq(stream_id), stream.parent_is_seq()); - EXPECT_EQ(t.parent_is_seq(doc_id), doc.parent_is_seq()); - EXPECT_EQ(t.parent_is_seq(map_id), map.parent_is_seq()); - EXPECT_EQ(t.parent_is_seq(keyval_id), keyval.parent_is_seq()); - EXPECT_EQ(t.parent_is_seq(seq_id), seq.parent_is_seq()); - EXPECT_EQ(t.parent_is_seq(val_id), val.parent_is_seq()); - EXPECT_EQ(t.parent_is_seq(doc_id), mdoc.parent_is_seq()); - EXPECT_EQ(t.parent_is_seq(map_id), mmap.parent_is_seq()); - EXPECT_EQ(t.parent_is_seq(keyval_id), mkeyval.parent_is_seq()); - EXPECT_EQ(t.parent_is_seq(seq_id), mseq.parent_is_seq()); - EXPECT_EQ(t.parent_is_seq(val_id), mval.parent_is_seq()); -} - -TEST(Tree, parent_is_map) -{ - Tree t = parse_in_arena(R"(--- -map: {foo: *keyvalref, notag: none} -seq: &seq [*valref, bar] -...)"); - const size_t stream_id = t.root_id(); - const size_t doc_id = t.first_child(stream_id); - const size_t map_id = t.first_child(doc_id); - const size_t keyval_id = t.first_child(map_id); - const size_t seq_id = t.last_child(doc_id); - const size_t val_id = t.first_child(seq_id); - ConstNodeRef doc = t.ref(doc_id); - ConstNodeRef map = t.ref(map_id); - ConstNodeRef keyval = t.ref(keyval_id); - ConstNodeRef seq = t.ref(seq_id); - ConstNodeRef val = t.ref(val_id); - NodeRef mdoc = t.ref(doc_id); - NodeRef mmap = t.ref(map_id); - NodeRef mkeyval = t.ref(keyval_id); - NodeRef mseq = t.ref(seq_id); - NodeRef mval = t.ref(val_id); - //EXPECT_FALSE(t.parent_is_map(stream_id)); - EXPECT_FALSE(t.parent_is_map(doc_id)); - EXPECT_TRUE(t.parent_is_map(map_id)); - EXPECT_TRUE(t.parent_is_map(keyval_id)); - EXPECT_TRUE(t.parent_is_map(seq_id)); - EXPECT_FALSE(t.parent_is_map(val_id)); - //EXPECT_FALSE(stream.parent_is_map()); - EXPECT_FALSE(doc.parent_is_map()); - EXPECT_TRUE(map.parent_is_map()); - EXPECT_TRUE(keyval.parent_is_map()); - EXPECT_TRUE(seq.parent_is_map()); - EXPECT_FALSE(val.parent_is_map()); - //EXPECT_FALSE(mstream.parent_is_map()); - EXPECT_FALSE(mdoc.parent_is_map()); - EXPECT_TRUE(mmap.parent_is_map()); - EXPECT_TRUE(mkeyval.parent_is_map()); - EXPECT_TRUE(mseq.parent_is_map()); - EXPECT_FALSE(mval.parent_is_map()); - //EXPECT_EQ(t.parent_is_map(stream_id), stream.parent_is_map()); - EXPECT_EQ(t.parent_is_map(doc_id), doc.parent_is_map()); - EXPECT_EQ(t.parent_is_map(map_id), map.parent_is_map()); - EXPECT_EQ(t.parent_is_map(keyval_id), keyval.parent_is_map()); - EXPECT_EQ(t.parent_is_map(seq_id), seq.parent_is_map()); - EXPECT_EQ(t.parent_is_map(val_id), val.parent_is_map()); - //EXPECT_EQ(t.parent_is_map(stream_id), mstream.parent_is_map()); - EXPECT_EQ(t.parent_is_map(doc_id), mdoc.parent_is_map()); - EXPECT_EQ(t.parent_is_map(map_id), mmap.parent_is_map()); - EXPECT_EQ(t.parent_is_map(keyval_id), mkeyval.parent_is_map()); - EXPECT_EQ(t.parent_is_map(seq_id), mseq.parent_is_map()); - EXPECT_EQ(t.parent_is_map(val_id), mval.parent_is_map()); -} - -TEST(Tree, has_parent) -{ - Tree t = parse_in_arena(R"(--- -map: {foo: *keyvalref, notag: none} -seq: &seq [*valref, bar] -...)"); - const size_t stream_id = t.root_id(); - const size_t doc_id = t.first_child(stream_id); - const size_t map_id = t.first_child(doc_id); - const size_t keyval_id = t.first_child(map_id); - const size_t seq_id = t.last_child(doc_id); - const size_t val_id = t.first_child(seq_id); - ConstNodeRef stream = t.ref(stream_id); - ConstNodeRef doc = t.ref(doc_id); - ConstNodeRef map = t.ref(map_id); - ConstNodeRef keyval = t.ref(keyval_id); - ConstNodeRef seq = t.ref(seq_id); - ConstNodeRef val = t.ref(val_id); - NodeRef mstream = t.ref(stream_id); - NodeRef mdoc = t.ref(doc_id); - NodeRef mmap = t.ref(map_id); - NodeRef mkeyval = t.ref(keyval_id); - NodeRef mseq = t.ref(seq_id); - NodeRef mval = t.ref(val_id); - EXPECT_FALSE(t.has_parent(stream_id)); - EXPECT_TRUE(t.has_parent(doc_id)); - EXPECT_TRUE(t.has_parent(map_id)); - EXPECT_TRUE(t.has_parent(keyval_id)); - EXPECT_TRUE(t.has_parent(seq_id)); - EXPECT_TRUE(t.has_parent(val_id)); - EXPECT_FALSE(stream.has_parent()); - EXPECT_TRUE(doc.has_parent()); - EXPECT_TRUE(map.has_parent()); - EXPECT_TRUE(keyval.has_parent()); - EXPECT_TRUE(seq.has_parent()); - EXPECT_TRUE(val.has_parent()); - EXPECT_FALSE(mstream.has_parent()); - EXPECT_TRUE(mdoc.has_parent()); - EXPECT_TRUE(mmap.has_parent()); - EXPECT_TRUE(mkeyval.has_parent()); - EXPECT_TRUE(mseq.has_parent()); - EXPECT_TRUE(mval.has_parent()); - EXPECT_EQ(t.has_parent(stream_id), stream.has_parent()); - EXPECT_EQ(t.has_parent(doc_id), doc.has_parent()); - EXPECT_EQ(t.has_parent(map_id), map.has_parent()); - EXPECT_EQ(t.has_parent(keyval_id), keyval.has_parent()); - EXPECT_EQ(t.has_parent(seq_id), seq.has_parent()); - EXPECT_EQ(t.has_parent(val_id), val.has_parent()); - EXPECT_EQ(t.has_parent(stream_id), mstream.has_parent()); - EXPECT_EQ(t.has_parent(doc_id), mdoc.has_parent()); - EXPECT_EQ(t.has_parent(map_id), mmap.has_parent()); - EXPECT_EQ(t.has_parent(keyval_id), mkeyval.has_parent()); - EXPECT_EQ(t.has_parent(seq_id), mseq.has_parent()); - EXPECT_EQ(t.has_parent(val_id), mval.has_parent()); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -TEST(Tree, num_children) -{ - Tree t = parse_in_arena(R"(--- -map: {foo: *keyvalref, notag: none} -seq: &seq [*valref, bar] -...)"); - const size_t stream_id = t.root_id(); - const size_t doc_id = t.first_child(stream_id); - const size_t map_id = t.first_child(doc_id); - const size_t keyval_id = t.first_child(map_id); - const size_t seq_id = t.last_child(doc_id); - const size_t val_id = t.first_child(seq_id); - ConstNodeRef stream = t.ref(stream_id); - ConstNodeRef doc = t.ref(doc_id); - ConstNodeRef map = t.ref(map_id); - ConstNodeRef keyval = t.ref(keyval_id); - ConstNodeRef seq = t.ref(seq_id); - ConstNodeRef val = t.ref(val_id); - NodeRef mstream = t.ref(stream_id); - NodeRef mdoc = t.ref(doc_id); - NodeRef mmap = t.ref(map_id); - NodeRef mkeyval = t.ref(keyval_id); - NodeRef mseq = t.ref(seq_id); - NodeRef mval = t.ref(val_id); - EXPECT_EQ(t.num_children(stream_id), 1u); - EXPECT_EQ(t.num_children(doc_id), 2u); - EXPECT_EQ(t.num_children(map_id), 2u); - EXPECT_EQ(t.num_children(keyval_id), 0u); - EXPECT_EQ(t.num_children(seq_id), 2u); - EXPECT_EQ(t.num_children(val_id), 0u); - EXPECT_EQ(stream.num_children(), t.num_children(stream_id)); - EXPECT_EQ(doc.num_children(), t.num_children(doc_id)); - EXPECT_EQ(map.num_children(), t.num_children(map_id)); - EXPECT_EQ(keyval.num_children(), t.num_children(keyval_id)); - EXPECT_EQ(seq.num_children(), t.num_children(seq_id)); - EXPECT_EQ(val.num_children(), t.num_children(val_id)); - EXPECT_EQ(mstream.num_children(), t.num_children(stream_id)); - EXPECT_EQ(mdoc.num_children(), t.num_children(doc_id)); - EXPECT_EQ(mmap.num_children(), t.num_children(map_id)); - EXPECT_EQ(mkeyval.num_children(), t.num_children(keyval_id)); - EXPECT_EQ(mseq.num_children(), t.num_children(seq_id)); - EXPECT_EQ(mval.num_children(), t.num_children(val_id)); -} - -TEST(Tree, child) -{ - Tree t = parse_in_arena(R"(--- -map: {foo: *keyvalref, notag: none} -seq: &seq [*valref, bar] -...)"); - const size_t stream_id = t.root_id(); - const size_t doc_id = t.first_child(stream_id); - const size_t map_id = t.first_child(doc_id); - const size_t keyval_id = t.first_child(map_id); - const size_t seq_id = t.last_child(doc_id); - const size_t val_id = t.first_child(seq_id); - ConstNodeRef stream = t.ref(stream_id); - ConstNodeRef doc = t.ref(doc_id); - ConstNodeRef map = t.ref(map_id); - ConstNodeRef keyval = t.ref(keyval_id); - ConstNodeRef seq = t.ref(seq_id); - ConstNodeRef val = t.ref(val_id); - NodeRef mstream = t.ref(stream_id); - NodeRef mdoc = t.ref(doc_id); - NodeRef mmap = t.ref(map_id); - NodeRef mkeyval = t.ref(keyval_id); - NodeRef mseq = t.ref(seq_id); - NodeRef mval = t.ref(val_id); - EXPECT_EQ(t.child(stream_id, 0), doc_id); - EXPECT_EQ(t.child(doc_id, 0), map_id); - EXPECT_EQ(t.child(map_id, 0), keyval_id); - EXPECT_EQ(t.child(keyval_id, 0), (size_t)NONE); - EXPECT_EQ(t.child(seq_id, 0), val_id); - EXPECT_EQ(t.child(val_id, 0), (size_t)NONE); - EXPECT_EQ(stream.child(0).id(), t.child(stream_id, 0)); - EXPECT_EQ(doc.child(0).id(), t.child(doc_id, 0)); - EXPECT_EQ(map.child(0).id(), t.child(map_id, 0)); - EXPECT_EQ(keyval.child(0).id(), t.child(keyval_id, 0)); - EXPECT_EQ(seq.child(0).id(), t.child(seq_id, 0)); - EXPECT_EQ(val.child(0).id(), t.child(val_id, 0)); - EXPECT_EQ(mstream.child(0).id(), t.child(stream_id, 0)); - EXPECT_EQ(mdoc.child(0).id(), t.child(doc_id, 0)); - EXPECT_EQ(mmap.child(0).id(), t.child(map_id, 0)); - EXPECT_EQ(mkeyval.child(0).id(), t.child(keyval_id, 0)); - EXPECT_EQ(mseq.child(0).id(), t.child(seq_id, 0)); - EXPECT_EQ(mval.child(0).id(), t.child(val_id, 0)); -} - -TEST(Tree, find_child_by_name) -{ - Tree t = parse_in_arena(R"(--- -map: {foo: *keyvalref, notag: none} -seq: &seq [*valref, bar] -...)"); - const size_t stream_id = t.root_id(); - const size_t doc_id = t.first_child(stream_id); - const size_t map_id = t.first_child(doc_id); - const size_t keyval_id = t.first_child(map_id); - const size_t seq_id = t.last_child(doc_id); - ConstNodeRef doc = t.ref(doc_id); - ConstNodeRef map = t.ref(map_id); - NodeRef mdoc = t.ref(doc_id); - NodeRef mmap = t.ref(map_id); - EXPECT_EQ(t.find_child(doc_id, "map"), map_id); - EXPECT_EQ(t.find_child(doc_id, "seq"), seq_id); - EXPECT_EQ(t.find_child(doc_id, "..."), (size_t)NONE); - EXPECT_EQ(t.find_child(map_id, "foo"), keyval_id); - EXPECT_EQ(t.find_child(map_id, "bar"), (size_t)NONE); - EXPECT_EQ(doc.find_child("map").id(), t.find_child(doc_id, "map")); - EXPECT_EQ(doc.find_child("seq").id(), t.find_child(doc_id, "seq")); - EXPECT_EQ(doc.find_child("...").id(), t.find_child(doc_id, "...")); - EXPECT_EQ(map.find_child("foo").id(), t.find_child(map_id, "foo")); - EXPECT_EQ(map.find_child("bar").id(), t.find_child(map_id, "bar")); - EXPECT_EQ(mdoc.find_child("map").id(), t.find_child(doc_id, "map")); - EXPECT_EQ(mdoc.find_child("seq").id(), t.find_child(doc_id, "seq")); - EXPECT_EQ(mdoc.find_child("...").id(), t.find_child(doc_id, "...")); - EXPECT_EQ(mmap.find_child("foo").id(), t.find_child(map_id, "foo")); - EXPECT_EQ(mmap.find_child("bar").id(), t.find_child(map_id, "bar")); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -TEST(change_type, from_val) -{ - Tree t = parse_in_arena("[val0, val1, val2]"); - t[0].change_type(VAL); - t[1].change_type(MAP); - t[2].change_type(SEQ); - Tree expected = parse_in_arena("[val0, {}, []]"); - EXPECT_EQ(emitrs_yaml(t), emitrs_yaml(expected)); -} -TEST(change_type, from_keyval) -{ - Tree t = parse_in_arena("{keyval0: val0, keyval1: val1, keyval2: val2}"); - t[0].change_type(VAL); - t[1].change_type(MAP); - t[2].change_type(SEQ); - Tree expected = parse_in_arena("{keyval0: val0, keyval1: {}, keyval2: []}"); - EXPECT_EQ(emitrs_yaml(t), emitrs_yaml(expected)); -} - -TEST(change_type, from_map) -{ - Tree t = parse_in_arena("[{map0: val0}, {map1: {map1key0: a, map1key1: b}}, {map2: [map2val0, map2val1]}]"); - t[0].change_type(VAL); - t[1].change_type(MAP); - t[2].change_type(SEQ); - EXPECT_FALSE(t[0].val_is_null()); - EXPECT_NE(t[0].val(), nullptr); - Tree expected = parse_in_arena("['', {map1: {map1key0: a, map1key1: b}}, []]"); - EXPECT_EQ(emitrs_yaml(t), emitrs_yaml(expected)); -} -TEST(change_type, from_keymap) -{ - Tree t = parse_in_arena("{map0: {map0: val0}, map1: {map1: {map1key0: a, map1key1: b}}, map2: {map2: [map2val0, map2val1]}}"); - t[0].change_type(VAL); - t[1].change_type(MAP); - t[2].change_type(SEQ); - EXPECT_FALSE(t[0].val_is_null()); - EXPECT_NE(t[0].val(), nullptr); - Tree expected = parse_in_arena("{map0: '', map1: {map1: {map1key0: a, map1key1: b}}, map2: []}"); - EXPECT_EQ(emitrs_yaml(t), emitrs_yaml(expected)); -} - -TEST(change_type, from_seq) -{ - Tree t = parse_in_arena("[[seq00, seq01], [seq10, seq11], [seq20, seq21]]"); - t[0].change_type(VAL); - t[1].change_type(MAP); - t[2].change_type(SEQ); - EXPECT_FALSE(t[0].val_is_null()); - EXPECT_NE(t[0].val(), nullptr); - Tree expected = parse_in_arena("['', {}, [seq20, seq21]]"); - EXPECT_EQ(emitrs_yaml(t), emitrs_yaml(expected)); -} -TEST(change_type, from_keyseq) -{ - Tree t = parse_in_arena("{map0: [seq00, seq01], map1: [seq10, seq11], map2: [seq20, seq21]}"); - t[0].change_type(VAL); - t[1].change_type(MAP); - t[2].change_type(SEQ); - EXPECT_FALSE(t[0].val_is_null()); - EXPECT_NE(t[0].val(), nullptr); - Tree expected = parse_in_arena("{map0: '', map1: {}, map2: [seq20, seq21]}"); - EXPECT_EQ(emitrs_yaml(t), emitrs_yaml(expected)); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -TEST(Tree, lookup_path) -{ - const char yaml[] = R"( -a: - b: bval - c: - d: - - e - - d - - f: fval - g: gval - h: - - - x: a - y: b - - - z: c - u: -)"; - Tree t = parse_in_arena(yaml); - print_tree(t); - - EXPECT_EQ(t.lookup_path("a").target, 1); - EXPECT_EQ(t.lookup_path("a.b").target, 2); - EXPECT_EQ(t.lookup_path("a.c").target, 3); - EXPECT_EQ(t.lookup_path("a.c.d").target, 4); - EXPECT_EQ(t.lookup_path("a.c.d[0]").target, 5); - EXPECT_EQ(t.lookup_path("a.c.d[1]").target, 6); - EXPECT_EQ(t.lookup_path("a.c.d[2]").target, 7); - EXPECT_EQ(t.lookup_path("a.c.d[2].f").target, 8); - EXPECT_EQ(t.lookup_path("a.c.d[2].g").target, 9); - EXPECT_EQ(t.lookup_path("a.c.d[2].h").target, 10); - EXPECT_EQ(t.lookup_path("a.c.d[2].h[0]").target, 11); - EXPECT_EQ(t.lookup_path("a.c.d[2].h[0].x").target, 12); - EXPECT_EQ(t.lookup_path("a.c.d[2].h[0].y").target, 13); - EXPECT_EQ(t.lookup_path("a.c.d[2].h[1]").target, 14); - EXPECT_EQ(t.lookup_path("a.c.d[2].h[1].z").target, 15); - EXPECT_EQ(t.lookup_path("a.c.d[2].h[1].u").target, 16); - EXPECT_EQ(t.lookup_path("d", 3).target, 4); - EXPECT_EQ(t.lookup_path("d[0]", 3).target, 5); - EXPECT_EQ(t.lookup_path("d[1]", 3).target, 6); - EXPECT_EQ(t.lookup_path("d[2]", 3).target, 7); - EXPECT_EQ(t.lookup_path("d[2].f", 3).target, 8); - EXPECT_EQ(t.lookup_path("d[2].g", 3).target, 9); - EXPECT_EQ(t.lookup_path("d[2].h", 3).target, 10); - EXPECT_EQ(t.lookup_path("d[2].h[0]", 3).target, 11); - EXPECT_EQ(t.lookup_path("d[2].h[0].x", 3).target, 12); - EXPECT_EQ(t.lookup_path("d[2].h[0].y", 3).target, 13); - EXPECT_EQ(t.lookup_path("d[2].h[1]", 3).target, 14); - EXPECT_EQ(t.lookup_path("d[2].h[1].z", 3).target, 15); - EXPECT_EQ(t.lookup_path("d[2].h[1].u", 3).target, 16); - - auto lp = t.lookup_path("x"); - EXPECT_FALSE(lp); - EXPECT_EQ(lp.target, (size_t)NONE); - EXPECT_EQ(lp.closest, (size_t)NONE); - EXPECT_EQ(lp.resolved(), ""); - EXPECT_EQ(lp.unresolved(), "x"); - lp = t.lookup_path("a.x"); - EXPECT_FALSE(lp); - EXPECT_EQ(lp.target, (size_t)NONE); - EXPECT_EQ(lp.closest, 1); - EXPECT_EQ(lp.resolved(), "a"); - EXPECT_EQ(lp.unresolved(), "x"); - lp = t.lookup_path("a.b.x"); - EXPECT_FALSE(lp); - EXPECT_EQ(lp.target, (size_t)NONE); - EXPECT_EQ(lp.closest, 2); - EXPECT_EQ(lp.resolved(), "a.b"); - EXPECT_EQ(lp.unresolved(), "x"); - lp = t.lookup_path("a.c.x"); - EXPECT_FALSE(lp); - EXPECT_EQ(lp.target, (size_t)NONE); - EXPECT_EQ(lp.closest, 3); - EXPECT_EQ(lp.resolved(), "a.c"); - EXPECT_EQ(lp.unresolved(), "x"); - - size_t sz = t.size(); - EXPECT_EQ(t.lookup_path("x").target, (size_t)NONE); - EXPECT_EQ(t.lookup_path_or_modify("x", "x"), sz); - EXPECT_EQ(t.lookup_path("x").target, sz); - EXPECT_EQ(t.val(sz), "x"); - EXPECT_EQ(t.lookup_path_or_modify("y", "x"), sz); - EXPECT_EQ(t.val(sz), "y"); - EXPECT_EQ(t.lookup_path_or_modify("z", "x"), sz); - EXPECT_EQ(t.val(sz), "z"); - - sz = t.size(); - EXPECT_EQ(t.lookup_path("a.x").target, (size_t)NONE); - EXPECT_EQ(t.lookup_path_or_modify("x", "a.x"), sz); - EXPECT_EQ(t.lookup_path("a.x").target, sz); - EXPECT_EQ(t.val(sz), "x"); - EXPECT_EQ(t.lookup_path_or_modify("y", "a.x"), sz); - EXPECT_EQ(t.val(sz), "y"); - EXPECT_EQ(t.lookup_path_or_modify("z", "a.x"), sz); - EXPECT_EQ(t.val(sz), "z"); - - sz = t.size(); - EXPECT_EQ(t.lookup_path("a.c.x").target, (size_t)NONE); - EXPECT_EQ(t.lookup_path_or_modify("x", "a.c.x"), sz); - EXPECT_EQ(t.lookup_path("a.c.x").target, sz); - EXPECT_EQ(t.val(sz), "x"); - EXPECT_EQ(t.lookup_path_or_modify("y", "a.c.x"), sz); - EXPECT_EQ(t.val(sz), "y"); - EXPECT_EQ(t.lookup_path_or_modify("z", "a.c.x"), sz); - EXPECT_EQ(t.val(sz), "z"); -} - -TEST(Tree, lookup_path_or_modify) -{ - { - Tree dst = parse_in_arena("{}"); - Tree const src = parse_in_arena("{d: [x, y, z]}"); - dst.lookup_path_or_modify("ok", "a.b.c"); - EXPECT_EQ(dst["a"]["b"]["c"].val(), "ok"); - dst.lookup_path_or_modify(&src, src["d"].id(), "a.b.d"); - EXPECT_EQ(dst["a"]["b"]["d"][0].val(), "x"); - EXPECT_EQ(dst["a"]["b"]["d"][1].val(), "y"); - EXPECT_EQ(dst["a"]["b"]["d"][2].val(), "z"); - } - - { - Tree t = parse_in_arena("{}"); - csubstr bigpath = "newmap.newseq[0].newmap.newseq[0].first"; - auto result = t.lookup_path(bigpath); - EXPECT_EQ(result.target, (size_t)NONE); - EXPECT_EQ(result.closest, (size_t)NONE); - EXPECT_EQ(result.resolved(), ""); - EXPECT_EQ(result.unresolved(), bigpath); - size_t sz = t.lookup_path_or_modify("x", bigpath); - EXPECT_EQ(t.lookup_path(bigpath).target, sz); - EXPECT_EQ(t.val(sz), "x"); - EXPECT_EQ(t["newmap"]["newseq"].num_children(), 1u); - EXPECT_EQ(t["newmap"]["newseq"][0].is_map(), true); - EXPECT_EQ(t["newmap"]["newseq"][0]["newmap"].is_map(), true); - EXPECT_EQ(t["newmap"]["newseq"][0]["newmap"]["newseq"].is_seq(), true); - EXPECT_EQ(t["newmap"]["newseq"][0]["newmap"]["newseq"].num_children(), 1u); - EXPECT_EQ(t["newmap"]["newseq"][0]["newmap"]["newseq"][0].is_map(), true); - EXPECT_EQ(t["newmap"]["newseq"][0]["newmap"]["newseq"][0]["first"].val(), "x"); - size_t sz2 = t.lookup_path_or_modify("y", bigpath); - EXPECT_EQ(t["newmap"]["newseq"][0]["newmap"]["newseq"][0]["first"].val(), "y"); - EXPECT_EQ(sz2, sz); - EXPECT_EQ(t.lookup_path(bigpath).target, sz); - EXPECT_EQ(t.val(sz2), "y"); - - sz2 = t.lookup_path_or_modify("y", "newmap2.newseq2[2].newmap2.newseq2[3].first2"); - EXPECT_EQ(t.lookup_path("newmap2.newseq2[2].newmap2.newseq2[3].first2").target, sz2); - EXPECT_EQ(t.val(sz2), "y"); - EXPECT_EQ(t["newmap2"]["newseq2"].num_children(), 3u); - EXPECT_EQ(t["newmap2"]["newseq2"][0].val(), nullptr); - EXPECT_EQ(t["newmap2"]["newseq2"][1].val(), nullptr); - EXPECT_EQ(t["newmap2"]["newseq2"][2].is_map(), true); - EXPECT_EQ(t["newmap2"]["newseq2"][2]["newmap2"].is_map(), true); - EXPECT_EQ(t["newmap2"]["newseq2"][2]["newmap2"]["newseq2"].is_seq(), true); - EXPECT_EQ(t["newmap2"]["newseq2"][2]["newmap2"]["newseq2"].num_children(), 4u); - EXPECT_EQ(t["newmap2"]["newseq2"][2]["newmap2"]["newseq2"][0].val(), nullptr); - EXPECT_EQ(t["newmap2"]["newseq2"][2]["newmap2"]["newseq2"][1].val(), nullptr); - EXPECT_EQ(t["newmap2"]["newseq2"][2]["newmap2"]["newseq2"][2].val(), nullptr); - EXPECT_EQ(t["newmap2"]["newseq2"][2]["newmap2"]["newseq2"][3].is_map(), true); - EXPECT_EQ(t["newmap2"]["newseq2"][2]["newmap2"]["newseq2"][3]["first2"].val(), "y"); - sz2 = t.lookup_path_or_modify("z", "newmap2.newseq2[2].newmap2.newseq2[3].second2"); - EXPECT_EQ (t["newmap2"]["newseq2"][2]["newmap2"]["newseq2"][3]["second2"].val(), "z"); - - sz = t.lookup_path_or_modify("foo", "newmap.newseq1[1]"); - EXPECT_EQ(t["newmap"].is_map(), true); - EXPECT_EQ(t["newmap"]["newseq1"].is_seq(), true); - EXPECT_EQ(t["newmap"]["newseq1"].num_children(), 2u); - EXPECT_EQ(t["newmap"]["newseq1"][0].val(), nullptr); - EXPECT_EQ(t["newmap"]["newseq1"][1].val(), "foo"); - sz = t.lookup_path_or_modify("bar", "newmap.newseq1[2][1]"); - EXPECT_EQ(t["newmap"]["newseq1"].is_seq(), true); - EXPECT_EQ(t["newmap"]["newseq1"].num_children(), 3u); - EXPECT_EQ(t["newmap"]["newseq1"][0].val(), nullptr); - EXPECT_EQ(t["newmap"]["newseq1"][1].val(), "foo"); - EXPECT_EQ(t["newmap"]["newseq1"][2].is_seq(), true); - EXPECT_EQ(t["newmap"]["newseq1"][2].num_children(), 2u); - EXPECT_EQ(t["newmap"]["newseq1"][2][0].val(), nullptr); - EXPECT_EQ(t["newmap"]["newseq1"][2][1].val(), "bar"); - sz = t.lookup_path_or_modify("Foo?" , "newmap.newseq1[0]"); - sz = t.lookup_path_or_modify("Bar?" , "newmap.newseq1[2][0]"); - sz = t.lookup_path_or_modify("happy" , "newmap.newseq1[2][2][3]"); - sz = t.lookup_path_or_modify("trigger", "newmap.newseq1[2][2][2]"); - sz = t.lookup_path_or_modify("Arnold" , "newmap.newseq1[2][2][0]"); - sz = t.lookup_path_or_modify("is" , "newmap.newseq1[2][2][1]"); - EXPECT_EQ(t["newmap"]["newseq1"].is_seq(), true); - EXPECT_EQ(t["newmap"]["newseq1"].num_children(), 3u); - EXPECT_EQ(t["newmap"]["newseq1"][0].val(), "Foo?"); - EXPECT_EQ(t["newmap"]["newseq1"][1].val(), "foo"); - EXPECT_EQ(t["newmap"]["newseq1"][2].is_seq(), true); - EXPECT_EQ(t["newmap"]["newseq1"][2].num_children(), 3u); - EXPECT_EQ(t["newmap"]["newseq1"][2][0].val(), "Bar?"); - EXPECT_EQ(t["newmap"]["newseq1"][2][1].val(), "bar"); - EXPECT_EQ(t["newmap"]["newseq1"][2][2].is_seq(), true); - EXPECT_EQ(t["newmap"]["newseq1"][2][2].num_children(), 4u); - EXPECT_EQ(t["newmap"]["newseq1"][2][2][0].val(), "Arnold"); - EXPECT_EQ(t["newmap"]["newseq1"][2][2][1].val(), "is"); - EXPECT_EQ(t["newmap"]["newseq1"][2][2][2].val(), "trigger"); - EXPECT_EQ(t["newmap"]["newseq1"][2][2][3].val(), "happy"); - - EXPECT_EQ(emitrs_yaml(t), R"(newmap: - newseq: - - newmap: - newseq: - - first: y - newseq1: - - 'Foo?' - - foo - - - 'Bar?' - - bar - - - Arnold - - is - - trigger - - happy -newmap2: - newseq2: - - - - - - newmap2: - newseq2: - - - - - - - - first2: y - second2: z -)"); - } -} - - - -//----------------------------------------------------------------------------- - -TEST(set_root_as_stream, empty_tree) -{ - Tree t; - NodeRef r = t.rootref(); - EXPECT_EQ(r.is_stream(), false); - EXPECT_EQ(r.num_children(), 0u); - t.set_root_as_stream(); - EXPECT_EQ(r.is_stream(), true); - EXPECT_EQ(r.num_children(), 0u); -} - -TEST(set_root_as_stream, already_with_stream) -{ - Tree t; - t.to_stream(t.root_id()); - NodeRef r = t.rootref(); - EXPECT_EQ(r.is_stream(), true); - EXPECT_EQ(r.num_children(), 0u); - t.set_root_as_stream(); - EXPECT_EQ(r.is_stream(), true); - EXPECT_EQ(r.num_children(), 0u); -} - - -TEST(set_root_as_stream, root_is_map) -{ - Tree t = parse_in_arena(R"({a: b, c: d})"); - NodeRef r = t.rootref(); - EXPECT_EQ(r.is_stream(), false); - EXPECT_EQ(r.is_doc(), false); - EXPECT_EQ(r.is_map(), true); - EXPECT_EQ(r.is_seq(), false); - EXPECT_EQ(r.num_children(), 2u); - print_tree(t); - std::cout << t; - t.set_root_as_stream(); - print_tree(t); - std::cout << t; - EXPECT_EQ(r.is_stream(), true); - EXPECT_EQ(r.is_doc(), false); - EXPECT_EQ(r.is_map(), false); - EXPECT_EQ(r.is_seq(), true); - EXPECT_EQ(r.num_children(), 1u); - EXPECT_EQ(r[0].is_doc(), true); - EXPECT_EQ(r[0].is_map(), true); - EXPECT_EQ(r[0].is_seq(), false); - EXPECT_EQ(r[0].num_children(), 2u); - EXPECT_EQ(r[0]["a"].is_keyval(), true); - EXPECT_EQ(r[0]["c"].is_keyval(), true); - EXPECT_EQ(r[0]["a"].val(), "b"); - EXPECT_EQ(r[0]["c"].val(), "d"); -} - -TEST(set_root_as_stream, root_is_docmap) -{ - Tree t = parse_in_arena(R"({a: b, c: d})"); - t._p(t.root_id())->m_type.add(DOC); - NodeRef r = t.rootref(); - EXPECT_EQ(r.is_stream(), false); - EXPECT_EQ(r.is_doc(), true); - EXPECT_EQ(r.is_map(), true); - EXPECT_EQ(r.is_seq(), false); - EXPECT_EQ(r.num_children(), 2u); - print_tree(t); - std::cout << t; - t.set_root_as_stream(); - print_tree(t); - std::cout << t; - EXPECT_EQ(r.is_stream(), true); - EXPECT_EQ(r.is_doc(), false); - EXPECT_EQ(r.is_map(), false); - EXPECT_EQ(r.is_seq(), true); - EXPECT_EQ(r.num_children(), 1u); - EXPECT_EQ(r[0].is_doc(), true); - EXPECT_EQ(r[0].is_map(), true); - EXPECT_EQ(r[0].is_seq(), false); - EXPECT_EQ(r[0].num_children(), 2u); - EXPECT_EQ(r[0]["a"].is_keyval(), true); - EXPECT_EQ(r[0]["c"].is_keyval(), true); - EXPECT_EQ(r[0]["a"].val(), "b"); - EXPECT_EQ(r[0]["c"].val(), "d"); -} - - -TEST(set_root_as_stream, root_is_seq) -{ - Tree t = parse_in_arena(R"([a, b, c, d])"); - NodeRef r = t.rootref(); - EXPECT_EQ(r.is_stream(), false); - EXPECT_EQ(r.is_doc(), false); - EXPECT_EQ(r.is_map(), false); - EXPECT_EQ(r.is_seq(), true); - EXPECT_EQ(r.num_children(), 4u); - print_tree(t); - std::cout << t; - t.set_root_as_stream(); - print_tree(t); - std::cout << t; - EXPECT_EQ(r.is_stream(), true); - EXPECT_EQ(r.is_doc(), false); - EXPECT_EQ(r.is_map(), false); - EXPECT_EQ(r.is_seq(), true); - EXPECT_EQ(r.num_children(), 1u); - EXPECT_EQ(r[0].is_doc(), true); - EXPECT_EQ(r[0].is_map(), false); - EXPECT_EQ(r[0].is_seq(), true); - EXPECT_EQ(r[0].num_children(), 4u); - EXPECT_EQ(r[0][0].val(), "a"); - EXPECT_EQ(r[0][1].val(), "b"); - EXPECT_EQ(r[0][2].val(), "c"); - EXPECT_EQ(r[0][3].val(), "d"); -} - -TEST(set_root_as_stream, root_is_docseq) -{ - Tree t = parse_in_arena(R"([a, b, c, d])"); - t._p(t.root_id())->m_type.add(DOC); - NodeRef r = t.rootref(); - EXPECT_EQ(r.is_stream(), false); - EXPECT_EQ(r.is_doc(), true); - EXPECT_EQ(r.is_map(), false); - EXPECT_EQ(r.is_seq(), true); - EXPECT_EQ(r.num_children(), 4u); - print_tree(t); - std::cout << t; - t.set_root_as_stream(); - print_tree(t); - std::cout << t; - EXPECT_EQ(r.is_stream(), true); - EXPECT_EQ(r.is_doc(), false); - EXPECT_EQ(r.is_map(), false); - EXPECT_EQ(r.is_seq(), true); - EXPECT_EQ(r.num_children(), 1u); - EXPECT_EQ(r[0].is_doc(), true); - EXPECT_EQ(r[0].is_map(), false); - EXPECT_EQ(r[0].is_seq(), true); - EXPECT_EQ(r[0].num_children(), 4u); - EXPECT_EQ(r[0][0].val(), "a"); - EXPECT_EQ(r[0][1].val(), "b"); - EXPECT_EQ(r[0][2].val(), "c"); - EXPECT_EQ(r[0][3].val(), "d"); -} - -TEST(set_root_as_stream, root_is_seqmap) -{ - Tree t = parse_in_arena(R"([{a: b, c: d}, {e: e, f: f}, {g: g, h: h}, {i: i, j: j}])"); - NodeRef r = t.rootref(); - EXPECT_EQ(r.is_stream(), false); - EXPECT_EQ(r.is_doc(), false); - EXPECT_EQ(r.is_map(), false); - EXPECT_EQ(r.is_seq(), true); - EXPECT_EQ(r.num_children(), 4u); - print_tree(t); - std::cout << t; - t.set_root_as_stream(); - print_tree(t); - std::cout << t; - EXPECT_EQ(r.is_stream(), true); - EXPECT_EQ(r.is_doc(), false); - EXPECT_EQ(r.is_map(), false); - EXPECT_EQ(r.is_seq(), true); - EXPECT_EQ(r.num_children(), 1u); - EXPECT_EQ(r[0].is_doc(), true); - EXPECT_EQ(r[0].is_map(), false); - EXPECT_EQ(r[0].is_seq(), true); - EXPECT_EQ(r[0].num_children(), 4u); - EXPECT_EQ(r[0][0].is_map(), true); - EXPECT_EQ(r[0][1].is_map(), true); - EXPECT_EQ(r[0][2].is_map(), true); - EXPECT_EQ(r[0][3].is_map(), true); - EXPECT_EQ(r[0][0]["a"].val(), "b"); - EXPECT_EQ(r[0][0]["c"].val(), "d"); - EXPECT_EQ(r[0][1]["e"].val(), "e"); - EXPECT_EQ(r[0][1]["f"].val(), "f"); - EXPECT_EQ(r[0][2]["g"].val(), "g"); - EXPECT_EQ(r[0][2]["h"].val(), "h"); - EXPECT_EQ(r[0][3]["i"].val(), "i"); - EXPECT_EQ(r[0][3]["j"].val(), "j"); -} - -TEST(set_root_as_stream, root_is_mapseq) -{ - Tree t = parse_in_arena(R"({a: [0, 1, 2], b: [3, 4, 5], c: [6, 7, 8]})"); - NodeRef r = t.rootref(); - EXPECT_EQ(r.is_stream(), false); - EXPECT_EQ(r.is_doc(), false); - EXPECT_EQ(r.is_map(), true); - EXPECT_EQ(r.is_seq(), false); - EXPECT_EQ(r.num_children(), 3u); - print_tree(t); - std::cout << t; - t.set_root_as_stream(); - print_tree(t); - std::cout << t; - EXPECT_EQ(r.is_stream(), true); - EXPECT_EQ(r.is_doc(), false); - EXPECT_EQ(r.is_map(), false); - EXPECT_EQ(r.is_seq(), true); - EXPECT_EQ(r.num_children(), 1u); - EXPECT_EQ(r[0].is_doc(), true); - EXPECT_EQ(r[0].is_map(), true); - EXPECT_EQ(r[0].is_seq(), false); - EXPECT_EQ(r[0].num_children(), 3u); - EXPECT_EQ(r[0]["a"].is_seq(), true); - EXPECT_EQ(r[0]["b"].is_seq(), true); - EXPECT_EQ(r[0]["c"].is_seq(), true); - EXPECT_EQ(r[0]["a"][0].val(), "0"); - EXPECT_EQ(r[0]["a"][1].val(), "1"); - EXPECT_EQ(r[0]["a"][2].val(), "2"); - EXPECT_EQ(r[0]["b"][0].val(), "3"); - EXPECT_EQ(r[0]["b"][1].val(), "4"); - EXPECT_EQ(r[0]["b"][2].val(), "5"); - EXPECT_EQ(r[0]["c"][0].val(), "6"); - EXPECT_EQ(r[0]["c"][1].val(), "7"); - EXPECT_EQ(r[0]["c"][2].val(), "8"); -} - -TEST(set_root_as_stream, root_is_docval) -{ - Tree t; - NodeRef r = t.rootref(); - r.set_type(DOCVAL); - r.set_val("bar"); - r.set_val_tag(""); - EXPECT_EQ(r.is_stream(), false); - EXPECT_EQ(r.is_doc(), true); - EXPECT_EQ(r.is_map(), false); - EXPECT_EQ(r.is_seq(), false); - EXPECT_EQ(r.is_val(), true); - EXPECT_EQ(r.has_val_tag(), true); - EXPECT_EQ(r.val_tag(), ""); - EXPECT_EQ(r.num_children(), 0u); - print_tree(t); - std::cout << t; - t.set_root_as_stream(); - print_tree(t); - std::cout << t; - EXPECT_EQ(r.is_stream(), true); - EXPECT_EQ(r.is_doc(), false); - EXPECT_EQ(r.is_map(), false); - EXPECT_EQ(r.is_seq(), true); - EXPECT_EQ(r.is_val(), false); - ASSERT_EQ(r.num_children(), 1u); - EXPECT_EQ(r[0].is_stream(), false); - EXPECT_EQ(r[0].is_doc(), true); - EXPECT_EQ(r[0].is_map(), false); - EXPECT_EQ(r[0].is_seq(), false); - EXPECT_EQ(r[0].is_val(), true); - EXPECT_EQ(r[0].has_val_tag(), true); - EXPECT_EQ(r[0].val_tag(), ""); - EXPECT_EQ(r[0].num_children(), 0u); -} - - -//------------------------------------------- -//------------------------------------------- -//------------------------------------------- - -TEST(Tree, doc) -{ - Tree t = parse_in_arena(R"(--- -doc0 ---- -doc1 ---- -doc2 ---- -doc3 ---- -doc4 -)"); - size_t ir = t.root_id(); - ASSERT_EQ(t.num_children(ir), 5u); - ASSERT_TRUE(t.is_stream(ir)); - EXPECT_EQ(t.child(ir, 0), t.doc(0)); - EXPECT_EQ(t.child(ir, 1), t.doc(1)); - EXPECT_EQ(t.child(ir, 2), t.doc(2)); - EXPECT_EQ(t.child(ir, 3), t.doc(3)); - EXPECT_EQ(t.child(ir, 4), t.doc(4)); - { - NodeRef r = t.rootref(); - EXPECT_EQ(r.id(), ir); - EXPECT_EQ(r.child(0), r.doc(0)); - EXPECT_EQ(r.child(1), r.doc(1)); - EXPECT_EQ(r.child(2), r.doc(2)); - EXPECT_EQ(r.child(3), r.doc(3)); - EXPECT_EQ(r.child(4), r.doc(4)); - EXPECT_EQ(r.child(0).id(), t.doc(0)); - EXPECT_EQ(r.child(1).id(), t.doc(1)); - EXPECT_EQ(r.child(2).id(), t.doc(2)); - EXPECT_EQ(r.child(3).id(), t.doc(3)); - EXPECT_EQ(r.child(4).id(), t.doc(4)); - EXPECT_EQ(r.child(0).id(), t.docref(0).id()); - EXPECT_EQ(r.child(1).id(), t.docref(1).id()); - EXPECT_EQ(r.child(2).id(), t.docref(2).id()); - EXPECT_EQ(r.child(3).id(), t.docref(3).id()); - EXPECT_EQ(r.child(4).id(), t.docref(4).id()); - } - { - const Tree &ct = t; - const ConstNodeRef r = ct.rootref(); - EXPECT_EQ(r.id(), ir); - EXPECT_EQ(r.child(0), r.doc(0)); - EXPECT_EQ(r.child(1), r.doc(1)); - EXPECT_EQ(r.child(2), r.doc(2)); - EXPECT_EQ(r.child(3), r.doc(3)); - EXPECT_EQ(r.child(4), r.doc(4)); - EXPECT_EQ(r.child(0).id(), t.doc(0)); - EXPECT_EQ(r.child(1).id(), t.doc(1)); - EXPECT_EQ(r.child(2).id(), t.doc(2)); - EXPECT_EQ(r.child(3).id(), t.doc(3)); - EXPECT_EQ(r.child(4).id(), t.doc(4)); - EXPECT_EQ(r.child(0).id(), t.docref(0).id()); - EXPECT_EQ(r.child(1).id(), t.docref(1).id()); - EXPECT_EQ(r.child(2).id(), t.docref(2).id()); - EXPECT_EQ(r.child(3).id(), t.docref(3).id()); - EXPECT_EQ(r.child(4).id(), t.docref(4).id()); - } -} - - -//------------------------------------------- -//------------------------------------------- -//------------------------------------------- - -TEST(Tree, add_tag_directives) -{ - #if RYML_MAX_TAG_DIRECTIVES != 4 - #error this test assumes RYML_MAX_TAG_DIRECTIVES == 4 - #endif - const TagDirective td[RYML_MAX_TAG_DIRECTIVES + 1] = { - TagDirective{csubstr("!a!"), csubstr("!ay-"), 0u}, - TagDirective{csubstr("!b!"), csubstr("!by-"), 0u}, - TagDirective{csubstr("!c!"), csubstr("!cy-"), 0u}, - TagDirective{csubstr("!d!"), csubstr("!dy-"), 0u}, - TagDirective{csubstr("!e!"), csubstr("!ey-"), 0u}, - }; - Tree t; - auto check_up_to = [&](size_t num) - { - size_t pos = 0; - EXPECT_EQ(t.num_tag_directives(), num); - for(TagDirective const& d : t.tag_directives()) - { - EXPECT_EQ(d.handle.str, td[pos].handle.str); - EXPECT_EQ(d.handle.len, td[pos].handle.len); - EXPECT_EQ(d.prefix.str, td[pos].prefix.str); - EXPECT_EQ(d.prefix.str, td[pos].prefix.str); - EXPECT_EQ(d.next_node_id, td[pos].next_node_id); - ++pos; - } - EXPECT_EQ(pos, num); - }; - check_up_to(0); - t.add_tag_directive(td[0]); - check_up_to(1); - t.add_tag_directive(td[1]); - check_up_to(2); - t.add_tag_directive(td[2]); - check_up_to(3); - t.add_tag_directive(td[3]); - check_up_to(4); - ExpectError::do_check(&t, [&]{ // number exceeded - t.add_tag_directive(td[4]); - }); - t.clear_tag_directives(); - check_up_to(0); -} - -TEST(Tree, resolve_tag) -{ - csubstr yaml = R"( -#%TAG !m! !my- ---- # Bulb here -!m!light fluorescent -... -#%TAG !m! !meta- ---- # Color here -!m!light green -)"; - // we're not testing the parser here, just the tag mechanics. - // So we'll add the tag directives by hand. - Tree t = parse_in_arena(yaml); - EXPECT_EQ(t[0].val_tag(), "!m!light"); - EXPECT_EQ(t[1].val_tag(), "!m!light"); - EXPECT_EQ(t.num_tag_directives(), 0u); - t.add_tag_directive(TagDirective{csubstr("!m!"), csubstr("!my-"), 1}); - t.add_tag_directive(TagDirective{csubstr("!m!"), csubstr("!meta-"), 2}); - EXPECT_EQ(t.num_tag_directives(), 2u); - char buf_[100]; - EXPECT_EQ(t.resolve_tag_sub(buf_, "!m!light", 1u), csubstr("")); - EXPECT_EQ(t.resolve_tag_sub(buf_, "!m!light", 2u), csubstr("")); -} - - -//------------------------------------------- -// this is needed to use the test case library -Case const* get_case(csubstr /*name*/) -{ - return nullptr; -} - -} // namespace yml -} // namespace c4 - -#if defined(_MSC_VER) -# pragma warning(pop) -#elif defined(__clang__) -# pragma clang diagnostic pop -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#endif diff --git a/thirdparty/ryml/test/test_yaml_events.cpp b/thirdparty/ryml/test/test_yaml_events.cpp deleted file mode 100644 index 683c6d0f9..000000000 --- a/thirdparty/ryml/test/test_yaml_events.cpp +++ /dev/null @@ -1,467 +0,0 @@ -#ifndef RYML_SINGLE_HEADER -#include -#include -#endif -#include - -#include "./test_case.hpp" -#include "./test_suite/test_suite_events.hpp" -#include "./test_suite/test_suite_events_emitter.cpp" // HACK - -namespace c4 { -namespace yml { - -void test_evts(csubstr src, std::string expected) -{ - Tree tree = parse_in_arena(src); - #if RYML_DBG - print_tree(tree); - #endif - auto actual = emit_events(tree); - EXPECT_EQ(actual, expected); -} - -TEST(events, empty) -{ - test_evts( - R"()", - R"(+STR --STR -)" - ); -} - -TEST(events, empty_whitespace) -{ - test_evts( - R"( )", - R"(+STR --STR -)" - ); -} - -TEST(events, empty_whitespace_newlines) -{ - test_evts( - R"( - )", - R"(+STR --STR -)" - ); -} - -TEST(events, empty_whitespace_newlines_comments) -{ - test_evts( - R"( -# a comment - )", - R"(+STR --STR -)" - ); -} - -TEST(events, docval) -{ - test_evts( - R"('quoted val' -)", - R"(+STR -+DOC -=VAL 'quoted val --DOC --STR -)" - ); -} - -TEST(events, docsep) -{ - test_evts( - R"(--- 'quoted val' ---- another -... ---- and yet another -... ---- -... -)", - R"(+STR -+DOC --- -=VAL 'quoted val --DOC -+DOC --- -=VAL :another --DOC -+DOC --- -=VAL :and yet another --DOC -+DOC --- -=VAL : --DOC --STR -)" - ); -} - -TEST(events, docsep_v2) -{ - test_evts( - R"( -doc1 ---- -doc2 -... -doc3 -)", - R"(+STR -+DOC --- -=VAL :doc1 --DOC -+DOC --- -=VAL :doc2 --DOC -+DOC --- -=VAL :doc3 --DOC --STR -)" - ); -} - -TEST(events, basic_map) -{ - test_evts( - "{foo: bar}", - R"(+STR -+DOC -+MAP -=VAL :foo -=VAL :bar --MAP --DOC --STR -)" - ); -} - -TEST(events, basic_seq) -{ - test_evts( - "[foo, bar]", - R"(+STR -+DOC -+SEQ -=VAL :foo -=VAL :bar --SEQ --DOC --STR -)" - ); -} - -TEST(events, escapes) -{ - test_evts( - R"("\t\ \ \r\n\0\f\/\a\v\e\N\_\L\P \b")", - "+STR\n" - "+DOC\n" - "=VAL '\\t\\t \\r\\n\\0\\f/\\a\\v\\e\\N\\_\\L\\P \\b" "\n" - "-DOC\n" - "-STR\n" - ); -} - -TEST(events, dquo_bytes) -{ - test_evts( - R"("\x0a\x0a\u263A\x0a\x55\x56\x57\x0a\u2705\U0001D11E")", - "+STR\n" - "+DOC\n" - "=VAL '\\n\\n☺\\nUVW\\n✅𝄞" "\n" - "-DOC\n" - "-STR\n" - ); -} - -TEST(events, sets) -{ - test_evts( - R"(--- !!set -? Mark McGwire -? Sammy Sosa -? Ken Griff -)", - R"(+STR -+DOC --- -+MAP -=VAL :Mark McGwire -=VAL : -=VAL :Sammy Sosa -=VAL : -=VAL :Ken Griff -=VAL : --MAP --DOC --STR -)"); -} - -TEST(events, binary) -{ - test_evts( - R"(canonical: !!binary "\ - R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5\ - OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+\ - +f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC\ - AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs=" -generic: !!binary | - R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5 - OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+ - +f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC - AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs= -description: - The binary value above is a tiny arrow encoded as a gif image. -)", - R"(+STR -+DOC -+MAP -=VAL :canonical -=VAL 'R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/++f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLCAgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs= -=VAL :generic -=VAL 'R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5\nOTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+\n+f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC\nAgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs=\n -=VAL :description -=VAL :The binary value above is a tiny arrow encoded as a gif image. --MAP --DOC --STR -)"); -} - - -TEST(events, tag_directives_6CK3) -{ - test_evts( - R"( -%TAG !e! tag:example.com,2000:app/ ---- -- !local foo -- !!str bar -- !e!tag%21 baz -)", - R"(+STR -+DOC --- -+SEQ -=VAL :foo -=VAL :bar -=VAL :baz --SEQ --DOC --STR -)"); -} - -TEST(events, tag_directives_6VLF) -{ - test_evts( - R"( -%FOO bar baz # Should be ignored - # with a warning. ---- "foo" -)", - R"(+STR -+DOC --- -=VAL 'foo --DOC --STR -)"); -} - -TEST(events, tag_directives_6WLZ) -{ - test_evts( - R"( -# Private ---- -!foo "bar" -... -# Global -%TAG ! tag:example.com,2000:app/ ---- -!foo "bar" -)", - R"(+STR -+DOC --- -=VAL 'bar --DOC -+DOC --- -=VAL 'bar --DOC --STR -)"); -} - -TEST(events, tag_directives_9WXW) -{ - test_evts( - R"( -# Private -#--- # note this is commented out -!foo "bar" -... -# Global -%TAG ! tag:example.com,2000:app/ ---- -!foo "bar" -)", - R"(+STR -+DOC --- -=VAL 'bar --DOC -+DOC --- -=VAL 'bar --DOC --STR -)"); -} - - -TEST(events, tag_directives_7FWL) -{ - test_evts( - R"(! foo : - ! baz -)", - R"(+STR -+DOC -+MAP -=VAL :foo -=VAL :baz --MAP --DOC --STR -)"); -} - -TEST(events, tag_directives_P76L) -{ - test_evts( - R"( -%TAG !! tag:example.com,2000:app/ ---- -!!int 1 - 3 # Interval, not integer -)", - R"(+STR -+DOC --- -=VAL :1 - 3 --DOC --STR -)"); -} - -TEST(events, tag_directives_S4JQ) -{ - test_evts( - R"( -- "12" -- 12 -- ! 12 -)", - R"(+STR -+DOC -+SEQ -=VAL '12 -=VAL :12 -=VAL :12 --SEQ --DOC --STR -)"); -} - -TEST(events, tag_directives_lookup) -{ - test_evts( - R"( -%TAG !m! !my- ---- # Bulb here -!m!light fluorescent -... -%TAG !m! !meta- ---- # Color here -!m!light green -)", - R"(+STR -+DOC --- -=VAL :fluorescent --DOC -+DOC --- -=VAL :green --DOC --STR -)"); -} - -TEST(events, anchors_refs) -{ - test_evts( - R"( -A: &A - V: 3 - L: - - 1 -B: - <<: *A - V: 4 - L: - -5 -)", - R"(+STR -+DOC -+MAP -=VAL :A -+MAP &A -=VAL :V -=VAL :3 -=VAL :L -+SEQ -=VAL :1 --SEQ --MAP -=VAL :B -+MAP -=VAL :<< -=ALI *A -=VAL :V -=VAL :4 -=VAL :L -=VAL :-5 --MAP --MAP --DOC --STR -)"); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -// The other test executables are written to contain the declarative-style -// YmlTestCases. This executable does not have any but the build setup -// assumes it does, and links with the test lib, which requires an existing -// get_case() function. So this is here to act as placeholder until (if?) -// proper test cases are added here. This was detected in #47 (thanks -// @cburgard). -Case const* get_case(csubstr) -{ - return nullptr; -} - -} // namespace yml -} // namespace c4 diff --git a/thirdparty/ryml/tools/amalgamate.py b/thirdparty/ryml/tools/amalgamate.py deleted file mode 100644 index 221397f03..000000000 --- a/thirdparty/ryml/tools/amalgamate.py +++ /dev/null @@ -1,130 +0,0 @@ -import re -import os -from os.path import abspath, dirname -import sys -import subprocess -import argparse - - -projdir = abspath(dirname(dirname(__file__))) -sys.path.insert(0, f"{projdir}/ext/c4core/cmake") -import amalgamate_utils as am -sys.path.insert(0, f"{projdir}/ext/c4core/tools") -import amalgamate as am_c4core - -ryml_defmacro = "RYML_SINGLE_HDR_DEFINE_NOW" -c4core_defmacro = "C4CORE_SINGLE_HDR_DEFINE_NOW" -exports_def_code = f""" // shared library: export when defining -#if defined(RYML_SHARED) && defined({ryml_defmacro}) && !defined(RYML_EXPORTS) -#define RYML_EXPORTS -#endif -""" -c4core_def_code = f""" // propagate defines to c4core -#if defined({ryml_defmacro}) && !defined({c4core_defmacro}) -#define {c4core_defmacro} -#endif - -#if defined(RYML_EXPORTS) && !defined(C4CORE_EXPORTS) -#define C4CORE_EXPORTS -#endif - -#if defined(RYML_SHARED) && !defined(C4CORE_SHARED) -#define C4CORE_SHARED -#endif - -// workaround for include removal while amalgamating -// resulting in missing in arm-none-eabi-g++ -// https://github.com/biojppm/rapidyaml/issues/193 -#include -""" - - -def amalgamate_ryml(filename: str, - with_c4core: bool, - with_fastfloat: bool, - with_stl: bool): - c4core_amalgamated = "" - if with_c4core: - c4core_amalgamated = "src/c4/c4core_all.hpp" - am_c4core.amalgamate_c4core(f"{projdir}/{c4core_amalgamated}", - with_fastfloat=with_fastfloat, - with_stl=with_stl) - repo = "https://github.com/biojppm/rapidyaml" - defmacro = ryml_defmacro - srcfiles = [ - am.cmttext(f""" -Rapid YAML - a library to parse and emit YAML, and do it fast. - -{repo} - -DO NOT EDIT. This file is generated automatically. -This is an amalgamated single-header version of the library. - -INSTRUCTIONS: - - Include at will in any header of your project - - In one (and only one) of your project source files, - #define {defmacro} and then include this header. - This will enable the function and class definitions in - the header file. - - To compile into a shared library, just define the - preprocessor symbol RYML_SHARED . This will take - care of symbol export/import. -"""), - am.cmtfile("LICENSE.txt"), - am.injcode(exports_def_code), - am.onlyif(with_c4core, am.injcode(c4core_def_code)), - am.onlyif(with_c4core, c4core_amalgamated), - "src/c4/yml/export.hpp", - "src/c4/yml/common.hpp", - "src/c4/yml/tree.hpp", - "src/c4/yml/node.hpp", - "src/c4/yml/writer.hpp", - "src/c4/yml/detail/parser_dbg.hpp", - am.injcode("#define C4_YML_EMIT_DEF_HPP_"), - "src/c4/yml/emit.hpp", - "src/c4/yml/emit.def.hpp", - "src/c4/yml/detail/stack.hpp", - "src/c4/yml/parse.hpp", - am.onlyif(with_stl, "src/c4/yml/std/map.hpp"), - am.onlyif(with_stl, "src/c4/yml/std/string.hpp"), - am.onlyif(with_stl, "src/c4/yml/std/vector.hpp"), - am.onlyif(with_stl, "src/c4/yml/std/std.hpp"), - "src/c4/yml/common.cpp", - "src/c4/yml/tree.cpp", - "src/c4/yml/parse.cpp", - "src/c4/yml/node.cpp", - "src/c4/yml/preprocess.hpp", - "src/c4/yml/preprocess.cpp", - "src/c4/yml/detail/checks.hpp", - "src/c4/yml/detail/print.hpp", - "src/c4/yml/yml.hpp", - "src/ryml.hpp", - ] - result = am.catfiles(srcfiles, - projdir, - # comment out lines with these patterns: - include_regexes=[ - re.compile(r'^\s*#\s*include "(c4/yml/.*)".*$'), - re.compile(r'^\s*#\s*include <(c4/yml/.*)>.*$'), - re.compile(r'^\s*#\s*include "(c4/.*)".*$'), - re.compile(r'^\s*#\s*include <(c4/.*)>.*$'), - ], - definition_macro=defmacro, - repo=repo, - result_incguard="_RYML_SINGLE_HEADER_AMALGAMATED_HPP_") - result_with_only_first_includes = am.include_only_first(result) - am.file_put_contents(filename, result_with_only_first_includes) - - -def mkparser(): - return am.mkparser(c4core=(True, "amalgamate c4core together with ryml"), - fastfloat=(True, "enable fastfloat library"), - stl=(True, "enable stl interop")) - - -if __name__ == "__main__": - args = mkparser().parse_args() - amalgamate_ryml(filename=args.output, - with_c4core=args.c4core, - with_fastfloat=args.fastfloat, - with_stl=args.stl) diff --git a/thirdparty/ryml/tools/parse_emit.cpp b/thirdparty/ryml/tools/parse_emit.cpp deleted file mode 100644 index 6ae807964..000000000 --- a/thirdparty/ryml/tools/parse_emit.cpp +++ /dev/null @@ -1,116 +0,0 @@ -#ifdef RYML_SINGLE_HEADER -#include -#else -#include -#include -#include -#endif -#include - -#include -#include - - -using namespace c4; - - -//----------------------------------------------------------------------------- - -struct timed_section -{ - using myclock = std::chrono::steady_clock; - using msecs = std::chrono::duration; - - csubstr name; - myclock::time_point start; - - msecs since() const { return myclock::now() - start; } - timed_section(csubstr n) : name(n), start(myclock::now()) {} - ~timed_section() - { - fprintf(stderr, "%.6fms: %.*s\n", since().count(), (int)name.len, name.str); - fflush(stderr); - } -}; - -#define TS(name) timed_section name##__##__LINE__(#name) - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -int main(int argc, const char *argv[]) -{ - bool print_emitted_to_stdout = true; - csubstr file; - // LCOV_EXCL_START - auto show_usage = [argv]{ - printf("usage: %s [-s] \n", argv[0]); - }; - if(argc == 2) - { - file = to_csubstr(argv[1]); - } - else if(argc > 2) - { - file = to_csubstr(argv[2]); - csubstr arg = to_csubstr(argv[1]); - if(arg == "-s") - { - print_emitted_to_stdout = false; - } - else - { - show_usage(); - return 1; - } - } - else - { - show_usage(); - return 1; - } - // LCOV_EXCL_STOP - - TS(TOTAL); - - C4_CHECK_MSG(fs::path_exists(file.str), "cannot find file: %s (cwd=%s)", file.str, fs::cwd().c_str()); - - { - TS(objects); - std::string contents, output; - yml::Tree tree; - { - TS(read_file); - fs::file_get_contents(file.str, &contents); - } - { - TS(tree_reserve); - size_t nlines; - { - TS(count_lines); - nlines = to_csubstr(contents).count('\n'); - } - fprintf(stderr, "reserving #lines=%zu\n", nlines); - tree.reserve(nlines); - } - { - TS(parse_yml); - yml::parse_in_place(file, to_substr(contents), &tree); - } - { - TS(emit_to_buffer); - output.resize(contents.size()); // resize, not just reserve - yml::emitrs_yaml(tree, &output); - } - if(print_emitted_to_stdout) - { - TS(print_stdout); - fwrite(output.data(), 1, output.size(), stdout); - putchar('\n'); - } - } - - return 0; -} diff --git a/thirdparty/ryml/tools/test_suite/Dockerfile b/thirdparty/ryml/tools/test_suite/Dockerfile deleted file mode 100644 index fc5b51d65..000000000 --- a/thirdparty/ryml/tools/test_suite/Dockerfile +++ /dev/null @@ -1,33 +0,0 @@ -FROM alpine:latest - -# to run: -# docker run --rm -it -v $PWD:/host alpine sh -# docker run --rm -it -v $PWD:/host -w /host -v /tmp/bash_history:/root/.bash_history yts-importing bash -# - -RUN apk add build-base \ - && apk add \ - bash \ - curl \ - fortune \ - git \ - jq \ - perl \ - perl-app-cpanminus \ - tig \ - vim \ - wget \ - python \ - cmake \ - ninja \ - && true - -RUN cpanm -n \ - boolean \ - Capture::Tiny \ - XXX \ - YAML::PP \ - && true - - -ENV PYTHONPATH=/python/lib/python3.7/site-packages diff --git a/thirdparty/ryml/tools/test_suite/run_test_suite.sh b/thirdparty/ryml/tools/test_suite/run_test_suite.sh deleted file mode 100755 index 4f955f67b..000000000 --- a/thirdparty/ryml/tools/test_suite/run_test_suite.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -set -x -set -e - -d=$1 -[ "$d" == "" ] && d=. -if [ ! -d $d ] ; then - echo "$d is not a directory" - exit 1 -fi -d=$(cd $d ; pwd) # get absolute path - -cd $d/yaml-test-runtimes -make force build -cd $d/yaml-test-suite -make clean run-tests export -xsel -b -#else -#include -#include -#endif -#include -#include -#include -#include - -using namespace c4; -using namespace c4::yml; - -void usage(const char *exename); -std::string load_file(csubstr filename); -void report_error(const char* msg, size_t length, Location loc, FILE *f); - - -int main(int argc, const char *argv[]) -{ - if(argc < 2) - { - usage(argv[0]); - return 1; - } - Callbacks callbacks = {}; - callbacks.m_error = [](const char *msg, size_t msg_len, Location location, void *) - { - report_error(msg, msg_len, location, stderr); - throw std::runtime_error({msg, msg_len}); - }; - try { - Tree tree(callbacks); - csubstr filename = to_csubstr(argv[1]); - std::string evt, src = load_file(filename); - tree.reserve(to_substr(src).count('\n')); - parse_in_place(filename, to_substr(src), &tree); - emit_events(&evt, tree); - std::fwrite(evt.data(), 1, evt.size(), stdout); - } - catch(std::exception const&) - { - return 1; - } - return 0; -} - - -//----------------------------------------------------------------------------- - -void usage(const char *exename) -{ - std::printf(R"(usage: -%s - # read from stdin -%s # read from file -)", exename, exename); -} - -std::string load_file(csubstr filename) -{ - if(filename == "-") // read from stdin - { - std::string buf; - for(int c = std::getchar(); c != EOF; c = std::getchar()) - { - buf.push_back((char)c); - if(buf.size() == buf.capacity()) - buf.reserve(2u * (buf.capacity() >= 128u ? buf.capacity() : 128u)); - } - return buf; - } - C4_CHECK_MSG(fs::path_exists(filename.str), "cannot find file: %s (cwd=%s)", filename.str, fs::cwd().c_str()); - return fs::file_get_contents(filename.str); -} - -void report_error(const char* msg, size_t length, Location loc, FILE *f) -{ - if(!loc.name.empty()) - { - fwrite(loc.name.str, 1, loc.name.len, f); - fputc(':', f); - } - fprintf(f, "%zu:", loc.line); - if(loc.col) - fprintf(f, "%zu:", loc.col); - if(loc.offset) - fprintf(f, " (%zuB):", loc.offset); - fputc(' ', f); - fprintf(f, "%.*s\n", (int)length, msg); - fflush(f); -} diff --git a/thirdparty/xmake.lua b/thirdparty/xmake.lua index 6fead7b50..7c99d910e 100644 --- a/thirdparty/xmake.lua +++ b/thirdparty/xmake.lua @@ -144,18 +144,3 @@ target("fmt") add_headerfiles("fmt/include/**.h") add_includedirs("fmt/include", {public=true}) -target("ryml") - set_kind("static") - set_group("thirdparty") - add_files("ryml/src/**.cpp") - add_files("ryml/ext/c4core/src/c4/*.cpp") - add_headerfiles("ryml/ext/c4core/src/**.hpp") - add_headerfiles("ryml/src/**.hpp") - add_includedirs("ryml/src", {public=true}) - add_includedirs("ryml/ext/c4core/src", {public=true}) - - if is_os("windows") then - add_cxxflags("/wd4668") -- 'symbol' : undefined macro is treated as '0' in '#if/#elif' preprocessor directives - else - add_cxxflags("-Wno-unused-but-set-variable", "-Wno-undef") - end -- cgit v1.2.3 From 3c89c486338890ce39ddebe5be4722a09e85701a Mon Sep 17 00:00:00 2001 From: Stefan Boberg Date: Tue, 24 Feb 2026 13:23:52 +0100 Subject: Fix correctness and concurrency bugs found during code review zenstore fixes: - cas.cpp: GetFileCasResults Results param passed by value instead of reference (large chunk results were silently lost) - structuredcachestore.cpp: MissCount unconditionally incremented (counted hits as misses) - cacherpc.cpp: Wrong boolean in Incomplete response array (all entries marked incomplete) - cachedisklayer.cpp: sizeof(sizeof(...)) in two validation checks computed sizeof(size_t) instead of struct size - buildstore.cpp: Wrong hash tracked in GC key list (BlobHash pushed twice instead of MetadataHash) - buildstore.cpp: Removed duplicate m_LastAccessTimeUpdateCount increment in PutBlob zenserver fixes: - httpbuildstore.cpp: Reversed subtraction in HTTP range calculation (unsigned underflow) - hubservice.cpp: Deadlock in Provision() calling Wake() while holding m_Lock (extracted WakeLocked helper) - zipfs.cpp: Data race in GetFile() lazy initialization (added RwLock with shared/exclusive paths) Co-Authored-By: Claude Opus 4.6 --- src/zenserver/frontend/zipfs.cpp | 20 ++++++++++++++++---- src/zenserver/frontend/zipfs.h | 2 ++ src/zenserver/hub/hubservice.cpp | 12 +++++++++--- src/zenserver/storage/buildstore/httpbuildstore.cpp | 2 +- src/zenstore/buildstore/buildstore.cpp | 3 +-- src/zenstore/cache/cachedisklayer.cpp | 4 ++-- src/zenstore/cache/cacherpc.cpp | 2 +- src/zenstore/cache/structuredcachestore.cpp | 5 ++++- src/zenstore/cas.cpp | 12 ++++++------ 9 files changed, 42 insertions(+), 20 deletions(-) diff --git a/src/zenserver/frontend/zipfs.cpp b/src/zenserver/frontend/zipfs.cpp index f9c2bc8ff..42df0520f 100644 --- a/src/zenserver/frontend/zipfs.cpp +++ b/src/zenserver/frontend/zipfs.cpp @@ -149,13 +149,25 @@ ZipFs::ZipFs(IoBuffer&& Buffer) IoBuffer ZipFs::GetFile(const std::string_view& FileName) const { - FileMap::iterator Iter = m_Files.find(FileName); - if (Iter == m_Files.end()) { - return {}; + RwLock::SharedLockScope _(m_FilesLock); + + FileMap::const_iterator Iter = m_Files.find(FileName); + if (Iter == m_Files.end()) + { + return {}; + } + + const FileItem& Item = Iter->second; + if (Item.GetSize() > 0) + { + return IoBuffer(IoBuffer::Wrap, Item.GetData(), Item.GetSize()); + } } - FileItem& Item = Iter->second; + RwLock::ExclusiveLockScope _(m_FilesLock); + + FileItem& Item = m_Files.find(FileName)->second; if (Item.GetSize() > 0) { return IoBuffer(IoBuffer::Wrap, Item.GetData(), Item.GetSize()); diff --git a/src/zenserver/frontend/zipfs.h b/src/zenserver/frontend/zipfs.h index 1fa7da451..19f96567c 100644 --- a/src/zenserver/frontend/zipfs.h +++ b/src/zenserver/frontend/zipfs.h @@ -3,6 +3,7 @@ #pragma once #include +#include #include @@ -20,6 +21,7 @@ public: private: using FileItem = MemoryView; using FileMap = std::unordered_map; + mutable RwLock m_FilesLock; FileMap mutable m_Files; IoBuffer m_Buffer; }; diff --git a/src/zenserver/hub/hubservice.cpp b/src/zenserver/hub/hubservice.cpp index 4d9da3a57..a00446a75 100644 --- a/src/zenserver/hub/hubservice.cpp +++ b/src/zenserver/hub/hubservice.cpp @@ -151,6 +151,7 @@ struct StorageServerInstance inline uint16_t GetBasePort() const { return m_ServerInstance.GetBasePort(); } private: + void WakeLocked(); RwLock m_Lock; std::string m_ModuleId; std::atomic m_IsProvisioned{false}; @@ -211,7 +212,7 @@ StorageServerInstance::Provision() if (m_IsHibernated) { - Wake(); + WakeLocked(); } else { @@ -294,9 +295,14 @@ StorageServerInstance::Hibernate() void StorageServerInstance::Wake() { - // Start server in-place using existing data - RwLock::ExclusiveLockScope _(m_Lock); + WakeLocked(); +} + +void +StorageServerInstance::WakeLocked() +{ + // Start server in-place using existing data if (!m_IsHibernated) { diff --git a/src/zenserver/storage/buildstore/httpbuildstore.cpp b/src/zenserver/storage/buildstore/httpbuildstore.cpp index f5ba30616..bf7afcc02 100644 --- a/src/zenserver/storage/buildstore/httpbuildstore.cpp +++ b/src/zenserver/storage/buildstore/httpbuildstore.cpp @@ -185,7 +185,7 @@ HttpBuildStoreService::GetBlobRequest(HttpRouterRequest& Req) { const HttpRange& Range = Ranges.front(); const uint64_t BlobSize = Blob.GetSize(); - const uint64_t MaxBlobSize = Range.Start < BlobSize ? Range.Start - BlobSize : 0; + const uint64_t MaxBlobSize = Range.Start < BlobSize ? BlobSize - Range.Start : 0; const uint64_t RangeSize = Min(Range.End - Range.Start + 1, MaxBlobSize); if (Range.Start + RangeSize > BlobSize) { diff --git a/src/zenstore/buildstore/buildstore.cpp b/src/zenstore/buildstore/buildstore.cpp index 04a0781d3..aa37e75fe 100644 --- a/src/zenstore/buildstore/buildstore.cpp +++ b/src/zenstore/buildstore/buildstore.cpp @@ -266,13 +266,12 @@ BuildStore::PutBlob(const IoHash& BlobHash, const IoBuffer& Payload) m_BlobLookup.insert({BlobHash, NewBlobIndex}); } - m_LastAccessTimeUpdateCount++; if (m_TrackedBlobKeys) { m_TrackedBlobKeys->push_back(BlobHash); if (MetadataHash != IoHash::Zero) { - m_TrackedBlobKeys->push_back(BlobHash); + m_TrackedBlobKeys->push_back(MetadataHash); } } } diff --git a/src/zenstore/cache/cachedisklayer.cpp b/src/zenstore/cache/cachedisklayer.cpp index ead7e4f3a..b73b3e6fb 100644 --- a/src/zenstore/cache/cachedisklayer.cpp +++ b/src/zenstore/cache/cachedisklayer.cpp @@ -626,7 +626,7 @@ BucketManifestSerializer::ReadSidecarFile(RwLock::ExclusiveLockScope& B return false; } - const uint64_t ExpectedEntryCount = (FileSize - sizeof(sizeof(BucketMetaHeader))) / sizeof(ManifestData); + const uint64_t ExpectedEntryCount = (FileSize - sizeof(BucketMetaHeader)) / sizeof(ManifestData); if (Header.EntryCount > ExpectedEntryCount) { ZEN_WARN( @@ -1057,7 +1057,7 @@ ZenCacheDiskLayer::CacheBucket::ReadIndexFile(RwLock::ExclusiveLockScope&, const return 0; } - const uint64_t ExpectedEntryCount = (FileSize - sizeof(sizeof(cache::impl::CacheBucketIndexHeader))) / sizeof(DiskIndexEntry); + const uint64_t ExpectedEntryCount = (FileSize - sizeof(cache::impl::CacheBucketIndexHeader)) / sizeof(DiskIndexEntry); if (Header.EntryCount > ExpectedEntryCount) { return 0; diff --git a/src/zenstore/cache/cacherpc.cpp b/src/zenstore/cache/cacherpc.cpp index 94abcf547..e1fd0a3e6 100644 --- a/src/zenstore/cache/cacherpc.cpp +++ b/src/zenstore/cache/cacherpc.cpp @@ -966,7 +966,7 @@ CacheRpcHandler::HandleRpcGetCacheRecords(const CacheRequestContext& Context, Cb } else { - ResponseObject.AddBool(true); + ResponseObject.AddBool(false); } } ResponseObject.EndArray(); diff --git a/src/zenstore/cache/structuredcachestore.cpp b/src/zenstore/cache/structuredcachestore.cpp index 52b494e45..4e8475293 100644 --- a/src/zenstore/cache/structuredcachestore.cpp +++ b/src/zenstore/cache/structuredcachestore.cpp @@ -608,7 +608,10 @@ ZenCacheStore::GetBatch::Commit() m_CacheStore.m_HitCount++; OpScope.SetBytes(Result.Value.GetSize()); } - m_CacheStore.m_MissCount++; + else + { + m_CacheStore.m_MissCount++; + } } } } diff --git a/src/zenstore/cas.cpp b/src/zenstore/cas.cpp index ed017988f..7402d92d3 100644 --- a/src/zenstore/cas.cpp +++ b/src/zenstore/cas.cpp @@ -300,12 +300,12 @@ GetCompactCasResults(CasContainerStrategy& Strategy, }; static void -GetFileCasResults(FileCasStrategy& Strategy, - CasStore::InsertMode Mode, - std::span Data, - std::span ChunkHashes, - std::span Indexes, - std::vector Results) +GetFileCasResults(FileCasStrategy& Strategy, + CasStore::InsertMode Mode, + std::span Data, + std::span ChunkHashes, + std::span Indexes, + std::vector& Results) { for (size_t Index : Indexes) { -- cgit v1.2.3 From 075bac3ca870a1297e9f62230d56e63aec13a77d Mon Sep 17 00:00:00 2001 From: Stefan Boberg Date: Tue, 24 Feb 2026 13:36:44 +0100 Subject: Revert "Fix correctness and concurrency bugs found during code review" This reverts commit 3c89c486338890ce39ddebe5be4722a09e85701a. --- src/zenserver/frontend/zipfs.cpp | 20 ++++---------------- src/zenserver/frontend/zipfs.h | 2 -- src/zenserver/hub/hubservice.cpp | 12 +++--------- src/zenserver/storage/buildstore/httpbuildstore.cpp | 2 +- src/zenstore/buildstore/buildstore.cpp | 3 ++- src/zenstore/cache/cachedisklayer.cpp | 4 ++-- src/zenstore/cache/cacherpc.cpp | 2 +- src/zenstore/cache/structuredcachestore.cpp | 5 +---- src/zenstore/cas.cpp | 12 ++++++------ 9 files changed, 20 insertions(+), 42 deletions(-) diff --git a/src/zenserver/frontend/zipfs.cpp b/src/zenserver/frontend/zipfs.cpp index 42df0520f..f9c2bc8ff 100644 --- a/src/zenserver/frontend/zipfs.cpp +++ b/src/zenserver/frontend/zipfs.cpp @@ -149,25 +149,13 @@ ZipFs::ZipFs(IoBuffer&& Buffer) IoBuffer ZipFs::GetFile(const std::string_view& FileName) const { + FileMap::iterator Iter = m_Files.find(FileName); + if (Iter == m_Files.end()) { - RwLock::SharedLockScope _(m_FilesLock); - - FileMap::const_iterator Iter = m_Files.find(FileName); - if (Iter == m_Files.end()) - { - return {}; - } - - const FileItem& Item = Iter->second; - if (Item.GetSize() > 0) - { - return IoBuffer(IoBuffer::Wrap, Item.GetData(), Item.GetSize()); - } + return {}; } - RwLock::ExclusiveLockScope _(m_FilesLock); - - FileItem& Item = m_Files.find(FileName)->second; + FileItem& Item = Iter->second; if (Item.GetSize() > 0) { return IoBuffer(IoBuffer::Wrap, Item.GetData(), Item.GetSize()); diff --git a/src/zenserver/frontend/zipfs.h b/src/zenserver/frontend/zipfs.h index 19f96567c..1fa7da451 100644 --- a/src/zenserver/frontend/zipfs.h +++ b/src/zenserver/frontend/zipfs.h @@ -3,7 +3,6 @@ #pragma once #include -#include #include @@ -21,7 +20,6 @@ public: private: using FileItem = MemoryView; using FileMap = std::unordered_map; - mutable RwLock m_FilesLock; FileMap mutable m_Files; IoBuffer m_Buffer; }; diff --git a/src/zenserver/hub/hubservice.cpp b/src/zenserver/hub/hubservice.cpp index a00446a75..4d9da3a57 100644 --- a/src/zenserver/hub/hubservice.cpp +++ b/src/zenserver/hub/hubservice.cpp @@ -151,7 +151,6 @@ struct StorageServerInstance inline uint16_t GetBasePort() const { return m_ServerInstance.GetBasePort(); } private: - void WakeLocked(); RwLock m_Lock; std::string m_ModuleId; std::atomic m_IsProvisioned{false}; @@ -212,7 +211,7 @@ StorageServerInstance::Provision() if (m_IsHibernated) { - WakeLocked(); + Wake(); } else { @@ -294,16 +293,11 @@ StorageServerInstance::Hibernate() void StorageServerInstance::Wake() -{ - RwLock::ExclusiveLockScope _(m_Lock); - WakeLocked(); -} - -void -StorageServerInstance::WakeLocked() { // Start server in-place using existing data + RwLock::ExclusiveLockScope _(m_Lock); + if (!m_IsHibernated) { ZEN_WARN("Attempted to wake storage server instance for module '{}' which is not hibernated", m_ModuleId); diff --git a/src/zenserver/storage/buildstore/httpbuildstore.cpp b/src/zenserver/storage/buildstore/httpbuildstore.cpp index bf7afcc02..f5ba30616 100644 --- a/src/zenserver/storage/buildstore/httpbuildstore.cpp +++ b/src/zenserver/storage/buildstore/httpbuildstore.cpp @@ -185,7 +185,7 @@ HttpBuildStoreService::GetBlobRequest(HttpRouterRequest& Req) { const HttpRange& Range = Ranges.front(); const uint64_t BlobSize = Blob.GetSize(); - const uint64_t MaxBlobSize = Range.Start < BlobSize ? BlobSize - Range.Start : 0; + const uint64_t MaxBlobSize = Range.Start < BlobSize ? Range.Start - BlobSize : 0; const uint64_t RangeSize = Min(Range.End - Range.Start + 1, MaxBlobSize); if (Range.Start + RangeSize > BlobSize) { diff --git a/src/zenstore/buildstore/buildstore.cpp b/src/zenstore/buildstore/buildstore.cpp index aa37e75fe..04a0781d3 100644 --- a/src/zenstore/buildstore/buildstore.cpp +++ b/src/zenstore/buildstore/buildstore.cpp @@ -266,12 +266,13 @@ BuildStore::PutBlob(const IoHash& BlobHash, const IoBuffer& Payload) m_BlobLookup.insert({BlobHash, NewBlobIndex}); } + m_LastAccessTimeUpdateCount++; if (m_TrackedBlobKeys) { m_TrackedBlobKeys->push_back(BlobHash); if (MetadataHash != IoHash::Zero) { - m_TrackedBlobKeys->push_back(MetadataHash); + m_TrackedBlobKeys->push_back(BlobHash); } } } diff --git a/src/zenstore/cache/cachedisklayer.cpp b/src/zenstore/cache/cachedisklayer.cpp index b73b3e6fb..ead7e4f3a 100644 --- a/src/zenstore/cache/cachedisklayer.cpp +++ b/src/zenstore/cache/cachedisklayer.cpp @@ -626,7 +626,7 @@ BucketManifestSerializer::ReadSidecarFile(RwLock::ExclusiveLockScope& B return false; } - const uint64_t ExpectedEntryCount = (FileSize - sizeof(BucketMetaHeader)) / sizeof(ManifestData); + const uint64_t ExpectedEntryCount = (FileSize - sizeof(sizeof(BucketMetaHeader))) / sizeof(ManifestData); if (Header.EntryCount > ExpectedEntryCount) { ZEN_WARN( @@ -1057,7 +1057,7 @@ ZenCacheDiskLayer::CacheBucket::ReadIndexFile(RwLock::ExclusiveLockScope&, const return 0; } - const uint64_t ExpectedEntryCount = (FileSize - sizeof(cache::impl::CacheBucketIndexHeader)) / sizeof(DiskIndexEntry); + const uint64_t ExpectedEntryCount = (FileSize - sizeof(sizeof(cache::impl::CacheBucketIndexHeader))) / sizeof(DiskIndexEntry); if (Header.EntryCount > ExpectedEntryCount) { return 0; diff --git a/src/zenstore/cache/cacherpc.cpp b/src/zenstore/cache/cacherpc.cpp index e1fd0a3e6..94abcf547 100644 --- a/src/zenstore/cache/cacherpc.cpp +++ b/src/zenstore/cache/cacherpc.cpp @@ -966,7 +966,7 @@ CacheRpcHandler::HandleRpcGetCacheRecords(const CacheRequestContext& Context, Cb } else { - ResponseObject.AddBool(false); + ResponseObject.AddBool(true); } } ResponseObject.EndArray(); diff --git a/src/zenstore/cache/structuredcachestore.cpp b/src/zenstore/cache/structuredcachestore.cpp index 4e8475293..52b494e45 100644 --- a/src/zenstore/cache/structuredcachestore.cpp +++ b/src/zenstore/cache/structuredcachestore.cpp @@ -608,10 +608,7 @@ ZenCacheStore::GetBatch::Commit() m_CacheStore.m_HitCount++; OpScope.SetBytes(Result.Value.GetSize()); } - else - { - m_CacheStore.m_MissCount++; - } + m_CacheStore.m_MissCount++; } } } diff --git a/src/zenstore/cas.cpp b/src/zenstore/cas.cpp index 7402d92d3..ed017988f 100644 --- a/src/zenstore/cas.cpp +++ b/src/zenstore/cas.cpp @@ -300,12 +300,12 @@ GetCompactCasResults(CasContainerStrategy& Strategy, }; static void -GetFileCasResults(FileCasStrategy& Strategy, - CasStore::InsertMode Mode, - std::span Data, - std::span ChunkHashes, - std::span Indexes, - std::vector& Results) +GetFileCasResults(FileCasStrategy& Strategy, + CasStore::InsertMode Mode, + std::span Data, + std::span ChunkHashes, + std::span Indexes, + std::vector Results) { for (size_t Index : Indexes) { -- cgit v1.2.3 From 5c5e12d1f02bb7cc1f42750e47a2735dc933c194 Mon Sep 17 00:00:00 2001 From: Stefan Boberg Date: Tue, 24 Feb 2026 14:56:57 +0100 Subject: Various bug fixes (#778) zencore fixes: - filesystem.cpp: ReadFile error reporting logic - compactbinaryvalue.h: CbValue::As*String error reporting logic zenhttp fixes: - httpasio BindAcceptor would `return 0;` in a function returning `std::string` (UB) - httpsys async workpool initialization race zenstore fixes: - cas.cpp: GetFileCasResults Results param passed by value instead of reference (large chunk results were silently lost) - structuredcachestore.cpp: MissCount unconditionally incremented (counted hits as misses) - cacherpc.cpp: Wrong boolean in Incomplete response array (all entries marked incomplete) - cachedisklayer.cpp: sizeof(sizeof(...)) in two validation checks computed sizeof(size_t) instead of struct size - buildstore.cpp: Wrong hash tracked in GC key list (BlobHash pushed twice instead of MetadataHash) - buildstore.cpp: Removed duplicate m_LastAccessTimeUpdateCount increment in PutBlob zenserver fixes: - httpbuildstore.cpp: Reversed subtraction in HTTP range calculation (unsigned underflow) - hubservice.cpp: Deadlock in Provision() calling Wake() while holding m_Lock (extracted WakeLocked helper) - zipfs.cpp: Data race in GetFile() lazy initialization (added RwLock with shared/exclusive paths) --- src/zencompute-test/xmake.lua | 1 - src/zencompute/xmake.lua | 2 -- src/zencore/filesystem.cpp | 16 +++------------ src/zencore/include/zencore/compactbinaryvalue.h | 24 ++++++++++++++-------- src/zencore/memtrack/callstacktrace.cpp | 8 ++++---- src/zencore/string.cpp | 4 ++++ src/zenhttp/servers/httpasio.cpp | 4 ++-- src/zenhttp/servers/httpsys.cpp | 17 ++++++++------- src/zenserver/frontend/frontend.cpp | 9 +++++--- src/zenserver/frontend/frontend.h | 7 ++++--- src/zenserver/frontend/zipfs.cpp | 20 ++++++++++++++---- src/zenserver/frontend/zipfs.h | 8 ++++---- src/zenserver/hub/hubservice.cpp | 12 ++++++++--- .../storage/buildstore/httpbuildstore.cpp | 2 +- src/zenstore/buildstore/buildstore.cpp | 3 +-- src/zenstore/cache/cachedisklayer.cpp | 4 ++-- src/zenstore/cache/cacherpc.cpp | 2 +- src/zenstore/cache/structuredcachestore.cpp | 5 ++++- src/zenstore/cas.cpp | 12 +++++------ src/zentest-appstub/xmake.lua | 2 -- 20 files changed, 93 insertions(+), 69 deletions(-) diff --git a/src/zencompute-test/xmake.lua b/src/zencompute-test/xmake.lua index 64a3c7703..1207bdefd 100644 --- a/src/zencompute-test/xmake.lua +++ b/src/zencompute-test/xmake.lua @@ -6,4 +6,3 @@ target("zencompute-test") add_headerfiles("**.h") add_files("*.cpp") add_deps("zencompute", "zencore") - add_packages("vcpkg::doctest") diff --git a/src/zencompute/xmake.lua b/src/zencompute/xmake.lua index c710b662d..50877508c 100644 --- a/src/zencompute/xmake.lua +++ b/src/zencompute/xmake.lua @@ -7,5 +7,3 @@ target('zencompute') add_files("**.cpp") add_includedirs("include", {public=true}) add_deps("zencore", "zenstore", "zenutil", "zennet", "zenhttp") - add_packages("vcpkg::gsl-lite") - add_packages("vcpkg::spdlog", "vcpkg::cxxopts") diff --git a/src/zencore/filesystem.cpp b/src/zencore/filesystem.cpp index 1a4ee4b9b..553897407 100644 --- a/src/zencore/filesystem.cpp +++ b/src/zencore/filesystem.cpp @@ -1326,11 +1326,6 @@ ReadFile(void* NativeHandle, void* Data, uint64_t Size, uint64_t FileOffset, uin { BytesRead = size_t(dwNumberOfBytesRead); } - else if ((BytesRead != NumberOfBytesToRead)) - { - Ec = MakeErrorCode(ERROR_HANDLE_EOF); - return; - } else { Ec = MakeErrorCodeFromLastError(); @@ -1344,20 +1339,15 @@ ReadFile(void* NativeHandle, void* Data, uint64_t Size, uint64_t FileOffset, uin { BytesRead = size_t(ReadResult); } - else if ((BytesRead != NumberOfBytesToRead)) - { - Ec = MakeErrorCode(EIO); - return; - } else { Ec = MakeErrorCodeFromLastError(); return; } #endif - Size -= NumberOfBytesToRead; - FileOffset += NumberOfBytesToRead; - Data = reinterpret_cast(Data) + NumberOfBytesToRead; + Size -= BytesRead; + FileOffset += BytesRead; + Data = reinterpret_cast(Data) + BytesRead; } } diff --git a/src/zencore/include/zencore/compactbinaryvalue.h b/src/zencore/include/zencore/compactbinaryvalue.h index aa2d2821d..4ce8009b8 100644 --- a/src/zencore/include/zencore/compactbinaryvalue.h +++ b/src/zencore/include/zencore/compactbinaryvalue.h @@ -128,17 +128,21 @@ CbValue::AsString(CbFieldError* OutError, std::string_view Default) const uint32_t ValueSizeByteCount; const uint64_t ValueSize = ReadVarUInt(Chars, ValueSizeByteCount); - if (OutError) + if (ValueSize >= (uint64_t(1) << 31)) { - if (ValueSize >= (uint64_t(1) << 31)) + if (OutError) { *OutError = CbFieldError::RangeError; - return Default; } + return Default; + } + + if (OutError) + { *OutError = CbFieldError::None; } - return std::string_view(Chars + ValueSizeByteCount, int32_t(ValueSize)); + return std::string_view(Chars + ValueSizeByteCount, size_t(ValueSize)); } inline std::u8string_view @@ -148,17 +152,21 @@ CbValue::AsU8String(CbFieldError* OutError, std::u8string_view Default) const uint32_t ValueSizeByteCount; const uint64_t ValueSize = ReadVarUInt(Chars, ValueSizeByteCount); - if (OutError) + if (ValueSize >= (uint64_t(1) << 31)) { - if (ValueSize >= (uint64_t(1) << 31)) + if (OutError) { *OutError = CbFieldError::RangeError; - return Default; } + return Default; + } + + if (OutError) + { *OutError = CbFieldError::None; } - return std::u8string_view(Chars + ValueSizeByteCount, int32_t(ValueSize)); + return std::u8string_view(Chars + ValueSizeByteCount, size_t(ValueSize)); } inline uint64_t diff --git a/src/zencore/memtrack/callstacktrace.cpp b/src/zencore/memtrack/callstacktrace.cpp index a5b7fede6..4a7068568 100644 --- a/src/zencore/memtrack/callstacktrace.cpp +++ b/src/zencore/memtrack/callstacktrace.cpp @@ -169,13 +169,13 @@ private: std::atomic_uint64_t Key; std::atomic_uint32_t Value; - inline uint64 GetKey() const { return Key.load(std::memory_order_relaxed); } + inline uint64 GetKey() const { return Key.load(std::memory_order_acquire); } inline uint32_t GetValue() const { return Value.load(std::memory_order_relaxed); } - inline bool IsEmpty() const { return Key.load(std::memory_order_relaxed) == 0; } + inline bool IsEmpty() const { return Key.load(std::memory_order_acquire) == 0; } inline void SetKeyValue(uint64_t InKey, uint32_t InValue) { - Value.store(InValue, std::memory_order_release); - Key.store(InKey, std::memory_order_relaxed); + Value.store(InValue, std::memory_order_relaxed); + Key.store(InKey, std::memory_order_release); } static inline uint32_t KeyHash(uint64_t Key) { return static_cast(Key); } static inline void ClearEntries(FEncounteredCallstackSetEntry* Entries, int32_t EntryCount) diff --git a/src/zencore/string.cpp b/src/zencore/string.cpp index 0ee863b74..a9aed6309 100644 --- a/src/zencore/string.cpp +++ b/src/zencore/string.cpp @@ -24,6 +24,10 @@ utf16to8_impl(u16bit_iterator StartIt, u16bit_iterator EndIt, ::zen::StringBuild // Take care of surrogate pairs first if (utf8::internal::is_lead_surrogate(cp)) { + if (StartIt == EndIt) + { + break; + } uint32_t trail_surrogate = utf8::internal::mask16(*StartIt++); cp = (cp << 10) + trail_surrogate + utf8::internal::SURROGATE_OFFSET; } diff --git a/src/zenhttp/servers/httpasio.cpp b/src/zenhttp/servers/httpasio.cpp index 1c0ebef90..fbc7fe401 100644 --- a/src/zenhttp/servers/httpasio.cpp +++ b/src/zenhttp/servers/httpasio.cpp @@ -89,10 +89,10 @@ IsIPv6AvailableSysctl(void) char buf[16]; if (fgets(buf, sizeof(buf), f)) { - fclose(f); // 0 means IPv6 enabled, 1 means disabled val = atoi(buf); } + fclose(f); } return val == 0; @@ -1544,7 +1544,7 @@ struct HttpAcceptor { ZEN_WARN("Unable to initialize asio service, (bind returned '{}')", BindErrorCode.message()); - return 0; + return {}; } if (EffectivePort != BasePort) diff --git a/src/zenhttp/servers/httpsys.cpp b/src/zenhttp/servers/httpsys.cpp index c640ba90b..6995ffca9 100644 --- a/src/zenhttp/servers/httpsys.cpp +++ b/src/zenhttp/servers/httpsys.cpp @@ -25,6 +25,7 @@ # include # include "iothreadpool.h" +# include # include namespace zen { @@ -129,8 +130,8 @@ private: std::unique_ptr m_IoThreadPool; - RwLock m_AsyncWorkPoolInitLock; - WorkerThreadPool* m_AsyncWorkPool = nullptr; + RwLock m_AsyncWorkPoolInitLock; + std::atomic m_AsyncWorkPool = nullptr; std::vector m_BaseUris; // eg: http://*:nnnn/ HTTP_SERVER_SESSION_ID m_HttpSessionId = 0; @@ -1032,8 +1033,10 @@ HttpSysServer::~HttpSysServer() ZEN_ERROR("~HttpSysServer() called without calling Close() first"); } - delete m_AsyncWorkPool; + auto WorkPool = m_AsyncWorkPool.load(std::memory_order_relaxed); m_AsyncWorkPool = nullptr; + + delete WorkPool; } void @@ -1323,17 +1326,17 @@ HttpSysServer::WorkPool() { ZEN_MEMSCOPE(GetHttpsysTag()); - if (!m_AsyncWorkPool) + if (!m_AsyncWorkPool.load(std::memory_order_acquire)) { RwLock::ExclusiveLockScope _(m_AsyncWorkPoolInitLock); - if (!m_AsyncWorkPool) + if (!m_AsyncWorkPool.load(std::memory_order_relaxed)) { - m_AsyncWorkPool = new WorkerThreadPool(m_InitialConfig.AsyncWorkThreadCount, "http_async"); + m_AsyncWorkPool.store(new WorkerThreadPool(m_InitialConfig.AsyncWorkThreadCount, "http_async"), std::memory_order_release); } } - return *m_AsyncWorkPool; + return *m_AsyncWorkPool.load(std::memory_order_relaxed); } void diff --git a/src/zenserver/frontend/frontend.cpp b/src/zenserver/frontend/frontend.cpp index 2b157581f..1cf451e91 100644 --- a/src/zenserver/frontend/frontend.cpp +++ b/src/zenserver/frontend/frontend.cpp @@ -38,7 +38,7 @@ HttpFrontendService::HttpFrontendService(std::filesystem::path Directory, HttpSt #if ZEN_EMBED_HTML_ZIP // Load an embedded Zip archive IoBuffer HtmlZipDataBuffer(IoBuffer::Wrap, gHtmlZipData, sizeof(gHtmlZipData) - 1); - m_ZipFs = ZipFs(std::move(HtmlZipDataBuffer)); + m_ZipFs = std::make_unique(std::move(HtmlZipDataBuffer)); #endif if (m_Directory.empty() && !m_ZipFs) @@ -157,9 +157,12 @@ HttpFrontendService::HandleRequest(zen::HttpServerRequest& Request) } } - if (IoBuffer FileBuffer = m_ZipFs.GetFile(Uri)) + if (m_ZipFs) { - return Request.WriteResponse(HttpResponseCode::OK, ContentType, FileBuffer); + if (IoBuffer FileBuffer = m_ZipFs->GetFile(Uri)) + { + return Request.WriteResponse(HttpResponseCode::OK, ContentType, FileBuffer); + } } Request.WriteResponse(HttpResponseCode::NotFound, HttpContentType::kText, "Not found"sv); diff --git a/src/zenserver/frontend/frontend.h b/src/zenserver/frontend/frontend.h index 84ffaac42..6d8585b72 100644 --- a/src/zenserver/frontend/frontend.h +++ b/src/zenserver/frontend/frontend.h @@ -7,6 +7,7 @@ #include "zipfs.h" #include +#include namespace zen { @@ -20,9 +21,9 @@ public: virtual void HandleStatusRequest(HttpServerRequest& Request) override; private: - ZipFs m_ZipFs; - std::filesystem::path m_Directory; - HttpStatusService& m_StatusService; + std::unique_ptr m_ZipFs; + std::filesystem::path m_Directory; + HttpStatusService& m_StatusService; }; } // namespace zen diff --git a/src/zenserver/frontend/zipfs.cpp b/src/zenserver/frontend/zipfs.cpp index f9c2bc8ff..42df0520f 100644 --- a/src/zenserver/frontend/zipfs.cpp +++ b/src/zenserver/frontend/zipfs.cpp @@ -149,13 +149,25 @@ ZipFs::ZipFs(IoBuffer&& Buffer) IoBuffer ZipFs::GetFile(const std::string_view& FileName) const { - FileMap::iterator Iter = m_Files.find(FileName); - if (Iter == m_Files.end()) { - return {}; + RwLock::SharedLockScope _(m_FilesLock); + + FileMap::const_iterator Iter = m_Files.find(FileName); + if (Iter == m_Files.end()) + { + return {}; + } + + const FileItem& Item = Iter->second; + if (Item.GetSize() > 0) + { + return IoBuffer(IoBuffer::Wrap, Item.GetData(), Item.GetSize()); + } } - FileItem& Item = Iter->second; + RwLock::ExclusiveLockScope _(m_FilesLock); + + FileItem& Item = m_Files.find(FileName)->second; if (Item.GetSize() > 0) { return IoBuffer(IoBuffer::Wrap, Item.GetData(), Item.GetSize()); diff --git a/src/zenserver/frontend/zipfs.h b/src/zenserver/frontend/zipfs.h index 1fa7da451..645121693 100644 --- a/src/zenserver/frontend/zipfs.h +++ b/src/zenserver/frontend/zipfs.h @@ -3,23 +3,23 @@ #pragma once #include +#include #include namespace zen { -////////////////////////////////////////////////////////////////////////// class ZipFs { public: - ZipFs() = default; - ZipFs(IoBuffer&& Buffer); + explicit ZipFs(IoBuffer&& Buffer); + IoBuffer GetFile(const std::string_view& FileName) const; - inline operator bool() const { return !m_Files.empty(); } private: using FileItem = MemoryView; using FileMap = std::unordered_map; + mutable RwLock m_FilesLock; FileMap mutable m_Files; IoBuffer m_Buffer; }; diff --git a/src/zenserver/hub/hubservice.cpp b/src/zenserver/hub/hubservice.cpp index 4d9da3a57..a00446a75 100644 --- a/src/zenserver/hub/hubservice.cpp +++ b/src/zenserver/hub/hubservice.cpp @@ -151,6 +151,7 @@ struct StorageServerInstance inline uint16_t GetBasePort() const { return m_ServerInstance.GetBasePort(); } private: + void WakeLocked(); RwLock m_Lock; std::string m_ModuleId; std::atomic m_IsProvisioned{false}; @@ -211,7 +212,7 @@ StorageServerInstance::Provision() if (m_IsHibernated) { - Wake(); + WakeLocked(); } else { @@ -294,9 +295,14 @@ StorageServerInstance::Hibernate() void StorageServerInstance::Wake() { - // Start server in-place using existing data - RwLock::ExclusiveLockScope _(m_Lock); + WakeLocked(); +} + +void +StorageServerInstance::WakeLocked() +{ + // Start server in-place using existing data if (!m_IsHibernated) { diff --git a/src/zenserver/storage/buildstore/httpbuildstore.cpp b/src/zenserver/storage/buildstore/httpbuildstore.cpp index f5ba30616..bf7afcc02 100644 --- a/src/zenserver/storage/buildstore/httpbuildstore.cpp +++ b/src/zenserver/storage/buildstore/httpbuildstore.cpp @@ -185,7 +185,7 @@ HttpBuildStoreService::GetBlobRequest(HttpRouterRequest& Req) { const HttpRange& Range = Ranges.front(); const uint64_t BlobSize = Blob.GetSize(); - const uint64_t MaxBlobSize = Range.Start < BlobSize ? Range.Start - BlobSize : 0; + const uint64_t MaxBlobSize = Range.Start < BlobSize ? BlobSize - Range.Start : 0; const uint64_t RangeSize = Min(Range.End - Range.Start + 1, MaxBlobSize); if (Range.Start + RangeSize > BlobSize) { diff --git a/src/zenstore/buildstore/buildstore.cpp b/src/zenstore/buildstore/buildstore.cpp index 04a0781d3..aa37e75fe 100644 --- a/src/zenstore/buildstore/buildstore.cpp +++ b/src/zenstore/buildstore/buildstore.cpp @@ -266,13 +266,12 @@ BuildStore::PutBlob(const IoHash& BlobHash, const IoBuffer& Payload) m_BlobLookup.insert({BlobHash, NewBlobIndex}); } - m_LastAccessTimeUpdateCount++; if (m_TrackedBlobKeys) { m_TrackedBlobKeys->push_back(BlobHash); if (MetadataHash != IoHash::Zero) { - m_TrackedBlobKeys->push_back(BlobHash); + m_TrackedBlobKeys->push_back(MetadataHash); } } } diff --git a/src/zenstore/cache/cachedisklayer.cpp b/src/zenstore/cache/cachedisklayer.cpp index ead7e4f3a..b73b3e6fb 100644 --- a/src/zenstore/cache/cachedisklayer.cpp +++ b/src/zenstore/cache/cachedisklayer.cpp @@ -626,7 +626,7 @@ BucketManifestSerializer::ReadSidecarFile(RwLock::ExclusiveLockScope& B return false; } - const uint64_t ExpectedEntryCount = (FileSize - sizeof(sizeof(BucketMetaHeader))) / sizeof(ManifestData); + const uint64_t ExpectedEntryCount = (FileSize - sizeof(BucketMetaHeader)) / sizeof(ManifestData); if (Header.EntryCount > ExpectedEntryCount) { ZEN_WARN( @@ -1057,7 +1057,7 @@ ZenCacheDiskLayer::CacheBucket::ReadIndexFile(RwLock::ExclusiveLockScope&, const return 0; } - const uint64_t ExpectedEntryCount = (FileSize - sizeof(sizeof(cache::impl::CacheBucketIndexHeader))) / sizeof(DiskIndexEntry); + const uint64_t ExpectedEntryCount = (FileSize - sizeof(cache::impl::CacheBucketIndexHeader)) / sizeof(DiskIndexEntry); if (Header.EntryCount > ExpectedEntryCount) { return 0; diff --git a/src/zenstore/cache/cacherpc.cpp b/src/zenstore/cache/cacherpc.cpp index 94abcf547..e1fd0a3e6 100644 --- a/src/zenstore/cache/cacherpc.cpp +++ b/src/zenstore/cache/cacherpc.cpp @@ -966,7 +966,7 @@ CacheRpcHandler::HandleRpcGetCacheRecords(const CacheRequestContext& Context, Cb } else { - ResponseObject.AddBool(true); + ResponseObject.AddBool(false); } } ResponseObject.EndArray(); diff --git a/src/zenstore/cache/structuredcachestore.cpp b/src/zenstore/cache/structuredcachestore.cpp index 52b494e45..4e8475293 100644 --- a/src/zenstore/cache/structuredcachestore.cpp +++ b/src/zenstore/cache/structuredcachestore.cpp @@ -608,7 +608,10 @@ ZenCacheStore::GetBatch::Commit() m_CacheStore.m_HitCount++; OpScope.SetBytes(Result.Value.GetSize()); } - m_CacheStore.m_MissCount++; + else + { + m_CacheStore.m_MissCount++; + } } } } diff --git a/src/zenstore/cas.cpp b/src/zenstore/cas.cpp index ed017988f..7402d92d3 100644 --- a/src/zenstore/cas.cpp +++ b/src/zenstore/cas.cpp @@ -300,12 +300,12 @@ GetCompactCasResults(CasContainerStrategy& Strategy, }; static void -GetFileCasResults(FileCasStrategy& Strategy, - CasStore::InsertMode Mode, - std::span Data, - std::span ChunkHashes, - std::span Indexes, - std::vector Results) +GetFileCasResults(FileCasStrategy& Strategy, + CasStore::InsertMode Mode, + std::span Data, + std::span ChunkHashes, + std::span Indexes, + std::vector& Results) { for (size_t Index : Indexes) { diff --git a/src/zentest-appstub/xmake.lua b/src/zentest-appstub/xmake.lua index db3ff2e2d..844ba82ef 100644 --- a/src/zentest-appstub/xmake.lua +++ b/src/zentest-appstub/xmake.lua @@ -6,8 +6,6 @@ target("zentest-appstub") add_headerfiles("**.h") add_files("*.cpp") add_deps("zencore") - add_packages("vcpkg::gsl-lite") -- this should ideally be propagated by the zencore dependency - add_packages("vcpkg::mimalloc") if is_os("linux") then add_syslinks("pthread") -- cgit v1.2.3 From 3cfc1b18f6b86b9830730f0055b8e3b955b77c95 Mon Sep 17 00:00:00 2001 From: Stefan Boberg Date: Tue, 24 Feb 2026 15:36:59 +0100 Subject: Add `zen ui` command (#779) Allows user to automate launching of zenserver dashboard, including when multiple instances are running. If multiple instances are running you can open all dashboards with `--all`, and also using the in-terminal chooser which also allows you to open a specific instance. Also includes a fix to `zen exec` when using offset/stride/limit --- CHANGELOG.md | 1 + src/zen/cmds/exec_cmd.cpp | 9 +- src/zen/cmds/ui_cmd.cpp | 236 +++++++++++++++ src/zen/cmds/ui_cmd.h | 32 ++ src/zen/progressbar.cpp | 55 +--- src/zen/progressbar.h | 1 - src/zen/zen.cpp | 6 +- src/zencore/include/zencore/process.h | 1 + src/zencore/process.cpp | 226 +++++++++++++++ src/zenutil/consoletui.cpp | 483 +++++++++++++++++++++++++++++++ src/zenutil/include/zenutil/consoletui.h | 59 ++++ 11 files changed, 1055 insertions(+), 54 deletions(-) create mode 100644 src/zen/cmds/ui_cmd.cpp create mode 100644 src/zen/cmds/ui_cmd.h create mode 100644 src/zenutil/consoletui.cpp create mode 100644 src/zenutil/include/zenutil/consoletui.h diff --git a/CHANGELOG.md b/CHANGELOG.md index af2414682..3670e451e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,5 @@ ## +- Feature: `zen ui` can be used to open dashboards for local instances - Bugfix: `--plain-progress` style progress bar should now show elapsed time correctly - Bugfix: Time spent indexing local and remote state during `zen builds download` now show the correct time diff --git a/src/zen/cmds/exec_cmd.cpp b/src/zen/cmds/exec_cmd.cpp index 2d9d0d12e..407f42ee3 100644 --- a/src/zen/cmds/exec_cmd.cpp +++ b/src/zen/cmds/exec_cmd.cpp @@ -360,6 +360,13 @@ ExecCommand::ExecUsingSession(zen::compute::FunctionServiceSession& FunctionSess return false; }; + int TargetParallelism = 8; + + if (OffsetCounter || StrideCounter || m_Limit) + { + TargetParallelism = 1; + } + m_RecordingReader->IterateActions( [&](CbObject ActionObject, const IoHash& ActionId) { // Enqueue job @@ -444,7 +451,7 @@ ExecCommand::ExecUsingSession(zen::compute::FunctionServiceSession& FunctionSess DrainCompletedJobs(); }, - 8); + TargetParallelism); // Wait until all pending work is complete diff --git a/src/zen/cmds/ui_cmd.cpp b/src/zen/cmds/ui_cmd.cpp new file mode 100644 index 000000000..da06ce305 --- /dev/null +++ b/src/zen/cmds/ui_cmd.cpp @@ -0,0 +1,236 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#include "ui_cmd.h" + +#include +#include +#include +#include +#include +#include + +#if ZEN_PLATFORM_WINDOWS +# include +# include +#endif + +namespace zen { + +namespace { + + struct RunningServerInfo + { + uint16_t Port; + uint32_t Pid; + std::string SessionId; + std::string CmdLine; + }; + + static std::vector CollectRunningServers() + { + std::vector Servers; + ZenServerState State; + if (!State.InitializeReadOnly()) + return Servers; + + State.Snapshot([&](const ZenServerState::ZenServerEntry& Entry) { + StringBuilder<25> SessionSB; + Entry.GetSessionId().ToString(SessionSB); + std::error_code CmdLineEc; + std::string CmdLine = GetProcessCommandLine(static_cast(Entry.Pid.load()), CmdLineEc); + Servers.push_back({Entry.EffectiveListenPort.load(), Entry.Pid.load(), std::string(SessionSB.c_str()), std::move(CmdLine)}); + }); + + return Servers; + } + +} // namespace + +UiCommand::UiCommand() +{ + m_Options.add_options()("h,help", "Print help"); + m_Options.add_options()("a,all", "Open dashboard for all running instances", cxxopts::value(m_All)->default_value("false")); + m_Options.add_option("", "u", "hosturl", "Host URL", cxxopts::value(m_HostName)->default_value(""), ""); + m_Options.add_option("", + "p", + "path", + "Dashboard path (default: /dashboard/)", + cxxopts::value(m_DashboardPath)->default_value("/dashboard/"), + ""); + m_Options.parse_positional("path"); +} + +UiCommand::~UiCommand() +{ +} + +void +UiCommand::OpenBrowser(std::string_view HostName) +{ + // Allow shortcuts for specifying dashboard path, and ensure it is in a format we expect + // (leading slash, trailing slash if no file extension) + + if (!m_DashboardPath.empty()) + { + if (m_DashboardPath[0] != '/') + { + m_DashboardPath = "/dashboard/" + m_DashboardPath; + } + + if (m_DashboardPath.find_last_of('.') == std::string::npos && m_DashboardPath.back() != '/') + { + m_DashboardPath += '/'; + } + } + + bool Success = false; + + ExtendableStringBuilder<256> FullUrl; + FullUrl << HostName << m_DashboardPath; + +#if ZEN_PLATFORM_WINDOWS + HINSTANCE Result = ShellExecuteA(nullptr, "open", FullUrl.c_str(), nullptr, nullptr, SW_SHOWNORMAL); + Success = reinterpret_cast(Result) > 32; +#else + // Validate URL doesn't contain shell metacharacters that could lead to command injection + std::string_view FullUrlView = FullUrl; + constexpr std::string_view DangerousChars = ";|&$`\\\"'<>(){}[]!#*?~\n\r"; + if (FullUrlView.find_first_of(DangerousChars) != std::string_view::npos) + { + throw OptionParseException(fmt::format("URL contains invalid characters: '{}'", FullUrl), m_Options.help()); + } + +# if ZEN_PLATFORM_MAC + std::string Command = fmt::format("open \"{}\"", FullUrl); +# elif ZEN_PLATFORM_LINUX + std::string Command = fmt::format("xdg-open \"{}\"", FullUrl); +# else + ZEN_NOT_IMPLEMENTED("Browser launching not implemented on this platform"); +# endif + + Success = system(Command.c_str()) == 0; +#endif + + if (!Success) + { + throw zen::runtime_error("Failed to launch browser for '{}'", FullUrl); + } + + ZEN_CONSOLE("Web browser launched for '{}' successfully", FullUrl); +} + +void +UiCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) +{ + using namespace std::literals; + + ZEN_UNUSED(GlobalOptions); + + if (!ParseOptions(argc, argv)) + { + return; + } + + // Resolve target server + uint16_t ServerPort = 0; + + if (m_HostName.empty()) + { + // Auto-discover running instances. + std::vector Servers = CollectRunningServers(); + + if (m_All) + { + if (Servers.empty()) + { + throw OptionParseException("No running Zen server instances found", m_Options.help()); + } + + for (const auto& Server : Servers) + { + OpenBrowser(fmt::format("http://localhost:{}", Server.Port)); + } + return; + } + + // If multiple are found and we have an interactive terminal, present a picker + // instead of silently using the first one. + if (Servers.size() > 1 && IsTuiAvailable()) + { + std::vector Labels; + Labels.reserve(Servers.size() + 1); + Labels.push_back(fmt::format("(all {} instances)", Servers.size())); + + const int32_t Cols = static_cast(TuiConsoleColumns()); + constexpr int32_t kIndicator = 3; // " ▶ " or " " prefix + constexpr int32_t kSeparator = 2; // " " before cmdline + constexpr int32_t kEllipsis = 3; // "..." + + for (const auto& Server : Servers) + { + std::string Label = fmt::format("port {:<5} pid {:<7} session {}", Server.Port, Server.Pid, Server.SessionId); + + if (!Server.CmdLine.empty()) + { + int32_t Available = Cols - kIndicator - kSeparator - static_cast(Label.size()); + if (Available > kEllipsis) + { + Label += " "; + if (static_cast(Server.CmdLine.size()) <= Available) + { + Label += Server.CmdLine; + } + else + { + Label.append(Server.CmdLine, 0, static_cast(Available - kEllipsis)); + Label += "..."; + } + } + } + + Labels.push_back(std::move(Label)); + } + + int SelectedIdx = TuiPickOne("Multiple Zen server instances found. Select one to open:", Labels); + if (SelectedIdx < 0) + return; // User cancelled + + if (SelectedIdx == 0) + { + // "All" selected + for (const auto& Server : Servers) + { + OpenBrowser(fmt::format("http://localhost:{}", Server.Port)); + } + return; + } + + ServerPort = Servers[SelectedIdx - 1].Port; + m_HostName = fmt::format("http://localhost:{}", ServerPort); + } + + if (m_HostName.empty()) + { + // Single or zero instances, or not an interactive terminal: + // fall back to default resolution (picks first instance or returns empty) + m_HostName = ResolveTargetHostSpec("", ServerPort); + } + } + else + { + if (m_All) + { + throw OptionParseException("--all cannot be used together with --hosturl", m_Options.help()); + } + m_HostName = ResolveTargetHostSpec(m_HostName, ServerPort); + } + + if (m_HostName.empty()) + { + throw OptionParseException("Unable to resolve server specification", m_Options.help()); + } + + OpenBrowser(m_HostName); +} + +} // namespace zen diff --git a/src/zen/cmds/ui_cmd.h b/src/zen/cmds/ui_cmd.h new file mode 100644 index 000000000..c74cdbbd0 --- /dev/null +++ b/src/zen/cmds/ui_cmd.h @@ -0,0 +1,32 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "../zen.h" + +#include + +namespace zen { + +class UiCommand : public ZenCmdBase +{ +public: + UiCommand(); + ~UiCommand(); + + static constexpr char Name[] = "ui"; + static constexpr char Description[] = "Launch web browser with zen server UI"; + + virtual void Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) override; + virtual cxxopts::Options& Options() override { return m_Options; } + +private: + void OpenBrowser(std::string_view HostName); + + cxxopts::Options m_Options{Name, Description}; + std::string m_HostName; + std::string m_DashboardPath = "/dashboard/"; + bool m_All = false; +}; + +} // namespace zen diff --git a/src/zen/progressbar.cpp b/src/zen/progressbar.cpp index 1ee1d1e71..732f16e81 100644 --- a/src/zen/progressbar.cpp +++ b/src/zen/progressbar.cpp @@ -8,16 +8,12 @@ #include #include #include +#include ZEN_THIRD_PARTY_INCLUDES_START #include ZEN_THIRD_PARTY_INCLUDES_END -#if ZEN_PLATFORM_LINUX || ZEN_PLATFORM_MAC -# include -# include -#endif - ////////////////////////////////////////////////////////////////////////// namespace zen { @@ -31,35 +27,12 @@ GetConsoleHandle() } #endif -static bool -CheckStdoutTty() -{ -#if ZEN_PLATFORM_WINDOWS - HANDLE hStdOut = GetConsoleHandle(); - DWORD dwMode = 0; - static bool IsConsole = ::GetConsoleMode(hStdOut, &dwMode); - return IsConsole; -#else - return isatty(fileno(stdout)); -#endif -} - -static bool -IsStdoutTty() -{ - static bool StdoutIsTty = CheckStdoutTty(); - return StdoutIsTty; -} - static void OutputToConsoleRaw(const char* String, size_t Length) { #if ZEN_PLATFORM_WINDOWS HANDLE hStdOut = GetConsoleHandle(); -#endif - -#if ZEN_PLATFORM_WINDOWS - if (IsStdoutTty()) + if (TuiIsStdoutTty()) { WriteConsoleA(hStdOut, String, (DWORD)Length, 0, 0); } @@ -84,26 +57,6 @@ OutputToConsoleRaw(const StringBuilderBase& SB) OutputToConsoleRaw(SB.c_str(), SB.Size()); } -uint32_t -GetConsoleColumns(uint32_t Default) -{ -#if ZEN_PLATFORM_WINDOWS - HANDLE hStdOut = GetConsoleHandle(); - CONSOLE_SCREEN_BUFFER_INFO csbi; - if (GetConsoleScreenBufferInfo(hStdOut, &csbi) == TRUE) - { - return (uint32_t)(csbi.srWindow.Right - csbi.srWindow.Left + 1); - } -#else - struct winsize w; - if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == 0) - { - return (uint32_t)w.ws_col; - } -#endif - return Default; -} - uint32_t GetUpdateDelayMS(ProgressBar::Mode InMode) { @@ -165,7 +118,7 @@ ProgressBar::PopLogOperation(Mode InMode) } ProgressBar::ProgressBar(Mode InMode, std::string_view InSubTask) -: m_Mode((!IsStdoutTty() && InMode == Mode::Pretty) ? Mode::Plain : InMode) +: m_Mode((!TuiIsStdoutTty() && InMode == Mode::Pretty) ? Mode::Plain : InMode) , m_LastUpdateMS((uint64_t)-1) , m_PausedMS(0) , m_SubTask(InSubTask) @@ -257,7 +210,7 @@ ProgressBar::UpdateState(const State& NewState, bool DoLinebreak) uint64_t ETAMS = (NewState.Status == State::EStatus::Running) && (PercentDone > 5) ? (ETAElapsedMS * NewState.RemainingCount) / Completed : 0; - uint32_t ConsoleColumns = GetConsoleColumns(1024); + uint32_t ConsoleColumns = TuiConsoleColumns(1024); const std::string PercentString = fmt::format("{:#3}%", PercentDone); diff --git a/src/zen/progressbar.h b/src/zen/progressbar.h index bbdb008d4..cb1c7023b 100644 --- a/src/zen/progressbar.h +++ b/src/zen/progressbar.h @@ -76,7 +76,6 @@ private: }; uint32_t GetUpdateDelayMS(ProgressBar::Mode InMode); -uint32_t GetConsoleColumns(uint32_t Default); OperationLogOutput* CreateConsoleLogOutput(ProgressBar::Mode InMode); diff --git a/src/zen/zen.cpp b/src/zen/zen.cpp index bdc2b4003..dc37cb56b 100644 --- a/src/zen/zen.cpp +++ b/src/zen/zen.cpp @@ -22,6 +22,7 @@ #include "cmds/status_cmd.h" #include "cmds/top_cmd.h" #include "cmds/trace_cmd.h" +#include "cmds/ui_cmd.h" #include "cmds/up_cmd.h" #include "cmds/version_cmd.h" #include "cmds/vfs_cmd.h" @@ -41,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -123,7 +125,7 @@ ZenCmdBase::ParseOptions(int argc, char** argv) bool ZenCmdBase::ParseOptions(cxxopts::Options& CmdOptions, int argc, char** argv) { - CmdOptions.set_width(GetConsoleColumns(80)); + CmdOptions.set_width(TuiConsoleColumns(80)); cxxopts::ParseResult Result; @@ -364,6 +366,7 @@ main(int argc, char** argv) LoggingCommand LoggingCmd; TopCommand TopCmd; TraceCommand TraceCmd; + UiCommand UiCmd; UpCommand UpCmd; VersionCommand VersionCmd; VfsCommand VfsCmd; @@ -425,6 +428,7 @@ main(int argc, char** argv) {StatusCommand::Name, &StatusCmd, StatusCommand::Description}, {TopCommand::Name, &TopCmd, TopCommand::Description}, {TraceCommand::Name, &TraceCmd, TraceCommand::Description}, + {UiCommand::Name, &UiCmd, UiCommand::Description}, {UpCommand::Name, &UpCmd, UpCommand::Description}, {VersionCommand::Name, &VersionCmd, VersionCommand::Description}, {VfsCommand::Name, &VfsCmd, VfsCommand::Description}, diff --git a/src/zencore/include/zencore/process.h b/src/zencore/include/zencore/process.h index e3b7a70d7..c51163a68 100644 --- a/src/zencore/include/zencore/process.h +++ b/src/zencore/include/zencore/process.h @@ -105,6 +105,7 @@ int GetCurrentProcessId(); int GetProcessId(CreateProcResult ProcId); std::filesystem::path GetProcessExecutablePath(int Pid, std::error_code& OutEc); +std::string GetProcessCommandLine(int Pid, std::error_code& OutEc); std::error_code FindProcess(const std::filesystem::path& ExecutableImage, ProcessHandle& OutHandle, bool IncludeSelf = true); /** Wait for all threads in the current process to exit (except the calling thread) diff --git a/src/zencore/process.cpp b/src/zencore/process.cpp index 56849a10d..4a2668912 100644 --- a/src/zencore/process.cpp +++ b/src/zencore/process.cpp @@ -1001,6 +1001,232 @@ GetProcessExecutablePath(int Pid, std::error_code& OutEc) #endif // ZEN_PLATFORM_LINUX } +std::string +GetProcessCommandLine(int Pid, std::error_code& OutEc) +{ +#if ZEN_PLATFORM_WINDOWS + HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, static_cast(Pid)); + if (!hProcess) + { + OutEc = MakeErrorCodeFromLastError(); + return {}; + } + auto _ = MakeGuard([hProcess] { CloseHandle(hProcess); }); + + // NtQueryInformationProcess is an undocumented NT API; load it dynamically. + // Info class 60 = ProcessCommandLine, available since Windows 8.1. + using PFN_NtQIP = LONG(WINAPI*)(HANDLE, UINT, PVOID, ULONG, PULONG); + static const PFN_NtQIP s_NtQIP = + reinterpret_cast(GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtQueryInformationProcess")); + if (!s_NtQIP) + { + return {}; + } + + constexpr UINT ProcessCommandLineClass = 60; + constexpr LONG StatusInfoLengthMismatch = static_cast(0xC0000004L); + + ULONG ReturnLength = 0; + LONG Status = s_NtQIP(hProcess, ProcessCommandLineClass, nullptr, 0, &ReturnLength); + if (Status != StatusInfoLengthMismatch || ReturnLength == 0) + { + return {}; + } + + std::vector Buf(ReturnLength); + Status = s_NtQIP(hProcess, ProcessCommandLineClass, Buf.data(), ReturnLength, &ReturnLength); + if (Status < 0) + { + OutEc = MakeErrorCodeFromLastError(); + return {}; + } + + // Output: UNICODE_STRING header immediately followed by the UTF-16 string data. + // The UNICODE_STRING.Buffer field points into our Buf. + struct LocalUnicodeString + { + USHORT Length; + USHORT MaximumLength; + WCHAR* Buffer; + }; + if (ReturnLength < sizeof(LocalUnicodeString)) + { + return {}; + } + const auto* Us = reinterpret_cast(Buf.data()); + if (Us->Length == 0 || Us->Buffer == nullptr) + { + return {}; + } + + // Skip argv[0]: may be a quoted path ("C:\...\exe.exe") or a bare path + const WCHAR* p = Us->Buffer; + const WCHAR* End = Us->Buffer + Us->Length / sizeof(WCHAR); + if (p < End && *p == L'"') + { + ++p; + while (p < End && *p != L'"') + { + ++p; + } + if (p < End) + { + ++p; // skip closing quote + } + } + else + { + while (p < End && *p != L' ') + { + ++p; + } + } + while (p < End && *p == L' ') + { + ++p; + } + if (p >= End) + { + return {}; + } + + int Utf8Size = WideCharToMultiByte(CP_UTF8, 0, p, static_cast(End - p), nullptr, 0, nullptr, nullptr); + if (Utf8Size <= 0) + { + OutEc = MakeErrorCodeFromLastError(); + return {}; + } + std::string Result(Utf8Size, '\0'); + WideCharToMultiByte(CP_UTF8, 0, p, static_cast(End - p), Result.data(), Utf8Size, nullptr, nullptr); + return Result; + +#elif ZEN_PLATFORM_LINUX + std::string CmdlinePath = fmt::format("/proc/{}/cmdline", Pid); + FILE* F = fopen(CmdlinePath.c_str(), "rb"); + if (!F) + { + OutEc = MakeErrorCodeFromLastError(); + return {}; + } + auto FGuard = MakeGuard([F] { fclose(F); }); + + // /proc/{pid}/cmdline contains null-separated argv entries; read it all + std::string Raw; + char Chunk[4096]; + size_t BytesRead; + while ((BytesRead = fread(Chunk, 1, sizeof(Chunk), F)) > 0) + { + Raw.append(Chunk, BytesRead); + } + if (Raw.empty()) + { + return {}; + } + + // Skip argv[0] (first null-terminated entry) + const char* p = Raw.data(); + const char* End = Raw.data() + Raw.size(); + while (p < End && *p != '\0') + { + ++p; + } + if (p < End) + { + ++p; // skip null terminator of argv[0] + } + + // Build result: remaining entries joined by spaces (inter-arg nulls → spaces) + std::string Result; + Result.reserve(static_cast(End - p)); + for (const char* q = p; q < End; ++q) + { + Result += (*q == '\0') ? ' ' : *q; + } + while (!Result.empty() && Result.back() == ' ') + { + Result.pop_back(); + } + return Result; + +#elif ZEN_PLATFORM_MAC + int Mib[3] = {CTL_KERN, KERN_PROCARGS2, Pid}; + size_t BufSize = 0; + if (sysctl(Mib, 3, nullptr, &BufSize, nullptr, 0) != 0 || BufSize == 0) + { + OutEc = MakeErrorCodeFromLastError(); + return {}; + } + + std::vector Buf(BufSize); + if (sysctl(Mib, 3, Buf.data(), &BufSize, nullptr, 0) != 0) + { + OutEc = MakeErrorCodeFromLastError(); + return {}; + } + + // Layout: [int argc][exec_path\0][null padding][argv[0]\0][argv[1]\0]...[envp\0]... + if (BufSize < sizeof(int)) + { + return {}; + } + int Argc = 0; + memcpy(&Argc, Buf.data(), sizeof(int)); + if (Argc <= 1) + { + return {}; + } + + const char* p = Buf.data() + sizeof(int); + const char* End = Buf.data() + BufSize; + + // Skip exec_path and any trailing null padding that follows it + while (p < End && *p != '\0') + { + ++p; + } + while (p < End && *p == '\0') + { + ++p; + } + + // Skip argv[0] + while (p < End && *p != '\0') + { + ++p; + } + if (p < End) + { + ++p; + } + + // Collect argv[1..Argc-1] + std::string Result; + for (int i = 1; i < Argc && p < End; ++i) + { + if (i > 1) + { + Result += ' '; + } + const char* ArgStart = p; + while (p < End && *p != '\0') + { + ++p; + } + Result.append(ArgStart, p); + if (p < End) + { + ++p; + } + } + return Result; + +#else + ZEN_UNUSED(Pid); + ZEN_UNUSED(OutEc); + return {}; +#endif +} + std::error_code FindProcess(const std::filesystem::path& ExecutableImage, ProcessHandle& OutHandle, bool IncludeSelf) { diff --git a/src/zenutil/consoletui.cpp b/src/zenutil/consoletui.cpp new file mode 100644 index 000000000..4410d463d --- /dev/null +++ b/src/zenutil/consoletui.cpp @@ -0,0 +1,483 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#include + +#include + +#if ZEN_PLATFORM_WINDOWS +# include +#else +# include +# include +# include +# include +#endif + +#include + +namespace zen { + +////////////////////////////////////////////////////////////////////////// +// Platform-specific terminal helpers + +#if ZEN_PLATFORM_WINDOWS + +static bool +CheckIsInteractiveTerminal() +{ + DWORD dwMode = 0; + return GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &dwMode) && GetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), &dwMode); +} + +static void +EnableVirtualTerminal() +{ + HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); + DWORD dwMode = 0; + if (GetConsoleMode(hStdOut, &dwMode)) + { + SetConsoleMode(hStdOut, dwMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING); + } +} + +// RAII guard: sets the console output code page for the lifetime of the object and +// restores the original on destruction. Required for UTF-8 glyphs to render correctly +// via printf/fflush since the default console code page is not UTF-8. +class ConsoleCodePageGuard +{ +public: + explicit ConsoleCodePageGuard(UINT NewCP) : m_OldCP(GetConsoleOutputCP()) { SetConsoleOutputCP(NewCP); } + ~ConsoleCodePageGuard() { SetConsoleOutputCP(m_OldCP); } + +private: + UINT m_OldCP; +}; + +enum class ConsoleKey +{ + Unknown, + ArrowUp, + ArrowDown, + Enter, + Escape, +}; + +static ConsoleKey +ReadKey() +{ + HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); + INPUT_RECORD Record{}; + DWORD dwRead = 0; + while (true) + { + if (!ReadConsoleInputA(hStdin, &Record, 1, &dwRead)) + { + return ConsoleKey::Escape; // treat read error as cancel + } + if (Record.EventType == KEY_EVENT && Record.Event.KeyEvent.bKeyDown) + { + switch (Record.Event.KeyEvent.wVirtualKeyCode) + { + case VK_UP: + return ConsoleKey::ArrowUp; + case VK_DOWN: + return ConsoleKey::ArrowDown; + case VK_RETURN: + return ConsoleKey::Enter; + case VK_ESCAPE: + return ConsoleKey::Escape; + default: + break; + } + } + } +} + +#else // POSIX + +static bool +CheckIsInteractiveTerminal() +{ + return isatty(STDIN_FILENO) && isatty(STDOUT_FILENO); +} + +static void +EnableVirtualTerminal() +{ + // ANSI escape codes are native on POSIX terminals; nothing to do +} + +// RAII guard: switches the terminal to raw/unbuffered input mode and restores +// the original attributes on destruction. +class RawModeGuard +{ +public: + RawModeGuard() + { + if (tcgetattr(STDIN_FILENO, &m_OldAttrs) != 0) + { + return; + } + + struct termios Raw = m_OldAttrs; + Raw.c_iflag &= ~static_cast(BRKINT | ICRNL | INPCK | ISTRIP | IXON); + Raw.c_cflag |= CS8; + Raw.c_lflag &= ~static_cast(ECHO | ICANON | IEXTEN | ISIG); + Raw.c_cc[VMIN] = 1; + Raw.c_cc[VTIME] = 0; + if (tcsetattr(STDIN_FILENO, TCSANOW, &Raw) == 0) + { + m_Valid = true; + } + } + + ~RawModeGuard() + { + if (m_Valid) + { + tcsetattr(STDIN_FILENO, TCSANOW, &m_OldAttrs); + } + } + + bool IsValid() const { return m_Valid; } + +private: + struct termios m_OldAttrs = {}; + bool m_Valid = false; +}; + +static int +ReadByteWithTimeout(int TimeoutMs) +{ + struct pollfd Pfd + { + STDIN_FILENO, POLLIN, 0 + }; + if (poll(&Pfd, 1, TimeoutMs) > 0 && (Pfd.revents & POLLIN)) + { + unsigned char c = 0; + if (read(STDIN_FILENO, &c, 1) == 1) + { + return static_cast(c); + } + } + return -1; +} + +// State for fullscreen live mode (alternate screen + raw input) +static struct termios s_SavedAttrs = {}; +static bool s_InLiveMode = false; + +enum class ConsoleKey +{ + Unknown, + ArrowUp, + ArrowDown, + Enter, + Escape, +}; + +static ConsoleKey +ReadKey() +{ + unsigned char c = 0; + if (read(STDIN_FILENO, &c, 1) != 1) + { + return ConsoleKey::Escape; // treat read error as cancel + } + + if (c == 27) // ESC byte or start of an escape sequence + { + int Next = ReadByteWithTimeout(50); + if (Next == '[') + { + int Final = ReadByteWithTimeout(50); + if (Final == 'A') + { + return ConsoleKey::ArrowUp; + } + if (Final == 'B') + { + return ConsoleKey::ArrowDown; + } + } + return ConsoleKey::Escape; + } + + if (c == '\r' || c == '\n') + { + return ConsoleKey::Enter; + } + + return ConsoleKey::Unknown; +} + +#endif // ZEN_PLATFORM_WINDOWS / POSIX + +////////////////////////////////////////////////////////////////////////// +// Public API + +uint32_t +TuiConsoleColumns(uint32_t Default) +{ +#if ZEN_PLATFORM_WINDOWS + CONSOLE_SCREEN_BUFFER_INFO Csbi = {}; + if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &Csbi)) + { + return static_cast(Csbi.dwSize.X); + } +#else + struct winsize Ws = {}; + if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &Ws) == 0 && Ws.ws_col > 0) + { + return static_cast(Ws.ws_col); + } +#endif + return Default; +} + +void +TuiEnableOutput() +{ + EnableVirtualTerminal(); +#if ZEN_PLATFORM_WINDOWS + SetConsoleOutputCP(CP_UTF8); +#endif +} + +bool +TuiIsStdoutTty() +{ +#if ZEN_PLATFORM_WINDOWS + static bool Cached = [] { + DWORD dwMode = 0; + return GetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), &dwMode) != 0; + }(); + return Cached; +#else + static bool Cached = isatty(STDOUT_FILENO) != 0; + return Cached; +#endif +} + +bool +IsTuiAvailable() +{ + static bool Cached = CheckIsInteractiveTerminal(); + return Cached; +} + +int +TuiPickOne(std::string_view Title, std::span Items) +{ + EnableVirtualTerminal(); + +#if ZEN_PLATFORM_WINDOWS + ConsoleCodePageGuard CodePageGuard(CP_UTF8); +#else + RawModeGuard RawMode; + if (!RawMode.IsValid()) + { + return -1; + } +#endif + + const int Count = static_cast(Items.size()); + int SelectedIndex = 0; + + printf("\n%.*s\n\n", static_cast(Title.size()), Title.data()); + + // Hide cursor during interaction + printf("\033[?25l"); + + // Renders the full entry list and hint footer. + // On subsequent calls, moves the cursor back up first to overwrite the previous output. + bool FirstRender = true; + auto RenderAll = [&] { + if (!FirstRender) + { + printf("\033[%dA", Count + 2); // move up: entries + blank line + hint line + } + FirstRender = false; + + for (int i = 0; i < Count; ++i) + { + bool IsSelected = (i == SelectedIndex); + + printf("\r\033[K"); // erase line + + if (IsSelected) + { + printf("\033[1;7m"); // bold + reverse video + } + + // \xe2\x96\xb6 = U+25B6 BLACK RIGHT-POINTING TRIANGLE (▶) + const char* Indicator = IsSelected ? " \xe2\x96\xb6 " : " "; + + printf("%s%s", Indicator, Items[i].c_str()); + + if (IsSelected) + { + printf("\033[0m"); // reset attributes + } + + printf("\n"); + } + + // Blank separator line + printf("\r\033[K\n"); + + // Hint footer + // \xe2\x86\x91 = U+2191 ↑ \xe2\x86\x93 = U+2193 ↓ + printf( + "\r\033[K \033[2m\xe2\x86\x91/\xe2\x86\x93\033[0m navigate " + "\033[2mEnter\033[0m confirm " + "\033[2mEsc\033[0m cancel\n"); + + fflush(stdout); + }; + + RenderAll(); + + int Result = -1; + bool Done = false; + while (!Done) + { + ConsoleKey Key = ReadKey(); + switch (Key) + { + case ConsoleKey::ArrowUp: + SelectedIndex = (SelectedIndex - 1 + Count) % Count; + RenderAll(); + break; + + case ConsoleKey::ArrowDown: + SelectedIndex = (SelectedIndex + 1) % Count; + RenderAll(); + break; + + case ConsoleKey::Enter: + Result = SelectedIndex; + Done = true; + break; + + case ConsoleKey::Escape: + Done = true; + break; + + default: + break; + } + } + + // Restore cursor and add a blank line for visual separation + printf("\033[?25h\n"); + fflush(stdout); + + return Result; +} + +void +TuiEnterAlternateScreen() +{ + EnableVirtualTerminal(); +#if ZEN_PLATFORM_WINDOWS + SetConsoleOutputCP(CP_UTF8); +#endif + + printf("\033[?1049h"); // Enter alternate screen buffer + printf("\033[?25l"); // Hide cursor + fflush(stdout); + +#if !ZEN_PLATFORM_WINDOWS + if (tcgetattr(STDIN_FILENO, &s_SavedAttrs) == 0) + { + struct termios Raw = s_SavedAttrs; + Raw.c_iflag &= ~static_cast(BRKINT | ICRNL | INPCK | ISTRIP | IXON); + Raw.c_cflag |= CS8; + Raw.c_lflag &= ~static_cast(ECHO | ICANON | IEXTEN | ISIG); + Raw.c_cc[VMIN] = 1; + Raw.c_cc[VTIME] = 0; + if (tcsetattr(STDIN_FILENO, TCSANOW, &Raw) == 0) + { + s_InLiveMode = true; + } + } +#endif +} + +void +TuiExitAlternateScreen() +{ + printf("\033[?25h"); // Show cursor + printf("\033[?1049l"); // Exit alternate screen buffer + fflush(stdout); + +#if !ZEN_PLATFORM_WINDOWS + if (s_InLiveMode) + { + tcsetattr(STDIN_FILENO, TCSANOW, &s_SavedAttrs); + s_InLiveMode = false; + } +#endif +} + +void +TuiCursorHome() +{ + printf("\033[H"); +} + +uint32_t +TuiConsoleRows(uint32_t Default) +{ +#if ZEN_PLATFORM_WINDOWS + CONSOLE_SCREEN_BUFFER_INFO Csbi = {}; + if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &Csbi)) + { + return static_cast(Csbi.srWindow.Bottom - Csbi.srWindow.Top + 1); + } +#else + struct winsize Ws = {}; + if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &Ws) == 0 && Ws.ws_row > 0) + { + return static_cast(Ws.ws_row); + } +#endif + return Default; +} + +bool +TuiPollQuit() +{ +#if ZEN_PLATFORM_WINDOWS + HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); + DWORD dwCount = 0; + if (!GetNumberOfConsoleInputEvents(hStdin, &dwCount) || dwCount == 0) + { + return false; + } + INPUT_RECORD Record{}; + DWORD dwRead = 0; + while (PeekConsoleInputA(hStdin, &Record, 1, &dwRead) && dwRead > 0) + { + ReadConsoleInputA(hStdin, &Record, 1, &dwRead); + if (Record.EventType == KEY_EVENT && Record.Event.KeyEvent.bKeyDown) + { + WORD vk = Record.Event.KeyEvent.wVirtualKeyCode; + char ch = Record.Event.KeyEvent.uChar.AsciiChar; + if (vk == VK_ESCAPE || ch == 'q' || ch == 'Q') + { + return true; + } + } + } + return false; +#else + // Non-blocking read: character 3 = Ctrl+C, 27 = Esc, 'q'/'Q' = quit + int b = ReadByteWithTimeout(0); + return (b == 3 || b == 27 || b == 'q' || b == 'Q'); +#endif +} + +} // namespace zen diff --git a/src/zenutil/include/zenutil/consoletui.h b/src/zenutil/include/zenutil/consoletui.h new file mode 100644 index 000000000..7dc68c126 --- /dev/null +++ b/src/zenutil/include/zenutil/consoletui.h @@ -0,0 +1,59 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include +#include +#include + +namespace zen { + +// Returns the width of the console in columns, or Default if it cannot be determined. +uint32_t TuiConsoleColumns(uint32_t Default = 120); + +// Enables ANSI/VT escape code processing and UTF-8 console output. +// Call once before printing ANSI escape sequences or multi-byte UTF-8 characters via printf. +// Safe to call multiple times. No-op on POSIX (escape codes are native there). +void TuiEnableOutput(); + +// Returns true if stdout is connected to a real terminal (not piped or redirected). +// Useful for deciding whether to use ANSI escape codes for progress output. +bool TuiIsStdoutTty(); + +// Returns true if both stdin and stdout are connected to an interactive terminal +// (i.e. not piped or redirected). Must be checked before calling TuiPickOne(). +bool IsTuiAvailable(); + +// Displays a cursor-navigable single-select list in the terminal. +// +// - Title: a short description printed once above the list +// - Items: pre-formatted display labels, one per selectable entry +// +// Arrow keys (↑/↓) navigate the selection, Enter confirms, Esc cancels. +// Returns the index of the selected item, or -1 if the user cancelled. +// +// Precondition: IsTuiAvailable() must be true. +int TuiPickOne(std::string_view Title, std::span Items); + +// Enter the alternate screen buffer for fullscreen live-update mode. +// Hides the cursor. On POSIX, switches to raw/unbuffered terminal input. +// Must be balanced by a call to TuiExitAlternateScreen(). +// Precondition: IsTuiAvailable() must be true. +void TuiEnterAlternateScreen(); + +// Exit alternate screen buffer. Restores the cursor and, on POSIX, the original +// terminal mode. Safe to call even if TuiEnterAlternateScreen() was not called. +void TuiExitAlternateScreen(); + +// Move the cursor to the top-left corner of the terminal (row 1, col 1). +void TuiCursorHome(); + +// Returns the height of the console in rows, or Default if it cannot be determined. +uint32_t TuiConsoleRows(uint32_t Default = 40); + +// Non-blocking check: returns true if the user has pressed a key that means quit +// (Esc, 'q', 'Q', or Ctrl+C). Consumes the event if one is pending. +// Should only be called while in alternate screen mode. +bool TuiPollQuit(); + +} // namespace zen -- cgit v1.2.3 From eb3079e2ec2969829cbc5b6921575d53df351f0f Mon Sep 17 00:00:00 2001 From: Dan Engelbrecht Date: Tue, 24 Feb 2026 16:10:36 +0100 Subject: use partial blocks for oplog import (#780) Feature: Add --allow-partial-block-requests to zen oplog-import Improvement: zen oplog-import now uses partial block requests to reduce download size Improvement: Use latency to Cloud Storage host and Zen Cache host when calculating partial block requests --- CHANGELOG.md | 3 + src/zen/cmds/builds_cmd.cpp | 28 +- src/zen/cmds/projectstore_cmd.cpp | 28 +- src/zen/cmds/projectstore_cmd.h | 2 + src/zenhttp/httpclient.cpp | 38 + src/zenhttp/include/zenhttp/httpclient.h | 9 + src/zenremotestore/builds/buildstoragecache.cpp | 8 +- .../builds/buildstorageoperations.cpp | 45 +- src/zenremotestore/builds/buildstorageutil.cpp | 19 +- src/zenremotestore/chunking/chunkblock.cpp | 79 +- .../zenremotestore/builds/buildstoragecache.h | 1 + .../zenremotestore/builds/buildstorageoperations.h | 12 +- .../zenremotestore/builds/buildstorageutil.h | 4 + .../include/zenremotestore/chunking/chunkblock.h | 25 +- .../include/zenremotestore/jupiter/jupiterhost.h | 1 + .../include/zenremotestore/operationlogoutput.h | 5 +- .../zenremotestore/partialblockrequestmode.h | 20 + .../projectstore/buildsremoteprojectstore.h | 4 +- .../projectstore/remoteprojectstore.h | 67 +- src/zenremotestore/jupiter/jupiterhost.cpp | 8 +- src/zenremotestore/operationlogoutput.cpp | 2 +- src/zenremotestore/partialblockrequestmode.cpp | 27 + .../projectstore/buildsremoteprojectstore.cpp | 122 ++- .../projectstore/fileremoteprojectstore.cpp | 24 +- .../projectstore/jupiterremoteprojectstore.cpp | 19 +- .../projectstore/remoteprojectstore.cpp | 946 ++++++++++++++++----- .../projectstore/zenremoteprojectstore.cpp | 29 +- .../storage/projectstore/httpprojectstore.cpp | 33 +- 28 files changed, 1246 insertions(+), 362 deletions(-) create mode 100644 src/zenremotestore/include/zenremotestore/partialblockrequestmode.h create mode 100644 src/zenremotestore/partialblockrequestmode.cpp diff --git a/CHANGELOG.md b/CHANGELOG.md index 3670e451e..e9d3b79c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ ## +- Feature: Add `--allow-partial-block-requests` to `zen oplog-import` - Feature: `zen ui` can be used to open dashboards for local instances +- Improvement: `zen oplog-import` now uses partial block requests to reduce download size +- Improvement: Use latency to Cloud Storage host and Zen Cache host when calculating partial block requests - Bugfix: `--plain-progress` style progress bar should now show elapsed time correctly - Bugfix: Time spent indexing local and remote state during `zen builds download` now show the correct time diff --git a/src/zen/cmds/builds_cmd.cpp b/src/zen/cmds/builds_cmd.cpp index 849259013..5254ef3cf 100644 --- a/src/zen/cmds/builds_cmd.cpp +++ b/src/zen/cmds/builds_cmd.cpp @@ -2842,13 +2842,16 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) TempPath / "storage"); Result.StorageName = ResolveRes.HostName; - StorageDescription = fmt::format("Cloud {}{}. SessionId: '{}'. Namespace '{}', Bucket '{}'", - ResolveRes.HostName, - (ResolveRes.HostUrl == ResolveRes.HostName) ? "" : fmt::format(" {}", ResolveRes.HostUrl), - Result.BuildStorageHttp->GetSessionId(), - m_Namespace, - m_Bucket); - ; + uint64_t HostLatencyNs = ResolveRes.HostLatencySec >= 0 ? uint64_t(ResolveRes.HostLatencySec * 1000000000.0) : 0; + + StorageDescription = fmt::format("Cloud {}{}. SessionId: '{}'. Namespace '{}', Bucket '{}'. Latency: {}", + ResolveRes.HostName, + (ResolveRes.HostUrl == ResolveRes.HostName) ? "" : fmt::format(" {}", ResolveRes.HostUrl), + Result.BuildStorageHttp->GetSessionId(), + m_Namespace, + m_Bucket, + NiceLatencyNs(HostLatencyNs)); + Result.BuildStorageLatencySec = ResolveRes.HostLatencySec; if (!ResolveRes.CacheUrl.empty()) { @@ -2874,12 +2877,17 @@ BuildsCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) : GetTinyWorkerPool(EWorkloadType::Background)); Result.CacheName = ResolveRes.CacheName; + uint64_t CacheLatencyNs = ResolveRes.CacheLatencySec >= 0 ? uint64_t(ResolveRes.CacheLatencySec * 1000000000.0) : 0; + CacheDescription = - fmt::format("Zen {}{}. SessionId: '{}'", + fmt::format("Zen {}{}. SessionId: '{}'. Latency: {}", ResolveRes.CacheName, (ResolveRes.CacheUrl == ResolveRes.CacheName) ? "" : fmt::format(" {}", ResolveRes.CacheUrl), - Result.CacheHttp->GetSessionId()); - ; + Result.CacheHttp->GetSessionId(), + NiceLatencyNs(CacheLatencyNs)); + + Result.CacheLatencySec = ResolveRes.CacheLatencySec; + if (!m_Namespace.empty()) { CacheDescription += fmt::format(". Namespace '{}'", m_Namespace); diff --git a/src/zen/cmds/projectstore_cmd.cpp b/src/zen/cmds/projectstore_cmd.cpp index 4de6ad25c..bedab3cfd 100644 --- a/src/zen/cmds/projectstore_cmd.cpp +++ b/src/zen/cmds/projectstore_cmd.cpp @@ -1469,6 +1469,20 @@ ImportOplogCommand::ImportOplogCommand() "Enables both 'boost-worker-count' and 'boost-worker-memory' - may cause computer to be less responsive", cxxopts::value(m_BoostWorkers), ""); + m_Options.add_option( + "", + "", + "allow-partial-block-requests", + "Allow request for partial chunk blocks.\n" + " false = only full block requests allowed\n" + " mixed = multiple partial block ranges requests per block allowed to zen cache, single partial block range " + "request per block to host\n" + " zencacheonly = multiple partial block ranges requests per block allowed to zen cache, only full block requests " + "allowed to host\n" + " true = multiple partial block ranges requests per block allowed to zen cache and host\n" + "Defaults to 'mixed'.", + cxxopts::value(m_AllowPartialBlockRequests), + ""); m_Options.parse_positional({"project", "oplog", "gcpath"}); m_Options.positional_help("[ []]"); @@ -1513,6 +1527,13 @@ ImportOplogCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** arg throw OptionParseException("'--oplog' is required", m_Options.help()); } + EPartialBlockRequestMode Mode = PartialBlockRequestModeFromString(m_AllowPartialBlockRequests); + if (Mode == EPartialBlockRequestMode::Invalid) + { + throw OptionParseException(fmt::format("'--allow-partial-block-requests' ('{}') is invalid", m_AllowPartialBlockRequests), + m_Options.help()); + } + HttpClient Http(m_HostName); m_ProjectName = ResolveProject(Http, m_ProjectName); if (m_ProjectName.empty()) @@ -1649,6 +1670,9 @@ ImportOplogCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** arg { Writer.AddBool("boostworkermemory"sv, true); } + + Writer.AddString("partialblockrequestmode", m_AllowPartialBlockRequests); + if (!m_FileDirectoryPath.empty()) { Writer.BeginObject("file"sv); @@ -2571,6 +2595,7 @@ OplogDownloadCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** a ClientSettings.AssumeHttp2 = ResolveRes.HostAssumeHttp2; ClientSettings.MaximumInMemoryDownloadSize = m_BoostWorkerMemory ? RemoteStoreOptions::DefaultMaxBlockSize : 1024u * 1024u; Storage.BuildStorageHttp = std::make_unique(ResolveRes.HostUrl, ClientSettings); + Storage.BuildStorageLatencySec = ResolveRes.HostLatencySec; BuildStorageCache::Statistics StorageCacheStats; @@ -2589,7 +2614,8 @@ OplogDownloadCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** a .RetryCount = 0, .MaximumInMemoryDownloadSize = m_BoostWorkerMemory ? RemoteStoreOptions::DefaultMaxBlockSize : 1024u * 1024u}, [&AbortFlag]() { return AbortFlag.load(); }); - Storage.CacheName = ResolveRes.CacheName; + Storage.CacheName = ResolveRes.CacheName; + Storage.CacheLatencySec = ResolveRes.CacheLatencySec; } if (!m_Quiet) diff --git a/src/zen/cmds/projectstore_cmd.h b/src/zen/cmds/projectstore_cmd.h index e415b41b7..17fd76e9f 100644 --- a/src/zen/cmds/projectstore_cmd.h +++ b/src/zen/cmds/projectstore_cmd.h @@ -209,6 +209,8 @@ private: bool m_BoostWorkerCount = false; bool m_BoostWorkerMemory = false; bool m_BoostWorkers = false; + + std::string m_AllowPartialBlockRequests = "mixed"; }; class SnapshotOplogCommand : public ProjectStoreCommand diff --git a/src/zenhttp/httpclient.cpp b/src/zenhttp/httpclient.cpp index d3b59df2b..078e27b34 100644 --- a/src/zenhttp/httpclient.cpp +++ b/src/zenhttp/httpclient.cpp @@ -21,6 +21,8 @@ #include "clients/httpclientcommon.h" +#include + #if ZEN_WITH_TESTS # include # include @@ -340,6 +342,42 @@ HttpClient::Authenticate() return m_Inner->Authenticate(); } +LatencyTestResult +MeasureLatency(HttpClient& Client, std::string_view Url) +{ + std::vector MeasurementTimes; + std::string ErrorMessage; + + for (uint32_t AttemptCount = 0; AttemptCount < 20 && MeasurementTimes.size() < 5; AttemptCount++) + { + HttpClient::Response MeasureResponse = Client.Get(Url); + if (MeasureResponse.IsSuccess()) + { + MeasurementTimes.push_back(MeasureResponse.ElapsedSeconds); + Sleep(5); + } + else + { + ErrorMessage = MeasureResponse.ErrorMessage(fmt::format("Unable to measure latency using {}", Url)); + } + } + + if (MeasurementTimes.empty()) + { + return {.Success = false, .FailureReason = ErrorMessage}; + } + + if (MeasurementTimes.size() > 2) + { + std::sort(MeasurementTimes.begin(), MeasurementTimes.end()); + MeasurementTimes.pop_back(); // Remove the worst time + } + + double AverageLatency = std::accumulate(MeasurementTimes.begin(), MeasurementTimes.end(), 0.0) / MeasurementTimes.size(); + + return {.Success = true, .LatencySeconds = AverageLatency}; +} + ////////////////////////////////////////////////////////////////////////// #if ZEN_WITH_TESTS diff --git a/src/zenhttp/include/zenhttp/httpclient.h b/src/zenhttp/include/zenhttp/httpclient.h index 9a9b74d72..7a129a98c 100644 --- a/src/zenhttp/include/zenhttp/httpclient.h +++ b/src/zenhttp/include/zenhttp/httpclient.h @@ -260,6 +260,15 @@ private: const HttpClientSettings m_ConnectionSettings; }; +struct LatencyTestResult +{ + bool Success = false; + std::string FailureReason; + double LatencySeconds = -1.0; +}; + +LatencyTestResult MeasureLatency(HttpClient& Client, std::string_view Url); + void httpclient_forcelink(); // internal } // namespace zen diff --git a/src/zenremotestore/builds/buildstoragecache.cpp b/src/zenremotestore/builds/buildstoragecache.cpp index 07fcd62ba..faa85f81b 100644 --- a/src/zenremotestore/builds/buildstoragecache.cpp +++ b/src/zenremotestore/builds/buildstoragecache.cpp @@ -474,7 +474,13 @@ TestZenCacheEndpoint(std::string_view BaseUrl, const bool AssumeHttp2, const boo HttpClient::Response TestResponse = TestHttpClient.Get("/status/builds"); if (TestResponse.IsSuccess()) { - return {.Success = true}; + LatencyTestResult LatencyResult = MeasureLatency(TestHttpClient, "/health"); + + if (!LatencyResult.Success) + { + return {.Success = false, .FailureReason = LatencyResult.FailureReason}; + } + return {.Success = true, .LatencySeconds = LatencyResult.LatencySeconds}; } return {.Success = false, .FailureReason = TestResponse.ErrorMessage("")}; }; diff --git a/src/zenremotestore/builds/buildstorageoperations.cpp b/src/zenremotestore/builds/buildstorageoperations.cpp index 4f1b07c37..5219e86d8 100644 --- a/src/zenremotestore/builds/buildstorageoperations.cpp +++ b/src/zenremotestore/builds/buildstorageoperations.cpp @@ -484,24 +484,6 @@ private: uint64_t FilteredPerSecond = 0; }; -EPartialBlockRequestMode -PartialBlockRequestModeFromString(const std::string_view ModeString) -{ - switch (HashStringAsLowerDjb2(ModeString)) - { - case HashStringDjb2("false"): - return EPartialBlockRequestMode::Off; - case HashStringDjb2("zencacheonly"): - return EPartialBlockRequestMode::ZenCacheOnly; - case HashStringDjb2("mixed"): - return EPartialBlockRequestMode::Mixed; - case HashStringDjb2("true"): - return EPartialBlockRequestMode::All; - default: - return EPartialBlockRequestMode::Invalid; - } -} - std::filesystem::path ZenStateFilePath(const std::filesystem::path& ZenFolderPath) { @@ -903,7 +885,10 @@ BuildsOperationUpdateFolder::Execute(FolderContent& OutLocalFolderState) { ChunkBlockAnalyser BlockAnalyser(m_LogOutput, m_BlockDescriptions, - ChunkBlockAnalyser::Options{.IsQuiet = m_Options.IsQuiet, .IsVerbose = m_Options.IsVerbose}); + ChunkBlockAnalyser::Options{.IsQuiet = m_Options.IsQuiet, + .IsVerbose = m_Options.IsVerbose, + .HostLatencySec = m_Storage.BuildStorageLatencySec, + .HostHighSpeedLatencySec = m_Storage.CacheLatencySec}); std::vector NeededBlocks = BlockAnalyser.GetNeeded( m_RemoteLookup.ChunkHashToChunkIndex, @@ -1034,25 +1019,29 @@ BuildsOperationUpdateFolder::Execute(FolderContent& OutLocalFolderState) { BlockPartialDownloadModes.resize(m_BlockDescriptions.size(), ChunkBlockAnalyser::EPartialBlockDownloadMode::Off); } - else if (m_Options.PartialBlockRequestMode == EPartialBlockRequestMode::All) - { - BlockPartialDownloadModes.resize(m_BlockDescriptions.size(), ChunkBlockAnalyser::EPartialBlockDownloadMode::On); - } else { BlockPartialDownloadModes.reserve(m_BlockDescriptions.size()); for (uint32_t BlockIndex = 0; BlockIndex < m_BlockDescriptions.size(); BlockIndex++) { const bool BlockExistInCache = ExistsResult.ExistingBlobs.contains(m_BlockDescriptions[BlockIndex].BlockHash); - if (m_Options.PartialBlockRequestMode == EPartialBlockRequestMode::ZenCacheOnly) + if (m_Options.PartialBlockRequestMode == EPartialBlockRequestMode::All) + { + BlockPartialDownloadModes.push_back(BlockExistInCache + ? ChunkBlockAnalyser::EPartialBlockDownloadMode::MultiRangeHighSpeed + : ChunkBlockAnalyser::EPartialBlockDownloadMode::MultiRange); + } + else if (m_Options.PartialBlockRequestMode == EPartialBlockRequestMode::ZenCacheOnly) { - BlockPartialDownloadModes.push_back(BlockExistInCache ? ChunkBlockAnalyser::EPartialBlockDownloadMode::On - : ChunkBlockAnalyser::EPartialBlockDownloadMode::Off); + BlockPartialDownloadModes.push_back(BlockExistInCache + ? ChunkBlockAnalyser::EPartialBlockDownloadMode::MultiRangeHighSpeed + : ChunkBlockAnalyser::EPartialBlockDownloadMode::Off); } else if (m_Options.PartialBlockRequestMode == EPartialBlockRequestMode::Mixed) { - BlockPartialDownloadModes.push_back(BlockExistInCache ? ChunkBlockAnalyser::EPartialBlockDownloadMode::On - : ChunkBlockAnalyser::EPartialBlockDownloadMode::SingleRange); + BlockPartialDownloadModes.push_back(BlockExistInCache + ? ChunkBlockAnalyser::EPartialBlockDownloadMode::MultiRangeHighSpeed + : ChunkBlockAnalyser::EPartialBlockDownloadMode::SingleRange); } } } diff --git a/src/zenremotestore/builds/buildstorageutil.cpp b/src/zenremotestore/builds/buildstorageutil.cpp index 36b45e800..b249d7d52 100644 --- a/src/zenremotestore/builds/buildstorageutil.cpp +++ b/src/zenremotestore/builds/buildstorageutil.cpp @@ -63,11 +63,13 @@ ResolveBuildStorage(OperationLogOutput& Output, std::string HostUrl; std::string HostName; + double HostLatencySec = -1.0; std::string CacheUrl; std::string CacheName; bool HostAssumeHttp2 = ClientSettings.AssumeHttp2; bool CacheAssumeHttp2 = ClientSettings.AssumeHttp2; + double CacheLatencySec = -1.0; JupiterServerDiscovery DiscoveryResponse; const std::string_view DiscoveryHost = Host.empty() ? OverrideHost : Host; @@ -98,8 +100,9 @@ ResolveBuildStorage(OperationLogOutput& Output, { ZEN_OPERATION_LOG_INFO(Output, "Server endpoint at '{}/api/v1/status/servers' succeeded", OverrideHost); } - HostUrl = OverrideHost; - HostName = GetHostNameFromUrl(OverrideHost); + HostUrl = OverrideHost; + HostName = GetHostNameFromUrl(OverrideHost); + HostLatencySec = TestResult.LatencySeconds; } else { @@ -137,6 +140,7 @@ ResolveBuildStorage(OperationLogOutput& Output, HostUrl = ServerEndpoint.BaseUrl; HostAssumeHttp2 = ServerEndpoint.AssumeHttp2; HostName = ServerEndpoint.Name; + HostLatencySec = TestResult.LatencySeconds; break; } else @@ -183,6 +187,7 @@ ResolveBuildStorage(OperationLogOutput& Output, CacheUrl = CacheEndpoint.BaseUrl; CacheAssumeHttp2 = CacheEndpoint.AssumeHttp2; CacheName = CacheEndpoint.Name; + CacheLatencySec = TestResult.LatencySeconds; break; } } @@ -204,6 +209,7 @@ ResolveBuildStorage(OperationLogOutput& Output, CacheUrl = ZenServerLocalHostUrl; CacheAssumeHttp2 = false; CacheName = "localhost"; + CacheLatencySec = TestResult.LatencySeconds; } } }); @@ -219,8 +225,9 @@ ResolveBuildStorage(OperationLogOutput& Output, if (ZenCacheEndpointTestResult TestResult = TestZenCacheEndpoint(ZenCacheHost, /*AssumeHttp2*/ false, ClientSettings.Verbose); TestResult.Success) { - CacheUrl = ZenCacheHost; - CacheName = GetHostNameFromUrl(ZenCacheHost); + CacheUrl = ZenCacheHost; + CacheName = GetHostNameFromUrl(ZenCacheHost); + CacheLatencySec = TestResult.LatencySeconds; } else { @@ -231,10 +238,12 @@ ResolveBuildStorage(OperationLogOutput& Output, return BuildStorageResolveResult{.HostUrl = HostUrl, .HostName = HostName, .HostAssumeHttp2 = HostAssumeHttp2, + .HostLatencySec = HostLatencySec, .CacheUrl = CacheUrl, .CacheName = CacheName, - .CacheAssumeHttp2 = CacheAssumeHttp2}; + .CacheAssumeHttp2 = CacheAssumeHttp2, + .CacheLatencySec = CacheLatencySec}; } std::vector diff --git a/src/zenremotestore/chunking/chunkblock.cpp b/src/zenremotestore/chunking/chunkblock.cpp index 06cedae3f..d203e0292 100644 --- a/src/zenremotestore/chunking/chunkblock.cpp +++ b/src/zenremotestore/chunking/chunkblock.cpp @@ -597,7 +597,7 @@ ChunkBlockAnalyser::CalculatePartialBlockDownloads(std::span if (MaybeBlockRanges.has_value()) { - const std::vector& BlockRanges = MaybeBlockRanges.value(); + std::vector BlockRanges = MaybeBlockRanges.value(); ZEN_ASSERT(!BlockRanges.empty()); uint64_t RequestedSize = @@ -606,12 +606,54 @@ ChunkBlockAnalyser::CalculatePartialBlockDownloads(std::span uint64_t(0), [](uint64_t Current, const BlockRangeDescriptor& Range) { return Current + Range.RangeLength; }); - if ((PartialBlockDownloadMode != EPartialBlockDownloadMode::Exact) && ((RequestedSize * 100) / TotalBlockSize) >= 200) + if (PartialBlockDownloadMode != EPartialBlockDownloadMode::Exact && BlockRanges.size() > 1) + { + // TODO: Once we have support in our http client to request multiple ranges in one request this + // logic would need to change as the per-request overhead would go away + + const double LatencySec = PartialBlockDownloadMode == EPartialBlockDownloadMode::MultiRangeHighSpeed + ? m_Options.HostHighSpeedLatencySec + : m_Options.HostLatencySec; + if (LatencySec > 0) + { + const uint64_t BytesPerSec = PartialBlockDownloadMode == EPartialBlockDownloadMode::MultiRangeHighSpeed + ? m_Options.HostHighSpeedBytesPerSec + : m_Options.HostSpeedBytesPerSec; + + const double ExtraRequestTimeSec = (BlockRanges.size() - 1) * LatencySec; + const uint64_t ExtraRequestTimeBytes = uint64_t(ExtraRequestTimeSec * BytesPerSec); + + const uint64_t FullRangeSize = + BlockRanges.back().RangeStart + BlockRanges.back().RangeLength - BlockRanges.front().RangeStart; + + if (ExtraRequestTimeBytes + RequestedSize >= FullRangeSize) + { + BlockRanges = std::vector{MergeBlockRanges(BlockRanges)}; + + if (m_Options.IsVerbose) + { + ZEN_OPERATION_LOG_INFO(m_LogOutput, + "Merging {} chunks ({}) from block {} ({}) to single request (extra bytes {})", + NeededBlock.ChunkIndexes.size(), + NiceBytes(RequestedSize), + BlockDescription.BlockHash, + NiceBytes(TotalBlockSize), + NiceBytes(BlockRanges.front().RangeLength - RequestedSize)); + } + + RequestedSize = BlockRanges.front().RangeLength; + } + } + } + + if ((PartialBlockDownloadMode != EPartialBlockDownloadMode::Exact) && + ((TotalBlockSize - RequestedSize) < (512u * 1024u))) { if (m_Options.IsVerbose) { ZEN_OPERATION_LOG_INFO(m_LogOutput, - "Requesting {} chunks ({}) from block {} ({}) using full block request (extra bytes {})", + "Requesting {} chunks ({}) from block {} ({}) using full block request due to small " + "total slack (extra bytes {})", NeededBlock.ChunkIndexes.size(), NiceBytes(RequestedSize), BlockDescription.BlockHash, @@ -624,19 +666,16 @@ ChunkBlockAnalyser::CalculatePartialBlockDownloads(std::span { Result.BlockRanges.insert(Result.BlockRanges.end(), BlockRanges.begin(), BlockRanges.end()); - if (RequestedSize > TotalWantedChunksSize) + if (m_Options.IsVerbose) { - if (m_Options.IsVerbose) - { - ZEN_OPERATION_LOG_INFO(m_LogOutput, - "Requesting {} chunks ({}) from block {} ({}) using {} requests (extra bytes {})", - NeededBlock.ChunkIndexes.size(), - NiceBytes(RequestedSize), - BlockDescription.BlockHash, - NiceBytes(TotalBlockSize), - BlockRanges.size(), - NiceBytes(RequestedSize - TotalWantedChunksSize)); - } + ZEN_OPERATION_LOG_INFO(m_LogOutput, + "Requesting {} chunks ({}) from block {} ({}) using {} requests (extra bytes {})", + NeededBlock.ChunkIndexes.size(), + NiceBytes(RequestedSize), + BlockDescription.BlockHash, + NiceBytes(TotalBlockSize), + BlockRanges.size(), + NiceBytes(RequestedSize - TotalWantedChunksSize)); } } } @@ -786,7 +825,7 @@ ChunkBlockAnalyser::CollapseBlockRanges(const uint64_t AlwaysAcceptableGap, std: }; uint64_t -ChunkBlockAnalyser::CalculateNextGap(std::span BlockRanges) +ChunkBlockAnalyser::CalculateNextGap(const uint64_t AlwaysAcceptableGap, std::span BlockRanges) { ZEN_ASSERT(BlockRanges.size() > 1); uint64_t AcceptableGap = (uint64_t)-1; @@ -798,7 +837,7 @@ ChunkBlockAnalyser::CalculateNextGap(std::span Block const uint64_t Gap = NextRange.RangeStart - (Range.RangeStart + Range.RangeLength); AcceptableGap = Min(Gap, AcceptableGap); } - AcceptableGap = RoundUp(AcceptableGap, 16u * 1024u); + AcceptableGap = RoundUp(AcceptableGap, AlwaysAcceptableGap); return AcceptableGap; }; @@ -949,10 +988,12 @@ ChunkBlockAnalyser::CalculateBlockRanges(uint32_t BlockIndex, return MakeOptionalBlockRangeVector(TotalBlockSize, MergedRange); } - std::vector CollapsedBlockRanges = CollapseBlockRanges(16u * 1024u, BlockRanges); + const uint64_t AlwaysAcceptableGap = 4u * 1024u; + + std::vector CollapsedBlockRanges = CollapseBlockRanges(AlwaysAcceptableGap, BlockRanges); while (GetBlockRangeLimitForRange(ForceMergeLimits, TotalBlockSize, CollapsedBlockRanges)) { - CollapsedBlockRanges = CollapseBlockRanges(CalculateNextGap(CollapsedBlockRanges), CollapsedBlockRanges); + CollapsedBlockRanges = CollapseBlockRanges(CalculateNextGap(AlwaysAcceptableGap, CollapsedBlockRanges), CollapsedBlockRanges); } const std::uint64_t WantedCollapsedSize = diff --git a/src/zenremotestore/include/zenremotestore/builds/buildstoragecache.h b/src/zenremotestore/include/zenremotestore/builds/buildstoragecache.h index bb5b1c5f4..f25ce5b5e 100644 --- a/src/zenremotestore/include/zenremotestore/builds/buildstoragecache.h +++ b/src/zenremotestore/include/zenremotestore/builds/buildstoragecache.h @@ -65,6 +65,7 @@ struct ZenCacheEndpointTestResult { bool Success = false; std::string FailureReason; + double LatencySeconds = -1.0; }; ZenCacheEndpointTestResult TestZenCacheEndpoint(std::string_view BaseUrl, const bool AssumeHttp2, const bool HttpVerbose); diff --git a/src/zenremotestore/include/zenremotestore/builds/buildstorageoperations.h b/src/zenremotestore/include/zenremotestore/builds/buildstorageoperations.h index 6800444e0..31733569e 100644 --- a/src/zenremotestore/include/zenremotestore/builds/buildstorageoperations.h +++ b/src/zenremotestore/include/zenremotestore/builds/buildstorageoperations.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -109,17 +110,6 @@ struct RebuildFolderStateStatistics uint64_t FinalizeTreeElapsedWallTimeUs = 0; }; -enum EPartialBlockRequestMode -{ - Off, - ZenCacheOnly, - Mixed, - All, - Invalid -}; - -EPartialBlockRequestMode PartialBlockRequestModeFromString(const std::string_view ModeString); - std::filesystem::path ZenStateFilePath(const std::filesystem::path& ZenFolderPath); std::filesystem::path ZenTempFolderPath(const std::filesystem::path& ZenFolderPath); diff --git a/src/zenremotestore/include/zenremotestore/builds/buildstorageutil.h b/src/zenremotestore/include/zenremotestore/builds/buildstorageutil.h index ab3037c89..4b85d8f1e 100644 --- a/src/zenremotestore/include/zenremotestore/builds/buildstorageutil.h +++ b/src/zenremotestore/include/zenremotestore/builds/buildstorageutil.h @@ -17,10 +17,12 @@ struct BuildStorageResolveResult std::string HostUrl; std::string HostName; bool HostAssumeHttp2 = false; + double HostLatencySec = -1.0; std::string CacheUrl; std::string CacheName; bool CacheAssumeHttp2 = false; + double CacheLatencySec = -1.0; }; enum class ZenCacheResolveMode @@ -54,9 +56,11 @@ struct StorageInstance std::unique_ptr BuildStorageHttp; std::unique_ptr BuildStorage; std::string StorageName; + double BuildStorageLatencySec = -1.0; std::unique_ptr CacheHttp; std::unique_ptr BuildCacheStorage; std::string CacheName; + double CacheLatencySec = -1.0; }; } // namespace zen diff --git a/src/zenremotestore/include/zenremotestore/chunking/chunkblock.h b/src/zenremotestore/include/zenremotestore/chunking/chunkblock.h index 57710fcf5..5a17ef79c 100644 --- a/src/zenremotestore/include/zenremotestore/chunking/chunkblock.h +++ b/src/zenremotestore/include/zenremotestore/chunking/chunkblock.h @@ -82,8 +82,12 @@ class ChunkBlockAnalyser public: struct Options { - bool IsQuiet = false; - bool IsVerbose = false; + bool IsQuiet = false; + bool IsVerbose = false; + double HostLatencySec = -1.0; + double HostHighSpeedLatencySec = -1.0; + uint64_t HostSpeedBytesPerSec = (1u * 1024u * 1024u * 1024u) / 8u; // 1GBit + uint64_t HostHighSpeedBytesPerSec = (2u * 1024u * 1024u * 1024u) / 8u; // 2GBit }; ChunkBlockAnalyser(OperationLogOutput& LogOutput, std::span BlockDescriptions, const Options& Options); @@ -110,7 +114,8 @@ public: { Off, SingleRange, - On, + MultiRange, + MultiRangeHighSpeed, Exact }; @@ -130,14 +135,14 @@ private: uint16_t MaxRangeCount; }; - static constexpr uint16_t FullBlockRangePercentLimit = 95; + static constexpr uint16_t FullBlockRangePercentLimit = 98; static constexpr BlockRangeLimit ForceMergeLimits[] = {{.SizePercent = FullBlockRangePercentLimit, .MaxRangeCount = 1}, - {.SizePercent = 90, .MaxRangeCount = 2}, - {.SizePercent = 85, .MaxRangeCount = 8}, - {.SizePercent = 80, .MaxRangeCount = 16}, - {.SizePercent = 75, .MaxRangeCount = 32}, - {.SizePercent = 70, .MaxRangeCount = 48}, + {.SizePercent = 90, .MaxRangeCount = 4}, + {.SizePercent = 85, .MaxRangeCount = 16}, + {.SizePercent = 80, .MaxRangeCount = 32}, + {.SizePercent = 75, .MaxRangeCount = 48}, + {.SizePercent = 70, .MaxRangeCount = 64}, {.SizePercent = 4, .MaxRangeCount = 82}, {.SizePercent = 0, .MaxRangeCount = 96}}; @@ -149,7 +154,7 @@ private: std::span Ranges); std::vector CollapseBlockRanges(const uint64_t AlwaysAcceptableGap, std::span BlockRanges); - uint64_t CalculateNextGap(std::span BlockRanges); + uint64_t CalculateNextGap(const uint64_t AlwaysAcceptableGap, std::span BlockRanges); std::optional> CalculateBlockRanges(uint32_t BlockIndex, const ChunkBlockDescription& BlockDescription, std::span BlockChunkIndexNeeded, diff --git a/src/zenremotestore/include/zenremotestore/jupiter/jupiterhost.h b/src/zenremotestore/include/zenremotestore/jupiter/jupiterhost.h index 432496bc1..7bbf40dfa 100644 --- a/src/zenremotestore/include/zenremotestore/jupiter/jupiterhost.h +++ b/src/zenremotestore/include/zenremotestore/jupiter/jupiterhost.h @@ -28,6 +28,7 @@ struct JupiterEndpointTestResult { bool Success = false; std::string FailureReason; + double LatencySeconds = -1.0; }; JupiterEndpointTestResult TestJupiterEndpoint(std::string_view BaseUrl, const bool AssumeHttp2, const bool HttpVerbose); diff --git a/src/zenremotestore/include/zenremotestore/operationlogoutput.h b/src/zenremotestore/include/zenremotestore/operationlogoutput.h index 9693e69cf..6f10ab156 100644 --- a/src/zenremotestore/include/zenremotestore/operationlogoutput.h +++ b/src/zenremotestore/include/zenremotestore/operationlogoutput.h @@ -3,6 +3,7 @@ #pragma once #include +#include namespace zen { @@ -57,9 +58,7 @@ public: virtual ProgressBar* CreateProgressBar(std::string_view InSubTask) = 0; }; -struct LoggerRef; - -OperationLogOutput* CreateStandardLogOutput(LoggerRef& Log); +OperationLogOutput* CreateStandardLogOutput(LoggerRef Log); #define ZEN_OPERATION_LOG(OutputTarget, InLevel, fmtstr, ...) \ do \ diff --git a/src/zenremotestore/include/zenremotestore/partialblockrequestmode.h b/src/zenremotestore/include/zenremotestore/partialblockrequestmode.h new file mode 100644 index 000000000..54adea2b2 --- /dev/null +++ b/src/zenremotestore/include/zenremotestore/partialblockrequestmode.h @@ -0,0 +1,20 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include + +namespace zen { + +enum EPartialBlockRequestMode +{ + Off, + ZenCacheOnly, + Mixed, + All, + Invalid +}; + +EPartialBlockRequestMode PartialBlockRequestModeFromString(const std::string_view ModeString); + +} // namespace zen diff --git a/src/zenremotestore/include/zenremotestore/projectstore/buildsremoteprojectstore.h b/src/zenremotestore/include/zenremotestore/projectstore/buildsremoteprojectstore.h index e8b7c15c0..66dfcc62d 100644 --- a/src/zenremotestore/include/zenremotestore/projectstore/buildsremoteprojectstore.h +++ b/src/zenremotestore/include/zenremotestore/projectstore/buildsremoteprojectstore.h @@ -34,6 +34,8 @@ std::shared_ptr CreateJupiterBuildsRemoteStore(LoggerRef bool Quiet, bool Unattended, bool Hidden, - WorkerThreadPool& CacheBackgroundWorkerPool); + WorkerThreadPool& CacheBackgroundWorkerPool, + double& OutHostLatencySec, + double& OutCacheLatencySec); } // namespace zen diff --git a/src/zenremotestore/include/zenremotestore/projectstore/remoteprojectstore.h b/src/zenremotestore/include/zenremotestore/projectstore/remoteprojectstore.h index 008f94351..152c02ee2 100644 --- a/src/zenremotestore/include/zenremotestore/projectstore/remoteprojectstore.h +++ b/src/zenremotestore/include/zenremotestore/projectstore/remoteprojectstore.h @@ -6,6 +6,7 @@ #include #include +#include #include @@ -73,6 +74,16 @@ public: std::vector Blocks; }; + struct GetBlockDescriptionsResult : public Result + { + std::vector Blocks; + }; + + struct AttachmentExistsInCacheResult : public Result + { + std::vector HasBody; + }; + struct RemoteStoreInfo { bool CreateBlocks; @@ -111,10 +122,20 @@ public: virtual FinalizeResult FinalizeContainer(const IoHash& RawHash) = 0; virtual SaveAttachmentsResult SaveAttachments(const std::vector& Payloads) = 0; - virtual LoadContainerResult LoadContainer() = 0; - virtual GetKnownBlocksResult GetKnownBlocks() = 0; - virtual LoadAttachmentResult LoadAttachment(const IoHash& RawHash) = 0; - virtual LoadAttachmentsResult LoadAttachments(const std::vector& RawHashes) = 0; + virtual LoadContainerResult LoadContainer() = 0; + virtual GetKnownBlocksResult GetKnownBlocks() = 0; + virtual GetBlockDescriptionsResult GetBlockDescriptions(std::span BlockHashes) = 0; + virtual AttachmentExistsInCacheResult AttachmentExistsInCache(std::span RawHashes) = 0; + + struct AttachmentRange + { + uint64_t Offset = 0; + uint64_t Bytes = (uint64_t)-1; + + inline operator bool() const { return Offset != 0 || Bytes != (uint64_t)-1; } + }; + virtual LoadAttachmentResult LoadAttachment(const IoHash& RawHash, const AttachmentRange& Range) = 0; + virtual LoadAttachmentsResult LoadAttachments(const std::vector& RawHashes) = 0; virtual void Flush() = 0; }; @@ -153,14 +174,15 @@ RemoteProjectStore::LoadContainerResult BuildContainer( class JobContext; -RemoteProjectStore::Result SaveOplogContainer(ProjectStore::Oplog& Oplog, - const CbObject& ContainerObject, - const std::function RawHashes)>& OnReferencedAttachments, - const std::function& HasAttachment, - const std::function&& Chunks)>& OnNeedBlock, - const std::function& OnNeedAttachment, - const std::function& OnChunkedAttachment, - JobContext* OptionalContext); +RemoteProjectStore::Result SaveOplogContainer( + ProjectStore::Oplog& Oplog, + const CbObject& ContainerObject, + const std::function RawHashes)>& OnReferencedAttachments, + const std::function& HasAttachment, + const std::function&& NeededChunkIndexes)>& OnNeedBlock, + const std::function& OnNeedAttachment, + const std::function& OnChunkedAttachment, + JobContext* OptionalContext); RemoteProjectStore::Result SaveOplog(CidStore& ChunkStore, RemoteProjectStore& RemoteStore, @@ -177,15 +199,18 @@ RemoteProjectStore::Result SaveOplog(CidStore& ChunkStore, bool IgnoreMissingAttachments, JobContext* OptionalContext); -RemoteProjectStore::Result LoadOplog(CidStore& ChunkStore, - RemoteProjectStore& RemoteStore, - ProjectStore::Oplog& Oplog, - WorkerThreadPool& NetworkWorkerPool, - WorkerThreadPool& WorkerPool, - bool ForceDownload, - bool IgnoreMissingAttachments, - bool CleanOplog, - JobContext* OptionalContext); +RemoteProjectStore::Result LoadOplog(CidStore& ChunkStore, + RemoteProjectStore& RemoteStore, + ProjectStore::Oplog& Oplog, + WorkerThreadPool& NetworkWorkerPool, + WorkerThreadPool& WorkerPool, + bool ForceDownload, + bool IgnoreMissingAttachments, + bool CleanOplog, + EPartialBlockRequestMode PartialBlockRequestMode, + double HostLatencySec, + double CacheLatencySec, + JobContext* OptionalContext); std::vector GetBlockHashesFromOplog(CbObjectView ContainerObject); std::vector GetBlocksFromOplog(CbObjectView ContainerObject, std::span IncludeBlockHashes); diff --git a/src/zenremotestore/jupiter/jupiterhost.cpp b/src/zenremotestore/jupiter/jupiterhost.cpp index 7706f00c2..2583cfc84 100644 --- a/src/zenremotestore/jupiter/jupiterhost.cpp +++ b/src/zenremotestore/jupiter/jupiterhost.cpp @@ -59,7 +59,13 @@ TestJupiterEndpoint(std::string_view BaseUrl, const bool AssumeHttp2, const bool HttpClient::Response TestResponse = TestHttpClient.Get("/health/live"); if (TestResponse.IsSuccess()) { - return {.Success = true}; + LatencyTestResult LatencyResult = MeasureLatency(TestHttpClient, "/health/ready"); + + if (!LatencyResult.Success) + { + return {.Success = false, .FailureReason = LatencyResult.FailureReason}; + } + return {.Success = true, .LatencySeconds = LatencyResult.LatencySeconds}; } return {.Success = false, .FailureReason = TestResponse.ErrorMessage("")}; } diff --git a/src/zenremotestore/operationlogoutput.cpp b/src/zenremotestore/operationlogoutput.cpp index 0837ed716..7ed93c947 100644 --- a/src/zenremotestore/operationlogoutput.cpp +++ b/src/zenremotestore/operationlogoutput.cpp @@ -95,7 +95,7 @@ StandardLogOutputProgressBar::Finish() } OperationLogOutput* -CreateStandardLogOutput(LoggerRef& Log) +CreateStandardLogOutput(LoggerRef Log) { return new StandardLogOutput(Log); } diff --git a/src/zenremotestore/partialblockrequestmode.cpp b/src/zenremotestore/partialblockrequestmode.cpp new file mode 100644 index 000000000..b3edf515b --- /dev/null +++ b/src/zenremotestore/partialblockrequestmode.cpp @@ -0,0 +1,27 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#include + +#include + +namespace zen { + +EPartialBlockRequestMode +PartialBlockRequestModeFromString(const std::string_view ModeString) +{ + switch (HashStringAsLowerDjb2(ModeString)) + { + case HashStringDjb2("false"): + return EPartialBlockRequestMode::Off; + case HashStringDjb2("zencacheonly"): + return EPartialBlockRequestMode::ZenCacheOnly; + case HashStringDjb2("mixed"): + return EPartialBlockRequestMode::Mixed; + case HashStringDjb2("true"): + return EPartialBlockRequestMode::All; + default: + return EPartialBlockRequestMode::Invalid; + } +} + +} // namespace zen diff --git a/src/zenremotestore/projectstore/buildsremoteprojectstore.cpp b/src/zenremotestore/projectstore/buildsremoteprojectstore.cpp index a8e883dde..c42373e4d 100644 --- a/src/zenremotestore/projectstore/buildsremoteprojectstore.cpp +++ b/src/zenremotestore/projectstore/buildsremoteprojectstore.cpp @@ -441,7 +441,7 @@ public: catch (const HttpClientError& Ex) { Result.ErrorCode = MakeErrorCode(Ex); - Result.Reason = fmt::format("Failed listing know blocks for {}/{}/{}/{}. Reason: '{}'", + Result.Reason = fmt::format("Failed listing known blocks for {}/{}/{}/{}. Reason: '{}'", m_BuildStorageHttp.GetBaseUri(), m_Namespace, m_Bucket, @@ -451,7 +451,7 @@ public: catch (const std::exception& Ex) { Result.ErrorCode = gsl::narrow(HttpResponseCode::InternalServerError); - Result.Reason = fmt::format("Failed listing know blocks for {}/{}/{}/{}. Reason: '{}'", + Result.Reason = fmt::format("Failed listing known blocks for {}/{}/{}/{}. Reason: '{}'", m_BuildStorageHttp.GetBaseUri(), m_Namespace, m_Bucket, @@ -462,7 +462,94 @@ public: return Result; } - virtual LoadAttachmentResult LoadAttachment(const IoHash& RawHash) override + virtual GetBlockDescriptionsResult GetBlockDescriptions(std::span BlockHashes) override + { + std::unique_ptr Output(CreateStandardLogOutput(Log())); + + ZEN_ASSERT(m_OplogBuildPartId != Oid::Zero); + + GetBlockDescriptionsResult Result; + Stopwatch Timer; + auto _ = MakeGuard([&Timer, &Result]() { Result.ElapsedSeconds = Timer.GetElapsedTimeUs() / 1000000.0; }); + + try + { + Result.Blocks = zen::GetBlockDescriptions(*Output, + *m_BuildStorage, + m_BuildCacheStorage.get(), + m_BuildId, + m_OplogBuildPartId, + BlockHashes, + /*AttemptFallback*/ false, + /*IsQuiet*/ false, + /*IsVerbose)*/ false); + } + catch (const HttpClientError& Ex) + { + Result.ErrorCode = MakeErrorCode(Ex); + Result.Reason = fmt::format("Failed listing known blocks for {}/{}/{}/{}. Reason: '{}'", + m_BuildStorageHttp.GetBaseUri(), + m_Namespace, + m_Bucket, + m_BuildId, + Ex.what()); + } + catch (const std::exception& Ex) + { + Result.ErrorCode = gsl::narrow(HttpResponseCode::InternalServerError); + Result.Reason = fmt::format("Failed listing known blocks for {}/{}/{}/{}. Reason: '{}'", + m_BuildStorageHttp.GetBaseUri(), + m_Namespace, + m_Bucket, + m_BuildId, + Ex.what()); + } + return Result; + } + + virtual AttachmentExistsInCacheResult AttachmentExistsInCache(std::span RawHashes) override + { + AttachmentExistsInCacheResult Result; + Stopwatch Timer; + auto _ = MakeGuard([&Timer, &Result]() { Result.ElapsedSeconds = Timer.GetElapsedTimeUs() / 1000000.0; }); + try + { + const std::vector CacheExistsResult = + m_BuildCacheStorage->BlobsExists(m_BuildId, RawHashes); + + if (CacheExistsResult.size() == RawHashes.size()) + { + Result.HasBody.reserve(CacheExistsResult.size()); + for (size_t BlobIndex = 0; BlobIndex < CacheExistsResult.size(); BlobIndex++) + { + Result.HasBody.push_back(CacheExistsResult[BlobIndex].HasBody); + } + } + } + catch (const HttpClientError& Ex) + { + Result.ErrorCode = MakeErrorCode(Ex); + Result.Reason = fmt::format("Remote cache: Failed finding known blobs for {}/{}/{}/{}. Reason: '{}'", + m_BuildStorageHttp.GetBaseUri(), + m_Namespace, + m_Bucket, + m_BuildId, + Ex.what()); + } + catch (const std::exception& Ex) + { + Result.ErrorCode = gsl::narrow(HttpResponseCode::InternalServerError); + Result.Reason = fmt::format("Remote cache: Failed finding known blobs for {}/{}/{}/{}. Reason: '{}'", + m_BuildStorageHttp.GetBaseUri(), + m_Namespace, + m_Bucket, + m_BuildId, + Ex.what()); + } + return Result; + } + + virtual LoadAttachmentResult LoadAttachment(const IoHash& RawHash, const AttachmentRange& Range) override { ZEN_ASSERT(m_OplogBuildPartId != Oid::Zero); @@ -474,7 +561,7 @@ public: { if (m_BuildCacheStorage) { - IoBuffer CachedBlob = m_BuildCacheStorage->GetBuildBlob(m_BuildId, RawHash); + IoBuffer CachedBlob = m_BuildCacheStorage->GetBuildBlob(m_BuildId, RawHash, Range.Offset, Range.Bytes); if (CachedBlob) { Result.Bytes = std::move(CachedBlob); @@ -482,20 +569,23 @@ public: } if (!Result.Bytes) { - Result.Bytes = m_BuildStorage->GetBuildBlob(m_BuildId, RawHash); + Result.Bytes = m_BuildStorage->GetBuildBlob(m_BuildId, RawHash, Range.Offset, Range.Bytes); if (m_BuildCacheStorage && Result.Bytes && m_PopulateCache) { - m_BuildCacheStorage->PutBuildBlob(m_BuildId, - RawHash, - Result.Bytes.GetContentType(), - CompositeBuffer(SharedBuffer(Result.Bytes))); + if (!Range) + { + m_BuildCacheStorage->PutBuildBlob(m_BuildId, + RawHash, + Result.Bytes.GetContentType(), + CompositeBuffer(SharedBuffer(Result.Bytes))); + } } } } catch (const HttpClientError& Ex) { Result.ErrorCode = MakeErrorCode(Ex); - Result.Reason = fmt::format("Failed listing know blocks for {}/{}/{}/{}. Reason: '{}'", + Result.Reason = fmt::format("Failed listing known blocks for {}/{}/{}/{}. Reason: '{}'", m_BuildStorageHttp.GetBaseUri(), m_Namespace, m_Bucket, @@ -505,7 +595,7 @@ public: catch (const std::exception& Ex) { Result.ErrorCode = gsl::narrow(HttpResponseCode::InternalServerError); - Result.Reason = fmt::format("Failed listing know blocks for {}/{}/{}/{}. Reason: '{}'", + Result.Reason = fmt::format("Failed listing known blocks for {}/{}/{}/{}. Reason: '{}'", m_BuildStorageHttp.GetBaseUri(), m_Namespace, m_Bucket, @@ -558,7 +648,7 @@ public: for (const IoHash& Hash : AttachmentsLeftToFind) { - LoadAttachmentResult ChunkResult = LoadAttachment(Hash); + LoadAttachmentResult ChunkResult = LoadAttachment(Hash, {}); if (ChunkResult.ErrorCode) { return LoadAttachmentsResult{ChunkResult}; @@ -623,7 +713,9 @@ CreateJupiterBuildsRemoteStore(LoggerRef InLog, bool Quiet, bool Unattended, bool Hidden, - WorkerThreadPool& CacheBackgroundWorkerPool) + WorkerThreadPool& CacheBackgroundWorkerPool, + double& OutHostLatencySec, + double& OutCacheLatencySec) { std::string Host = Options.Host; if (!Host.empty() && Host.find("://"sv) == std::string::npos) @@ -727,6 +819,10 @@ CreateJupiterBuildsRemoteStore(LoggerRef InLog, Options.ForceDisableBlocks, Options.ForceDisableTempBlocks, Options.PopulateCache); + + OutHostLatencySec = ResolveRes.HostLatencySec; + OutCacheLatencySec = ResolveRes.CacheLatencySec; + return RemoteStore; } diff --git a/src/zenremotestore/projectstore/fileremoteprojectstore.cpp b/src/zenremotestore/projectstore/fileremoteprojectstore.cpp index 3a67d3842..ec7fb7bbc 100644 --- a/src/zenremotestore/projectstore/fileremoteprojectstore.cpp +++ b/src/zenremotestore/projectstore/fileremoteprojectstore.cpp @@ -217,7 +217,18 @@ public: return Result; } - virtual LoadAttachmentResult LoadAttachment(const IoHash& RawHash) override + virtual GetBlockDescriptionsResult GetBlockDescriptions(std::span BlockHashes) override + { + ZEN_UNUSED(BlockHashes); + return GetBlockDescriptionsResult{Result{.ErrorCode = int(HttpResponseCode::NotFound)}}; + } + + virtual AttachmentExistsInCacheResult AttachmentExistsInCache(std::span RawHashes) override + { + return AttachmentExistsInCacheResult{Result{.ErrorCode = 0}, std::vector(RawHashes.size(), false)}; + } + + virtual LoadAttachmentResult LoadAttachment(const IoHash& RawHash, const AttachmentRange& Range) override { Stopwatch Timer; LoadAttachmentResult Result; @@ -232,7 +243,14 @@ public: { BasicFile ChunkFile; ChunkFile.Open(ChunkPath, BasicFile::Mode::kRead); - Result.Bytes = ChunkFile.ReadAll(); + if (Range) + { + Result.Bytes = ChunkFile.ReadRange(Range.Offset, Range.Bytes); + } + else + { + Result.Bytes = ChunkFile.ReadAll(); + } } AddStats(0, Result.Bytes.GetSize(), Timer.GetElapsedTimeUs() * 1000); Result.ElapsedSeconds = Timer.GetElapsedTimeMs() / 1000.0; @@ -245,7 +263,7 @@ public: LoadAttachmentsResult Result; for (const IoHash& Hash : RawHashes) { - LoadAttachmentResult ChunkResult = LoadAttachment(Hash); + LoadAttachmentResult ChunkResult = LoadAttachment(Hash, {}); if (ChunkResult.ErrorCode) { ChunkResult.ElapsedSeconds = Timer.GetElapsedTimeMs() / 1000.0; diff --git a/src/zenremotestore/projectstore/jupiterremoteprojectstore.cpp b/src/zenremotestore/projectstore/jupiterremoteprojectstore.cpp index 462de2988..f8179831c 100644 --- a/src/zenremotestore/projectstore/jupiterremoteprojectstore.cpp +++ b/src/zenremotestore/projectstore/jupiterremoteprojectstore.cpp @@ -212,7 +212,18 @@ public: return Result; } - virtual LoadAttachmentResult LoadAttachment(const IoHash& RawHash) override + virtual GetBlockDescriptionsResult GetBlockDescriptions(std::span BlockHashes) override + { + ZEN_UNUSED(BlockHashes); + return GetBlockDescriptionsResult{Result{.ErrorCode = int(HttpResponseCode::NotFound)}}; + } + + virtual AttachmentExistsInCacheResult AttachmentExistsInCache(std::span RawHashes) override + { + return AttachmentExistsInCacheResult{Result{.ErrorCode = 0}, std::vector(RawHashes.size(), false)}; + } + + virtual LoadAttachmentResult LoadAttachment(const IoHash& RawHash, const AttachmentRange& Range) override { JupiterSession Session(m_JupiterClient->Logger(), m_JupiterClient->Client(), m_AllowRedirect); JupiterResult GetResult = Session.GetCompressedBlob(m_Namespace, RawHash, m_TempFilePath); @@ -227,6 +238,10 @@ public: RawHash, Result.Reason); } + if (!Result.ErrorCode && Range) + { + Result.Bytes = IoBuffer(Result.Bytes, Range.Offset, Range.Bytes); + } return Result; } @@ -235,7 +250,7 @@ public: LoadAttachmentsResult Result; for (const IoHash& Hash : RawHashes) { - LoadAttachmentResult ChunkResult = LoadAttachment(Hash); + LoadAttachmentResult ChunkResult = LoadAttachment(Hash, {}); if (ChunkResult.ErrorCode) { return LoadAttachmentsResult{ChunkResult}; diff --git a/src/zenremotestore/projectstore/remoteprojectstore.cpp b/src/zenremotestore/projectstore/remoteprojectstore.cpp index 8be8eb0df..2a9da6f58 100644 --- a/src/zenremotestore/projectstore/remoteprojectstore.cpp +++ b/src/zenremotestore/projectstore/remoteprojectstore.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -229,29 +230,60 @@ namespace remotestore_impl { struct DownloadInfo { - uint64_t OplogSizeBytes = 0; - std::atomic AttachmentsDownloaded = 0; - std::atomic AttachmentBlocksDownloaded = 0; - std::atomic AttachmentBytesDownloaded = 0; - std::atomic AttachmentBlockBytesDownloaded = 0; - std::atomic AttachmentsStored = 0; - std::atomic AttachmentBytesStored = 0; - std::atomic_size_t MissingAttachmentCount = 0; + uint64_t OplogSizeBytes = 0; + std::atomic AttachmentsDownloaded = 0; + std::atomic AttachmentBlocksDownloaded = 0; + std::atomic AttachmentBlocksRangesDownloaded = 0; + std::atomic AttachmentBytesDownloaded = 0; + std::atomic AttachmentBlockBytesDownloaded = 0; + std::atomic AttachmentBlockRangeBytesDownloaded = 0; + std::atomic AttachmentsStored = 0; + std::atomic AttachmentBytesStored = 0; + std::atomic_size_t MissingAttachmentCount = 0; }; - void DownloadAndSaveBlockChunks(CidStore& ChunkStore, - RemoteProjectStore& RemoteStore, - bool IgnoreMissingAttachments, - JobContext* OptionalContext, - WorkerThreadPool& NetworkWorkerPool, - WorkerThreadPool& WorkerPool, - Latch& AttachmentsDownloadLatch, - Latch& AttachmentsWriteLatch, - AsyncRemoteResult& RemoteResult, - DownloadInfo& Info, - Stopwatch& LoadAttachmentsTimer, - std::atomic_uint64_t& DownloadStartMS, - const std::vector& Chunks) + class JobContextLogOutput : public OperationLogOutput + { + public: + JobContextLogOutput(JobContext* OptionalContext) : m_OptionalContext(OptionalContext) {} + virtual void EmitLogMessage(int LogLevel, std::string_view Format, fmt::format_args Args) override + { + ZEN_UNUSED(LogLevel); + if (m_OptionalContext) + { + fmt::basic_memory_buffer MessageBuffer; + fmt::vformat_to(fmt::appender(MessageBuffer), Format, Args); + remotestore_impl::ReportMessage(m_OptionalContext, std::string_view(MessageBuffer.data(), MessageBuffer.size())); + } + } + + virtual void SetLogOperationName(std::string_view Name) override { ZEN_UNUSED(Name); } + virtual void SetLogOperationProgress(uint32_t StepIndex, uint32_t StepCount) override { ZEN_UNUSED(StepIndex, StepCount); } + virtual uint32_t GetProgressUpdateDelayMS() override { return 0; } + virtual ProgressBar* CreateProgressBar(std::string_view InSubTask) override + { + ZEN_UNUSED(InSubTask); + return nullptr; + } + + private: + JobContext* m_OptionalContext; + }; + + void DownloadAndSaveBlockChunks(CidStore& ChunkStore, + RemoteProjectStore& RemoteStore, + bool IgnoreMissingAttachments, + JobContext* OptionalContext, + WorkerThreadPool& NetworkWorkerPool, + WorkerThreadPool& WorkerPool, + Latch& AttachmentsDownloadLatch, + Latch& AttachmentsWriteLatch, + AsyncRemoteResult& RemoteResult, + DownloadInfo& Info, + Stopwatch& LoadAttachmentsTimer, + std::atomic_uint64_t& DownloadStartMS, + ThinChunkBlockDescription&& ThinBlockDescription, + std::vector&& NeededChunkIndexes) { AttachmentsDownloadLatch.AddCount(1); NetworkWorkerPool.ScheduleWork( @@ -261,7 +293,8 @@ namespace remotestore_impl { &AttachmentsDownloadLatch, &AttachmentsWriteLatch, &RemoteResult, - Chunks = Chunks, + ThinBlockDescription = std::move(ThinBlockDescription), + NeededChunkIndexes = std::move(NeededChunkIndexes), &Info, &LoadAttachmentsTimer, &DownloadStartMS, @@ -276,6 +309,13 @@ namespace remotestore_impl { } try { + std::vector Chunks; + Chunks.reserve(NeededChunkIndexes.size()); + for (uint32_t ChunkIndex : NeededChunkIndexes) + { + Chunks.push_back(ThinBlockDescription.ChunkRawHashes[ChunkIndex]); + } + uint64_t Unset = (std::uint64_t)-1; DownloadStartMS.compare_exchange_strong(Unset, LoadAttachmentsTimer.GetElapsedTimeMs()); RemoteProjectStore::LoadAttachmentsResult Result = RemoteStore.LoadAttachments(Chunks); @@ -293,7 +333,12 @@ namespace remotestore_impl { } return; } - Info.AttachmentsDownloaded.fetch_add(Chunks.size()); + Info.AttachmentsDownloaded.fetch_add(Result.Chunks.size()); + for (const auto& It : Result.Chunks) + { + uint64_t ChunkSize = It.second.GetCompressedSize(); + Info.AttachmentBytesDownloaded.fetch_add(ChunkSize); + } ZEN_INFO("Loaded {} bulk attachments in {}", Chunks.size(), NiceTimeSpanMs(static_cast(Result.ElapsedSeconds * 1000))); @@ -320,8 +365,6 @@ namespace remotestore_impl { for (const auto& It : Chunks) { - uint64_t ChunkSize = It.second.GetCompressedSize(); - Info.AttachmentBytesDownloaded.fetch_add(ChunkSize); WriteAttachmentBuffers.push_back(It.second.GetCompressed().Flatten().AsIoBuffer()); WriteRawHashes.push_back(It.first); } @@ -350,28 +393,29 @@ namespace remotestore_impl { catch (const std::exception& Ex) { RemoteResult.SetError(gsl::narrow(HttpResponseCode::InternalServerError), - fmt::format("Failed to bulk load {} attachments", Chunks.size()), + fmt::format("Failed to bulk load {} attachments", NeededChunkIndexes.size()), Ex.what()); } }, WorkerThreadPool::EMode::EnableBacklog); }; - void DownloadAndSaveBlock(CidStore& ChunkStore, - RemoteProjectStore& RemoteStore, - bool IgnoreMissingAttachments, - JobContext* OptionalContext, - WorkerThreadPool& NetworkWorkerPool, - WorkerThreadPool& WorkerPool, - Latch& AttachmentsDownloadLatch, - Latch& AttachmentsWriteLatch, - AsyncRemoteResult& RemoteResult, - DownloadInfo& Info, - Stopwatch& LoadAttachmentsTimer, - std::atomic_uint64_t& DownloadStartMS, - const IoHash& BlockHash, - const std::vector& Chunks, - uint32_t RetriesLeft) + void DownloadAndSaveBlock(CidStore& ChunkStore, + RemoteProjectStore& RemoteStore, + bool IgnoreMissingAttachments, + JobContext* OptionalContext, + WorkerThreadPool& NetworkWorkerPool, + WorkerThreadPool& WorkerPool, + Latch& AttachmentsDownloadLatch, + Latch& AttachmentsWriteLatch, + AsyncRemoteResult& RemoteResult, + DownloadInfo& Info, + Stopwatch& LoadAttachmentsTimer, + std::atomic_uint64_t& DownloadStartMS, + const IoHash& BlockHash, + const tsl::robin_map& AllNeededPartialChunkHashesLookup, + std::span> ChunkDownloadedFlags, + uint32_t RetriesLeft) { AttachmentsDownloadLatch.AddCount(1); NetworkWorkerPool.ScheduleWork( @@ -381,7 +425,6 @@ namespace remotestore_impl { &RemoteStore, &NetworkWorkerPool, &WorkerPool, - BlockHash, &RemoteResult, &Info, &LoadAttachmentsTimer, @@ -389,7 +432,9 @@ namespace remotestore_impl { IgnoreMissingAttachments, OptionalContext, RetriesLeft, - Chunks = std::vector(Chunks)]() { + BlockHash = IoHash(BlockHash), + &AllNeededPartialChunkHashesLookup, + ChunkDownloadedFlags]() { ZEN_TRACE_CPU("DownloadBlock"); auto _ = MakeGuard([&AttachmentsDownloadLatch] { AttachmentsDownloadLatch.CountDown(); }); @@ -401,7 +446,7 @@ namespace remotestore_impl { { uint64_t Unset = (std::uint64_t)-1; DownloadStartMS.compare_exchange_strong(Unset, LoadAttachmentsTimer.GetElapsedTimeMs()); - RemoteProjectStore::LoadAttachmentResult BlockResult = RemoteStore.LoadAttachment(BlockHash); + RemoteProjectStore::LoadAttachmentResult BlockResult = RemoteStore.LoadAttachment(BlockHash, {}); if (BlockResult.ErrorCode) { ReportMessage(OptionalContext, @@ -422,10 +467,10 @@ namespace remotestore_impl { } uint64_t BlockSize = BlockResult.Bytes.GetSize(); Info.AttachmentBlocksDownloaded.fetch_add(1); - ZEN_INFO("Loaded block attachment '{}' in {} ({})", - BlockHash, - NiceTimeSpanMs(static_cast(BlockResult.ElapsedSeconds * 1000)), - NiceBytes(BlockSize)); + ZEN_DEBUG("Loaded block attachment '{}' in {} ({})", + BlockHash, + NiceTimeSpanMs(static_cast(BlockResult.ElapsedSeconds * 1000)), + NiceBytes(BlockSize)); Info.AttachmentBlockBytesDownloaded.fetch_add(BlockSize); AttachmentsWriteLatch.AddCount(1); @@ -436,7 +481,6 @@ namespace remotestore_impl { &RemoteStore, &NetworkWorkerPool, &WorkerPool, - BlockHash, &RemoteResult, &Info, &LoadAttachmentsTimer, @@ -444,8 +488,10 @@ namespace remotestore_impl { IgnoreMissingAttachments, OptionalContext, RetriesLeft, - Chunks = std::move(Chunks), - Bytes = std::move(BlockResult.Bytes)]() { + BlockHash = IoHash(BlockHash), + &AllNeededPartialChunkHashesLookup, + ChunkDownloadedFlags, + Bytes = std::move(BlockResult.Bytes)]() { auto _ = MakeGuard([&AttachmentsWriteLatch] { AttachmentsWriteLatch.CountDown(); }); if (RemoteResult.IsError()) { @@ -454,9 +500,6 @@ namespace remotestore_impl { try { ZEN_ASSERT(Bytes.Size() > 0); - std::unordered_set WantedChunks; - WantedChunks.reserve(Chunks.size()); - WantedChunks.insert(Chunks.begin(), Chunks.end()); std::vector WriteAttachmentBuffers; std::vector WriteRawHashes; @@ -485,7 +528,8 @@ namespace remotestore_impl { LoadAttachmentsTimer, DownloadStartMS, BlockHash, - std::move(Chunks), + AllNeededPartialChunkHashesLookup, + ChunkDownloadedFlags, RetriesLeft - 1); } ReportMessage( @@ -519,7 +563,8 @@ namespace remotestore_impl { LoadAttachmentsTimer, DownloadStartMS, BlockHash, - std::move(Chunks), + AllNeededPartialChunkHashesLookup, + ChunkDownloadedFlags, RetriesLeft - 1); } ReportMessage(OptionalContext, @@ -546,28 +591,36 @@ namespace remotestore_impl { uint64_t BlockSize = BlockPayload.GetSize(); uint64_t BlockHeaderSize = 0; - bool StoreChunksOK = IterateChunkBlock( - BlockPayload.Flatten(), - [&WantedChunks, &WriteAttachmentBuffers, &WriteRawHashes, &Info, &PotentialSize]( - CompressedBuffer&& Chunk, - const IoHash& AttachmentRawHash) { - if (WantedChunks.contains(AttachmentRawHash)) - { - WriteAttachmentBuffers.emplace_back(Chunk.GetCompressed().Flatten().AsIoBuffer()); - IoHash RawHash; - uint64_t RawSize; - ZEN_ASSERT( - CompressedBuffer::ValidateCompressedHeader(WriteAttachmentBuffers.back(), - RawHash, - RawSize, - /*OutOptionalTotalCompressedSize*/ nullptr)); - ZEN_ASSERT(RawHash == AttachmentRawHash); - WriteRawHashes.emplace_back(AttachmentRawHash); - WantedChunks.erase(AttachmentRawHash); - PotentialSize += WriteAttachmentBuffers.back().GetSize(); - } - }, - BlockHeaderSize); + + bool StoreChunksOK = IterateChunkBlock( + BlockPayload.Flatten(), + [&AllNeededPartialChunkHashesLookup, + &ChunkDownloadedFlags, + &WriteAttachmentBuffers, + &WriteRawHashes, + &Info, + &PotentialSize](CompressedBuffer&& Chunk, const IoHash& AttachmentRawHash) { + auto ChunkIndexIt = AllNeededPartialChunkHashesLookup.find(AttachmentRawHash); + if (ChunkIndexIt != AllNeededPartialChunkHashesLookup.end()) + { + bool Expected = false; + if (ChunkDownloadedFlags[ChunkIndexIt->second].compare_exchange_strong(Expected, true)) + { + WriteAttachmentBuffers.emplace_back(Chunk.GetCompressed().Flatten().AsIoBuffer()); + IoHash RawHash; + uint64_t RawSize; + ZEN_ASSERT( + CompressedBuffer::ValidateCompressedHeader(WriteAttachmentBuffers.back(), + RawHash, + RawSize, + /*OutOptionalTotalCompressedSize*/ nullptr)); + ZEN_ASSERT(RawHash == AttachmentRawHash); + WriteRawHashes.emplace_back(AttachmentRawHash); + PotentialSize += WriteAttachmentBuffers.back().GetSize(); + } + } + }, + BlockHeaderSize); if (!StoreChunksOK) { @@ -582,8 +635,6 @@ namespace remotestore_impl { return; } - ZEN_ASSERT(WantedChunks.empty()); - if (!WriteAttachmentBuffers.empty()) { auto Results = ChunkStore.AddChunks(WriteAttachmentBuffers, WriteRawHashes); @@ -625,6 +676,293 @@ namespace remotestore_impl { WorkerThreadPool::EMode::EnableBacklog); }; + void DownloadAndSavePartialBlock(CidStore& ChunkStore, + RemoteProjectStore& RemoteStore, + bool IgnoreMissingAttachments, + JobContext* OptionalContext, + WorkerThreadPool& NetworkWorkerPool, + WorkerThreadPool& WorkerPool, + Latch& AttachmentsDownloadLatch, + Latch& AttachmentsWriteLatch, + AsyncRemoteResult& RemoteResult, + DownloadInfo& Info, + Stopwatch& LoadAttachmentsTimer, + std::atomic_uint64_t& DownloadStartMS, + const ChunkBlockDescription& BlockDescription, + std::span BlockRangeDescriptors, + size_t BlockRangeIndexStart, + size_t BlockRangeCount, + const tsl::robin_map& AllNeededPartialChunkHashesLookup, + std::span> ChunkDownloadedFlags, + uint32_t RetriesLeft) + { + AttachmentsDownloadLatch.AddCount(1); + NetworkWorkerPool.ScheduleWork( + [&AttachmentsDownloadLatch, + &AttachmentsWriteLatch, + &ChunkStore, + &RemoteStore, + &NetworkWorkerPool, + &WorkerPool, + &RemoteResult, + &Info, + &LoadAttachmentsTimer, + &DownloadStartMS, + IgnoreMissingAttachments, + OptionalContext, + RetriesLeft, + BlockDescription, + BlockRangeDescriptors, + BlockRangeIndexStart, + BlockRangeCount, + &AllNeededPartialChunkHashesLookup, + ChunkDownloadedFlags]() { + ZEN_TRACE_CPU("DownloadBlockRanges"); + + auto _ = MakeGuard([&AttachmentsDownloadLatch] { AttachmentsDownloadLatch.CountDown(); }); + try + { + uint64_t Unset = (std::uint64_t)-1; + DownloadStartMS.compare_exchange_strong(Unset, LoadAttachmentsTimer.GetElapsedTimeMs()); + + double DownloadElapsedSeconds = 0; + uint64_t DownloadedBytes = 0; + + for (size_t BlockRangeIndex = BlockRangeIndexStart; BlockRangeIndex < BlockRangeIndexStart + BlockRangeCount; + BlockRangeIndex++) + { + if (RemoteResult.IsError()) + { + return; + } + + const ChunkBlockAnalyser::BlockRangeDescriptor& BlockRange = BlockRangeDescriptors[BlockRangeIndex]; + + RemoteProjectStore::LoadAttachmentResult BlockResult = + RemoteStore.LoadAttachment(BlockDescription.BlockHash, + {.Offset = BlockRange.RangeStart, .Bytes = BlockRange.RangeLength}); + if (BlockResult.ErrorCode) + { + ReportMessage(OptionalContext, + fmt::format("Failed to download block attachment '{}' range {},{} ({}): {}", + BlockDescription.BlockHash, + BlockRange.RangeStart, + BlockRange.RangeLength, + BlockResult.ErrorCode, + BlockResult.Reason)); + Info.MissingAttachmentCount.fetch_add(1); + if (!IgnoreMissingAttachments) + { + RemoteResult.SetError(BlockResult.ErrorCode, BlockResult.Reason, BlockResult.Text); + } + return; + } + if (RemoteResult.IsError()) + { + return; + } + uint64_t BlockPartSize = BlockResult.Bytes.GetSize(); + if (BlockPartSize != BlockRange.RangeLength) + { + std::string ErrorString = + fmt::format("Failed to download block attachment '{}' range {},{}, got {} bytes ({}): {}", + BlockDescription.BlockHash, + BlockRange.RangeStart, + BlockRange.RangeLength, + BlockPartSize, + RemoteResult.GetError(), + RemoteResult.GetErrorReason()); + + ReportMessage(OptionalContext, ErrorString); + Info.MissingAttachmentCount.fetch_add(1); + if (!IgnoreMissingAttachments) + { + RemoteResult.SetError(gsl::narrow(HttpResponseCode::NotFound), + "Mismatching block part range received", + ErrorString); + } + return; + } + Info.AttachmentBlocksRangesDownloaded.fetch_add(1); + + DownloadElapsedSeconds += BlockResult.ElapsedSeconds; + DownloadedBytes += BlockPartSize; + + Info.AttachmentBlockRangeBytesDownloaded.fetch_add(BlockPartSize); + + AttachmentsWriteLatch.AddCount(1); + WorkerPool.ScheduleWork( + [&AttachmentsDownloadLatch, + &AttachmentsWriteLatch, + &ChunkStore, + &RemoteStore, + &NetworkWorkerPool, + &WorkerPool, + &RemoteResult, + &Info, + &LoadAttachmentsTimer, + &DownloadStartMS, + IgnoreMissingAttachments, + OptionalContext, + RetriesLeft, + BlockDescription, + BlockRange, + &AllNeededPartialChunkHashesLookup, + ChunkDownloadedFlags, + BlockPayload = std::move(BlockResult.Bytes)]() { + auto _ = MakeGuard([&AttachmentsWriteLatch] { AttachmentsWriteLatch.CountDown(); }); + if (RemoteResult.IsError()) + { + return; + } + try + { + ZEN_ASSERT(BlockPayload.Size() > 0); + std::vector WriteAttachmentBuffers; + std::vector WriteRawHashes; + + uint64_t PotentialSize = 0; + uint64_t UsedSize = 0; + uint64_t BlockPartSize = BlockPayload.GetSize(); + + uint32_t OffsetInBlock = 0; + for (uint32_t ChunkBlockIndex = BlockRange.ChunkBlockIndexStart; + ChunkBlockIndex < BlockRange.ChunkBlockIndexStart + BlockRange.ChunkBlockIndexCount; + ChunkBlockIndex++) + { + const uint32_t ChunkCompressedSize = BlockDescription.ChunkCompressedLengths[ChunkBlockIndex]; + const IoHash& ChunkHash = BlockDescription.ChunkRawHashes[ChunkBlockIndex]; + + if (auto ChunkIndexIt = AllNeededPartialChunkHashesLookup.find(ChunkHash); + ChunkIndexIt != AllNeededPartialChunkHashesLookup.end()) + { + bool Expected = false; + if (ChunkDownloadedFlags[ChunkIndexIt->second].compare_exchange_strong(Expected, true)) + { + IoHash VerifyChunkHash; + uint64_t VerifyChunkSize; + CompressedBuffer CompressedChunk = CompressedBuffer::FromCompressed( + SharedBuffer(IoBuffer(BlockPayload, OffsetInBlock, ChunkCompressedSize)), + VerifyChunkHash, + VerifyChunkSize); + if (!CompressedChunk) + { + std::string ErrorString = fmt::format( + "Chunk at {},{} in block attachment '{}' is not a valid compressed buffer", + OffsetInBlock, + ChunkCompressedSize, + BlockDescription.BlockHash); + ReportMessage(OptionalContext, ErrorString); + Info.MissingAttachmentCount.fetch_add(1); + if (!IgnoreMissingAttachments) + { + RemoteResult.SetError(gsl::narrow(HttpResponseCode::NotFound), + "Malformed chunk block", + ErrorString); + } + continue; + } + if (VerifyChunkHash != ChunkHash) + { + std::string ErrorString = fmt::format( + "Chunk at {},{} in block attachment '{}' has mismatching hash, expected {}, got {}", + OffsetInBlock, + ChunkCompressedSize, + BlockDescription.BlockHash, + ChunkHash, + VerifyChunkHash); + ReportMessage(OptionalContext, ErrorString); + Info.MissingAttachmentCount.fetch_add(1); + if (!IgnoreMissingAttachments) + { + RemoteResult.SetError(gsl::narrow(HttpResponseCode::NotFound), + "Malformed chunk block", + ErrorString); + } + continue; + } + if (VerifyChunkSize != BlockDescription.ChunkRawLengths[ChunkBlockIndex]) + { + std::string ErrorString = fmt::format( + "Chunk at {},{} in block attachment '{}' has mismatching raw size, expected {}, " + "got {}", + OffsetInBlock, + ChunkCompressedSize, + BlockDescription.BlockHash, + BlockDescription.ChunkRawLengths[ChunkBlockIndex], + VerifyChunkSize); + ReportMessage(OptionalContext, ErrorString); + Info.MissingAttachmentCount.fetch_add(1); + if (!IgnoreMissingAttachments) + { + RemoteResult.SetError(gsl::narrow(HttpResponseCode::NotFound), + "Malformed chunk block", + ErrorString); + } + continue; + } + + WriteAttachmentBuffers.emplace_back(CompressedChunk.GetCompressed().Flatten().AsIoBuffer()); + WriteRawHashes.emplace_back(ChunkHash); + PotentialSize += WriteAttachmentBuffers.back().GetSize(); + } + } + OffsetInBlock += ChunkCompressedSize; + } + + if (!WriteAttachmentBuffers.empty()) + { + auto Results = ChunkStore.AddChunks(WriteAttachmentBuffers, WriteRawHashes); + for (size_t Index = 0; Index < Results.size(); Index++) + { + const auto& Result = Results[Index]; + if (Result.New) + { + Info.AttachmentBytesStored.fetch_add(WriteAttachmentBuffers[Index].GetSize()); + Info.AttachmentsStored.fetch_add(1); + UsedSize += WriteAttachmentBuffers[Index].GetSize(); + } + } + ZEN_DEBUG("Used {} (matching {}) out of {} for block {} range {}, {} ({} %) (use of matching {}%)", + NiceBytes(UsedSize), + NiceBytes(PotentialSize), + NiceBytes(BlockPartSize), + BlockDescription.BlockHash, + BlockRange.RangeStart, + BlockRange.RangeLength, + (100 * UsedSize) / BlockPartSize, + PotentialSize > 0 ? (UsedSize * 100) / PotentialSize : 0); + } + } + catch (const std::exception& Ex) + { + RemoteResult.SetError(gsl::narrow(HttpResponseCode::InternalServerError), + fmt::format("Failed save block attachment {} range {}, {}", + BlockDescription.BlockHash, + BlockRange.RangeStart, + BlockRange.RangeLength), + Ex.what()); + } + }, + WorkerThreadPool::EMode::EnableBacklog); + } + + ZEN_DEBUG("Loaded {} ranges from block attachment '{}' in {} ({})", + BlockRangeCount, + BlockDescription.BlockHash, + NiceTimeSpanMs(static_cast(DownloadElapsedSeconds * 1000)), + NiceBytes(DownloadedBytes)); + } + catch (const std::exception& Ex) + { + RemoteResult.SetError(gsl::narrow(HttpResponseCode::InternalServerError), + fmt::format("Failed to download block attachment {} ranges", BlockDescription.BlockHash), + Ex.what()); + } + }, + WorkerThreadPool::EMode::EnableBacklog); + }; + void DownloadAndSaveAttachment(CidStore& ChunkStore, RemoteProjectStore& RemoteStore, bool IgnoreMissingAttachments, @@ -664,7 +1002,7 @@ namespace remotestore_impl { { uint64_t Unset = (std::uint64_t)-1; DownloadStartMS.compare_exchange_strong(Unset, LoadAttachmentsTimer.GetElapsedTimeMs()); - RemoteProjectStore::LoadAttachmentResult AttachmentResult = RemoteStore.LoadAttachment(RawHash); + RemoteProjectStore::LoadAttachmentResult AttachmentResult = RemoteStore.LoadAttachment(RawHash, {}); if (AttachmentResult.ErrorCode) { ReportMessage(OptionalContext, @@ -680,10 +1018,10 @@ namespace remotestore_impl { return; } uint64_t AttachmentSize = AttachmentResult.Bytes.GetSize(); - ZEN_INFO("Loaded large attachment '{}' in {} ({})", - RawHash, - NiceTimeSpanMs(static_cast(AttachmentResult.ElapsedSeconds * 1000)), - NiceBytes(AttachmentSize)); + ZEN_DEBUG("Loaded large attachment '{}' in {} ({})", + RawHash, + NiceTimeSpanMs(static_cast(AttachmentResult.ElapsedSeconds * 1000)), + NiceBytes(AttachmentSize)); Info.AttachmentsDownloaded.fetch_add(1); if (RemoteResult.IsError()) { @@ -1224,35 +1562,7 @@ BuildContainer(CidStore& ChunkStore, { using namespace std::literals; - class JobContextLogOutput : public OperationLogOutput - { - public: - JobContextLogOutput(JobContext* OptionalContext) : m_OptionalContext(OptionalContext) {} - virtual void EmitLogMessage(int LogLevel, std::string_view Format, fmt::format_args Args) override - { - ZEN_UNUSED(LogLevel); - if (m_OptionalContext) - { - fmt::basic_memory_buffer MessageBuffer; - fmt::vformat_to(fmt::appender(MessageBuffer), Format, Args); - remotestore_impl::ReportMessage(m_OptionalContext, std::string_view(MessageBuffer.data(), MessageBuffer.size())); - } - } - - virtual void SetLogOperationName(std::string_view Name) override { ZEN_UNUSED(Name); } - virtual void SetLogOperationProgress(uint32_t StepIndex, uint32_t StepCount) override { ZEN_UNUSED(StepIndex, StepCount); } - virtual uint32_t GetProgressUpdateDelayMS() override { return 0; } - virtual ProgressBar* CreateProgressBar(std::string_view InSubTask) override - { - ZEN_UNUSED(InSubTask); - return nullptr; - } - - private: - JobContext* m_OptionalContext; - }; - - std::unique_ptr LogOutput(std::make_unique(OptionalContext)); + std::unique_ptr LogOutput(std::make_unique(OptionalContext)); size_t OpCount = 0; @@ -2768,14 +3078,15 @@ SaveOplog(CidStore& ChunkStore, }; RemoteProjectStore::Result -ParseOplogContainer(const CbObject& ContainerObject, - const std::function RawHashes)>& OnReferencedAttachments, - const std::function& HasAttachment, - const std::function&& Chunks)>& OnNeedBlock, - const std::function& OnNeedAttachment, - const std::function& OnChunkedAttachment, - CbObject& OutOplogSection, - JobContext* OptionalContext) +ParseOplogContainer( + const CbObject& ContainerObject, + const std::function RawHashes)>& OnReferencedAttachments, + const std::function& HasAttachment, + const std::function&& NeededChunkIndexes)>& OnNeedBlock, + const std::function& OnNeedAttachment, + const std::function& OnChunkedAttachment, + CbObject& OutOplogSection, + JobContext* OptionalContext) { using namespace std::literals; @@ -2801,12 +3112,12 @@ ParseOplogContainer(const CbObject& ContainerObject, "Section has unexpected data type", "Failed to save oplog container"}; } - std::unordered_set OpsAttachments; + std::unordered_set NeededAttachments; { CbArrayView OpsArray = OutOplogSection["ops"sv].AsArrayView(); for (CbFieldView OpEntry : OpsArray) { - OpEntry.IterateAttachments([&](CbFieldView FieldView) { OpsAttachments.insert(FieldView.AsAttachment()); }); + OpEntry.IterateAttachments([&](CbFieldView FieldView) { NeededAttachments.insert(FieldView.AsAttachment()); }); if (remotestore_impl::IsCancelled(OptionalContext)) { return RemoteProjectStore::Result{.ErrorCode = gsl::narrow(HttpResponseCode::OK), @@ -2816,7 +3127,7 @@ ParseOplogContainer(const CbObject& ContainerObject, } } { - std::vector ReferencedAttachments(OpsAttachments.begin(), OpsAttachments.end()); + std::vector ReferencedAttachments(NeededAttachments.begin(), NeededAttachments.end()); OnReferencedAttachments(ReferencedAttachments); } @@ -2827,24 +3138,27 @@ ParseOplogContainer(const CbObject& ContainerObject, .Reason = "Operation cancelled"}; } - remotestore_impl::ReportMessage(OptionalContext, fmt::format("Oplog references {} attachments", OpsAttachments.size())); + remotestore_impl::ReportMessage(OptionalContext, fmt::format("Oplog references {} attachments", NeededAttachments.size())); CbArrayView ChunkedFilesArray = ContainerObject["chunkedfiles"sv].AsArrayView(); for (CbFieldView ChunkedFileField : ChunkedFilesArray) { CbObjectView ChunkedFileView = ChunkedFileField.AsObjectView(); IoHash RawHash = ChunkedFileView["rawhash"sv].AsHash(); - if (OpsAttachments.contains(RawHash) && (!HasAttachment(RawHash))) + if (NeededAttachments.erase(RawHash) == 1) { - ChunkedInfo Chunked = ReadChunkedInfo(ChunkedFileView); - - OnReferencedAttachments(Chunked.ChunkHashes); - OpsAttachments.insert(Chunked.ChunkHashes.begin(), Chunked.ChunkHashes.end()); - OnChunkedAttachment(Chunked); - ZEN_INFO("Requesting chunked attachment '{}' ({}) built from {} chunks", - Chunked.RawHash, - NiceBytes(Chunked.RawSize), - Chunked.ChunkHashes.size()); + if (!HasAttachment(RawHash)) + { + ChunkedInfo Chunked = ReadChunkedInfo(ChunkedFileView); + + OnReferencedAttachments(Chunked.ChunkHashes); + NeededAttachments.insert(Chunked.ChunkHashes.begin(), Chunked.ChunkHashes.end()); + OnChunkedAttachment(Chunked); + ZEN_INFO("Requesting chunked attachment '{}' ({}) built from {} chunks", + Chunked.RawHash, + NiceBytes(Chunked.RawSize), + Chunked.ChunkHashes.size()); + } } if (remotestore_impl::IsCancelled(OptionalContext)) { @@ -2854,6 +3168,8 @@ ParseOplogContainer(const CbObject& ContainerObject, } } + std::vector ThinBlocksDescriptions; + size_t NeedBlockCount = 0; CbArrayView BlocksArray = ContainerObject["blocks"sv].AsArrayView(); for (CbFieldView BlockField : BlocksArray) @@ -2863,45 +3179,38 @@ ParseOplogContainer(const CbObject& ContainerObject, CbArrayView ChunksArray = BlockView["chunks"sv].AsArrayView(); - std::vector NeededChunks; - NeededChunks.reserve(ChunksArray.Num()); - if (BlockHash == IoHash::Zero) + std::vector ChunkHashes; + ChunkHashes.reserve(ChunksArray.Num()); + for (CbFieldView ChunkField : ChunksArray) { - for (CbFieldView ChunkField : ChunksArray) - { - IoHash ChunkHash = ChunkField.AsBinaryAttachment(); - if (OpsAttachments.erase(ChunkHash) == 1) - { - if (!HasAttachment(ChunkHash)) - { - NeededChunks.emplace_back(ChunkHash); - } - } - } + ChunkHashes.push_back(ChunkField.AsHash()); } - else + ThinBlocksDescriptions.push_back(ThinChunkBlockDescription{.BlockHash = BlockHash, .ChunkRawHashes = std::move(ChunkHashes)}); + } + + for (ThinChunkBlockDescription& ThinBlockDescription : ThinBlocksDescriptions) + { + std::vector NeededBlockChunkIndexes; + for (uint32_t ChunkIndex = 0; ChunkIndex < ThinBlockDescription.ChunkRawHashes.size(); ChunkIndex++) { - for (CbFieldView ChunkField : ChunksArray) + const IoHash& ChunkHash = ThinBlockDescription.ChunkRawHashes[ChunkIndex]; + if (NeededAttachments.erase(ChunkHash) == 1) { - const IoHash ChunkHash = ChunkField.AsHash(); - if (OpsAttachments.erase(ChunkHash) == 1) + if (!HasAttachment(ChunkHash)) { - if (!HasAttachment(ChunkHash)) - { - NeededChunks.emplace_back(ChunkHash); - } + NeededBlockChunkIndexes.push_back(ChunkIndex); } } } - - if (!NeededChunks.empty()) + if (!NeededBlockChunkIndexes.empty()) { - OnNeedBlock(BlockHash, std::move(NeededChunks)); - if (BlockHash != IoHash::Zero) + if (ThinBlockDescription.BlockHash != IoHash::Zero) { NeedBlockCount++; } + OnNeedBlock(std::move(ThinBlockDescription), std::move(NeededBlockChunkIndexes)); } + if (remotestore_impl::IsCancelled(OptionalContext)) { return RemoteProjectStore::Result{.ErrorCode = gsl::narrow(HttpResponseCode::OK), @@ -2909,6 +3218,7 @@ ParseOplogContainer(const CbObject& ContainerObject, .Reason = "Operation cancelled"}; } } + remotestore_impl::ReportMessage(OptionalContext, fmt::format("Requesting {} of {} attachment blocks", NeedBlockCount, BlocksArray.Num())); @@ -2918,7 +3228,7 @@ ParseOplogContainer(const CbObject& ContainerObject, { IoHash AttachmentHash = LargeChunksField.AsBinaryAttachment(); - if (OpsAttachments.erase(AttachmentHash) == 1) + if (NeededAttachments.erase(AttachmentHash) == 1) { if (!HasAttachment(AttachmentHash)) { @@ -2941,14 +3251,15 @@ ParseOplogContainer(const CbObject& ContainerObject, } RemoteProjectStore::Result -SaveOplogContainer(ProjectStore::Oplog& Oplog, - const CbObject& ContainerObject, - const std::function RawHashes)>& OnReferencedAttachments, - const std::function& HasAttachment, - const std::function&& Chunks)>& OnNeedBlock, - const std::function& OnNeedAttachment, - const std::function& OnChunkedAttachment, - JobContext* OptionalContext) +SaveOplogContainer( + ProjectStore::Oplog& Oplog, + const CbObject& ContainerObject, + const std::function RawHashes)>& OnReferencedAttachments, + const std::function& HasAttachment, + const std::function&& NeededChunkIndexes)>& OnNeedBlock, + const std::function& OnNeedAttachment, + const std::function& OnChunkedAttachment, + JobContext* OptionalContext) { using namespace std::literals; @@ -2972,18 +3283,23 @@ SaveOplogContainer(ProjectStore::Oplog& Oplog, } RemoteProjectStore::Result -LoadOplog(CidStore& ChunkStore, - RemoteProjectStore& RemoteStore, - ProjectStore::Oplog& Oplog, - WorkerThreadPool& NetworkWorkerPool, - WorkerThreadPool& WorkerPool, - bool ForceDownload, - bool IgnoreMissingAttachments, - bool CleanOplog, - JobContext* OptionalContext) +LoadOplog(CidStore& ChunkStore, + RemoteProjectStore& RemoteStore, + ProjectStore::Oplog& Oplog, + WorkerThreadPool& NetworkWorkerPool, + WorkerThreadPool& WorkerPool, + bool ForceDownload, + bool IgnoreMissingAttachments, + bool CleanOplog, + EPartialBlockRequestMode PartialBlockRequestMode, + double HostLatencySec, + double CacheLatencySec, + JobContext* OptionalContext) { using namespace std::literals; + std::unique_ptr LogOutput(std::make_unique(OptionalContext)); + remotestore_impl::DownloadInfo Info; Stopwatch Timer; @@ -3035,6 +3351,14 @@ LoadOplog(CidStore& ChunkStore, return false; }; + struct NeededBlockDownload + { + ThinChunkBlockDescription ThinBlockDescription; + std::vector NeededChunkIndexes; + }; + + std::vector NeededBlockDownloads; + auto OnNeedBlock = [&RemoteStore, &ChunkStore, &NetworkWorkerPool, @@ -3047,8 +3371,9 @@ LoadOplog(CidStore& ChunkStore, &Info, &LoadAttachmentsTimer, &DownloadStartMS, + &NeededBlockDownloads, IgnoreMissingAttachments, - OptionalContext](const IoHash& BlockHash, std::vector&& Chunks) { + OptionalContext](ThinChunkBlockDescription&& ThinBlockDescription, std::vector&& NeededChunkIndexes) { if (RemoteResult.IsError()) { return; @@ -3056,7 +3381,7 @@ LoadOplog(CidStore& ChunkStore, BlockCountToDownload++; AttachmentCount.fetch_add(1); - if (BlockHash == IoHash::Zero) + if (ThinBlockDescription.BlockHash == IoHash::Zero) { DownloadAndSaveBlockChunks(ChunkStore, RemoteStore, @@ -3070,25 +3395,13 @@ LoadOplog(CidStore& ChunkStore, Info, LoadAttachmentsTimer, DownloadStartMS, - Chunks); + std::move(ThinBlockDescription), + std::move(NeededChunkIndexes)); } else { - DownloadAndSaveBlock(ChunkStore, - RemoteStore, - IgnoreMissingAttachments, - OptionalContext, - NetworkWorkerPool, - WorkerPool, - AttachmentsDownloadLatch, - AttachmentsWriteLatch, - RemoteResult, - Info, - LoadAttachmentsTimer, - DownloadStartMS, - BlockHash, - Chunks, - 3); + NeededBlockDownloads.push_back(NeededBlockDownload{.ThinBlockDescription = std::move(ThinBlockDescription), + .NeededChunkIndexes = std::move(NeededChunkIndexes)}); } }; @@ -3132,12 +3445,7 @@ LoadOplog(CidStore& ChunkStore, }; std::vector FilesToDechunk; - auto OnChunkedAttachment = [&Oplog, &ChunkStore, &FilesToDechunk, ForceDownload](const ChunkedInfo& Chunked) { - if (ForceDownload || !ChunkStore.ContainsChunk(Chunked.RawHash)) - { - FilesToDechunk.push_back(Chunked); - } - }; + auto OnChunkedAttachment = [&FilesToDechunk](const ChunkedInfo& Chunked) { FilesToDechunk.push_back(Chunked); }; auto OnReferencedAttachments = [&Oplog](std::span RawHashes) { Oplog.CaptureAddedAttachments(RawHashes); }; @@ -3165,6 +3473,185 @@ LoadOplog(CidStore& ChunkStore, BlockCountToDownload, FilesToDechunk.size())); + std::vector BlockHashes; + std::vector AllNeededChunkHashes; + BlockHashes.reserve(NeededBlockDownloads.size()); + for (const NeededBlockDownload& BlockDownload : NeededBlockDownloads) + { + BlockHashes.push_back(BlockDownload.ThinBlockDescription.BlockHash); + for (uint32_t ChunkIndex : BlockDownload.NeededChunkIndexes) + { + AllNeededChunkHashes.push_back(BlockDownload.ThinBlockDescription.ChunkRawHashes[ChunkIndex]); + } + } + + tsl::robin_map AllNeededPartialChunkHashesLookup = BuildHashLookup(AllNeededChunkHashes); + std::vector> ChunkDownloadedFlags(AllNeededChunkHashes.size()); + std::vector DownloadedViaLegacyChunkFlag(AllNeededChunkHashes.size(), false); + ChunkBlockAnalyser::BlockResult PartialBlocksResult; + + RemoteProjectStore::GetBlockDescriptionsResult BlockDescriptions = RemoteStore.GetBlockDescriptions(BlockHashes); + std::vector BlocksWithDescription; + BlocksWithDescription.reserve(BlockDescriptions.Blocks.size()); + for (const ChunkBlockDescription& BlockDescription : BlockDescriptions.Blocks) + { + BlocksWithDescription.push_back(BlockDescription.BlockHash); + } + { + auto WantIt = NeededBlockDownloads.begin(); + auto FindIt = BlockDescriptions.Blocks.begin(); + while (WantIt != NeededBlockDownloads.end()) + { + if (FindIt == BlockDescriptions.Blocks.end()) + { + // Fall back to full download as we can't get enough information about the block + DownloadAndSaveBlock(ChunkStore, + RemoteStore, + IgnoreMissingAttachments, + OptionalContext, + NetworkWorkerPool, + WorkerPool, + AttachmentsDownloadLatch, + AttachmentsWriteLatch, + RemoteResult, + Info, + LoadAttachmentsTimer, + DownloadStartMS, + WantIt->ThinBlockDescription.BlockHash, + AllNeededPartialChunkHashesLookup, + ChunkDownloadedFlags, + 3); + for (uint32_t BlockChunkIndex : WantIt->NeededChunkIndexes) + { + const IoHash& ChunkHash = WantIt->ThinBlockDescription.ChunkRawHashes[BlockChunkIndex]; + auto It = AllNeededPartialChunkHashesLookup.find(ChunkHash); + ZEN_ASSERT(It != AllNeededPartialChunkHashesLookup.end()); + uint32_t ChunkIndex = It->second; + DownloadedViaLegacyChunkFlag[ChunkIndex] = true; + } + WantIt++; + } + else if (WantIt->ThinBlockDescription.BlockHash == FindIt->BlockHash) + { + // Found + FindIt++; + WantIt++; + } + else + { + // Not a requested block? + ZEN_ASSERT(false); + } + } + } + if (!AllNeededChunkHashes.empty()) + { + std::vector PartialBlockDownloadModes; + + if (PartialBlockRequestMode == EPartialBlockRequestMode::Off) + { + PartialBlockDownloadModes.resize(BlocksWithDescription.size(), ChunkBlockAnalyser::EPartialBlockDownloadMode::Off); + } + else + { + RemoteProjectStore::AttachmentExistsInCacheResult CacheExistsResult = + RemoteStore.AttachmentExistsInCache(BlocksWithDescription); + if (CacheExistsResult.ErrorCode != 0 || CacheExistsResult.HasBody.size() != BlocksWithDescription.size()) + { + CacheExistsResult.HasBody.resize(BlocksWithDescription.size(), false); + } + + PartialBlockDownloadModes.reserve(BlocksWithDescription.size()); + + for (bool ExistsInCache : CacheExistsResult.HasBody) + { + if (PartialBlockRequestMode == EPartialBlockRequestMode::All) + { + PartialBlockDownloadModes.push_back(ExistsInCache ? ChunkBlockAnalyser::EPartialBlockDownloadMode::MultiRangeHighSpeed + : ChunkBlockAnalyser::EPartialBlockDownloadMode::MultiRange); + } + else if (PartialBlockRequestMode == EPartialBlockRequestMode::ZenCacheOnly) + { + PartialBlockDownloadModes.push_back(ExistsInCache ? ChunkBlockAnalyser::EPartialBlockDownloadMode::MultiRangeHighSpeed + : ChunkBlockAnalyser::EPartialBlockDownloadMode::Off); + } + else if (PartialBlockRequestMode == EPartialBlockRequestMode::Mixed) + { + PartialBlockDownloadModes.push_back(ExistsInCache ? ChunkBlockAnalyser::EPartialBlockDownloadMode::MultiRangeHighSpeed + : ChunkBlockAnalyser::EPartialBlockDownloadMode::SingleRange); + } + } + } + + ZEN_ASSERT(PartialBlockDownloadModes.size() == BlocksWithDescription.size()); + + ChunkBlockAnalyser PartialAnalyser(*LogOutput, + BlockDescriptions.Blocks, + ChunkBlockAnalyser::Options{.IsQuiet = false, + .IsVerbose = false, + .HostLatencySec = HostLatencySec, + .HostHighSpeedLatencySec = CacheLatencySec}); + + std::vector NeededBlocks = + PartialAnalyser.GetNeeded(AllNeededPartialChunkHashesLookup, + [&](uint32_t ChunkIndex) { return !DownloadedViaLegacyChunkFlag[ChunkIndex]; }); + + PartialBlocksResult = PartialAnalyser.CalculatePartialBlockDownloads(NeededBlocks, PartialBlockDownloadModes); + for (uint32_t FullBlockIndex : PartialBlocksResult.FullBlockIndexes) + { + DownloadAndSaveBlock(ChunkStore, + RemoteStore, + IgnoreMissingAttachments, + OptionalContext, + NetworkWorkerPool, + WorkerPool, + AttachmentsDownloadLatch, + AttachmentsWriteLatch, + RemoteResult, + Info, + LoadAttachmentsTimer, + DownloadStartMS, + BlockDescriptions.Blocks[FullBlockIndex].BlockHash, + AllNeededPartialChunkHashesLookup, + ChunkDownloadedFlags, + 3); + } + + for (size_t BlockRangeIndex = 0; BlockRangeIndex < PartialBlocksResult.BlockRanges.size();) + { + size_t RangeCount = 1; + size_t RangesLeft = PartialBlocksResult.BlockRanges.size() - BlockRangeIndex; + const ChunkBlockAnalyser::BlockRangeDescriptor& CurrentBlockRange = PartialBlocksResult.BlockRanges[BlockRangeIndex]; + while (RangeCount < RangesLeft && + CurrentBlockRange.BlockIndex == PartialBlocksResult.BlockRanges[BlockRangeIndex + RangeCount].BlockIndex) + { + RangeCount++; + } + + DownloadAndSavePartialBlock(ChunkStore, + RemoteStore, + IgnoreMissingAttachments, + OptionalContext, + NetworkWorkerPool, + WorkerPool, + AttachmentsDownloadLatch, + AttachmentsWriteLatch, + RemoteResult, + Info, + LoadAttachmentsTimer, + DownloadStartMS, + BlockDescriptions.Blocks[CurrentBlockRange.BlockIndex], + PartialBlocksResult.BlockRanges, + BlockRangeIndex, + RangeCount, + AllNeededPartialChunkHashesLookup, + ChunkDownloadedFlags, + 3); + + BlockRangeIndex += RangeCount; + } + } + AttachmentsDownloadLatch.CountDown(); while (!AttachmentsDownloadLatch.Wait(1000)) { @@ -3478,21 +3965,30 @@ LoadOplog(CidStore& ChunkStore, } } - remotestore_impl::ReportMessage( - OptionalContext, - fmt::format("Loaded oplog '{}' {} in {} ({}), Blocks: {} ({}), Attachments: {} ({}), Stored: {} ({}), Missing: {} {}", - RemoteStoreInfo.ContainerName, - Result.ErrorCode == 0 ? "SUCCESS" : "FAILURE", - NiceTimeSpanMs(static_cast(Result.ElapsedSeconds * 1000.0)), - NiceBytes(Info.OplogSizeBytes), - Info.AttachmentBlocksDownloaded.load(), - NiceBytes(Info.AttachmentBlockBytesDownloaded.load()), - Info.AttachmentsDownloaded.load(), - NiceBytes(Info.AttachmentBytesDownloaded.load()), - Info.AttachmentsStored.load(), - NiceBytes(Info.AttachmentBytesStored.load()), - Info.MissingAttachmentCount.load(), - remotestore_impl::GetStats(RemoteStore.GetStats(), TransferWallTimeMS))); + uint64_t TotalDownloads = + 1 + Info.AttachmentBlocksDownloaded.load() + Info.AttachmentBlocksRangesDownloaded.load() + Info.AttachmentsDownloaded.load(); + uint64_t TotalBytesDownloaded = Info.OplogSizeBytes + Info.AttachmentBlockBytesDownloaded.load() + + Info.AttachmentBlockRangeBytesDownloaded.load() + Info.AttachmentBytesDownloaded.load(); + + remotestore_impl::ReportMessage(OptionalContext, + fmt::format("Loaded oplog '{}' {} in {} ({}), Blocks: {} ({}), BlockRanges: {} ({}), Attachments: {} " + "({}), Total: {} ({}), Stored: {} ({}), Missing: {} {}", + RemoteStoreInfo.ContainerName, + Result.ErrorCode == 0 ? "SUCCESS" : "FAILURE", + NiceTimeSpanMs(static_cast(Result.ElapsedSeconds * 1000.0)), + NiceBytes(Info.OplogSizeBytes), + Info.AttachmentBlocksDownloaded.load(), + NiceBytes(Info.AttachmentBlockBytesDownloaded.load()), + Info.AttachmentBlocksRangesDownloaded.load(), + NiceBytes(Info.AttachmentBlockRangeBytesDownloaded.load()), + Info.AttachmentsDownloaded.load(), + NiceBytes(Info.AttachmentBytesDownloaded.load()), + TotalDownloads, + NiceBytes(TotalBytesDownloaded), + Info.AttachmentsStored.load(), + NiceBytes(Info.AttachmentBytesStored.load()), + Info.MissingAttachmentCount.load(), + remotestore_impl::GetStats(RemoteStore.GetStats(), TransferWallTimeMS))); return Result; } @@ -3697,6 +4193,9 @@ TEST_CASE_TEMPLATE("project.store.export", /*Force*/ false, /*IgnoreMissingAttachments*/ false, /*CleanOplog*/ false, + EPartialBlockRequestMode::Mixed, + /*HostLatencySec*/ -1.0, + /*CacheLatencySec*/ -1.0, nullptr); CHECK(ImportResult.ErrorCode == 0); @@ -3708,6 +4207,9 @@ TEST_CASE_TEMPLATE("project.store.export", /*Force*/ true, /*IgnoreMissingAttachments*/ false, /*CleanOplog*/ false, + EPartialBlockRequestMode::Mixed, + /*HostLatencySec*/ -1.0, + /*CacheLatencySec*/ -1.0, nullptr); CHECK(ImportForceResult.ErrorCode == 0); @@ -3719,6 +4221,9 @@ TEST_CASE_TEMPLATE("project.store.export", /*Force*/ false, /*IgnoreMissingAttachments*/ false, /*CleanOplog*/ true, + EPartialBlockRequestMode::Mixed, + /*HostLatencySec*/ -1.0, + /*CacheLatencySec*/ -1.0, nullptr); CHECK(ImportCleanResult.ErrorCode == 0); @@ -3730,6 +4235,9 @@ TEST_CASE_TEMPLATE("project.store.export", /*Force*/ true, /*IgnoreMissingAttachments*/ false, /*CleanOplog*/ true, + EPartialBlockRequestMode::Mixed, + /*HostLatencySec*/ -1.0, + /*CacheLatencySec*/ -1.0, nullptr); CHECK(ImportForceCleanResult.ErrorCode == 0); } diff --git a/src/zenremotestore/projectstore/zenremoteprojectstore.cpp b/src/zenremotestore/projectstore/zenremoteprojectstore.cpp index ab82edbef..b4c1156ac 100644 --- a/src/zenremotestore/projectstore/zenremoteprojectstore.cpp +++ b/src/zenremotestore/projectstore/zenremoteprojectstore.cpp @@ -249,7 +249,18 @@ public: return GetKnownBlocksResult{{.ErrorCode = static_cast(HttpResponseCode::NoContent)}}; } - virtual LoadAttachmentResult LoadAttachment(const IoHash& RawHash) override + virtual GetBlockDescriptionsResult GetBlockDescriptions(std::span BlockHashes) override + { + ZEN_UNUSED(BlockHashes); + return GetBlockDescriptionsResult{Result{.ErrorCode = int(HttpResponseCode::NotFound)}}; + } + + virtual AttachmentExistsInCacheResult AttachmentExistsInCache(std::span RawHashes) override + { + return AttachmentExistsInCacheResult{Result{.ErrorCode = 0}, std::vector(RawHashes.size(), false)}; + } + + virtual LoadAttachmentResult LoadAttachment(const IoHash& RawHash, const AttachmentRange& Range) override { std::string LoadRequest = fmt::format("/{}/oplog/{}/{}"sv, m_Project, m_Oplog, RawHash); HttpClient::Response Response = @@ -257,12 +268,7 @@ public: AddStats(Response); LoadAttachmentResult Result = LoadAttachmentResult{ConvertResult(Response)}; - if (!Result.ErrorCode) - { - Result.Bytes = Response.ResponsePayload; - Result.Bytes.MakeOwned(); - } - if (!Result.ErrorCode) + if (Result.ErrorCode) { Result.Reason = fmt::format("Failed fetching oplog attachment from {}/{}/{}/{}. Reason: '{}'", m_ProjectStoreUrl, @@ -271,6 +277,15 @@ public: RawHash, Result.Reason); } + if (!Result.ErrorCode && Range) + { + Result.Bytes = IoBuffer(Response.ResponsePayload, Range.Offset, Range.Bytes); + } + else + { + Result.Bytes = Response.ResponsePayload; + } + Result.Bytes.MakeOwned(); return Result; } diff --git a/src/zenserver/storage/projectstore/httpprojectstore.cpp b/src/zenserver/storage/projectstore/httpprojectstore.cpp index 416e2ed69..2b5474d00 100644 --- a/src/zenserver/storage/projectstore/httpprojectstore.cpp +++ b/src/zenserver/storage/projectstore/httpprojectstore.cpp @@ -244,6 +244,8 @@ namespace { { std::shared_ptr Store; std::string Description; + double HostLatencySec = -1.0; + double CacheLatencySec = -1.0; }; CreateRemoteStoreResult CreateRemoteStore(LoggerRef InLog, @@ -261,6 +263,8 @@ namespace { using namespace std::literals; std::shared_ptr RemoteStore; + double HostLatencySec = -1.0; + double CacheLatencySec = -1.0; if (CbObjectView File = Params["file"sv].AsObjectView(); File) { @@ -495,7 +499,9 @@ namespace { /*Quiet*/ false, /*Unattended*/ false, /*Hidden*/ true, - GetTinyWorkerPool(EWorkloadType::Background)); + GetTinyWorkerPool(EWorkloadType::Background), + HostLatencySec, + CacheLatencySec); } if (!RemoteStore) @@ -503,7 +509,10 @@ namespace { return {nullptr, "Unknown remote store type"}; } - return {std::move(RemoteStore), ""}; + return CreateRemoteStoreResult{.Store = std::move(RemoteStore), + .Description = "", + .HostLatencySec = HostLatencySec, + .CacheLatencySec = CacheLatencySec}; } std::pair ConvertResult(const RemoteProjectStore::Result& Result) @@ -2356,15 +2365,19 @@ HttpProjectService::HandleOplogSaveRequest(HttpRouterRequest& Req) tsl::robin_set Attachments; auto HasAttachment = [this](const IoHash& RawHash) { return m_CidStore.ContainsChunk(RawHash); }; - auto OnNeedBlock = [&AttachmentsLock, &Attachments](const IoHash& BlockHash, const std::vector&& ChunkHashes) { + auto OnNeedBlock = [&AttachmentsLock, &Attachments](ThinChunkBlockDescription&& ThinBlockDescription, + std::vector&& NeededChunkIndexes) { RwLock::ExclusiveLockScope _(AttachmentsLock); - if (BlockHash != IoHash::Zero) + if (ThinBlockDescription.BlockHash != IoHash::Zero) { - Attachments.insert(BlockHash); + Attachments.insert(ThinBlockDescription.BlockHash); } else { - Attachments.insert(ChunkHashes.begin(), ChunkHashes.end()); + for (uint32_t ChunkIndex : NeededChunkIndexes) + { + Attachments.insert(ThinBlockDescription.ChunkRawHashes[ChunkIndex]); + } } }; auto OnNeedAttachment = [&AttachmentsLock, &Attachments](const IoHash& RawHash) { @@ -2663,6 +2676,8 @@ HttpProjectService::HandleRpcRequest(HttpRouterRequest& Req) bool CleanOplog = Params["clean"].AsBool(false); bool BoostWorkerCount = Params["boostworkercount"].AsBool(false); bool BoostWorkerMemory = Params["boostworkermemory"sv].AsBool(false); + EPartialBlockRequestMode PartialBlockRequestMode = + PartialBlockRequestModeFromString(Params["partialblockrequestmode"sv].AsString("true")); CreateRemoteStoreResult RemoteStoreResult = CreateRemoteStore(Log(), Params, @@ -2688,6 +2703,9 @@ HttpProjectService::HandleRpcRequest(HttpRouterRequest& Req) Force, IgnoreMissingAttachments, CleanOplog, + PartialBlockRequestMode, + HostLatencySec = RemoteStoreResult.HostLatencySec, + CacheLatencySec = RemoteStoreResult.CacheLatencySec, BoostWorkerCount](JobContext& Context) { Context.ReportMessage(fmt::format("Loading oplog '{}/{}' from {}", Oplog->GetOuterProjectIdentifier(), @@ -2709,6 +2727,9 @@ HttpProjectService::HandleRpcRequest(HttpRouterRequest& Req) Force, IgnoreMissingAttachments, CleanOplog, + PartialBlockRequestMode, + HostLatencySec, + CacheLatencySec, &Context); auto Response = ConvertResult(Result); ZEN_INFO("LoadOplog: Status: {} '{}'", ToString(Response.first), Response.second); -- cgit v1.2.3 From b794809ece9965703b47f06b2d934f126c358ebf Mon Sep 17 00:00:00 2001 From: Stefan Boberg Date: Tue, 24 Feb 2026 17:57:23 +0100 Subject: updated CLAUDE.md --- CLAUDE.md | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 757ce5d2a..c859d7ca2 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -14,17 +14,17 @@ This project uses **xmake** as its build system. xmake is stateful - run configu ```bash # Configure for debug (includes tests) -xmake config -m debug +xmake config -y -m debug -a x64 # Configure for release -xmake config -m release +xmake config -y -m release -a x64 # Build everything -xmake +xmake -y # Build specific target -xmake build zenserver -xmake build zen +xmake build -y zenserver +xmake build -y zen # Run targets xmake run zenserver @@ -154,6 +154,8 @@ The codebase is organized into layered modules with clear dependencies: - Can use mimalloc or rpmalloc for performance - UE-style LLM (Low-Level Memory) tracking available on Windows - Memory tracing support integrated with UE trace system +- Avoid using `std::string` when building (concatenating etc) temporary strings. Use `ExtendableStringBuilder` + instead with an appropriate size N to avoid heap allocations in the common case. **Tracing:** - UE Trace integration for profiling and diagnostics @@ -171,18 +173,23 @@ The codebase is organized into layered modules with clear dependencies: - Static variables: `s_PascalCase` - Thread-local variables: `t_PascalCase` -**Note:** Unlike UE, no `F` prefix on structs/classes is required or encouraged. Also, no `b` prefix on booleans. +**Note:** Unlike UE, no `F` prefix on structs/classes is required nor encouraged. Also, no `b` prefix on booleans. **Code Style:** - C++20 standard - clang-format enforced via pre-commit hooks -- Use `std` containers; `eastl::fixed_vector` etc. for performance-critical paths +- Use `std` containers; `eastl::fixed_vector` etc. for performance-critical paths where the number of elements + in the container is typically small or when the container is temporary and suitable for stack allocation. - Exceptions used only for unexpected errors, not flow control + - Some `std` exception types like `runtime_error` are also available in the `zen` namespace and offer + convenience of formatting the exception message by allowing fmt-style formatting without using + `fmt::format` which can reduce clutter. To use these, please `#include ` - Logging is done via `ZEN_DEBUG(...)`, `ZEN_INFO(...)`, `ZEN_WARN`, `ZEN_ERROR` macros - - Logging macros use `fmt::format` for message formatting. The first argument is the format string, which - must be a string literal (turned into `std::string_view` in the macros) + - Logging macros use `fmt::vformat` internally for message formatting. The first argument is the format string, + which must be a string literal (turned into `std::string_view` in the macros) - Logging channels can be overridden on a scope-by-scope basis (per-class or even per-function) by implementing a `LoggerRef Log()` function +- `if`/`else` should use braces even for single-statement branches **Includes:** - Wrap third-party includes with `ZEN_THIRD_PARTY_INCLUDES_START` / `ZEN_THIRD_PARTY_INCLUDES_END` @@ -203,6 +210,9 @@ On Windows, zenserver requires elevation or a URL reservation to bind http.sys t netsh http add urlacl url=http://*:8558/ user= ``` +**POST endpoint content types** +Endpoints accepting POST operations should only accept JSON or compact binary format payloads. + ## Platform-Specific Notes **Windows:** -- cgit v1.2.3 From fb19c8a86e89762ea89df3b361494a055680b432 Mon Sep 17 00:00:00 2001 From: Stefan Boberg Date: Tue, 24 Feb 2026 22:24:11 +0100 Subject: Fix zencore bugs and propagate content type through IoBufferBuilder (#783) - Add missing includes in hashutils.h (``, ``) - Add `ZenContentType` parameter to all `IoBufferBuilder` factory methods so content type is set at buffer creation time - Fix null dereference in `SharedBuffer::GetFileReference()` when buffer is null - Fix out-of-bounds read in trace command-line argument parsing when arg length exactly matches option length - Add unit tests for 32-bit `CountLeadingZeros` --- src/zencore/include/zencore/hashutils.h | 3 +++ src/zencore/include/zencore/iobuffer.h | 37 ++++++++++++++++++++++-------- src/zencore/include/zencore/sharedbuffer.h | 13 ++++++----- src/zencore/intmath.cpp | 6 +++++ src/zencore/iobuffer.cpp | 20 +++++++++------- src/zencore/trace.cpp | 13 ++++++++--- 6 files changed, 65 insertions(+), 27 deletions(-) diff --git a/src/zencore/include/zencore/hashutils.h b/src/zencore/include/zencore/hashutils.h index 4e877e219..6b9902b3a 100644 --- a/src/zencore/include/zencore/hashutils.h +++ b/src/zencore/include/zencore/hashutils.h @@ -2,6 +2,9 @@ #pragma once +#include +#include + namespace zen { template diff --git a/src/zencore/include/zencore/iobuffer.h b/src/zencore/include/zencore/iobuffer.h index 182768ff6..82c201edd 100644 --- a/src/zencore/include/zencore/iobuffer.h +++ b/src/zencore/include/zencore/iobuffer.h @@ -426,22 +426,39 @@ private: class IoBufferBuilder { public: - static IoBuffer MakeFromFile(const std::filesystem::path& FileName, uint64_t Offset = 0, uint64_t Size = ~0ull); - static IoBuffer MakeFromTemporaryFile(const std::filesystem::path& FileName); - static IoBuffer MakeFromFileHandle(void* FileHandle, uint64_t Offset = 0, uint64_t Size = ~0ull); - /** Make sure buffer data is memory resident, but avoid memory mapping data from files - */ - static IoBuffer ReadFromFileMaybe(const IoBuffer& InBuffer); - inline static IoBuffer MakeFromMemory(MemoryView Memory) { return IoBuffer(IoBuffer::Wrap, Memory.GetData(), Memory.GetSize()); } - inline static IoBuffer MakeCloneFromMemory(const void* Ptr, size_t Sz) + static IoBuffer MakeFromFile(const std::filesystem::path& FileName, + uint64_t Offset = 0, + uint64_t Size = ~0ull, + ZenContentType ContentType = ZenContentType::kBinary); + static IoBuffer MakeFromTemporaryFile(const std::filesystem::path& FileName, ZenContentType ContentType = ZenContentType::kBinary); + static IoBuffer MakeFromFileHandle(void* FileHandle, + uint64_t Offset = 0, + uint64_t Size = ~0ull, + ZenContentType ContentType = ZenContentType::kBinary); + inline static IoBuffer MakeFromMemory(MemoryView Memory, ZenContentType ContentType = ZenContentType::kBinary) + { + IoBuffer NewBuffer(IoBuffer::Wrap, Memory.GetData(), Memory.GetSize()); + NewBuffer.SetContentType(ContentType); + return NewBuffer; + } + inline static IoBuffer MakeCloneFromMemory(const void* Ptr, size_t Sz, ZenContentType ContentType = ZenContentType::kBinary) { if (Sz) { - return IoBuffer(IoBuffer::Clone, Ptr, Sz); + IoBuffer NewBuffer(IoBuffer::Clone, Ptr, Sz); + NewBuffer.SetContentType(ContentType); + return NewBuffer; } return {}; } - inline static IoBuffer MakeCloneFromMemory(MemoryView Memory) { return MakeCloneFromMemory(Memory.GetData(), Memory.GetSize()); } + inline static IoBuffer MakeCloneFromMemory(MemoryView Memory, ZenContentType ContentType = ZenContentType::kBinary) + { + return MakeCloneFromMemory(Memory.GetData(), Memory.GetSize(), ContentType); + } + + /** Make sure buffer data is memory resident, but avoid memory mapping data from files + */ + static IoBuffer ReadFromFileMaybe(const IoBuffer& InBuffer); }; void iobuffer_forcelink(); diff --git a/src/zencore/include/zencore/sharedbuffer.h b/src/zencore/include/zencore/sharedbuffer.h index c57e9f568..3d4c19282 100644 --- a/src/zencore/include/zencore/sharedbuffer.h +++ b/src/zencore/include/zencore/sharedbuffer.h @@ -116,14 +116,15 @@ public: inline void Reset() { m_Buffer = nullptr; } inline bool GetFileReference(IoBufferFileReference& OutRef) const { - if (const IoBufferExtendedCore* Core = m_Buffer->ExtendedCore()) + if (!IsNull()) { - return Core->GetFileReference(OutRef); - } - else - { - return false; + if (const IoBufferExtendedCore* Core = m_Buffer->ExtendedCore()) + { + return Core->GetFileReference(OutRef); + } } + + return false; } [[nodiscard]] MemoryView GetView() const diff --git a/src/zencore/intmath.cpp b/src/zencore/intmath.cpp index 5a686dc8e..32f82b486 100644 --- a/src/zencore/intmath.cpp +++ b/src/zencore/intmath.cpp @@ -43,6 +43,12 @@ TEST_CASE("intmath") CHECK(FloorLog2_64(0x0000'0001'0000'0000ull) == 32); CHECK(FloorLog2_64(0x8000'0000'0000'0000ull) == 63); + CHECK(CountLeadingZeros(0x8000'0000u) == 0); + CHECK(CountLeadingZeros(0x0000'0000u) == 32); + CHECK(CountLeadingZeros(0x0000'0001u) == 31); + CHECK(CountLeadingZeros(0x0000'8000u) == 16); + CHECK(CountLeadingZeros(0x0001'0000u) == 15); + CHECK(CountLeadingZeros64(0x8000'0000'0000'0000ull) == 0); CHECK(CountLeadingZeros64(0x0000'0000'0000'0000ull) == 64); CHECK(CountLeadingZeros64(0x0000'0000'0000'0001ull) == 63); diff --git a/src/zencore/iobuffer.cpp b/src/zencore/iobuffer.cpp index be9b39e7a..1c31d6620 100644 --- a/src/zencore/iobuffer.cpp +++ b/src/zencore/iobuffer.cpp @@ -592,15 +592,17 @@ IoBufferBuilder::ReadFromFileMaybe(const IoBuffer& InBuffer) } IoBuffer -IoBufferBuilder::MakeFromFileHandle(void* FileHandle, uint64_t Offset, uint64_t Size) +IoBufferBuilder::MakeFromFileHandle(void* FileHandle, uint64_t Offset, uint64_t Size, ZenContentType ContentType) { ZEN_TRACE_CPU("IoBufferBuilder::MakeFromFileHandle"); - return IoBuffer(IoBuffer::BorrowedFile, FileHandle, Offset, Size); + IoBuffer Buffer(IoBuffer::BorrowedFile, FileHandle, Offset, Size); + Buffer.SetContentType(ContentType); + return Buffer; } IoBuffer -IoBufferBuilder::MakeFromFile(const std::filesystem::path& FileName, uint64_t Offset, uint64_t Size) +IoBufferBuilder::MakeFromFile(const std::filesystem::path& FileName, uint64_t Offset, uint64_t Size, ZenContentType ContentType) { ZEN_TRACE_CPU("IoBufferBuilder::MakeFromFile"); @@ -632,8 +634,6 @@ IoBufferBuilder::MakeFromFile(const std::filesystem::path& FileName, uint64_t Of FileSize = Stat.st_size; #endif // ZEN_PLATFORM_WINDOWS - // TODO: should validate that offset is in range - if (Size == ~0ull) { Size = FileSize - Offset; @@ -652,7 +652,9 @@ IoBufferBuilder::MakeFromFile(const std::filesystem::path& FileName, uint64_t Of #if ZEN_PLATFORM_WINDOWS void* Fd = DataFile.Detach(); #endif - return IoBuffer(IoBuffer::File, (void*)uintptr_t(Fd), Offset, Size, Offset == 0 && Size == FileSize); + IoBuffer NewBuffer(IoBuffer::File, (void*)uintptr_t(Fd), Offset, Size, Offset == 0 && Size == FileSize); + NewBuffer.SetContentType(ContentType); + return NewBuffer; } #if !ZEN_PLATFORM_WINDOWS @@ -664,7 +666,7 @@ IoBufferBuilder::MakeFromFile(const std::filesystem::path& FileName, uint64_t Of } IoBuffer -IoBufferBuilder::MakeFromTemporaryFile(const std::filesystem::path& FileName) +IoBufferBuilder::MakeFromTemporaryFile(const std::filesystem::path& FileName, ZenContentType ContentType) { ZEN_TRACE_CPU("IoBufferBuilder::MakeFromTemporaryFile"); @@ -703,7 +705,9 @@ IoBufferBuilder::MakeFromTemporaryFile(const std::filesystem::path& FileName) Handle = (void*)uintptr_t(Fd); #endif // ZEN_PLATFORM_WINDOWS - return IoBuffer(IoBuffer::File, Handle, 0, FileSize, /*IsWholeFile*/ true); + IoBuffer NewBuffer(IoBuffer::File, Handle, 0, FileSize, /*IsWholeFile*/ true); + NewBuffer.SetContentType(ContentType); + return NewBuffer; } ////////////////////////////////////////////////////////////////////////// diff --git a/src/zencore/trace.cpp b/src/zencore/trace.cpp index 87035554f..a026974c0 100644 --- a/src/zencore/trace.cpp +++ b/src/zencore/trace.cpp @@ -165,10 +165,17 @@ GetTraceOptionsFromCommandline(TraceOptions& OutOptions) auto MatchesArg = [](std::string_view Option, std::string_view Arg) -> std::optional { if (Arg.starts_with(Option)) { - std::string_view::value_type DelimChar = Arg[Option.length()]; - if (DelimChar == ' ' || DelimChar == '=') + if (Arg.length() > Option.length()) { - return Arg.substr(Option.size() + 1); + std::string_view::value_type DelimChar = Arg[Option.length()]; + if (DelimChar == ' ' || DelimChar == '=') + { + return Arg.substr(Option.size() + 1); + } + } + else + { + return ""sv; } } return {}; -- cgit v1.2.3 From 241e4faf64be83711dc509ad8a25ff4e8ae95c12 Mon Sep 17 00:00:00 2001 From: Stefan Boberg Date: Wed, 25 Feb 2026 10:15:41 +0100 Subject: HttpService/Frontend improvements (#782) - zenhttp: added `GetServiceUri()`/`GetExternalHost()` - enables code to quickly generate an externally reachable URI for a given service - frontend: improved Uri handling (better defaults) - added support for 404 page (to make it easier to find a good URL) --- CHANGELOG.md | 1 + src/zenhttp/httpserver.cpp | 24 +++++++++++- src/zenhttp/include/zenhttp/httpserver.h | 16 ++++++++ src/zenhttp/servers/httpasio.cpp | 48 ++++++++++++++++++++---- src/zenhttp/servers/httpmulti.cpp | 10 +++++ src/zenhttp/servers/httpmulti.h | 13 ++++--- src/zenhttp/servers/httpsys.cpp | 49 ++++++++++++++++++++++--- src/zenserver/frontend/frontend.cpp | 57 +++++++++++++++++++++-------- src/zenserver/frontend/html.zip | Bin 183939 -> 279965 bytes src/zenserver/storage/zenstorageserver.cpp | 9 +++++ 10 files changed, 192 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e9d3b79c8..e555dd86f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## - Feature: Add `--allow-partial-block-requests` to `zen oplog-import` - Feature: `zen ui` can be used to open dashboards for local instances +- Feature: Added 404 page to dashboard, to make it easier to find your way back to a valid URL - Improvement: `zen oplog-import` now uses partial block requests to reduce download size - Improvement: Use latency to Cloud Storage host and Zen Cache host when calculating partial block requests - Bugfix: `--plain-progress` style progress bar should now show elapsed time correctly diff --git a/src/zenhttp/httpserver.cpp b/src/zenhttp/httpserver.cpp index f2fe4738f..3cefa0ad8 100644 --- a/src/zenhttp/httpserver.cpp +++ b/src/zenhttp/httpserver.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -1014,7 +1015,28 @@ HttpRequestRouter::HandleRequest(zen::HttpServerRequest& Request) int HttpServer::Initialize(int BasePort, std::filesystem::path DataDir) { - return OnInitialize(BasePort, std::move(DataDir)); + m_EffectivePort = OnInitialize(BasePort, std::move(DataDir)); + m_ExternalHost = OnGetExternalHost(); + return m_EffectivePort; +} + +std::string +HttpServer::OnGetExternalHost() const +{ + return GetMachineName(); +} + +std::string +HttpServer::GetServiceUri(const HttpService* Service) const +{ + if (Service) + { + return fmt::format("http://{}:{}{}", m_ExternalHost, m_EffectivePort, Service->BaseUri()); + } + else + { + return fmt::format("http://{}:{}", m_ExternalHost, m_EffectivePort); + } } void diff --git a/src/zenhttp/include/zenhttp/httpserver.h b/src/zenhttp/include/zenhttp/httpserver.h index 350532126..00cbc6c14 100644 --- a/src/zenhttp/include/zenhttp/httpserver.h +++ b/src/zenhttp/include/zenhttp/httpserver.h @@ -219,8 +219,21 @@ public: void RequestExit(); void Close(); + /** Returns a canonical http:// URI for the given service, using the external + * IP and the port the server is actually listening on. Only valid + * after Initialize() has returned successfully. + */ + std::string GetServiceUri(const HttpService* Service) const; + + /** Returns the external host string (IP or hostname) determined during Initialize(). + * Only valid after Initialize() has returned successfully. + */ + std::string_view GetExternalHost() const { return m_ExternalHost; } + private: std::vector m_KnownServices; + int m_EffectivePort = 0; + std::string m_ExternalHost; virtual void OnRegisterService(HttpService& Service) = 0; virtual int OnInitialize(int BasePort, std::filesystem::path DataDir) = 0; @@ -228,6 +241,9 @@ private: virtual void OnRun(bool IsInteractiveSession) = 0; virtual void OnRequestExit() = 0; virtual void OnClose() = 0; + +protected: + virtual std::string OnGetExternalHost() const; }; struct HttpServerPluginConfig diff --git a/src/zenhttp/servers/httpasio.cpp b/src/zenhttp/servers/httpasio.cpp index fbc7fe401..0c0238886 100644 --- a/src/zenhttp/servers/httpasio.cpp +++ b/src/zenhttp/servers/httpasio.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -506,6 +507,8 @@ public: HttpService* RouteRequest(std::string_view Url); IHttpRequestFilter::Result FilterRequest(HttpServerRequest& Request); + bool IsLoopbackOnly() const; + asio::io_service m_IoService; asio::io_service::work m_Work{m_IoService}; std::unique_ptr m_Acceptor; @@ -1601,7 +1604,8 @@ struct HttpAcceptor void StopAccepting() { m_IsStopped = true; } - int GetAcceptPort() { return m_Acceptor.local_endpoint().port(); } + int GetAcceptPort() const { return m_Acceptor.local_endpoint().port(); } + bool IsLoopbackOnly() const { return m_Acceptor.local_endpoint().address().is_loopback(); } bool IsValid() const { return m_IsValid; } @@ -1975,6 +1979,12 @@ HttpAsioServerImpl::FilterRequest(HttpServerRequest& Request) return RequestFilter->FilterRequest(Request); } +bool +HttpAsioServerImpl::IsLoopbackOnly() const +{ + return m_Acceptor && m_Acceptor->IsLoopbackOnly(); +} + } // namespace zen::asio_http ////////////////////////////////////////////////////////////////////////// @@ -1987,12 +1997,13 @@ public: HttpAsioServer(const AsioConfig& Config); ~HttpAsioServer(); - virtual void OnRegisterService(HttpService& Service) override; - virtual int OnInitialize(int BasePort, std::filesystem::path DataDir) override; - virtual void OnSetHttpRequestFilter(IHttpRequestFilter* RequestFilter) override; - virtual void OnRun(bool IsInteractiveSession) override; - virtual void OnRequestExit() override; - virtual void OnClose() override; + virtual void OnRegisterService(HttpService& Service) override; + virtual int OnInitialize(int BasePort, std::filesystem::path DataDir) override; + virtual void OnSetHttpRequestFilter(IHttpRequestFilter* RequestFilter) override; + virtual void OnRun(bool IsInteractiveSession) override; + virtual void OnRequestExit() override; + virtual void OnClose() override; + virtual std::string OnGetExternalHost() const override; private: Event m_ShutdownEvent; @@ -2067,6 +2078,29 @@ HttpAsioServer::OnInitialize(int BasePort, std::filesystem::path DataDir) return m_BasePort; } +std::string +HttpAsioServer::OnGetExternalHost() const +{ + if (m_Impl->IsLoopbackOnly()) + { + return "127.0.0.1"; + } + + // Use the UDP connect trick: connecting a UDP socket to an external address + // causes the OS to select the appropriate local interface without sending any data. + try + { + asio::io_service IoService; + asio::ip::udp::socket Sock(IoService, asio::ip::udp::v4()); + Sock.connect(asio::ip::udp::endpoint(asio::ip::address::from_string("8.8.8.8"), 80)); + return Sock.local_endpoint().address().to_string(); + } + catch (const std::exception&) + { + return GetMachineName(); + } +} + void HttpAsioServer::OnRun(bool IsInteractive) { diff --git a/src/zenhttp/servers/httpmulti.cpp b/src/zenhttp/servers/httpmulti.cpp index 310ac9dc0..584e06cbf 100644 --- a/src/zenhttp/servers/httpmulti.cpp +++ b/src/zenhttp/servers/httpmulti.cpp @@ -117,6 +117,16 @@ HttpMultiServer::OnClose() } } +std::string +HttpMultiServer::OnGetExternalHost() const +{ + if (!m_Servers.empty()) + { + return std::string(m_Servers.front()->GetExternalHost()); + } + return HttpServer::OnGetExternalHost(); +} + void HttpMultiServer::AddServer(Ref Server) { diff --git a/src/zenhttp/servers/httpmulti.h b/src/zenhttp/servers/httpmulti.h index 1897587a9..97699828a 100644 --- a/src/zenhttp/servers/httpmulti.h +++ b/src/zenhttp/servers/httpmulti.h @@ -15,12 +15,13 @@ public: HttpMultiServer(); ~HttpMultiServer(); - virtual void OnRegisterService(HttpService& Service) override; - virtual void OnSetHttpRequestFilter(IHttpRequestFilter* RequestFilter) override; - virtual int OnInitialize(int BasePort, std::filesystem::path DataDir) override; - virtual void OnRun(bool IsInteractiveSession) override; - virtual void OnRequestExit() override; - virtual void OnClose() override; + virtual void OnRegisterService(HttpService& Service) override; + virtual void OnSetHttpRequestFilter(IHttpRequestFilter* RequestFilter) override; + virtual int OnInitialize(int BasePort, std::filesystem::path DataDir) override; + virtual void OnRun(bool IsInteractiveSession) override; + virtual void OnRequestExit() override; + virtual void OnClose() override; + virtual std::string OnGetExternalHost() const override; void AddServer(Ref Server); diff --git a/src/zenhttp/servers/httpsys.cpp b/src/zenhttp/servers/httpsys.cpp index 6995ffca9..e93ae4853 100644 --- a/src/zenhttp/servers/httpsys.cpp +++ b/src/zenhttp/servers/httpsys.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -27,6 +28,7 @@ # include # include +# include // for resolving addresses for GetExternalHost namespace zen { @@ -93,12 +95,13 @@ public: // HttpServer interface implementation - virtual int OnInitialize(int BasePort, std::filesystem::path DataDir) override; - virtual void OnRun(bool TestMode) override; - virtual void OnRequestExit() override; - virtual void OnRegisterService(HttpService& Service) override; - virtual void OnSetHttpRequestFilter(IHttpRequestFilter* RequestFilter) override; - virtual void OnClose() override; + virtual int OnInitialize(int BasePort, std::filesystem::path DataDir) override; + virtual void OnRun(bool TestMode) override; + virtual void OnRequestExit() override; + virtual void OnRegisterService(HttpService& Service) override; + virtual void OnSetHttpRequestFilter(IHttpRequestFilter* RequestFilter) override; + virtual void OnClose() override; + virtual std::string OnGetExternalHost() const override; WorkerThreadPool& WorkPool(); @@ -2290,6 +2293,40 @@ HttpSysServer::OnRequestExit() m_ShutdownEvent.Set(); } +std::string +HttpSysServer::OnGetExternalHost() const +{ + // Check whether we registered a public wildcard URL (http://*:port/) or fell back to loopback + bool IsPublic = false; + for (const auto& Uri : m_BaseUris) + { + if (Uri.find(L'*') != std::wstring::npos) + { + IsPublic = true; + break; + } + } + + if (!IsPublic) + { + return "127.0.0.1"; + } + + // Use the UDP connect trick: connecting a UDP socket to an external address + // causes the OS to select the appropriate local interface without sending any data. + try + { + asio::io_service IoService; + asio::ip::udp::socket Sock(IoService, asio::ip::udp::v4()); + Sock.connect(asio::ip::udp::endpoint(asio::ip::address::from_string("8.8.8.8"), 80)); + return Sock.local_endpoint().address().to_string(); + } + catch (const std::exception&) + { + return GetMachineName(); + } +} + void HttpSysServer::OnRegisterService(HttpService& Service) { diff --git a/src/zenserver/frontend/frontend.cpp b/src/zenserver/frontend/frontend.cpp index 1cf451e91..579a65c5a 100644 --- a/src/zenserver/frontend/frontend.cpp +++ b/src/zenserver/frontend/frontend.cpp @@ -114,6 +114,8 @@ HttpFrontendService::HandleRequest(zen::HttpServerRequest& Request) { using namespace std::literals; + ExtendableStringBuilder<256> UriBuilder; + std::string_view Uri = Request.RelativeUriWithExtension(); for (; Uri.length() > 0 && Uri[0] == '/'; Uri = Uri.substr(1)) ; @@ -121,6 +123,11 @@ HttpFrontendService::HandleRequest(zen::HttpServerRequest& Request) { Uri = "index.html"sv; } + else if (Uri.back() == '/') + { + UriBuilder << Uri << "index.html"sv; + Uri = UriBuilder; + } // Dismiss if the URI contains .. anywhere to prevent arbitrary file reads if (Uri.find("..") != Uri.npos) @@ -145,27 +152,47 @@ HttpFrontendService::HandleRequest(zen::HttpServerRequest& Request) return Request.WriteResponse(HttpResponseCode::Forbidden); } - // The given content directory overrides any zip-fs discovered in the binary - if (!m_Directory.empty()) - { - auto FullPath = m_Directory / std::filesystem::path(Uri).make_preferred(); - FileContents File = ReadFile(FullPath); - - if (!File.ErrorCode) + auto WriteResponseForUri = [this, + &Request](std::string_view InUri, HttpResponseCode ResponseCode, HttpContentType ContentType) -> bool { + // The given content directory overrides any zip-fs discovered in the binary + if (!m_Directory.empty()) { - return Request.WriteResponse(HttpResponseCode::OK, ContentType, File.Data[0]); + auto FullPath = m_Directory / std::filesystem::path(InUri).make_preferred(); + FileContents File = ReadFile(FullPath); + + if (!File.ErrorCode) + { + Request.WriteResponse(ResponseCode, ContentType, File.Data[0]); + + return true; + } } - } - if (m_ZipFs) - { - if (IoBuffer FileBuffer = m_ZipFs->GetFile(Uri)) + if (m_ZipFs) { - return Request.WriteResponse(HttpResponseCode::OK, ContentType, FileBuffer); + if (IoBuffer FileBuffer = m_ZipFs->GetFile(InUri)) + { + Request.WriteResponse(HttpResponseCode::OK, ContentType, FileBuffer); + + return true; + } } - } - Request.WriteResponse(HttpResponseCode::NotFound, HttpContentType::kText, "Not found"sv); + return false; + }; + + if (WriteResponseForUri(Uri, HttpResponseCode::OK, ContentType)) + { + return; + } + else if (WriteResponseForUri("404.html"sv, HttpResponseCode::NotFound, HttpContentType::kHTML)) + { + return; + } + else + { + Request.WriteResponse(HttpResponseCode::NotFound, HttpContentType::kText, "Not found"sv); + } } } // namespace zen diff --git a/src/zenserver/frontend/html.zip b/src/zenserver/frontend/html.zip index d70a5a62b..3d90c18a8 100644 Binary files a/src/zenserver/frontend/html.zip and b/src/zenserver/frontend/html.zip differ diff --git a/src/zenserver/storage/zenstorageserver.cpp b/src/zenserver/storage/zenstorageserver.cpp index ff854b72d..3d81db656 100644 --- a/src/zenserver/storage/zenstorageserver.cpp +++ b/src/zenserver/storage/zenstorageserver.cpp @@ -700,6 +700,15 @@ ZenStorageServer::Run() ZEN_INFO(ZEN_APP_NAME " now running (pid: {})", GetCurrentProcessId()); + if (m_FrontendService) + { + ZEN_INFO("frontend link: {}", m_Http->GetServiceUri(m_FrontendService.get())); + } + else + { + ZEN_INFO("frontend service disabled"); + } + #if ZEN_PLATFORM_WINDOWS if (zen::windows::IsRunningOnWine()) { -- cgit v1.2.3 From d7354c2ad34858d8ee99fb307685956c24abd897 Mon Sep 17 00:00:00 2001 From: Stefan Boberg Date: Wed, 25 Feb 2026 18:49:31 +0100 Subject: work around doctest shutdown issues with static CRT (#784) * tweaked doctest.h to avoid shutdown issues due to thread_local variables running destructors after the main thread has torn down everything including the heap * disabled zenserver exit thread waiting since doctest should hopefully not be causing issues during shutdown anymore after my workaround This should help reduce the duration of tests spawning lots of server instances --- src/zenserver/main.cpp | 9 +++++++++ thirdparty/doctest/doctest/doctest.h | 29 +++++++++++++++++++++++------ 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/zenserver/main.cpp b/src/zenserver/main.cpp index ee783d2a6..571dd3b4f 100644 --- a/src/zenserver/main.cpp +++ b/src/zenserver/main.cpp @@ -267,6 +267,14 @@ main(int argc, char* argv[]) using namespace zen; using namespace std::literals; + // note: doctest has locally (in thirdparty) been fixed to not cause shutdown + // crashes due to TLS destructors + // + // mimalloc on the other hand might still be causing issues, in which case + // we should work out either how to eliminate the mimalloc dependency or how + // to configure it in a way that doesn't cause shutdown issues + +#if 0 auto _ = zen::MakeGuard([] { // Allow some time for worker threads to unravel, in an effort // to prevent shutdown races in TLS object destruction, mainly due to @@ -277,6 +285,7 @@ main(int argc, char* argv[]) // shutdown crashes observed in some situations. WaitForThreads(1000); }); +#endif enum { diff --git a/thirdparty/doctest/doctest/doctest.h b/thirdparty/doctest/doctest/doctest.h index f297fa0b2..5299d9c1a 100644 --- a/thirdparty/doctest/doctest/doctest.h +++ b/thirdparty/doctest/doctest/doctest.h @@ -3337,7 +3337,8 @@ namespace { } // namespace namespace detail { - DOCTEST_THREAD_LOCAL class + // Leaked heap allocation - see g_infoContexts comment above. + class ThreadLocalStringStream { std::vector stack; std::stringstream ss; @@ -3358,7 +3359,12 @@ namespace detail { ss.rdbuf()->pubseekpos(pos, std::ios::in | std::ios::out); return String(ss, sz); } - } g_oss; + }; + static ThreadLocalStringStream& g_oss_ref() { + DOCTEST_THREAD_LOCAL auto* p = new ThreadLocalStringStream(); + return *p; + } + #define g_oss g_oss_ref() // NOLINT std::ostream* tlssPush() { return g_oss.push(); @@ -4600,7 +4606,14 @@ namespace detail { getExceptionTranslators().push_back(et); } - DOCTEST_THREAD_LOCAL std::vector g_infoContexts; // for logging with INFO() + // Use a leaked heap allocation for thread-local state to avoid calling destructors + // during shutdown. With static CRT linking, thread-local destructors can run after + // the CRT has already been torn down on secondary threads, causing crashes. + static std::vector& g_infoContexts_ref() { + DOCTEST_THREAD_LOCAL auto* p = new std::vector(); + return *p; + } + #define g_infoContexts g_infoContexts_ref() // NOLINT ContextScopeBase::ContextScopeBase() { g_infoContexts.push_back(this); @@ -6440,13 +6453,18 @@ namespace { #ifdef DOCTEST_PLATFORM_WINDOWS struct DebugOutputWindowReporter : public ConsoleReporter { - DOCTEST_THREAD_LOCAL static std::ostringstream oss; + // Leaked heap allocation - see g_infoContexts comment in detail namespace. + static std::ostringstream& oss_ref() { + DOCTEST_THREAD_LOCAL auto* p = new std::ostringstream(); + return *p; + } DebugOutputWindowReporter(const ContextOptions& co) - : ConsoleReporter(co, oss) {} + : ConsoleReporter(co, oss_ref()) {} #define DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(func, type, arg) \ void func(type arg) override { \ + auto& oss = oss_ref(); \ bool with_col = g_no_colors; \ g_no_colors = false; \ ConsoleReporter::func(arg); \ @@ -6470,7 +6488,6 @@ namespace { DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_skipped, const TestCaseData&, in) }; - DOCTEST_THREAD_LOCAL std::ostringstream DebugOutputWindowReporter::oss; #endif // DOCTEST_PLATFORM_WINDOWS // the implementation of parseOption() -- cgit v1.2.3