inweb-bootstrap/docs/foundation-module/7-vnr.html
2020-04-07 00:53:26 +01:00

322 lines
44 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>7/vn</title>
<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">
<!--Weave of '7/vnr' generated by 7-->
<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 Number Ranges</b></li></ul><p class="purpose">Ranges of acceptable version numbers.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Ranges</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. Ranges. </b>We often want to check if a semver lies in a given precedence range, which we
store as an "interval" in the mathematical sense. For example, the range <code class="display"><span class="extract">[2,6)</span></code>
means all versions from 2.0.0 (inclusve) up to, but not equal to, 6.0.0. The
lower end is called "closed" because it includes the end-value 2.0.0, and the
upper end "open" because it does not. An infinite end means that there
os no restriction in that direction; an empty end means that, in fact, the
interval is the empty set, that is, that no version number can ever satisfy it.
</p>
<p class="inwebparagraph">The <code class="display"><span class="extract">end_value</span></code> element is meaningful only for <code class="display"><span class="extract">CLOSED_RANGE_END</span></code> and <code class="display"><span class="extract">OPEN_RANGE_END</span></code>
ends. If one end is marked <code class="display"><span class="extract">EMPTY_RANGE_END</span></code>, so must the other be: it makes
no sense for an interval to be empty seen from one end but not the other.
</p>
<pre class="definitions">
<span class="definitionkeyword">enum</span> <span class="constant">CLOSED_RANGE_END</span><span class="definitionkeyword"> from </span><span class="constant">1</span>
<span class="definitionkeyword">enum</span> <span class="constant">OPEN_RANGE_END</span>
<span class="definitionkeyword">enum</span> <span class="constant">INFINITE_RANGE_END</span>
<span class="definitionkeyword">enum</span> <span class="constant">EMPTY_RANGE_END</span>
</pre>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">range_end</span><span class="plain"> {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">end_type</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">end_value</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">range_end</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">semver_range</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">range_end</span><span class="plain"> </span><span class="identifier">lower</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">range_end</span><span class="plain"> </span><span class="identifier">upper</span><span class="plain">;</span>
<span class="constant">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">semver_range</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure range_end is private to this section.</p>
<p class="endnote">The structure semver_range is private to this section.</p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b>As hinted above, the notation <code class="display"><span class="extract">[</span></code> and <code class="display"><span class="extract">]</span></code> is used for closed ends, and <code class="display"><span class="extract">(</span></code>
and <code class="display"><span class="extract">)</span></code> for open ones.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">VersionNumberRanges::write_range</span><span class="plain">(</span><span class="constant">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">semver_range</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">R</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"no range"</span><span class="plain">);</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">-&gt;</span><span class="identifier">lower</span><span class="plain">.</span><span class="element">end_type</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">CLOSED_RANGE_END:</span><span class="plain"> </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"[%v,"</span><span class="plain">, &amp;(</span><span class="identifier">R</span><span class="plain">-&gt;</span><span class="element">lower</span><span class="plain">.</span><span class="element">end_value</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">OPEN_RANGE_END:</span><span class="plain"> </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"(%v,"</span><span class="plain">, &amp;(</span><span class="identifier">R</span><span class="plain">-&gt;</span><span class="element">lower</span><span class="plain">.</span><span class="element">end_value</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">INFINITE_RANGE_END:</span><span class="plain"> </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"(-infty,"</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">EMPTY_RANGE_END:</span><span class="plain"> </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"empty"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">-&gt;</span><span class="identifier">upper</span><span class="plain">.</span><span class="element">end_type</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">CLOSED_RANGE_END:</span><span class="plain"> </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%v]"</span><span class="plain">, &amp;(</span><span class="identifier">R</span><span class="plain">-&gt;</span><span class="element">upper</span><span class="plain">.</span><span class="element">end_value</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">OPEN_RANGE_END:</span><span class="plain"> </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%v)"</span><span class="plain">, &amp;(</span><span class="identifier">R</span><span class="plain">-&gt;</span><span class="element">upper</span><span class="plain">.</span><span class="element">end_value</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">INFINITE_RANGE_END:</span><span class="plain"> </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"infty)"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function VersionNumberRanges::write_range appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>The "allow anything" range runs from minus to plus infinity. Every version
number lies in this range.
</p>
<pre class="display">
<span class="reserved">semver_range</span><span class="plain"> *</span><span class="functiontext">VersionNumberRanges::any_range</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">semver_range</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">semver_range</span><span class="plain">);</span>
<span class="identifier">R</span><span class="plain">-&gt;</span><span class="element">lower</span><span class="plain">.</span><span class="element">end_type</span><span class="plain"> = </span><span class="constant">INFINITE_RANGE_END</span><span class="plain">;</span>
<span class="identifier">R</span><span class="plain">-&gt;</span><span class="element">lower</span><span class="plain">.</span><span class="element">end_value</span><span class="plain"> = </span><span class="functiontext">VersionNumbers::null</span><span class="plain">();</span>
<span class="identifier">R</span><span class="plain">-&gt;</span><span class="element">upper</span><span class="plain">.</span><span class="element">end_type</span><span class="plain"> = </span><span class="constant">INFINITE_RANGE_END</span><span class="plain">;</span>
<span class="identifier">R</span><span class="plain">-&gt;</span><span class="element">upper</span><span class="plain">.</span><span class="element">end_value</span><span class="plain"> = </span><span class="functiontext">VersionNumbers::null</span><span class="plain">();</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">R</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VersionNumberRanges::is_any_range</span><span class="plain">(</span><span class="reserved">semver_range</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">R</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">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">R</span><span class="plain">-&gt;</span><span class="element">lower</span><span class="plain">.</span><span class="element">end_type</span><span class="plain"> == </span><span class="constant">INFINITE_RANGE_END</span><span class="plain">) &amp;&amp; (</span><span class="identifier">R</span><span class="plain">-&gt;</span><span class="element">upper</span><span class="plain">.</span><span class="element">end_type</span><span class="plain"> == </span><span class="constant">INFINITE_RANGE_END</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>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function VersionNumberRanges::any_range is used in <a href="#SP4">&#167;4</a>, <a href="#SP5">&#167;5</a>.</p>
<p class="endnote">The function VersionNumberRanges::is_any_range appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. </b>The "compatibility" range for a given version lies at the heart of semver:
to be compatible with version <code class="display"><span class="extract">V</span></code>, version <code class="display"><span class="extract">W</span></code> must be of equal or greater
precedence, and must have the same major version number. For example,
for <code class="display"><span class="extract">2.1.7</span></code> the range will be <code class="display"><span class="extract">[2.1.7, 3-A)</span></code>, all versions at least 2.1.7 but
not as high as 3.0.0-A.
</p>
<p class="inwebparagraph">Note that <code class="display"><span class="extract">3.0.0-A</span></code> is the least precendent version allowed by semver with
major version 3. The <code class="display"><span class="extract">-</span></code> gives it lower precedence than all release versions of
3.0.0; the fact that upper case <code class="display"><span class="extract">A</span></code> is alphabetically the earliest non-empty
alphanumeric string gives it lower precendence than all other prerelease
versions.
</p>
<pre class="display">
<span class="reserved">semver_range</span><span class="plain"> *</span><span class="functiontext">VersionNumberRanges::compatibility_range</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">semver_range</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain"> = </span><span class="functiontext">VersionNumberRanges::any_range</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="constant">FALSE</span><span class="plain">) {</span>
<span class="identifier">R</span><span class="plain">-&gt;</span><span class="element">lower</span><span class="plain">.</span><span class="element">end_type</span><span class="plain"> = </span><span class="constant">CLOSED_RANGE_END</span><span class="plain">;</span>
<span class="identifier">R</span><span class="plain">-&gt;</span><span class="element">lower</span><span class="plain">.</span><span class="element">end_value</span><span class="plain"> = </span><span class="identifier">V</span><span class="plain">;</span>
<span class="identifier">R</span><span class="plain">-&gt;</span><span class="element">upper</span><span class="plain">.</span><span class="element">end_type</span><span class="plain"> = </span><span class="constant">OPEN_RANGE_END</span><span class="plain">;</span>
<span class="reserved">semantic_version_number</span><span class="plain"> </span><span class="identifier">W</span><span class="plain"> = </span><span class="functiontext">VersionNumbers::null</span><span class="plain">();</span>
<span class="identifier">W</span><span class="plain">.</span><span class="element">version_numbers</span><span class="plain">[0] = </span><span class="identifier">V</span><span class="plain">.</span><span class="element">version_numbers</span><span class="plain">[0] + </span><span class="constant">1</span><span class="plain">;</span>
<span class="identifier">W</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="identifier">I</span><span class="string">"A"</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">.</span><span class="element">prerelease_segments</span><span class="plain">);</span>
<span class="identifier">R</span><span class="plain">-&gt;</span><span class="element">upper</span><span class="plain">.</span><span class="element">end_value</span><span class="plain"> = </span><span class="identifier">W</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">R</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function VersionNumberRanges::compatibility_range appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. </b>More straightforwardly, these ranges are for anything from V, or up to V,
inclusive:
</p>
<pre class="display">
<span class="reserved">semver_range</span><span class="plain"> *</span><span class="functiontext">VersionNumberRanges::at_least_range</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">semver_range</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain"> = </span><span class="functiontext">VersionNumberRanges::any_range</span><span class="plain">();</span>
<span class="identifier">R</span><span class="plain">-&gt;</span><span class="element">lower</span><span class="plain">.</span><span class="element">end_type</span><span class="plain"> = </span><span class="constant">CLOSED_RANGE_END</span><span class="plain">;</span>
<span class="identifier">R</span><span class="plain">-&gt;</span><span class="element">lower</span><span class="plain">.</span><span class="element">end_value</span><span class="plain"> = </span><span class="identifier">V</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">R</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">semver_range</span><span class="plain"> *</span><span class="functiontext">VersionNumberRanges::at_most_range</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">semver_range</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain"> = </span><span class="functiontext">VersionNumberRanges::any_range</span><span class="plain">();</span>
<span class="identifier">R</span><span class="plain">-&gt;</span><span class="element">upper</span><span class="plain">.</span><span class="element">end_type</span><span class="plain"> = </span><span class="constant">CLOSED_RANGE_END</span><span class="plain">;</span>
<span class="identifier">R</span><span class="plain">-&gt;</span><span class="element">upper</span><span class="plain">.</span><span class="element">end_value</span><span class="plain"> = </span><span class="identifier">V</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">R</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function VersionNumberRanges::at_least_range appears nowhere else.</p>
<p class="endnote">The function VersionNumberRanges::at_most_range appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. </b>Here we test whether V is at least a given end, and then at most:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VersionNumberRanges::version_ge_end</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">range_end</span><span class="plain"> </span><span class="identifier">E</span><span class="plain">) {</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">E</span><span class="plain">.</span><span class="identifier">end_type</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">CLOSED_RANGE_END:</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="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="functiontext">VersionNumbers::ge</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">, </span><span class="identifier">E</span><span class="plain">.</span><span class="element">end_value</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">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">OPEN_RANGE_END:</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="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="functiontext">VersionNumbers::gt</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">, </span><span class="identifier">E</span><span class="plain">.</span><span class="element">end_value</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">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">INFINITE_RANGE_END:</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">case</span><span class="plain"> </span><span class="identifier">EMPTY_RANGE_END:</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">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VersionNumberRanges::version_le_end</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">range_end</span><span class="plain"> </span><span class="identifier">E</span><span class="plain">) {</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">E</span><span class="plain">.</span><span class="identifier">end_type</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">CLOSED_RANGE_END:</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="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="functiontext">VersionNumbers::le</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">, </span><span class="identifier">E</span><span class="plain">.</span><span class="element">end_value</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">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">OPEN_RANGE_END:</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="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="functiontext">VersionNumbers::lt</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">, </span><span class="identifier">E</span><span class="plain">.</span><span class="element">end_value</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">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">INFINITE_RANGE_END:</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">case</span><span class="plain"> </span><span class="identifier">EMPTY_RANGE_END:</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">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function VersionNumberRanges::version_ge_end is used in <a href="#SP7">&#167;7</a>.</p>
<p class="endnote">The function VersionNumberRanges::version_le_end is used in <a href="#SP7">&#167;7</a>.</p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. </b>This allows a simple way to write:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VersionNumberRanges::in_range</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">semver_range</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">R</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">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">VersionNumberRanges::version_ge_end</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">-&gt;</span><span class="element">lower</span><span class="plain">)) &amp;&amp;</span>
<span class="plain">(</span><span class="functiontext">VersionNumberRanges::version_le_end</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">-&gt;</span><span class="element">upper</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>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function VersionNumberRanges::in_range appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. </b>The following decides which end restriction is stricter: it returns 1
of <code class="display"><span class="extract">E1</span></code> is, -1 if <code class="display"><span class="extract">E2</span></code> is, and 0 if they are equally onerous.
</p>
<p class="inwebparagraph">The empty set is as strict as it gets: nothing qualifies.
</p>
<p class="inwebparagraph">Similarly, infinite ends are as relaxed as can be: everything qualifies.
</p>
<p class="inwebparagraph">And otherwise, we need to know which end we're looking at in order to decide:
a lower end of <code class="display"><span class="extract">[4, ...]</span></code> is stricter than a lower end of <code class="display"><span class="extract">[3, ...]</span></code>, but an
upper end of <code class="display"><span class="extract">[..., 4]</span></code> is not as strict as an upper end of <code class="display"><span class="extract">[..., 3]</span></code>. Where
the boundary value is the same, open ends are stricter than closed ends.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VersionNumberRanges::stricter</span><span class="plain">(</span><span class="reserved">range_end</span><span class="plain"> </span><span class="identifier">E1</span><span class="plain">, </span><span class="reserved">range_end</span><span class="plain"> </span><span class="identifier">E2</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">lower</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">E1</span><span class="plain">.</span><span class="element">end_type</span><span class="plain"> == </span><span class="constant">EMPTY_RANGE_END</span><span class="plain">) &amp;&amp; (</span><span class="identifier">E2</span><span class="plain">.</span><span class="element">end_type</span><span class="plain"> == </span><span class="constant">EMPTY_RANGE_END</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="identifier">E1</span><span class="plain">.</span><span class="element">end_type</span><span class="plain"> == </span><span class="constant">EMPTY_RANGE_END</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">if</span><span class="plain"> (</span><span class="identifier">E2</span><span class="plain">.</span><span class="element">end_type</span><span class="plain"> == </span><span class="constant">EMPTY_RANGE_END</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> -1;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">E1</span><span class="plain">.</span><span class="element">end_type</span><span class="plain"> == </span><span class="constant">INFINITE_RANGE_END</span><span class="plain">) &amp;&amp; (</span><span class="identifier">E2</span><span class="plain">.</span><span class="element">end_type</span><span class="plain"> == </span><span class="constant">INFINITE_RANGE_END</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="identifier">E1</span><span class="plain">.</span><span class="element">end_type</span><span class="plain"> == </span><span class="constant">INFINITE_RANGE_END</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> -1;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">E2</span><span class="plain">.</span><span class="element">end_type</span><span class="plain"> == </span><span class="constant">INFINITE_RANGE_END</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">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="functiontext">VersionNumbers::cmp</span><span class="plain">(</span><span class="identifier">E1</span><span class="plain">.</span><span class="element">end_value</span><span class="plain">, </span><span class="identifier">E2</span><span class="plain">.</span><span class="element">end_value</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="reserved">if</span><span class="plain"> (</span><span class="identifier">lower</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">c</span><span class="plain">; </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> -</span><span class="identifier">c</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">E1</span><span class="plain">.</span><span class="element">end_type</span><span class="plain"> == </span><span class="identifier">E2</span><span class="plain">.</span><span class="element">end_type</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="identifier">E1</span><span class="plain">.</span><span class="element">end_type</span><span class="plain"> == </span><span class="constant">CLOSED_RANGE_END</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="constant">1</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function VersionNumberRanges::stricter is used in <a href="#SP9">&#167;9</a>.</p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. </b>And so we finally arrive at the following, which intersects two ranges:
that is, it changes <code class="display"><span class="extract">R1</span></code> to the range of versions which lie inside both the
original <code class="display"><span class="extract">R1</span></code> and also <code class="display"><span class="extract">R2</span></code>. (This is used by Inbuild when an extension is
included in two different places in the source text, but with possibly
different version needs.) The return value is true if an actual change took
place, and false otherwise.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VersionNumberRanges::intersect_range</span><span class="plain">(</span><span class="reserved">semver_range</span><span class="plain"> *</span><span class="identifier">R1</span><span class="plain">, </span><span class="reserved">semver_range</span><span class="plain"> *</span><span class="identifier">R2</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">lc</span><span class="plain"> = </span><span class="functiontext">VersionNumberRanges::stricter</span><span class="plain">(</span><span class="identifier">R1</span><span class="plain">-&gt;</span><span class="element">lower</span><span class="plain">, </span><span class="identifier">R2</span><span class="plain">-&gt;</span><span class="element">lower</span><span class="plain">, </span><span class="constant">TRUE</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">uc</span><span class="plain"> = </span><span class="functiontext">VersionNumberRanges::stricter</span><span class="plain">(</span><span class="identifier">R1</span><span class="plain">-&gt;</span><span class="element">upper</span><span class="plain">, </span><span class="identifier">R2</span><span class="plain">-&gt;</span><span class="element">upper</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">lc</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) &amp;&amp; (</span><span class="identifier">uc</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>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">lc</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">R1</span><span class="plain">-&gt;</span><span class="element">lower</span><span class="plain"> = </span><span class="identifier">R2</span><span class="plain">-&gt;</span><span class="element">lower</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">uc</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">R1</span><span class="plain">-&gt;</span><span class="element">upper</span><span class="plain"> = </span><span class="identifier">R2</span><span class="plain">-&gt;</span><span class="element">upper</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">R1</span><span class="plain">-&gt;</span><span class="element">lower</span><span class="plain">.</span><span class="element">end_type</span><span class="plain"> == </span><span class="constant">EMPTY_RANGE_END</span><span class="plain">) </span><span class="identifier">R1</span><span class="plain">-&gt;</span><span class="element">upper</span><span class="plain">.</span><span class="element">end_type</span><span class="plain"> = </span><span class="constant">EMPTY_RANGE_END</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">R1</span><span class="plain">-&gt;</span><span class="element">upper</span><span class="plain">.</span><span class="element">end_type</span><span class="plain"> == </span><span class="constant">EMPTY_RANGE_END</span><span class="plain">) </span><span class="identifier">R1</span><span class="plain">-&gt;</span><span class="element">lower</span><span class="plain">.</span><span class="element">end_type</span><span class="plain"> = </span><span class="constant">EMPTY_RANGE_END</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">R1</span><span class="plain">-&gt;</span><span class="element">lower</span><span class="plain">.</span><span class="element">end_type</span><span class="plain"> != </span><span class="constant">INFINITE_RANGE_END</span><span class="plain">) &amp;&amp; (</span><span class="identifier">R1</span><span class="plain">-&gt;</span><span class="element">upper</span><span class="plain">.</span><span class="element">end_type</span><span class="plain"> != </span><span class="constant">INFINITE_RANGE_END</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">VersionNumbers::cmp</span><span class="plain">(</span><span class="identifier">R1</span><span class="plain">-&gt;</span><span class="element">lower</span><span class="plain">.</span><span class="element">end_value</span><span class="plain">, </span><span class="identifier">R1</span><span class="plain">-&gt;</span><span class="element">upper</span><span class="plain">.</span><span class="element">end_value</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="plain">((</span><span class="identifier">c</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) &amp;&amp; ((</span><span class="identifier">R1</span><span class="plain">-&gt;</span><span class="element">lower</span><span class="plain">.</span><span class="element">end_type</span><span class="plain"> == </span><span class="constant">OPEN_RANGE_END</span><span class="plain">) ||</span>
<span class="plain">(</span><span class="identifier">R1</span><span class="plain">-&gt;</span><span class="element">upper</span><span class="plain">.</span><span class="identifier">end_type</span><span class="plain"> == </span><span class="constant">OPEN_RANGE_END</span><span class="plain">)))) {</span>
<span class="identifier">R1</span><span class="plain">-&gt;</span><span class="element">lower</span><span class="plain">.</span><span class="identifier">end_type</span><span class="plain"> = </span><span class="constant">EMPTY_RANGE_END</span><span class="plain">; </span><span class="identifier">R1</span><span class="plain">-&gt;</span><span class="element">upper</span><span class="plain">.</span><span class="element">end_type</span><span class="plain"> = </span><span class="constant">EMPTY_RANGE_END</span><span class="plain">;</span>
<span class="plain">}</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="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function VersionNumberRanges::intersect_range appears nowhere else.</p>
<hr class="tocbar">
<ul class="toc"><li><a href="7-vn.html">Back to 'Version Numbers'</a></li><li><i>(This section ends Chapter 7: Semantic Versioning.)</i></li></ul><hr class="tocbar">
<!--End of weave-->
</main>
</body>
</html>