4#include "Stroika/Foundation/StroikaPreComp.h"
10#if qStroika_Foundation_Common_Platform_POSIX
13#if qStroika_Foundation_Common_Platform_Linux
14#include <sys/sysinfo.h>
17#elif qStroika_Foundation_Common_Platform_Windows
20#include <VersionHelpers.h>
24#include "Stroika/Foundation/Characters/FloatConversion.h"
26#include "Stroika/Foundation/Characters/SDKString.h"
27#include "Stroika/Foundation/Characters/String2Int.h"
30#if qStroika_Foundation_Common_Platform_Windows
31#include "Stroika/Foundation/Common/Platform/Windows/Registry.h"
33#include "Stroika/Foundation/Containers/Sequence.h"
34#include "Stroika/Foundation/Containers/Set.h"
35#include "Stroika/Foundation/Execution/Exceptions.h"
36#if qStroika_Foundation_Common_Platform_Windows
37#include "Stroika/Foundation/Execution/Platform/Windows/Exception.h"
46#if qStroika_Foundation_Common_Platform_POSIX
48#include "Stroika/Foundation/Execution/ProcessRunner.h"
49#include "Stroika/Foundation/Streams/iostream/FStreamSupport.h"
56using namespace Stroika::Foundation::Streams;
57using namespace Stroika::Foundation::Time;
69String SystemConfiguration::BootInformation::ToString ()
const
73 sb <<
"Booted-At: "sv << fBootedAt;
99String SystemConfiguration::CPU::ToString ()
const
103 sb <<
"Cores: "sv << fCores;
113String SystemConfiguration::Memory::ToString ()
const
117 sb <<
"Page-Size: "sv << fPageSize;
118 sb <<
", Total-Physical-RAM: "sv << fTotalPhysicalRAM;
119 sb <<
", Total-Virtual-RAM: "sv << fTotalVirtualRAM;
133 sb <<
"Hostname: "sv << fHostname;
143String SystemConfiguration::OperatingSystem::ToString ()
const
147 sb <<
"Token-Name: "sv + fTokenName;
148 sb <<
", Short-Pretty-Name: "sv + fShortPrettyName;
149 sb <<
", Pretty-Name-With-Major-Version: "sv + fPrettyNameWithMajorVersion;
150 sb <<
", Pretty-Name-With-Details: "sv + fPrettyNameWithVersionDetails;
151 sb <<
", Major-Minor-Version-String: "sv + fMajorMinorVersionString;
152 sb <<
", RFC1945-Compat-Product-Token-With-Version: "sv + fRFC1945CompatProductTokenWithVersion;
153 sb <<
", Bits: "sv << fBits;
154 if (fPreferredInstallerTechnology) {
155 sb <<
", Preferred-Installer-Technology: "sv << *fPreferredInstallerTechnology;
166String SystemConfiguration::ToString ()
const
170 sb <<
"Boot-Information: " << fBootInformation;
171 sb <<
", CPU: "sv << fCPU;
172 sb <<
", Memory: "sv << fMemory;
173 sb <<
", Actual-Operating-System: "sv << fActualOperatingSystem;
174 sb <<
", Apparent-Operating-System: "sv << fApparentOperatingSystem;
175 sb <<
", Computer-Names: "sv << fComputerNames;
185unsigned int SystemConfiguration::CPU::GetNumberOfSockets ()
const
188 for (
const auto& i : fCores) {
189 socketIds.
Add (i.fSocketID);
191 return static_cast<unsigned int> (socketIds.
size ());
199SystemConfiguration::BootInformation Common::GetSystemConfiguration_BootInformation ()
202 static const SystemConfiguration::BootInformation kCachedResult_ = [] () {
203 SystemConfiguration::BootInformation result;
204#if qStroika_Foundation_Common_Platform_Linux
207 result.fBootedAt = DateTime::Now ().AddSeconds (-info.uptime);
208#elif qStroika_Foundation_Common_Platform_POSIX
211 bool succeeded{
false};
212 static const filesystem::path kProcUptimeFileName_{
"/proc/uptime"};
220 BinaryToText::Reader::New (IO::FileSystem::FileInputStream::New (kProcUptimeFileName_, IO::FileSystem::FileInputStream::eNotSeekable))
223 if (t.
size () >= 2) {
224 result.fBootedAt = DateTime::Now ().AddSeconds (-Characters::FloatConversion::ToFloat<double> (t[0]));
240 [[maybe_unused]]
auto&& cleanup =
Execution::Finally ([] ()
noexcept { ::endutxent (); });
242 for (
const utmpx* i = ::getutxent (); i !=
nullptr; i = ::getutxent ()) {
243 if (i->ut_type == BOOT_TIME) {
244 result.fBootedAt = DateTime{i->ut_tv};
251#elif qStroika_Foundation_Common_Platform_Windows
253#if _WIN32_WINNT >= 0x0600
254 result.fBootedAt = DateTime::Now ().AddSeconds (-
static_cast<int> (::GetTickCount64 () / 1000));
256 result.fBootedAt = DateTime::Now ().AddSeconds (-
static_cast<int> (::GetTickCount () / 1000));
263 return kCachedResult_;
271SystemConfiguration::CPU Common::GetSystemConfiguration_CPU ()
275 using CPU = SystemConfiguration::CPU;
277#if qStroika_Foundation_Common_Platform_Linux
280 static const filesystem::path kProcCPUInfoFileName_{
"/proc/cpuinfo"sv};
362 optional<String> foundProcessor;
363 optional<unsigned int> currentProcessorID;
364 optional<String> currentModelName;
365 optional<unsigned int> currentSocketID;
367 BinaryToText::Reader::New (IO::FileSystem::FileInputStream::New (kProcCPUInfoFileName_, IO::FileSystem::FileInputStream::eNotSeekable))
369#if USE_NOISY_TRACE_IN_THIS_MODULE_
370 DbgTrace (
"in Configuration::GetSystemConfiguration_CPU capture_ line={}"_f, line);
372 static const String kOldProcessorLabel_{
"Processor"sv};
373 static const String kProcessorIDLabel_{
"processor"sv};
374 static const String kModelNameLabel_{
"model name"sv};
375 static const String kSocketIDLabel_{
"physical id"sv};
376 if (not line.Trim ().empty ()) {
378 if (lineTokens.
size () >= 2) {
379 String firstTrimedToken = lineTokens[0].Trim ();
380 size_t afterColon = *line.
Find (
':') + 1;
381 if (firstTrimedToken == kOldProcessorLabel_) {
382 foundProcessor = line.SubString (afterColon).Trim ();
384 else if (firstTrimedToken == kProcessorIDLabel_) {
385 currentProcessorID = String2Int<unsigned int> (line.SubString (afterColon).Trim ());
387 else if (firstTrimedToken == kModelNameLabel_) {
388 currentModelName = line.SubString (afterColon).Trim ();
390 else if (firstTrimedToken == kSocketIDLabel_) {
391 currentSocketID = String2Int<unsigned int> (line.SubString (afterColon).Trim ());
396 if (currentProcessorID) {
397 String useModelName = Memory::NullCoalesce (foundProcessor);
398 Memory::CopyToIf (&useModelName, currentModelName);
399 result.fCores.Append (CPU::CoreDetails{Memory::NullCoalesce (currentSocketID), useModelName});
402 currentProcessorID = nullopt;
403 currentModelName = nullopt;
404 currentSocketID = nullopt;
407 if (currentProcessorID) {
408 String useModelName = Memory::NullCoalesce (foundProcessor);
409 Memory::CopyToIf (&useModelName, currentModelName);
410 result.fCores.Append (CPU::CoreDetails{Memory::NullCoalesce (currentSocketID), useModelName});
413#elif qStroika_Foundation_Common_Platform_Windows
420 DWORD logicalProcessorCount = 0;
421 DWORD processorCoreCount = 0;
422 DWORD processorPackageCount = 0;
424 auto countSetBits = [] (ULONG_PTR bitMask) -> DWORD {
425 DWORD LSHIFT =
sizeof (ULONG_PTR) * 8 - 1;
426 DWORD bitSetCount = 0;
427 ULONG_PTR bitTest = (ULONG_PTR)1 << LSHIFT;
428 for (DWORD i = 0; i <= LSHIFT; ++i) {
429 bitSetCount += ((bitMask & bitTest) ? 1 : 0);
434 typedef BOOL (WINAPI * LPFN_GLPI) (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, PDWORD);
435 DISABLE_COMPILER_MSC_WARNING_START (6387)
436 LPFN_GLPI glpi = (LPFN_GLPI)::GetProcAddress (::GetModuleHandle (TEXT ("kernel32")), "GetLogicalProcessorInformation");
437 DISABLE_COMPILER_MSC_WARNING_END (6387)
439 StackBuffer<
byte> buffer{Memory::eUninitialized,
sizeof (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)};
440 DWORD returnLength = 0;
442 DWORD rc = glpi (
reinterpret_cast<PSYSTEM_LOGICAL_PROCESSOR_INFORMATION
> (buffer.begin ()), &returnLength);
444 if (GetLastError () == ERROR_INSUFFICIENT_BUFFER) {
445 buffer.GrowToSize_uninitialized (returnLength);
455 PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr =
reinterpret_cast<PSYSTEM_LOGICAL_PROCESSOR_INFORMATION
> (buffer.begin ());
456 DWORD byteOffset = 0;
457 while (byteOffset +
sizeof (SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= returnLength) {
458 switch (ptr->Relationship) {
459 case RelationNumaNode:
461 case RelationProcessorCore:
462 ++processorCoreCount;
464 logicalProcessorCount += countSetBits (ptr->ProcessorMask);
468 case RelationProcessorPackage:
470 ++processorPackageCount;
473 DbgTrace (
"Error: Unsupported LOGICAL_PROCESSOR_RELATIONSHIP value."_f);
476 byteOffset +=
sizeof (SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
481 static const String kProcessorType_ = [] () {
482 int CPUInfo[4] = {-1};
483 char CPUBrandString[0x40];
485 ::__cpuid (CPUInfo, 0x80000000);
486 uint32_t nExIds = CPUInfo[0];
487 for (uint32_t i = 0x80000000; i <= nExIds; ++i) {
488 ::__cpuid (CPUInfo, i);
491 (void)::memcpy (CPUBrandString, CPUInfo,
sizeof (CPUInfo));
492 else if (i == 0x80000003)
493 (void)::memcpy (CPUBrandString + 16, CPUInfo,
sizeof (CPUInfo));
494 else if (i == 0x80000004)
495 (void)::memcpy (CPUBrandString + 32, CPUInfo,
sizeof (CPUInfo));
497 return String{CPUBrandString};
501 ::SYSTEM_INFO sysInfo{};
502 ::GetNativeSystemInfo (&sysInfo);
503 Assert (sysInfo.dwNumberOfProcessors == logicalProcessorCount);
505 for (
unsigned int socketNum = 0; socketNum < processorPackageCount; ++socketNum) {
506 unsigned int logProcessorsPerSocket = logicalProcessorCount / processorPackageCount;
507 for (DWORD i = 0; i < logProcessorsPerSocket; ++i) {
508 result.fCores.Append (CPU::CoreDetails{socketNum, kProcessorType_});
521SystemConfiguration::Memory Common::GetSystemConfiguration_Memory ()
523 using Memory = SystemConfiguration::Memory;
525#if qStroika_Foundation_Common_Platform_POSIX
528 static const size_t kPageSize_{
static_cast<size_t> (::sysconf (_SC_PAGESIZE))};
529 result.fPageSize = kPageSize_;
530 result.fTotalPhysicalRAM = ::sysconf (_SC_PHYS_PAGES) * kPageSize_;
531#elif qStroika_Foundation_Common_Platform_Windows
532 ::SYSTEM_INFO sysInfo{};
533 ::GetNativeSystemInfo (&sysInfo);
534 result.fPageSize = sysInfo.dwPageSize;
536 ::MEMORYSTATUSEX memStatus{};
537 memStatus.dwLength =
sizeof (memStatus);
538 Verify (::GlobalMemoryStatusEx (&memStatus));
539 result.fTotalPhysicalRAM = memStatus.ullTotalPhys;
540 result.fTotalVirtualRAM = memStatus.ullTotalVirtual;
552 using OperatingSystem = SystemConfiguration::OperatingSystem;
553 static const OperatingSystem kCachedResult_ = [] () -> OperatingSystem {
555#if qStroika_Foundation_Common_Platform_POSIX
556 tmp.fTokenName =
"Unix"sv;
561 DbgTrace (
"Failure running uname"_f);
566 tmp.fShortPrettyName = p.fUnnamedSection.fProperties.LookupValue (
"NAME"sv);
567 tmp.fPrettyNameWithMajorVersion = p.fUnnamedSection.fProperties.LookupValue (
"PRETTY_NAME"sv);
568 tmp.fMajorMinorVersionString = p.fUnnamedSection.fProperties.LookupValue (
"VERSION_ID"sv);
571 DbgTrace (
"Failure reading /etc/os-release: {}"_f, current_exception ());
573 if (tmp.fShortPrettyName.empty ()) {
576 tmp.fShortPrettyName =
"Centos"sv;
577 tmp.fPrettyNameWithMajorVersion = n;
579 if (tokens.
size () >= 3) {
580 tmp.fMajorMinorVersionString = tokens[2];
584 DbgTrace (
"Failure reading /etc/centos-release {}"_f, current_exception ());
587 if (tmp.fShortPrettyName.empty ()) {
590 tmp.fShortPrettyName =
"RedHat"sv;
591 tmp.fPrettyNameWithMajorVersion = n;
593 if (tokens.
size () >= 3) {
594 tmp.fMajorMinorVersionString = tokens[2];
598 DbgTrace (
"Failure reading /etc/redhat-release {}"_f, current_exception ());
601 if (tmp.fShortPrettyName.empty ()) {
602 tmp.fShortPrettyName = tmp.fTokenName;
604 if (tmp.fPrettyNameWithMajorVersion.empty ()) {
605 tmp.fPrettyNameWithMajorVersion = tmp.fShortPrettyName;
607 if (tmp.fPrettyNameWithVersionDetails.empty ()) {
608 tmp.fPrettyNameWithVersionDetails = tmp.fPrettyNameWithMajorVersion;
610 if (tmp.fRFC1945CompatProductTokenWithVersion.empty ()) {
611 tmp.fRFC1945CompatProductTokenWithVersion = tmp.fShortPrettyName.Trim ().ReplaceAll (
" "sv,
"-"sv);
612 if (not tmp.fMajorMinorVersionString.empty ()) {
613 tmp.fRFC1945CompatProductTokenWithVersion = tmp.fRFC1945CompatProductTokenWithVersion +
"/"sv + tmp.fMajorMinorVersionString;
617#if defined(_POSIX_V6_LP64_OFF64)
625 tmp.fBits = ::sysconf (_SC_V6_LP64_OFF64) == _POSIX_V6_LP64_OFF64 ? 64 : 32;
626#elif defined(_V6_LP64_OFF64)
628 tmp.fBits = ::sysconf (_SC_V6_LP64_OFF64) == _V6_LP64_OFF64 ? 64 : 32;
632 DbgTrace (
"_SC_V6_LP64_OFF64/_POSIX_V6_LP64_OFF64 not available - so assuming 32-bit..."_f);
635 using Characters::CompareOptions;
638 if (not tmp.fPreferredInstallerTechnology.has_value ()) {
640 if (nameEqComparer (tmp.fShortPrettyName,
"Centos"sv) or nameEqComparer (tmp.fShortPrettyName,
"RedHat"sv)) {
641 tmp.fPreferredInstallerTechnology = SystemConfiguration::OperatingSystem::InstallerTechnology::eRPM;
643 else if (nameEqComparer (tmp.fShortPrettyName,
"Ubuntu"sv)) {
644 tmp.fPreferredInstallerTechnology = SystemConfiguration::OperatingSystem::InstallerTechnology::eDPKG;
648 if (not tmp.fPreferredInstallerTechnology.has_value ()) {
651 tmp.fPreferredInstallerTechnology = SystemConfiguration::OperatingSystem::InstallerTechnology::eDPKG;
656 if (not tmp.fPreferredInstallerTechnology.has_value ()) {
659 tmp.fPreferredInstallerTechnology = SystemConfiguration::OperatingSystem::InstallerTechnology::eRPM;
664#elif qStroika_Foundation_Common_Platform_Windows
665 tmp.fTokenName =
"Windows"sv;
678 String kernelOSBuildVersion;
689 const wchar_t* kkernel32_ = L
"kernel32.dll";
691 const auto cbInfo = ::GetFileVersionInfoSizeExW (FILE_VER_GET_NEUTRAL, kkernel32_, &dummy);
692 StackBuffer<char> buffer{Memory::eUninitialized, cbInfo};
693 Verify (::GetFileVersionInfoExW (FILE_VER_GET_NEUTRAL, kkernel32_, dummy,
static_cast<DWORD
> (buffer.size ()), &buffer[0]));
696 Verify (::VerQueryValueW (buffer.data (), L
"\\", &p, &size));
697 Assert (size >=
sizeof (VS_FIXEDFILEINFO));
698 Assert (p !=
nullptr);
699 auto pFixed =
static_cast<const VS_FIXEDFILEINFO*
> (p);
700 kernelVersion =
"{}.{}"_f(HIWORD (pFixed->dwFileVersionMS), LOWORD (pFixed->dwFileVersionMS));
701 kernelOSBuildVersion =
"{}.{}"_f(HIWORD (pFixed->dwFileVersionLS), LOWORD (pFixed->dwFileVersionLS));
711 optional<String> platformVersion;
712 optional<String> productName;
713 optional<String> currentVersion;
716 if (
auto o = kWinVersionInfo_.Lookup (
"ReleaseId"sv)) {
717 platformVersion = o.As<
String> ();
719 if (
auto o = kWinVersionInfo_.Lookup (
"ProductName"sv)) {
725 if (
auto oMajor = kWinVersionInfo_.Lookup (
"CurrentMajorVersionNumber"sv)) {
726 if (
auto oMinor = kWinVersionInfo_.Lookup (
"CurrentMinorVersionNumber"sv)) {
734 if (not currentVersion) {
735 if (
auto o = kWinVersionInfo_.Lookup (
"CurrentVersion"sv)) {
741 DbgTrace (
"Exception suppressed looking up windows version in registry: {}"_f, current_exception ());
745 if (currentVersion ==
"10.0"sv and Characters::FloatConversion::ToFloat<double> (kernelOSBuildVersion) >= 21996.0) {
746 currentVersion =
"11.0"sv;
747 if (productName and productName->StartsWith (
"Windows 10"sv)) {
748 productName =
"Windows 11"sv + productName->SubString (10);
750 platformVersion = nullopt;
753 if (tmp.fShortPrettyName.empty ()) {
754 tmp.fShortPrettyName = productName.value_or (
"Windows"sv);
756 tmp.fPrettyNameWithMajorVersion = tmp.fShortPrettyName;
760 if (platformVersion) {
761 sb <<
" Version "sv + *platformVersion;
763 if (not kernelVersion.empty ()) {
764 sb <<
" (OS Build "sv + kernelOSBuildVersion +
")"sv;
766 tmp.fPrettyNameWithVersionDetails = sb.
str ();
769 tmp.fMajorMinorVersionString = currentVersion.value_or (
"unknown"sv);
770 tmp.fRFC1945CompatProductTokenWithVersion =
"Windows/"sv + tmp.fMajorMinorVersionString;
771 if constexpr (
sizeof (
void*) == 4) {
776 typedef BOOL (WINAPI * LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
777 DISABLE_COMPILER_MSC_WARNING_START (6387)
778 LPFN_ISWOW64PROCESS isWow64Process =
779 (LPFN_ISWOW64PROCESS)::GetProcAddress (::GetModuleHandle (TEXT (
"kernel32")),
"IsWow64Process");
780 DISABLE_COMPILER_MSC_WARNING_END (6387)
781 if (
nullptr != isWow64Process) {
782 BOOL isWOW64 =
false;
783 (void)isWow64Process (::GetCurrentProcess (), &isWOW64);
791 Assert (
sizeof (
void*) == 8);
794 tmp.fPreferredInstallerTechnology = SystemConfiguration::OperatingSystem::InstallerTechnology::eMSI;
800 return kCachedResult_;
803#if qStroika_Foundation_Common_Platform_Windows
804#pragma comment(lib, "Mincore.lib")
808 using OperatingSystem = SystemConfiguration::OperatingSystem;
809 static const OperatingSystem kCachedResult_ = [] () -> OperatingSystem {
812#if qStroika_Foundation_Common_Platform_Windows
814 optional<String> winCompatibilityVersionName;
815 optional<String> winCompatibilityVersionNumber;
817 if (not winCompatibilityVersionName and IsWindows10OrGreater ()) {
818 winCompatibilityVersionName =
"10.0"sv;
819 winCompatibilityVersionNumber =
"10.0"sv;
821 if (not winCompatibilityVersionName and IsWindows8Point1OrGreater ()) {
822 winCompatibilityVersionName =
"8.1"sv;
823 winCompatibilityVersionNumber =
"6.3"sv;
825 if (not winCompatibilityVersionName and IsWindows8OrGreater ()) {
826 winCompatibilityVersionName =
"8.0"sv;
827 winCompatibilityVersionNumber =
"6.2"sv;
829 if (not winCompatibilityVersionName and IsWindows7SP1OrGreater ()) {
831 winCompatibilityVersionName =
"7.1"sv;
832 winCompatibilityVersionNumber =
"6.2"sv;
834 if (not winCompatibilityVersionName and IsWindows7OrGreater ()) {
835 winCompatibilityVersionName =
"7.0"sv;
836 winCompatibilityVersionNumber =
"6.1"sv;
839 String useWinMajorMinorVersionNameStr = winCompatibilityVersionName.value_or (
"unknown"sv);
840 String useWinMajorMinorVersionNumberStr = winCompatibilityVersionNumber.value_or (
"unknown"sv);
841 tmp.fShortPrettyName =
"Windows "sv + useWinMajorMinorVersionNameStr;
842 tmp.fPrettyNameWithMajorVersion = tmp.fShortPrettyName;
843 tmp.fPrettyNameWithVersionDetails = tmp.fShortPrettyName;
844 tmp.fMajorMinorVersionString = useWinMajorMinorVersionNumberStr;
845 tmp.fRFC1945CompatProductTokenWithVersion =
"Windows/"sv + useWinMajorMinorVersionNumberStr;
849 return kCachedResult_;
857#if 0 && qStroika_Foundation_Common_Platform_POSIX
861 struct addrinfo* res;
862 struct addrinfo hints {};
863 hints.ai_socktype = SOCK_STREAM;
864 hints.ai_flags = AI_CANONNAME;
865 int e = getaddrinfo(
nullptr,
nullptr, &hints, &res);
871 for (
struct addrinfo* r = res; r != NULL; r = r->ai_next) {
872 name = r->ai_canonname ;
882 ComputerNames result;
883#if qStroika_Foundation_Common_Platform_POSIX
884#if defined(HOST_NAME_MAX)
885 char nameBuf[HOST_NAME_MAX + 1];
890 nameBuf[Memory::NEltsOf (nameBuf) - 1] =
'\0';
892#elif qStroika_Foundation_Common_Platform_Windows
893 constexpr COMPUTER_NAME_FORMAT kUseNameFormat_ = ComputerNameNetBIOS;
895 (void)::GetComputerNameEx (kUseNameFormat_,
nullptr, &dwSize);
896 StackBuffer<SDKChar> buf{Memory::eUninitialized, dwSize};
912 [[maybe_unused]]
static auto computeViaStdThreadHardwareConcurrency = [] () {
return std::thread::hardware_concurrency (); };
913 [[maybe_unused]]
static auto computeViaGetSystemConfiguration_CPU = [] () {
914 return Common::GetSystemConfiguration_CPU ().GetNumberOfLogicalCores ();
916#if qStroika_Foundation_Debug_AssertionsChecked
917 static auto compute = [=] () {
918 unsigned int hc = computeViaStdThreadHardwareConcurrency ();
919 unsigned int sysConfigLogCores = computeViaGetSystemConfiguration_CPU ();
921 return sysConfigLogCores;
924 auto compute = computeViaGetSystemConfiguration_CPU;
928 static atomic<unsigned int> sCachedValue_ = compute ();
930 if (now > sCachedAt_.load () + allowedStaleness) {
931 sCachedValue_ = compute ();
934 return sCachedValue_;
944 return SystemConfiguration{GetSystemConfiguration_BootInformation (),
945 GetSystemConfiguration_CPU (),
946 GetSystemConfiguration_Memory (),
949 GetSystemConfiguration_ComputerNames ()};
#define AssertNotImplemented()
#define qStroika_Foundation_Debug_AssertionsChecked
The qStroika_Foundation_Debug_AssertionsChecked flag determines if assertions are checked and validat...
#define WeakAssert(c)
A WeakAssert() is for things that aren't guaranteed to be true, but are overwhelmingly likely to be t...
time_point< RealtimeClock, DurationSeconds > TimePointSeconds
TimePointSeconds is a simpler approach to chrono::time_point, which doesn't require using templates e...
Similar to String, but intended to more efficiently construct a String. Mutable type (String is large...
nonvirtual String str() const
String is like std::u32string, except it is much easier to use, often much more space efficient,...
static String FromSDKString(const SDKChar *from)
static String FromNarrowSDKString(const char *from)
nonvirtual String Trim(bool(*shouldBeTrimmed)(Character)=Character::IsWhitespace) const
nonvirtual Containers::Sequence< String > Tokenize() const
A generalization of a vector: a container whose elements are keyed by the natural numbers.
Set<T> is a container of T, where once an item is added, additionally adds () do nothing.
nonvirtual void Add(ArgByValueType< value_type > item)
Reader for INI format files.
nonvirtual Profile ReadProfile(const Streams::InputStream::Ptr< byte > &in)
though can read directly as VariantValue, reading as a Profile object maybe handier for this type of ...
Run the given command, and optionally support stdin/stdout/stderr as streams (either sync with Run,...
nonvirtual void Run(const Streams::InputStream::Ptr< byte > &in, const Streams::OutputStream::Ptr< byte > &out=nullptr, const Streams::OutputStream::Ptr< byte > &error=nullptr, ProgressMonitor::Updater progress=nullptr, Time::DurationSeconds timeout=Time::kInfinity)
Run the given external command/process (set by constructor) - with the given arguments,...
Logically halfway between std::array and std::vector; Smart 'direct memory array' - which when needed...
nonvirtual Iterator< T > Find(THAT_FUNCTION &&that, Execution::SequencePolicy seq=Execution::SequencePolicy::eDEFAULT) const
Run the argument bool-returning function (or lambda) on each element of the container,...
nonvirtual size_t size() const
Returns the number of items contained.
T String2Int(span< const CHAR_T > s)
SystemConfiguration::OperatingSystem GetSystemConfiguration_ActualOperatingSystem()
SystemConfiguration GetSystemConfiguration()
Get the System Configuration object - note not a system global - because the configuration can change...
SystemConfiguration::OperatingSystem GetSystemConfiguration_ApparentOperatingSystem()
unsigned int GetNumberOfLogicalCPUCores(const chrono::duration< double > &allowedStaleness=1min)
return the number of currently available CPU cores on this (virtual) machine
auto Finally(FUNCTION &&f) -> Private_::FinallySentry< FUNCTION >
INT_TYPE ThrowPOSIXErrNoIfNegative(INT_TYPE returnCode)
Ptr New(const InputStream::Ptr< byte > &src, optional< AutomaticCodeCvtFlags > codeCvtFlags={}, optional< SeekableFlag > seekable={}, ReadAhead readAhead=eReadAheadAllowed)
Create an InputStream::Ptr<Character> from the arguments (usually binary source) - which can be used ...
nonvirtual String ToString() const
nonvirtual String ToString() const