Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
Version.cpp
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#include "Stroika/Foundation/StroikaPreComp.h"
5
7#include "Stroika/Foundation/Common/StroikaConfig.h"
8#include "Stroika/Foundation/Execution/Exceptions.h"
10
11#include "Version.h"
12
13using namespace Stroika::Foundation;
15using namespace Stroika::Foundation::Common;
16using namespace Stroika::Foundation::Execution;
17
18/*
19 ********************************************************************************
20 *********************************** Version ************************************
21 ********************************************************************************
22 */
24{
25 int major = 0;
26 int minor = 0;
27 int verStageOctet = 0;
28 int verSubStageOctet = 0;
29 String win32Version4DotStr = win32Version4DotString; // copy so can call c_str() on copy
30 DISABLE_COMPILER_MSC_WARNING_START (4996) // MSVC SILLY WARNING ABOUT USING swscanf_s
31 int nMatchingItems = ::swscanf (win32Version4DotStr.As<wstring> ().c_str (), L"%d.%d.%d.%d", &major, &minor, &verStageOctet, &verSubStageOctet);
32 DISABLE_COMPILER_MSC_WARNING_END (4996)
33 static const RuntimeErrorException kException_{"Invalid Version String"sv};
34 if (major < 0 or major > 255) [[unlikely]] {
35 Throw (kException_);
36 }
37 if (minor < 0 or minor > 255) [[unlikely]] {
38 Throw (kException_);
39 }
40 int verStage = static_cast<uint16_t> (verStageOctet) >> 5;
41 Assert (verStage == Memory::BitSubstring (verStageOctet, 5, 8)); // really only true cuz verStageOctet SB 8-bits - so if this fails, this answer probably better --LGP 2016-07-08
42 uint16_t verSubStage =
43 static_cast<uint16_t> ((Memory::BitSubstring (verStageOctet, 0, 5) << 7) + Memory::BitSubstring (verSubStageOctet, 1, 8));
44 bool verFinal = verSubStageOctet & 0x1;
45 if (nMatchingItems != 4 or not(ToInt (VersionStage::eSTART) <= verStage and verStage <= ToInt (VersionStage::eLAST))) {
46 DbgTrace ("win32Version4DotString={}"_f, win32Version4DotStr);
47 Throw (kException_);
48 }
49 return Version{static_cast<uint8_t> (major), static_cast<uint8_t> (minor), static_cast<VersionStage> (verStage), verSubStage, verFinal};
50}
51
53{
54 uint8_t major = 0;
55 uint8_t minor = 0;
56
57 wstring ppv = prettyVersionString.As<wstring> (); // copy so can c_str()
58
59 // Helper to throw if out of range
60 DISABLE_COMPILER_CLANG_WARNING_START ("clang diagnostic ignored \"-Wunused-lambda-capture\"");
61 auto my_wcstol_ = [&ppv] (const wchar_t* i, wchar_t** endResult) -> uint8_t {
62 long l = wcstol (i, endResult, 10);
63 if (l < 0 or l > numeric_limits<uint8_t>::max ()) [[unlikely]] {
64 DbgTrace (L"prettyVersionString={}"_f, ppv);
65 static const RuntimeErrorException kException_{"Invalid Version String: component out of range"_k};
66 Throw (kException_);
67 }
68 return static_cast<uint8_t> (l);
69 };
70 DISABLE_COMPILER_CLANG_WARNING_END ("clang diagnostic ignored \"-Wunused-lambda-capture\"");
71
72 const wchar_t* i = ppv.c_str ();
73 wchar_t* tokenEnd = nullptr;
74 major = my_wcstol_ (i, &tokenEnd); // @todo should validate, but no biggie
75 if (i == tokenEnd) [[unlikely]] {
76 DbgTrace (L"prettyVersionString={}"_f, ppv);
77 static const RuntimeErrorException kException_{"Invalid Version String"sv};
78 Throw (kException_);
79 }
80 Assert (static_cast<size_t> (i - ppv.c_str ()) <= prettyVersionString.length ());
81 i = tokenEnd + 1; // end plus '.' separator
82
83 minor = my_wcstol_ (i, &tokenEnd);
84 if (i == tokenEnd) [[unlikely]] {
85 DbgTrace ("prettyVersionString={}"_f, ppv);
86 Throw (RuntimeErrorException{"Invalid Version String"sv}); // require form 1.0a3, or at least 1.0, but no 1
87 }
88 Assert (static_cast<size_t> (i - ppv.c_str ()) <= ppv.length ());
89 i = tokenEnd;
90
91 VersionStage verStage = VersionStage::Release;
92 switch (*i) {
93 case '\0': {
94 // e.g. 1.0
95 return Version (major, minor, VersionStage::Release, 0);
96 }
97 case 'a': {
98 verStage = VersionStage::Alpha;
99 i += 1;
100 } break;
101 case 'b': {
102 verStage = VersionStage::Beta;
103 i += 1;
104 } break;
105 case 'd': {
106 verStage = VersionStage::Dev;
107 i += 1;
108 } break;
109 case 'r': {
110 verStage = VersionStage::ReleaseCandidate;
111 i += 2; // rc
112 } break;
113 case '.': {
114 // e.g. 1.0.3
115 verStage = VersionStage::Release;
116 i += 1;
117 } break;
118 }
119 Assert (static_cast<size_t> (i - ppv.c_str ()) <= ppv.size ());
120 uint8_t verSubStage = my_wcstol_ (i, &tokenEnd);
121 if (i == tokenEnd) [[unlikely]] {
122 DbgTrace (L"prettyVersionString={}"_f, ppv);
123 static const RuntimeErrorException kException_{"Invalid Version String"sv};
124 Throw (kException_); // require form 1.0a3, or at least 1.0, but no 1
125 }
126 i = tokenEnd;
127 bool finalBuild = true;
128 if (*i == 'x') {
129 finalBuild = false;
130 }
131 Assert (static_cast<size_t> (i - ppv.c_str ()) <= ppv.size ());
132 return Version{major, minor, verStage, verSubStage, finalBuild};
133}
134
135Characters::String Version::AsWin32Version4DotString () const
136{
137 return "{}.{}.{}.{}"_f(fMajorVer, fMinorVer, (static_cast<uint8_t> (fVerStage) << 5) | (fVerSubStage >> 7),
138 (static_cast<uint8_t> (fVerSubStage & 0x7f) << 1) | static_cast<uint8_t> (fFinalBuild));
139}
140
141Characters::String Version::AsPrettyVersionString () const
142{
143 StringBuilder stageStr{"?"sv};
144 switch (fVerStage) {
145 case VersionStage::Dev:
146 stageStr = "d"sv;
147 break;
148 case VersionStage::Alpha:
149 stageStr = "a"sv;
150 break;
151 case VersionStage::Beta:
152 stageStr = "b"sv;
153 break;
154 case VersionStage::ReleaseCandidate:
155 stageStr = "rc"sv;
156 break;
157 case VersionStage::Release:
158 stageStr = fVerSubStage == 0 ? String{} : "."sv;
159 break;
160 }
161 StringBuilder verSubStagStr;
162 if (fVerSubStage != 0) {
163 verSubStagStr = "{}"_f(fVerSubStage);
164 }
165 if (not fFinalBuild) {
166 verSubStagStr += "x"sv;
167 }
168 return "{}.{}{}{}"_f(fMajorVer, fMinorVer, stageStr, verSubStagStr);
169}
170
172{
173 return "{}.{}"_f(fMajorVer, fMinorVer);
174}
#define DbgTrace
Definition Trace.h:309
Similar to String, but intended to more efficiently construct a String. Mutable type (String is large...
String is like std::u32string, except it is much easier to use, often much more space efficient,...
Definition String.h:201
nonvirtual size_t length() const noexcept
Definition String.inl:1045
void Throw(T &&e2Throw)
identical to builtin C++ 'throw' except that it does helpful, type dependent DbgTrace() messages firs...
Definition Throw.inl:43
static Version FromPrettyVersionString(const Characters::String &prettyVersionString)
Definition Version.cpp:52
nonvirtual Characters::String AsMajorMinorString() const
Definition Version.cpp:171
static Version FromWin32Version4DotString(const Characters::String &win32Version4DotString)
Definition Version.cpp:23