inweb-bootstrap/docs/foundation-module/7-vn.html

437 lines
57 KiB
HTML
Raw Normal View History

2020-03-23 15:04:43 +00:00
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
2020-04-08 22:41:00 +00:00
<title>Version Numbers</title>
2020-03-23 15:04:43 +00:00
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="../inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body>
<nav role="navigation">
<h1><a href="../webs.html">Sources</a></h1>
<ul>
<li><a href="../inweb/index.html">inweb</a></li>
</ul>
<h2>Foundation</h2>
<ul>
<li><a href="../foundation-module/index.html">foundation-module</a></li>
<li><a href="../foundation-test/index.html">foundation-test</a></li>
</ul>
</nav>
<main role="main">
2020-04-08 22:41:00 +00:00
<!--Weave of 'Version Numbers' generated by 7-->
2020-03-23 15:04:43 +00:00
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">foundation</a></li><li><a href="index.html#7">Chapter 7: Semantic Versioning</a></li><li><b>Version Numbers</b></li></ul><p class="purpose">Semantic version numbers such as 3.7.1.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Standard adoption</a></li><li><a href="#SP5">&#167;5. Printing and parsing</a></li><li><a href="#SP8">&#167;8. Precendence</a></li><li><a href="#SP11">&#167;11. Trichotomy</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. Standard adoption. </b>The Semantic Version Number standard, semver 2.0.0, provides a strict set
of rules for the format and meaning of version numbers: see <code class="display"><span class="extract">https://semver.org</span></code>.
</p>
<p class="inwebparagraph">Prior to the standard most version numbers in computing usage looked like
dot-divided runs of non-negative integers: for example, 4, 7.1, and 0.2.3.
The standard now requires exactly three: major, minor and patch. It's
therefore formally incorrect to have a version 2, or a version 2.3. We will
not be so strict on the textual form, which we will allow to be abbreviated.
Thus:
</p>
<p class="inwebparagraph"></p>
<ul class="items"><li>(a) The text <code class="display"><span class="extract">6.4.7</span></code> is understood to mean 6.4.7 and printed back as <code class="display"><span class="extract">6.4.7</span></code>
</li><li>(b) The text <code class="display"><span class="extract">6</span></code> is understood to mean 6.0.0 and printed back as <code class="display"><span class="extract">6</span></code>
</li><li>(c) The text <code class="display"><span class="extract">6.1</span></code> is understood to mean 6.1.0 and printed back as <code class="display"><span class="extract">6.1</span></code>
</li><li>(d) The text <code class="display"><span class="extract">6.1.0</span></code> is understood to mean 6.1.0 and printed back as <code class="display"><span class="extract">6.1.0</span></code>
</li></ul>
<p class="inwebparagraph">Similarly, the absence of a version number (called "null" below) will be
understood to mean 0.0.0, but will be distinguished from the explicit choice
to number something as 0.0.0.
</p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b>A complication is that Inform 7 extensions have for many years allowed two
forms of version number: either just <code class="display"><span class="extract">N</span></code>, which fits the scheme above, or
<code class="display"><span class="extract">N/DDDDDD</span></code>, which does not. This is a format which was chosen for sentimental
reasons: IF enthusiasts know it well from the banner text of the Infocom
titles of the 1980s. This story file, for instance, was compiled at the
time of the Reykjavik summit between Presidents Gorbachev and Reagan:
</p>
<pre class="display">
<span class="plain">Moonmist</span>
<span class="plain">Infocom interactive fiction - a mystery story</span>
<span class="plain">Copyright (c) 1986 by Infocom, Inc. All rights reserved.</span>
<span class="plain">Moonmist is a trademark of Infocom, Inc.</span>
<span class="plain">Release number 9 / Serial number 861022</span>
</pre>
<p class="inwebparagraph">Story file collectors customarily abbreviate this in catalogues to <code class="display"><span class="extract">9/861022</span></code>.
</p>
<p class="inwebparagraph">We will therefore allow this notation, and convert it silently each way.
<code class="display"><span class="extract">N/DDDDDD</span></code> is equivalent to <code class="display"><span class="extract">N.DDDDDD</span></code>. Thus, <code class="display"><span class="extract">9/861022</span></code> means 9.861022.0 in
semver precedence order.
</p>
<p class="inwebparagraph">In all non-textual respects, and in particular on precedence rules, we follow
the standard exactly. The only reason we allow these abbreviations is because
we don't want to force Inform extension writers to type "Version 3.4.1 of
Such-and-Such by Me begins here", and so on: it would break all existing
extensions, for one thing, and it looks unfriendly.
</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>In the array below, unspecified numbers are stored as <code class="display"><span class="extract">-1</span></code>. The three
components are otherwise required to be non-negative integers.
</p>
<p class="inwebparagraph">Semver allows for more elaborate forms: for example <code class="display"><span class="extract">3.1.41-alpha.72.zeta+6Q45</span></code>
would mean 3.1.41 but with prerelease versioning <code class="display"><span class="extract">alpha.72.zeta</span></code> and build
metadata <code class="display"><span class="extract">6Q45</span></code>. The <code class="display"><span class="extract">prerelease_segments</span></code> list for this would be a list of
three texts: <code class="display"><span class="extract">alpha</span></code>, <code class="display"><span class="extract">72</span></code>, <code class="display"><span class="extract">zeta</span></code>.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">SEMVER_NUMBER_DEPTH</span><span class="plain"> </span><span class="constant">3</span><span class="plain"> </span><span class="comment"> major, minor, patch</span>
2020-03-23 15:04:43 +00:00
</pre>
<pre class="display">
2020-04-06 11:26:10 +00:00
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">semantic_version_number</span><span class="plain"> {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">version_numbers</span><span class="plain">[</span><span class="constant">SEMVER_NUMBER_DEPTH</span><span class="plain">];</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">linked_list</span><span class="plain"> *</span><span class="identifier">prerelease_segments</span><span class="plain">; </span><span class="comment"> of <code class="display"><span class="extract">text_stream</span></code></span>
2020-04-06 11:26:10 +00:00
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">build_metadata</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">semantic_version_number</span><span class="plain">;</span>
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">semantic_version_number_holder</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">version</span><span class="plain">;</span>
<span class="constant">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">semantic_version_number_holder</span><span class="plain">;</span>
2020-03-23 15:04:43 +00:00
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure semantic_version_number is accessed in 7/vnr and here.</p>
<p class="endnote">The structure semantic_version_number_holder is private to this section.</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. </b>All invalid strings of numbers &mdash; i.e., breaking the above rules &mdash; are
called "null" versions, and can never be valid as the version of anything.
Instead they are used to represent the absence of a version number.
(In particular, a string of <code class="display"><span class="extract">-1</span></code>s is null.)
</p>
<pre class="display">
2020-04-06 11:26:10 +00:00
<span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="functiontext">VersionNumbers::null</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
2020-03-23 15:04:43 +00:00
<span class="plain">#</span><span class="identifier">pragma</span><span class="plain"> </span><span class="identifier">clang</span><span class="plain"> </span><span class="identifier">diagnostic</span><span class="plain"> </span><span class="identifier">push</span>
<span class="plain">#</span><span class="identifier">pragma</span><span class="plain"> </span><span class="identifier">clang</span><span class="plain"> </span><span class="identifier">diagnostic</span><span class="plain"> </span><span class="identifier">ignored</span><span class="plain"> </span><span class="string">"-Wconditional-uninitialized"</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="constant">SEMVER_NUMBER_DEPTH</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) </span><span class="identifier">V</span><span class="plain">.</span><span class="element">version_numbers</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = -1;</span>
<span class="identifier">V</span><span class="plain">.</span><span class="element">prerelease_segments</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">V</span><span class="plain">.</span><span class="element">build_metadata</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">V</span><span class="plain">;</span>
2020-03-23 15:04:43 +00:00
<span class="plain">#</span><span class="identifier">pragma</span><span class="plain"> </span><span class="identifier">clang</span><span class="plain"> </span><span class="identifier">diagnostic</span><span class="plain"> </span><span class="identifier">pop</span>
<span class="plain">}</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VersionNumbers::is_null</span><span class="plain">(</span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V</span><span class="plain">) {</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0, </span><span class="identifier">allow</span><span class="plain">=</span><span class="constant">TRUE</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="constant">SEMVER_NUMBER_DEPTH</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">V</span><span class="plain">.</span><span class="element">version_numbers</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] &lt; -1) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">; </span><span class="comment"> should never happen</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">V</span><span class="plain">.</span><span class="element">version_numbers</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] == -1) </span><span class="identifier">allow</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">allow</span><span class="plain"> == </span><span class="constant">FALSE</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">; </span><span class="comment"> should never happen</span>
2020-03-23 15:04:43 +00:00
<span class="plain">}</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">V</span><span class="plain">.</span><span class="element">version_numbers</span><span class="plain">[0] &lt; </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
2020-03-23 15:04:43 +00:00
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
2020-04-02 12:30:38 +00:00
<p class="endnote">The function VersionNumbers::null is used in <a href="#SP7">&#167;7</a>, <a href="#SP7_1">&#167;7.1</a>, 7/vnr (<a href="7-vnr.html#SP3">&#167;3</a>, <a href="7-vnr.html#SP4">&#167;4</a>), 8/ws (<a href="8-ws.html#SP5_2">&#167;5.2</a>).</p>
2020-03-23 15:04:43 +00:00
<p class="endnote">The function VersionNumbers::is_null is used in <a href="#SP5">&#167;5</a>, 7/vnr (<a href="7-vnr.html#SP4">&#167;4</a>, <a href="7-vnr.html#SP6">&#167;6</a>), 8/bf (<a href="8-bf.html#SP6">&#167;6</a>).</p>
2020-03-23 15:04:43 +00:00
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. Printing and parsing. </b>Printing is simple enough:
</p>
<pre class="display">
2020-04-06 11:26:10 +00:00
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">VersionNumbers::to_text</span><span class="plain">(</span><span class="constant">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">VersionNumbers::is_null</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">)) { </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"null"</span><span class="plain">); </span><span class="reserved">return</span><span class="plain">; }</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; (</span><span class="identifier">i</span><span class="plain">&lt;</span><span class="constant">SEMVER_NUMBER_DEPTH</span><span class="plain">) &amp;&amp; (</span><span class="identifier">V</span><span class="plain">.</span><span class="element">version_numbers</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] &gt;= </span><span class="constant">0</span><span class="plain">); </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">&gt;0) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"."</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%d"</span><span class="plain">, </span><span class="identifier">V</span><span class="plain">.</span><span class="element">version_numbers</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]);</span>
2020-03-23 15:04:43 +00:00
<span class="plain">}</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">V</span><span class="plain">.</span><span class="element">prerelease_segments</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER_LINKED_LIST</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain">, </span><span class="identifier">V</span><span class="plain">.</span><span class="element">prerelease_segments</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain">++ == </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"-"</span><span class="plain">); </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"."</span><span class="plain">);</span>
2020-03-23 15:04:43 +00:00
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%S"</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">V</span><span class="plain">.</span><span class="element">build_metadata</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"+%S"</span><span class="plain">, </span><span class="identifier">V</span><span class="plain">.</span><span class="element">build_metadata</span><span class="plain">);</span>
2020-03-23 15:04:43 +00:00
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function VersionNumbers::to_text is used in <a href="#SP6">&#167;6</a>.</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. </b>And this provides for the <code class="display"><span class="extract">%v</span></code> escape, though we must be careful when
using this to pass a pointer to the version, not the version itself;
variadic macros are not carefully enough type-checked by <code class="display"><span class="extract">clang</span></code> or <code class="display"><span class="extract">gcc</span></code>
to catch this sort of slip.
</p>
<pre class="display">
2020-04-06 11:26:10 +00:00
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">VersionNumbers::writer</span><span class="plain">(</span><span class="constant">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">format_string</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> *</span><span class="identifier">vE</span><span class="plain">) {</span>
<span class="reserved">semantic_version_number</span><span class="plain"> *</span><span class="identifier">V</span><span class="plain"> = (</span><span class="reserved">semantic_version_number</span><span class="plain"> *) </span><span class="identifier">vE</span><span class="plain">;</span>
<span class="functiontext">VersionNumbers::to_text</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, *</span><span class="identifier">V</span><span class="plain">);</span>
2020-03-23 15:04:43 +00:00
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
2020-04-09 17:32:37 +00:00
<p class="endnote">The function VersionNumbers::writer is used in 1/fm (<a href="1-fm.html#SP8_1">&#167;8.1</a>).</p>
2020-03-23 15:04:43 +00:00
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. </b>Parsing is much more of a slog. The following returns a null version if
the text <code class="display"><span class="extract">T</span></code> is in any respect malformed, i.e., if it deviates from the
above specification in even the most trivial way. We parse the three parts
of a semver version in order: e.g. <code class="display"><span class="extract">3.1.41-alpha.72.zeta+6Q45</span></code> the first
part is up to the hyphen, the second part between the hyphen and the plus
sign, and the third part runs to the end. The second and third parts are
optional, but if both are given, they must be in that order.
</p>
<pre class="definitions">
2020-04-06 11:26:10 +00:00
<span class="definitionkeyword">enum</span> <span class="constant">MMP_SEMVERPART</span><span class="definitionkeyword"> from </span><span class="constant">1</span>
<span class="definitionkeyword">enum</span> <span class="constant">PRE_SEMVERPART</span>
<span class="definitionkeyword">enum</span> <span class="constant">BM_SEMVERPART</span>
2020-03-23 15:04:43 +00:00
</pre>
<pre class="display">
2020-04-06 11:26:10 +00:00
<span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="functiontext">VersionNumbers::from_text</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">) {</span>
<span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V</span><span class="plain"> = </span><span class="functiontext">VersionNumbers::null</span><span class="plain">();</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">component</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">, </span><span class="identifier">val</span><span class="plain"> = -1, </span><span class="identifier">dots_used</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">, </span><span class="identifier">slashes_used</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">, </span><span class="identifier">count</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">part</span><span class="plain"> = </span><span class="constant">MMP_SEMVERPART</span><span class="plain">;</span>
2020-03-23 15:04:43 +00:00
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">prerelease</span><span class="plain">);</span>
<span class="identifier">LOOP_THROUGH_TEXT</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">) {</span>
2020-04-06 11:26:10 +00:00
<span class="identifier">wchar_t</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="functiontext">Str::get</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">);</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">part</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">MMP_SEMVERPART:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'.'</span><span class="plain">) </span><span class="identifier">dots_used</span><span class="plain">++;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'/'</span><span class="plain">) </span><span class="identifier">slashes_used</span><span class="plain">++;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'.'</span><span class="plain">) || (</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'/'</span><span class="plain">) || (</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'-'</span><span class="plain">) || (</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'+'</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">val</span><span class="plain"> == -1) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">VersionNumbers::null</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">component</span><span class="plain"> &gt;= </span><span class="constant">SEMVER_NUMBER_DEPTH</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">VersionNumbers::null</span><span class="plain">();</span>
<span class="identifier">V</span><span class="plain">.</span><span class="element">version_numbers</span><span class="plain">[</span><span class="identifier">component</span><span class="plain">] = </span><span class="identifier">val</span><span class="plain">;</span>
2020-04-04 19:46:43 +00:00
<span class="identifier">component</span><span class="plain">++; </span><span class="identifier">val</span><span class="plain"> = -1; </span><span class="identifier">count</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'-'</span><span class="plain">) </span><span class="identifier">part</span><span class="plain"> = </span><span class="constant">PRE_SEMVERPART</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'+'</span><span class="plain">) </span><span class="identifier">part</span><span class="plain"> = </span><span class="constant">BM_SEMVERPART</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Characters::isdigit</span><span class="plain">(</span><span class="identifier">c</span><span class="plain">)) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">digit</span><span class="plain"> = </span><span class="identifier">c</span><span class="plain"> - </span><span class="character">'0'</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">val</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) &amp;&amp; (</span><span class="identifier">slashes_used</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">VersionNumbers::null</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">val</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">val</span><span class="plain"> = </span><span class="identifier">digit</span><span class="plain">; </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">val</span><span class="plain"> = </span><span class="constant">10</span><span class="plain">*</span><span class="identifier">val</span><span class="plain"> + </span><span class="identifier">digit</span><span class="plain">;</span>
2020-03-23 15:04:43 +00:00
<span class="identifier">count</span><span class="plain">++;</span>
2020-04-06 11:26:10 +00:00
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">VersionNumbers::null</span><span class="plain">();</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">PRE_SEMVERPART:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'.'</span><span class="plain">) {</span>
2020-03-23 15:04:43 +00:00
&lt;<span class="cwebmacro">Add prerelease content</span> <span class="cwebmacronumber">7.1</span>&gt;<span class="plain">;</span>
2020-04-06 11:26:10 +00:00
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'+'</span><span class="plain">) {</span>
&lt;<span class="cwebmacro">Add prerelease content</span> <span class="cwebmacronumber">7.1</span>&gt;<span class="plain">; </span><span class="identifier">part</span><span class="plain"> = </span><span class="constant">BM_SEMVERPART</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
2020-03-23 15:04:43 +00:00
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">prerelease</span><span class="plain">, </span><span class="identifier">c</span><span class="plain">);</span>
<span class="plain">}</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">BM_SEMVERPART:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">V</span><span class="plain">.</span><span class="element">build_metadata</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">V</span><span class="plain">.</span><span class="element">build_metadata</span><span class="plain"> = </span><span class="functiontext">Str::new</span><span class="plain">();</span>
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">.</span><span class="element">build_metadata</span><span class="plain">, </span><span class="identifier">c</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
2020-03-23 15:04:43 +00:00
<span class="plain">}</span>
<span class="plain">}</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">part</span><span class="plain"> == </span><span class="constant">PRE_SEMVERPART</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">prerelease</span><span class="plain">) &gt; </span><span class="constant">0</span><span class="plain">)) </span>&lt;<span class="cwebmacro">Add prerelease content</span> <span class="cwebmacronumber">7.1</span>&gt;<span class="plain">;</span>
2020-03-23 15:04:43 +00:00
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">prerelease</span><span class="plain">);</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">dots_used</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">) &amp;&amp; (</span><span class="identifier">slashes_used</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">VersionNumbers::null</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">slashes_used</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">component</span><span class="plain"> &gt; </span><span class="constant">1</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">VersionNumbers::null</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">count</span><span class="plain"> != </span><span class="constant">6</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">VersionNumbers::null</span><span class="plain">();</span>
2020-03-23 15:04:43 +00:00
<span class="plain">}</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">part</span><span class="plain"> == </span><span class="constant">MMP_SEMVERPART</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">val</span><span class="plain"> == -1) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">VersionNumbers::null</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">component</span><span class="plain"> &gt;= </span><span class="constant">SEMVER_NUMBER_DEPTH</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">VersionNumbers::null</span><span class="plain">();</span>
<span class="identifier">V</span><span class="plain">.</span><span class="element">version_numbers</span><span class="plain">[</span><span class="identifier">component</span><span class="plain">] = </span><span class="identifier">val</span><span class="plain">;</span>
2020-03-23 15:04:43 +00:00
<span class="plain">}</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">V</span><span class="plain">;</span>
2020-03-23 15:04:43 +00:00
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function VersionNumbers::from_text is used in 8/bf (<a href="8-bf.html#SP6">&#167;6</a>).</p>
2020-03-23 15:04:43 +00:00
<p class="inwebparagraph"><a id="SP7_1"></a><b>&#167;7.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Add prerelease content</span> <span class="cwebmacronumber">7.1</span>&gt; =
</code></p>
<pre class="displaydefn">
2020-04-06 11:26:10 +00:00
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">prerelease</span><span class="plain">) == </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">VersionNumbers::null</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">V</span><span class="plain">.</span><span class="element">prerelease_segments</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">V</span><span class="plain">.</span><span class="element">prerelease_segments</span><span class="plain"> = </span><span class="identifier">NEW_LINKED_LIST</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain">);</span>
<span class="identifier">ADD_TO_LINKED_LIST</span><span class="plain">(</span><span class="functiontext">Str::duplicate</span><span class="plain">(</span><span class="identifier">prerelease</span><span class="plain">), </span><span class="reserved">text_stream</span><span class="plain">, </span><span class="identifier">V</span><span class="plain">.</span><span class="element">prerelease_segments</span><span class="plain">);</span>
<span class="functiontext">Str::clear</span><span class="plain">(</span><span class="identifier">prerelease</span><span class="plain">);</span>
2020-03-23 15:04:43 +00:00
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7">&#167;7</a> (three times).</p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. Precendence. </b>The most important part of the semver standard is the rule on which versions
take precedence over which others, and we follow it exactly. The following
criteria are used in turn: major version; minor version; patch version;
any prerelease elements, which must be compared numerically if consisting
of digits only, and alphabetically otherwise; and finally the number of
prerelease elements. Build metadata is disregarded entirely.
</p>
<pre class="display">
2020-04-06 11:26:10 +00:00
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VersionNumbers::le</span><span class="plain">(</span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V1</span><span class="plain">, </span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V2</span><span class="plain">) {</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="constant">SEMVER_NUMBER_DEPTH</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">N1</span><span class="plain"> = </span><span class="functiontext">VersionNumbers::floor</span><span class="plain">(</span><span class="identifier">V1</span><span class="plain">.</span><span class="element">version_numbers</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">N2</span><span class="plain"> = </span><span class="functiontext">VersionNumbers::floor</span><span class="plain">(</span><span class="identifier">V2</span><span class="plain">.</span><span class="element">version_numbers</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">N1</span><span class="plain"> &gt; </span><span class="identifier">N2</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">N1</span><span class="plain"> &lt; </span><span class="identifier">N2</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
2020-03-23 15:04:43 +00:00
<span class="plain">}</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">linked_list_item</span><span class="plain"> *</span><span class="identifier">I1</span><span class="plain"> = (</span><span class="identifier">V1</span><span class="plain">.</span><span class="element">prerelease_segments</span><span class="plain">)?(</span><span class="functiontext">LinkedLists::first</span><span class="plain">(</span><span class="identifier">V1</span><span class="plain">.</span><span class="element">prerelease_segments</span><span class="plain">)):</span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">linked_list_item</span><span class="plain"> *</span><span class="identifier">I2</span><span class="plain"> = (</span><span class="identifier">V2</span><span class="plain">.</span><span class="element">prerelease_segments</span><span class="plain">)?(</span><span class="functiontext">LinkedLists::first</span><span class="plain">(</span><span class="identifier">V2</span><span class="plain">.</span><span class="element">prerelease_segments</span><span class="plain">)):</span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">while</span><span class="plain"> ((</span><span class="identifier">I1</span><span class="plain">) &amp;&amp; (</span><span class="identifier">I2</span><span class="plain">)) {</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">T1</span><span class="plain"> = (</span><span class="reserved">text_stream</span><span class="plain"> *) </span><span class="functiontext">LinkedLists::content</span><span class="plain">(</span><span class="identifier">I1</span><span class="plain">);</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">T2</span><span class="plain"> = (</span><span class="reserved">text_stream</span><span class="plain"> *) </span><span class="functiontext">LinkedLists::content</span><span class="plain">(</span><span class="identifier">I2</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">N1</span><span class="plain"> = </span><span class="functiontext">VersionNumbers::strict_atoi</span><span class="plain">(</span><span class="identifier">T1</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">N2</span><span class="plain"> = </span><span class="functiontext">VersionNumbers::strict_atoi</span><span class="plain">(</span><span class="identifier">T2</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">N1</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) &amp;&amp; (</span><span class="identifier">N2</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">N1</span><span class="plain"> &lt; </span><span class="identifier">N2</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">N1</span><span class="plain"> &gt; </span><span class="identifier">N2</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::ne</span><span class="plain">(</span><span class="identifier">T1</span><span class="plain">, </span><span class="identifier">T2</span><span class="plain">)) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="functiontext">Str::cmp</span><span class="plain">(</span><span class="identifier">T1</span><span class="plain">, </span><span class="identifier">T2</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
2020-03-23 15:04:43 +00:00
<span class="plain">}</span>
<span class="plain">}</span>
2020-04-06 11:26:10 +00:00
<span class="identifier">I1</span><span class="plain"> = </span><span class="functiontext">LinkedLists::next</span><span class="plain">(</span><span class="identifier">I1</span><span class="plain">);</span>
<span class="identifier">I2</span><span class="plain"> = </span><span class="functiontext">LinkedLists::next</span><span class="plain">(</span><span class="identifier">I2</span><span class="plain">);</span>
2020-03-23 15:04:43 +00:00
<span class="plain">}</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">I1</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) &amp;&amp; (</span><span class="identifier">I2</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">I1</span><span class="plain">) &amp;&amp; (</span><span class="identifier">I2</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
2020-03-23 15:04:43 +00:00
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function VersionNumbers::le is used in <a href="#SP11">&#167;11</a>, 7/vnr (<a href="7-vnr.html#SP6">&#167;6</a>).</p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. </b>The effect of this is to read unspecified versions of major, minor or patch
as if they were 0:
</p>
<pre class="display">
2020-04-06 11:26:10 +00:00
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VersionNumbers::floor</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">N</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">N</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">N</span><span class="plain">;</span>
2020-03-23 15:04:43 +00:00
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function VersionNumbers::floor is used in <a href="#SP8">&#167;8</a>.</p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. </b>This returns a non-negative integer if <code class="display"><span class="extract">T</span></code> contains only digits, and <code class="display"><span class="extract">-1</span></code>
otherwise. If the value has more than about 10 digits, then the result will
not be meaningful, which I think is a technical violation of the standard.
</p>
<pre class="display">
2020-04-06 11:26:10 +00:00
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VersionNumbers::strict_atoi</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">) {</span>
2020-03-23 15:04:43 +00:00
<span class="identifier">LOOP_THROUGH_TEXT</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">)</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Characters::isdigit</span><span class="plain">(</span><span class="functiontext">Str::get</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">)) == </span><span class="constant">FALSE</span><span class="plain">)</span>
<span class="reserved">return</span><span class="plain"> -1;</span>
<span class="identifier">wchar_t</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="functiontext">Str::get_first_char</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'0'</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">) &gt; </span><span class="constant">1</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> -1;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Str::atoi</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
2020-03-23 15:04:43 +00:00
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function VersionNumbers::strict_atoi is used in <a href="#SP8">&#167;8</a>.</p>
<p class="inwebparagraph"><a id="SP11"></a><b>&#167;11. Trichotomy. </b>We now use the above function to construct ordering relations on semvers.
These are trichotomous, that is, for each pair <code class="display"><span class="extract">V1, V2</span></code>, exactly one of the
<code class="display"><span class="extract">VersionNumbers::eq(V1, V2)</span></code>, <code class="display"><span class="extract">VersionNumbers::gt(V1, V2)</span></code>, <code class="display"><span class="extract">VersionNumbers::lt(V1, V2)</span></code>
is true.
</p>
<pre class="display">
2020-04-06 11:26:10 +00:00
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VersionNumbers::eq</span><span class="plain">(</span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V1</span><span class="plain">, </span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V2</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">VersionNumbers::le</span><span class="plain">(</span><span class="identifier">V1</span><span class="plain">, </span><span class="identifier">V2</span><span class="plain">)) &amp;&amp; (</span><span class="functiontext">VersionNumbers::le</span><span class="plain">(</span><span class="identifier">V2</span><span class="plain">, </span><span class="identifier">V1</span><span class="plain">)))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
2020-03-23 15:04:43 +00:00
<span class="plain">}</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VersionNumbers::ne</span><span class="plain">(</span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V1</span><span class="plain">, </span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V2</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> (</span><span class="functiontext">VersionNumbers::eq</span><span class="plain">(</span><span class="identifier">V1</span><span class="plain">, </span><span class="identifier">V2</span><span class="plain">))?</span><span class="identifier">FALSE:TRUE</span><span class="plain">;</span>
2020-03-23 15:04:43 +00:00
<span class="plain">}</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VersionNumbers::gt</span><span class="plain">(</span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V1</span><span class="plain">, </span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V2</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> (</span><span class="functiontext">VersionNumbers::le</span><span class="plain">(</span><span class="identifier">V1</span><span class="plain">, </span><span class="identifier">V2</span><span class="plain">))?</span><span class="identifier">FALSE:TRUE</span><span class="plain">;</span>
2020-03-23 15:04:43 +00:00
<span class="plain">}</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VersionNumbers::ge</span><span class="plain">(</span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V1</span><span class="plain">, </span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V2</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">VersionNumbers::le</span><span class="plain">(</span><span class="identifier">V2</span><span class="plain">, </span><span class="identifier">V1</span><span class="plain">);</span>
2020-03-23 15:04:43 +00:00
<span class="plain">}</span>
2020-04-06 11:26:10 +00:00
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VersionNumbers::lt</span><span class="plain">(</span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V1</span><span class="plain">, </span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V2</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> (</span><span class="functiontext">VersionNumbers::ge</span><span class="plain">(</span><span class="identifier">V1</span><span class="plain">, </span><span class="identifier">V2</span><span class="plain">))?</span><span class="identifier">FALSE:TRUE</span><span class="plain">;</span>
2020-03-23 15:04:43 +00:00
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function VersionNumbers::eq is used in <a href="#SP12">&#167;12</a>.</p>
<p class="endnote">The function VersionNumbers::ne appears nowhere else.</p>
<p class="endnote">The function VersionNumbers::gt is used in <a href="#SP12">&#167;12</a>, 7/vnr (<a href="7-vnr.html#SP6">&#167;6</a>).</p>
<p class="endnote">The function VersionNumbers::ge is used in 7/vnr (<a href="7-vnr.html#SP6">&#167;6</a>).</p>
<p class="endnote">The function VersionNumbers::lt is used in 7/vnr (<a href="7-vnr.html#SP6">&#167;6</a>).</p>
<p class="inwebparagraph"><a id="SP12"></a><b>&#167;12. </b>And the following can be used for sorting, following the <code class="display"><span class="extract">strcmp</span></code> convention.
</p>
<pre class="display">
2020-04-06 11:26:10 +00:00
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VersionNumbers::cmp</span><span class="plain">(</span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V1</span><span class="plain">, </span><span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">V2</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">VersionNumbers::eq</span><span class="plain">(</span><span class="identifier">V1</span><span class="plain">, </span><span class="identifier">V2</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">VersionNumbers::gt</span><span class="plain">(</span><span class="identifier">V1</span><span class="plain">, </span><span class="identifier">V2</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">1</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> -1;</span>
2020-03-23 15:04:43 +00:00
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function VersionNumbers::cmp is used in 7/vnr (<a href="7-vnr.html#SP8">&#167;8</a>, <a href="7-vnr.html#SP9">&#167;9</a>).</p>
<hr class="tocbar">
<ul class="toc"><li><i>(This section begins Chapter 7: Semantic Versioning.)</i></li><li><a href="7-vnr.html">Continue with 'Version Number Ranges'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</main>
</body>
</html>