mirror of
https://github.com/jashkenas/coffeescript.git
synced 2026-01-14 01:07:55 -05:00
734 lines
25 KiB
HTML
734 lines
25 KiB
HTML
<!DOCTYPE html>
|
|
|
|
<html>
|
|
<head>
|
|
<title>sourcemap.coffee</title>
|
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
|
<meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
|
|
<link rel="stylesheet" media="all" href="docco.css" />
|
|
</head>
|
|
<body>
|
|
<div id="container">
|
|
<div id="background"></div>
|
|
|
|
<ul id="jump_to">
|
|
<li>
|
|
<a class="large" href="javascript:void(0);">Jump To …</a>
|
|
<a class="small" href="javascript:void(0);">+</a>
|
|
<div id="jump_wrapper">
|
|
<div id="jump_page">
|
|
|
|
|
|
<a class="source" href="browser.html">
|
|
browser.coffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="cake.html">
|
|
cake.coffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="coffee-script.html">
|
|
coffee-script.coffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="command.html">
|
|
command.coffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="grammar.html">
|
|
grammar.coffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="helpers.html">
|
|
helpers.coffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="index.html">
|
|
index.coffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="lexer.html">
|
|
lexer.coffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="nodes.html">
|
|
nodes.coffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="optparse.html">
|
|
optparse.coffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="repl.html">
|
|
repl.coffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="rewriter.html">
|
|
rewriter.coffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="scope.html">
|
|
scope.litcoffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="sourcemap.html">
|
|
sourcemap.coffee
|
|
</a>
|
|
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
|
|
<ul class="sections">
|
|
|
|
<li id="title">
|
|
<div class="annotation">
|
|
<h1>sourcemap.coffee</h1>
|
|
</div>
|
|
</li>
|
|
|
|
|
|
|
|
<li id="section-1">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap for-h3">
|
|
<a class="pilcrow" href="#section-1">¶</a>
|
|
</div>
|
|
<h3>LineMapping</h3>
|
|
<p>Hold data about mappings for one line of generated source code.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre><span class="class"><span class="keyword">class</span> <span class="title">LineMapping</span></span>
|
|
constructor: (<span class="property">@generatedLine</span>) -></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-2">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-2">¶</a>
|
|
</div>
|
|
<p>columnMap keeps track of which columns we've already mapped.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> <span class="property">@columnMap</span> = {}</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-3">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-3">¶</a>
|
|
</div>
|
|
<p>columnMappings is an array of all column mappings, sorted by generated-column.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> <span class="property">@columnMappings</span> = []
|
|
|
|
addMapping: (generatedColumn, [sourceLine, sourceColumn], options={}) ->
|
|
<span class="keyword">if</span> <span class="property">@columnMap</span>[generatedColumn] <span class="keyword">and</span> options.noReplace</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-4">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-4">¶</a>
|
|
</div>
|
|
<p>We already have a mapping for this column.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> <span class="keyword">return</span>
|
|
|
|
<span class="property">@columnMap</span>[generatedColumn] = {
|
|
generatedLine: <span class="property">@generatedLine</span>
|
|
generatedColumn
|
|
sourceLine
|
|
sourceColumn
|
|
}
|
|
|
|
<span class="property">@columnMappings</span>.push <span class="property">@columnMap</span>[generatedColumn]
|
|
<span class="property">@columnMappings</span>.sort (a,b) -> a.generatedColumn - b.generatedColumn
|
|
|
|
getSourcePosition: (generatedColumn) ->
|
|
answer = <span class="literal">null</span>
|
|
lastColumnMapping = <span class="literal">null</span>
|
|
<span class="keyword">for</span> columnMapping <span class="keyword">in</span> <span class="property">@columnMappings</span>
|
|
<span class="keyword">if</span> columnMapping.generatedColumn > generatedColumn
|
|
<span class="keyword">break</span>
|
|
<span class="keyword">else</span>
|
|
lastColumnMapping = columnMapping
|
|
<span class="keyword">if</span> lastColumnMapping
|
|
answer = [lastColumnMapping.sourceLine, lastColumnMapping.sourceColumn]</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-5">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap for-h3">
|
|
<a class="pilcrow" href="#section-5">¶</a>
|
|
</div>
|
|
<h3>SourceMap</h3>
|
|
<p>Maps locations in a generated source file back to locations in the original source file.
|
|
|
|
</p>
|
|
<p>This is intentionally agnostic towards how a source map might be represented on disk. A
|
|
SourceMap can be converted to a "v3" style sourcemap with <code>#generateV3SourceMap()</code>, for example
|
|
but the SourceMap class itself knows nothing about v3 source maps.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre><span class="class"><span class="keyword">class</span> <span class="title">exports</span>.<span class="title">SourceMap</span></span>
|
|
constructor: () -></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-6">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-6">¶</a>
|
|
</div>
|
|
<p><code>generatedLines</code> is an array of LineMappings, one per generated line.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> <span class="property">@generatedLines</span> = []</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-7">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-7">¶</a>
|
|
</div>
|
|
<p>Adds a mapping to this SourceMap.
|
|
|
|
</p>
|
|
<p><code>sourceLocation</code> and <code>generatedLocation</code> are both [line, column] arrays.
|
|
|
|
</p>
|
|
<p>If <code>options.noReplace</code> is true, then if there is already a mapping for
|
|
the specified <code>generatedLine</code> and <code>generatedColumn</code>, this will have no effect.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> addMapping: (sourceLocation, generatedLocation, options={}) ->
|
|
[generatedLine, generatedColumn] = generatedLocation
|
|
|
|
lineMapping = <span class="property">@generatedLines</span>[generatedLine]
|
|
<span class="keyword">if</span> <span class="keyword">not</span> lineMapping
|
|
lineMapping = <span class="property">@generatedLines</span>[generatedLine] = <span class="keyword">new</span> LineMapping(generatedLine)
|
|
|
|
lineMapping.addMapping generatedColumn, sourceLocation, options</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-8">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-8">¶</a>
|
|
</div>
|
|
<p>Returns [sourceLine, sourceColumn], or null if no mapping could be found.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> getSourcePosition: ([generatedLine, generatedColumn]) ->
|
|
answer = <span class="literal">null</span>
|
|
lineMapping = <span class="property">@generatedLines</span>[generatedLine]
|
|
<span class="keyword">if</span> <span class="keyword">not</span> lineMapping</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-9">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-9">¶</a>
|
|
</div>
|
|
<p>TODO: Search backwards for the line?
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> <span class="keyword">else</span>
|
|
answer = lineMapping.getSourcePosition generatedColumn
|
|
|
|
answer</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-10">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-10">¶</a>
|
|
</div>
|
|
<p><code>fn</code> will be called once for every recorded mapping, in the order in
|
|
which they occur in the generated source. <code>fn</code> will be passed an object
|
|
with four properties: sourceLine, sourceColumn, generatedLine, and
|
|
generatedColumn.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> forEachMapping: (fn) ->
|
|
<span class="keyword">for</span> lineMapping, generatedLineNumber <span class="keyword">in</span> <span class="property">@generatedLines</span>
|
|
<span class="keyword">if</span> lineMapping
|
|
<span class="keyword">for</span> columnMapping <span class="keyword">in</span> lineMapping.columnMappings
|
|
fn(columnMapping)</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-11">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap for-h3">
|
|
<a class="pilcrow" href="#section-11">¶</a>
|
|
</div>
|
|
<h3>generateV3SourceMap</h3>
|
|
<p>Builds a V3 source map from a SourceMap object.
|
|
Returns the generated JSON as a string.
|
|
|
|
</p>
|
|
<p><code>options.sourceRoot</code> may be used to specify the sourceRoot written to the source map. Also,
|
|
<code>options.sourceFiles</code> and <code>options.generatedFile</code> may be passed to set "sources" and "file",
|
|
respectively. Note that <code>sourceFiles</code> must be an array.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre>exports.<span class="function"><span class="title">generateV3SourceMap</span></span> = (sourceMap, options={}, code) ->
|
|
sourceRoot = options.sourceRoot <span class="keyword">or</span> <span class="string">""</span>
|
|
sourceFiles = options.sourceFiles <span class="keyword">or</span> [<span class="string">""</span>]
|
|
generatedFile = options.generatedFile <span class="keyword">or</span> <span class="string">""</span>
|
|
|
|
writingGeneratedLine = <span class="number">0</span>
|
|
lastGeneratedColumnWritten = <span class="number">0</span>
|
|
lastSourceLineWritten = <span class="number">0</span>
|
|
lastSourceColumnWritten = <span class="number">0</span>
|
|
needComma = <span class="literal">no</span>
|
|
|
|
mappings = <span class="string">""</span>
|
|
|
|
sourceMap.forEachMapping (mapping) ->
|
|
<span class="keyword">while</span> writingGeneratedLine < mapping.generatedLine
|
|
lastGeneratedColumnWritten = <span class="number">0</span>
|
|
needComma = <span class="literal">no</span>
|
|
mappings += <span class="string">";"</span>
|
|
writingGeneratedLine++</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-12">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-12">¶</a>
|
|
</div>
|
|
<p>Write a comma if we've already written a segment on this line.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> <span class="keyword">if</span> needComma
|
|
mappings += <span class="string">","</span>
|
|
needComma = <span class="literal">no</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-13">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-13">¶</a>
|
|
</div>
|
|
<p>Write the next segment.
|
|
Segments can be 1, 4, or 5 values. If just one, then it is a generated column which
|
|
doesn't match anything in the source code.
|
|
|
|
</p>
|
|
<p>Fields are all zero-based, and relative to the previous occurence unless otherwise noted:
|
|
<em> starting-column in generated source, relative to previous occurence for the current line.
|
|
</em> index into the "sources" list
|
|
<em> starting line in the original source
|
|
</em> starting column in the original source
|
|
* index into the "names" list associated with this segment.
|
|
|
|
</p>
|
|
<p>Add the generated start-column
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> mappings += exports.vlqEncodeValue(mapping.generatedColumn - lastGeneratedColumnWritten)
|
|
lastGeneratedColumnWritten = mapping.generatedColumn</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-14">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-14">¶</a>
|
|
</div>
|
|
<p>Add the index into the sources list
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> mappings += exports.vlqEncodeValue(<span class="number">0</span>)</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-15">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-15">¶</a>
|
|
</div>
|
|
<p>Add the source start-line
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> mappings += exports.vlqEncodeValue(mapping.sourceLine - lastSourceLineWritten)
|
|
lastSourceLineWritten = mapping.sourceLine</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-16">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-16">¶</a>
|
|
</div>
|
|
<p>Add the source start-column
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> mappings += exports.vlqEncodeValue(mapping.sourceColumn - lastSourceColumnWritten)
|
|
lastSourceColumnWritten = mapping.sourceColumn</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-17">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-17">¶</a>
|
|
</div>
|
|
<p>TODO: Do we care about symbol names for CoffeeScript? Probably not.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> needComma = <span class="literal">yes</span>
|
|
|
|
answer = {
|
|
version: <span class="number">3</span>
|
|
file: generatedFile
|
|
sourceRoot
|
|
sources: sourceFiles
|
|
names: []
|
|
mappings
|
|
}
|
|
answer.sourcesContent = [code] <span class="keyword">if</span> options.inline
|
|
|
|
<span class="keyword">return</span> JSON.stringify answer, <span class="literal">null</span>, <span class="number">2</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-18">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-18">¶</a>
|
|
</div>
|
|
<p>Load a SourceMap from a JSON string. Returns the SourceMap object.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre>exports.<span class="function"><span class="title">loadV3SourceMap</span></span> = (sourceMap) ->
|
|
todo()</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-19">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap for-h3">
|
|
<a class="pilcrow" href="#section-19">¶</a>
|
|
</div>
|
|
<h3>Base64 encoding helpers</h3>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre>BASE64_CHARS = <span class="string">'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'</span>
|
|
MAX_BASE64_VALUE = BASE64_CHARS.length - <span class="number">1</span>
|
|
|
|
<span class="function"><span class="title">encodeBase64Char</span></span> = (value) ->
|
|
<span class="keyword">if</span> value > MAX_BASE64_VALUE
|
|
<span class="keyword">throw</span> <span class="keyword">new</span> Error <span class="string">"Cannot encode value <span class="subst">#{value}</span> > <span class="subst">#{MAX_BASE64_VALUE}</span>"</span>
|
|
<span class="keyword">else</span> <span class="keyword">if</span> value < <span class="number">0</span>
|
|
<span class="keyword">throw</span> <span class="keyword">new</span> Error <span class="string">"Cannot encode value <span class="subst">#{value}</span> < 0"</span>
|
|
BASE64_CHARS[value]
|
|
|
|
<span class="function"><span class="title">decodeBase64Char</span></span> = (char) ->
|
|
value = BASE64_CHARS.indexOf char
|
|
<span class="keyword">if</span> value == -<span class="number">1</span>
|
|
<span class="keyword">throw</span> <span class="keyword">new</span> Error <span class="string">"Invalid Base 64 character: <span class="subst">#{char}</span>"</span>
|
|
value</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-20">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap for-h3">
|
|
<a class="pilcrow" href="#section-20">¶</a>
|
|
</div>
|
|
<h3>Base 64 VLQ encoding/decoding helpers</h3>
|
|
<p>Note that SourceMap VLQ encoding is "backwards". MIDI style VLQ encoding puts the
|
|
most-significant-bit (MSB) from the original value into the MSB of the VLQ encoded value
|
|
(see <a href="http://en.wikipedia.org/wiki/File:Uintvar_coding.svg">http://en.wikipedia.org/wiki/File:Uintvar_coding.svg</a>). SourceMap VLQ does things
|
|
the other way around, with the least significat four bits of the original value encoded
|
|
into the first byte of the VLQ encoded value.
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre>VLQ_SHIFT = <span class="number">5</span>
|
|
VLQ_CONTINUATION_BIT = <span class="number">1</span> << VLQ_SHIFT <span class="comment"># 0010 0000</span>
|
|
VLQ_VALUE_MASK = VLQ_CONTINUATION_BIT - <span class="number">1</span> <span class="comment"># 0001 1111</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-21">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-21">¶</a>
|
|
</div>
|
|
<p>Encode a value as Base 64 VLQ.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre>exports.<span class="function"><span class="title">vlqEncodeValue</span></span> = (value) -></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-22">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-22">¶</a>
|
|
</div>
|
|
<p>Least significant bit represents the sign.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> signBit = <span class="keyword">if</span> value < <span class="number">0</span> <span class="keyword">then</span> <span class="number">1</span> <span class="keyword">else</span> <span class="number">0</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-23">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-23">¶</a>
|
|
</div>
|
|
<p>Next bits are the actual value
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> valueToEncode = (Math.abs(value) << <span class="number">1</span>) + signBit
|
|
|
|
answer = <span class="string">""</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-24">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-24">¶</a>
|
|
</div>
|
|
<p>Make sure we encode at least one character, even if valueToEncode is 0.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> <span class="keyword">while</span> valueToEncode || !answer
|
|
nextVlqChunk = valueToEncode & VLQ_VALUE_MASK
|
|
valueToEncode = valueToEncode >> VLQ_SHIFT
|
|
|
|
<span class="keyword">if</span> valueToEncode
|
|
nextVlqChunk |= VLQ_CONTINUATION_BIT
|
|
|
|
answer += encodeBase64Char(nextVlqChunk)
|
|
|
|
<span class="keyword">return</span> answer</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-25">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-25">¶</a>
|
|
</div>
|
|
<p>Decode a Base 64 VLQ value.
|
|
|
|
</p>
|
|
<p>Returns <code>[value, consumed]</code> where <code>value</code> is the decoded value, and <code>consumed</code> is the number
|
|
of characters consumed from <code>str</code>.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre>exports.<span class="function"><span class="title">vlqDecodeValue</span></span> = (str, offset=<span class="number">0</span>) ->
|
|
position = offset
|
|
done = <span class="literal">false</span>
|
|
|
|
value = <span class="number">0</span>
|
|
continuationShift = <span class="number">0</span>
|
|
|
|
<span class="keyword">while</span> !done
|
|
nextVlqChunk = decodeBase64Char(str[position])
|
|
position += <span class="number">1</span>
|
|
|
|
nextChunkValue = nextVlqChunk & VLQ_VALUE_MASK
|
|
value += (nextChunkValue << continuationShift)
|
|
|
|
<span class="keyword">if</span> !(nextVlqChunk & VLQ_CONTINUATION_BIT)</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-26">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-26">¶</a>
|
|
</div>
|
|
<p>We'll be done after this character.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> done = <span class="literal">true</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-27">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-27">¶</a>
|
|
</div>
|
|
<p>Bits are encoded least-significant first (opposite of MIDI VLQ). Increase the
|
|
continuationShift, so the next byte will end up where it should in the value.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> continuationShift += VLQ_SHIFT
|
|
|
|
consumed = position - offset</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-28">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-28">¶</a>
|
|
</div>
|
|
<p>Least significant bit represents the sign.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> signBit = value & <span class="number">1</span>
|
|
value = value >> <span class="number">1</span>
|
|
|
|
<span class="keyword">if</span> signBit <span class="keyword">then</span> value = -value
|
|
|
|
<span class="keyword">return</span> [value, consumed]</pre></div></div>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
</div>
|
|
</body>
|
|
</html>
|