mozilla

Revision 428647 of StringView

  • Revision slug: Web/JavaScript/Typed_arrays/StringView
  • Revision title: StringView
  • Revision id: 428647
  • Created:
  • Creator: fusionchess
  • Is current revision? No
  • Comment

Revision Content

{{draft}}

The aims of this library are:

  • creating a C-like interface for strings (i.e. array of characters codes — an ArrayBufferView in JavaScript) based upon the JavaScript ArrayBuffer interface,
  • creating an highly scalable library, that anyone can extend by adding methods to the object StringView.prototype,
  • creating a collection of methods for such string-like objects (since now: stringViews) which work strictly on arrays of numbers rather than on creating new immutable JavaScript strings,
  • working with other Unicode encodings different from default JavaScript's UTF-16 {{domxref("DOMString")}}s,

Introduction

As web applications become more and more powerful, adding features such as audio and video manipulation, access to raw data using WebSockets, and so forth, it has become clear that there are times when it would be helpful for JavaScript code to be able to quickly and easily manipulate raw binary data. In the past, this had to be simulated by treating the raw data as a string and using the charCodeAt() method to read the bytes from the data buffer.

However, this is slow and error-prone, due to the need for multiple conversions (especially if the binary data is not actually byte-format data, but, for example, 32-bit integers or floats).

JavaScript typed arrays provide a mechanism for accessing raw binary data much more efficiently. The StringView constructor is one level above typed arrays.

The code

stringview.js

"use strict";

/*\
|*|
|*|  :: Number.isInteger() polyfill ::
|*|
|*|  https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger
|*|
\*/

if (!Number.isInteger) {
  Number.isInteger = function isInteger (nVal) {
    return typeof nVal === "number" && isFinite(nVal) && nVal > -9007199254740992 && nVal < 9007199254740992 && Math.floor(nVal) === nVal;
  };
}


/*\
|*|
|*|  StringView - Mozilla Developer Network - revision #2
|*|
|*|  https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays/StringView
|*|  https://developer.mozilla.org/User:fusionchess
|*|
|*|  This framework is released under the GNU Public License, version 3 or later.
|*|  http://www.gnu.org/licenses/gpl-3.0-standalone.html
|*|
\*/

function StringView (vInput, sEncoding /* optional (default: UTF-8) */, nOffset /* optional */, nLength /* optional */) {

  var fTAView, aWhole, aRaw, fPutOutptCode, fGetOutptChrSize, nInptLen, nStartIdx = isFinite(nOffset) ? nOffset : 0, nTranscrType = 15;

  if (sEncoding) { this.encoding = sEncoding.toString(); }

  encSwitch: switch (this.encoding) {
    case "UTF-8":
      fPutOutptCode = StringView.putUTF8CharCode;
      fGetOutptChrSize = StringView.getUTF8CharLength;
      fTAView = Uint8Array;
      break encSwitch;
    case "UTF-16":
      fPutOutptCode = StringView.putUTF16CharCode;
      fGetOutptChrSize = StringView.getUTF16CharLength;
      fTAView = Uint16Array;
      break encSwitch;
    case "UTF-32":
      fTAView = Uint32Array;
      nTranscrType &= 14;
      break encSwitch;
    default:
      /* case "ASCII", or case "BinaryString" or unknown cases */
      fTAView = Uint8Array;
      nTranscrType &= 14;
  }

  typeSwitch: switch (typeof vInput) {
    case "string":
      /* the input argument is a primitive string: a new buffer will be created. */
      nTranscrType &= 7;
      break typeSwitch;
    case "object":
      classSwitch: switch (vInput.constructor) {
        case StringView:
          /* the input argument is a stringView: a new buffer will be created. */
          nTranscrType &= 3;
          break typeSwitch;
        case String:
          /* the input argument is an objectified string: a new buffer will be created. */
          nTranscrType &= 7;
          break typeSwitch;
        case ArrayBuffer:
          /* the input argument is an arrayBuffer: the buffer will be shared. */
          aWhole = new fTAView(vInput);
          nInptLen = this.encoding === "UTF-32" ?
              vInput.byteLength >>> 2
            : this.encoding === "UTF-16" ?
              vInput.byteLength >>> 1
            :
              vInput.byteLength;
          aRaw = nStartIdx === 0 && (!isFinite(nLength) || nLength === nInptLen) ?
            aWhole
            : new fTAView(vInput, nStartIdx, !isFinite(nLength) ? nInptLen - nStartIdx : nLength);

          break typeSwitch;
        case Uint32Array:
        case Uint16Array:
        case Uint8Array:
          /* the input argument is a typedArray: the buffer, and possibly the array itself, will be shared. */
          fTAView = vInput.constructor;
          nInptLen = vInput.length;
          aWhole = vInput.byteOffset === 0 && vInput.length === (
            fTAView === Uint32Array ?
              vInput.buffer.byteLength >>> 2
            : fTAView === Uint16Array ?
              vInput.buffer.byteLength >>> 1
            :
              vInput.buffer.byteLength
          ) ? vInput : new fTAView(vInput.buffer);
          aRaw = nStartIdx === 0 && (!isFinite(nLength) || nLength === nInptLen) ?
            vInput
            : vInput.subarray(nStartIdx, isFinite(nLength) ? nStartIdx + nLength : nInptLen);

          break typeSwitch;
        default:
          /* the input argument is an array or another serializable object: a new typedArray will be created. */
          aWhole = new fTAView(vInput);
          nInptLen = aWhole.length;
          aRaw = nStartIdx === 0 && (!isFinite(nLength) || nLength === nInptLen) ?
            aWhole
            : aWhole.subarray(nStartIdx, isFinite(nLength) ? nStartIdx + nLength : nInptLen);
      }
      break typeSwitch;
    default:
      /* the input argument is a number, a boolean or a function: a new typedArray will be created. */
      aWhole = aRaw = new fTAView(Number(vInput) || 0);

  }

  if (nTranscrType < 8) {

    var vSource, nOutptLen, nCharStart, nCharEnd, nEndIdx, fGetInptChrSize, fGetInptChrCode;


    if (nTranscrType & 4) { /* input is string */

      vSource = vInput;
      nOutptLen = nInptLen = vSource.length;
      nTranscrType ^= this.encoding === "UTF-32" ? 0 : 2;
      /* ...or...: nTranscrType ^= Number(this.encoding !== "UTF-32") << 1; */
      nStartIdx = nCharStart = nOffset ? Math.max((nOutptLen + nOffset) % nOutptLen, 0) : 0;
      nEndIdx = nCharEnd = (Number.isInteger(nLength) ? Math.min(Math.max(nLength, 0) + nStartIdx, nOutptLen) : nOutptLen) - 1;

    } else { /* input is stringView */

      vSource = vInput.rawData;
      nInptLen = vInput.makeIndex();
      nStartIdx = nCharStart = nOffset ? Math.max((nInptLen + nOffset) % nInptLen, 0) : 0;
      nOutptLen = Number.isInteger(nLength) ? Math.min(Math.max(nLength, 0), nInptLen - nCharStart) : nInptLen;
      nEndIdx = nCharEnd = nOutptLen + nCharStart;

      if (vInput.encoding === "UTF-8") {
        fGetInptChrSize = StringView.getUTF8CharLength;
        fGetInptChrCode = StringView.loadUTF8CharCode;
      } else if (vInput.encoding === "UTF-16") {
        fGetInptChrSize = StringView.getUTF16CharLength;
        fGetInptChrCode = StringView.loadUTF16CharCode;
      } else {
        nTranscrType &= 1;
      }

    }

    if (nOutptLen === 0 || nTranscrType < 4 && vSource.encoding === this.encoding && nCharStart === 0 && nOutptLen === nInptLen) {

      /* the encoding is the same, the length too and the offset is 0... or the input is empty! */

      nTranscrType = 7;

    }

    conversionSwitch: switch (nTranscrType) {

      case 0:

      /* both the source and the new StringView have a fixed-length encoding... */

        aWhole = new fTAView(nOutptLen);
        for (var nOutptIdx = 0; nOutptIdx < nOutptLen; aWhole[nOutptIdx] = vSource[nStartIdx + nOutptIdx++]);
        break conversionSwitch;

      case 1:

      /* the source has a fixed-length encoding but the new StringView has a variable-length encoding... */

        /* mapping... */

        nOutptLen = 0;

        for (var nInptIdx = nStartIdx; nInptIdx < nEndIdx; nInptIdx++) {
          nOutptLen += fGetOutptChrSize(vSource[nInptIdx]);
        }

        aWhole = new fTAView(nOutptLen);

        /* transcription of the source... */

        for (var nInptIdx = nStartIdx, nOutptIdx = 0; nOutptIdx < nOutptLen; nInptIdx++) {
          nOutptIdx = fPutOutptCode(aWhole, vSource[nInptIdx], nOutptIdx);
        }

        break conversionSwitch;

      case 2:

      /* the source has a variable-length encoding but the new StringView has a fixed-length encoding... */

        /* mapping... */

        nStartIdx = 0;

        var nChrCode;

        for (nChrIdx = 0; nChrIdx < nCharStart; nChrIdx++) {
          nChrCode = fGetInptChrCode(vSource, nStartIdx);
          nStartIdx += fGetInptChrSize(nChrCode);
        }

        aWhole = new fTAView(nOutptLen);

        /* transcription of the source... */

        for (var nInptIdx = nStartIdx, nOutptIdx = 0; nOutptIdx < nOutptLen; nInptIdx += fGetInptChrSize(nChrCode), nOutptIdx++) {
          nChrCode = fGetInptChrCode(vSource, nInptIdx);
          aWhole[nOutptIdx] = nChrCode;
        }

        break conversionSwitch;

      case 3:

      /* both the source and the new StringView have a variable-length encoding... */

        /* mapping... */

        nOutptLen = 0;

        var nChrCode;

        for (var nChrIdx = 0, nInptIdx = 0; nChrIdx < nCharEnd; nInptIdx += fGetInptChrSize(nChrCode)) {
          nChrCode = fGetInptChrCode(vSource, nInptIdx);
          if (nChrIdx === nCharStart) { nStartIdx = nInptIdx; }
          if (++nChrIdx > nCharStart) { nOutptLen += fGetOutptChrSize(nChrCode); }
        }

        aWhole = new fTAView(nOutptLen);

        /* transcription... */

        for (var nInptIdx = nStartIdx, nOutptIdx = 0; nOutptIdx < nOutptLen; nInptIdx += fGetInptChrSize(nChrCode)) {
          nChrCode = fGetInptChrCode(vSource, nInptIdx);
          nOutptIdx = fPutOutptCode(aWhole, nChrCode, nOutptIdx);
        }

        break conversionSwitch;

      case 4:

      /* DOMString to ASCII or BinaryString or other unknown encodings */

        aWhole = new fTAView(nOutptLen);

        /* transcription... */

        for (var nIdx = 0; nIdx < nOutptLen; nIdx++) {
          aWhole[nIdx] = vSource.charCodeAt(nIdx) & 0xff;
        }

        break conversionSwitch;

      case 5:

      /* DOMString to UTF-8 or to UTF-16 */

        /* mapping... */

        nOutptLen = 0;

        for (var nMapIdx = 0; nMapIdx < nInptLen; nMapIdx++) {
          if (nMapIdx === nCharStart) { nStartIdx = nOutptLen; }
          nOutptLen += fGetOutptChrSize(vSource.charCodeAt(nMapIdx));
          if (nMapIdx === nCharEnd) { nEndIdx = nOutptLen; }
        }

        aWhole = new fTAView(nOutptLen);

        /* transcription... */

        for (var nOutptIdx = 0, nChrIdx = 0; nOutptIdx < nOutptLen; nChrIdx++) {
          nOutptIdx = fPutOutptCode(aWhole, vSource.charCodeAt(nChrIdx), nOutptIdx);
        }

        break conversionSwitch;

      case 6:

      /* DOMString to UTF-32 */

        aWhole = new fTAView(nOutptLen);

        /* transcription... */

        for (var nIdx = 0; nIdx < nOutptLen; nIdx++) {
          aWhole[nIdx] = vSource.charCodeAt(nIdx);
        }

        break conversionSwitch;

      case 7:

        aWhole = new fTAView(nOutptLen ? vSource : 0);
        break conversionSwitch;

    }

    aRaw = nTranscrType > 3 && (nStartIdx > 0 || nEndIdx < aWhole.length - 1) ? aWhole.subarray(nStartIdx, nEndIdx) : aWhole;

  }

  this.buffer = aWhole.buffer;
  this.bufferView = aWhole;
  this.rawData = aRaw;

  Object.freeze(this);

}

/* CONSTRUCTOR METHODS */

StringView.loadUTF8CharCode = function (aChars, nIdx) {

  var nLen = aChars.length, nPart = aChars[nIdx];

  return nPart > 251 && nPart < 254 && nIdx + 5 < nLen ?
      /* (nPart - 252 << 32) is not possible in ECMAScript! So...: */
      /* six bytes */ (nPart - 252) * 1073741824 + (aChars[nIdx + 1] - 128 << 24) + (aChars[nIdx + 2] - 128 << 18) + (aChars[nIdx + 3] - 128 << 12) + (aChars[nIdx + 4] - 128 << 6) + aChars[nIdx + 5] - 128
    : nPart > 247 && nPart < 252 && nIdx + 4 < nLen ?
      /* five bytes */ (nPart - 248 << 24) + (aChars[nIdx + 1] - 128 << 18) + (aChars[nIdx + 2] - 128 << 12) + (aChars[nIdx + 3] - 128 << 6) + aChars[nIdx + 4] - 128
    : nPart > 239 && nPart < 248 && nIdx + 3 < nLen ?
      /* four bytes */(nPart - 240 << 18) + (aChars[nIdx + 1] - 128 << 12) + (aChars[nIdx + 2] - 128 << 6) + aChars[nIdx + 3] - 128
    : nPart > 223 && nPart < 240 && nIdx + 2 < nLen ?
      /* three bytes */ (nPart - 224 << 12) + (aChars[nIdx + 1] - 128 << 6) + aChars[nIdx + 2] - 128
    : nPart > 191 && nPart < 224 && nIdx + 1 < nLen ?
      /* two bytes */ (nPart - 192 << 6) + aChars[nIdx + 1] - 128
    :
      /* one byte */ nPart;

};

StringView.putUTF8CharCode = function (aTarget, nChar, nPutAt) {

  var nIdx = nPutAt;

  if (nChar < 0x80 /* 128 */) {
    /* one byte */
    aTarget[nIdx++] = nChar;
  } else if (nChar < 0x800 /* 2048 */) {
    /* two bytes */
    aTarget[nIdx++] = 0xc0 /* 192 */ + (nChar >>> 6);
    aTarget[nIdx++] = 0x80 /* 128 */ + (nChar & 0x3f /* 63 */);
  } else if (nChar < 0x10000 /* 65536 */) {
    /* three bytes */
    aTarget[nIdx++] = 0xe0 /* 224 */ + (nChar >>> 12);
    aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar >>> 6) & 0x3f /* 63 */);
    aTarget[nIdx++] = 0x80 /* 128 */ + (nChar & 0x3f /* 63 */);
  } else if (nChar < 0x200000 /* 2097152 */) {
    /* four bytes */
    aTarget[nIdx++] = 0xf0 /* 240 */ + (nChar >>> 18);
    aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar >>> 12) & 0x3f /* 63 */);
    aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar >>> 6) & 0x3f /* 63 */);
    aTarget[nIdx++] = 0x80 /* 128 */ + (nChar & 0x3f /* 63 */);
  } else if (nChar < 0x4000000 /* 67108864 */) {
    /* five bytes */
    aTarget[nIdx++] = 0xf8 /* 248 */ + (nChar >>> 24);
    aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar >>> 18) & 0x3f /* 63 */);
    aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar >>> 12) & 0x3f /* 63 */);
    aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar >>> 6) & 0x3f /* 63 */);
    aTarget[nIdx++] = 0x80 /* 128 */ + (nChar & 0x3f /* 63 */);
  } else /* if (nChar <= 0x7fffffff) */ { /* 2147483647 */
    /* six bytes */
    aTarget[nIdx++] = 0xfc /* 252 */ + /* (nChar >>> 32) is not possible in ECMAScript! So...: */ (nChar / 1073741824);
    aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar >>> 24) & 0x3f /* 63 */);
    aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar >>> 18) & 0x3f /* 63 */);
    aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar >>> 12) & 0x3f /* 63 */);
    aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar >>> 6) & 0x3f /* 63 */);
    aTarget[nIdx++] = 0x80 /* 128 */ + (nChar & 0x3f /* 63 */);
  }

  return nIdx;

};

StringView.getUTF8CharLength = function (nChar) {
  return nChar < 0x80 ? 1 : nChar < 0x800 ? 2 : nChar < 0x10000 ? 3 : nChar < 0x200000 ? 4 : nChar < 0x4000000 ? 5 : 6;
};

StringView.loadUTF16CharCode = function (aChars, nIdx) {

  /* UTF-16 to DOMString decoding algorithm */
  var nFrstChr = aChars[nIdx];

  return nFrstChr > 0xD7BF /* 55231 */ && nIdx + 1 < aChars.length ?
    (nFrstChr - 0xD800 /* 55296 */ << 10) + aChars[nIdx + 1] + 0x2400 /* 9216 */
    : nFrstChr;

};

StringView.putUTF16CharCode = function (aTarget, nChar, nPutAt) {

  var nIdx = nPutAt;

  if (nChar < 0x10000 /* 65536 */) {
    /* one double-byte */
    aTarget[nIdx++] = nChar;
  } else {
    /* two double-bytes */
    aTarget[nIdx++] = 0xD7C0 /* 55232 */ + (nChar >> 10);
    aTarget[nIdx++] = 0xDC00 /* 56320 */ + (nChar & 0x3FF /* 1023 */);
  }

  return nIdx;

};

StringView.getUTF16CharLength = function (nChar) {
  return nChar < 0x10000 ? 1 : 2;
};

/* Array of bytes to base64 string decoding */

StringView.b64ToUint6 = function (nChr) {

  return nChr > 64 && nChr < 91 ?
      nChr - 65
    : nChr > 96 && nChr < 123 ?
      nChr - 71
    : nChr > 47 && nChr < 58 ?
      nChr + 4
    : nChr === 43 ?
      62
    : nChr === 47 ?
      63
    :
      0;

};

StringView.uint6ToB64 = function (nUint6) {

  return nUint6 < 26 ?
      nUint6 + 65
    : nUint6 < 52 ?
      nUint6 + 71
    : nUint6 < 62 ?
      nUint6 - 4
    : nUint6 === 62 ?
      43
    : nUint6 === 63 ?
      47
    :
      65;

};

/* Base64 string to array encoding */

StringView.bytesToBase64 = function (taBytes) {

  var sB64Enc = "";

  for (var nMod3, nLen = taBytes.length, nUint24 = 0, nIdx = 0; nIdx < nLen; nIdx++) {
    nMod3 = nIdx % 3;
    if (nIdx > 0 && (nIdx * 4 / 3) % 76 === 0) { sB64Enc += "\r\n"; }
    nUint24 |= taBytes[nIdx] << (16 >>> nMod3 & 24);
    if (nMod3 === 2 || taBytes.length - nIdx === 1) {
      sB64Enc += String.fromCharCode(StringView.uint6ToB64(nUint24 >>> 18 & 63), StringView.uint6ToB64(nUint24 >>> 12 & 63), StringView.uint6ToB64(nUint24 >>> 6 & 63), StringView.uint6ToB64(nUint24 & 63));
      nUint24 = 0;
    }
  }

  return sB64Enc.replace(/A(?=A$|$)/g, "=");

};


StringView.base64ToBytes = function (sBase64, nBlockBytes) {

  var
    sB64Enc = sBase64.replace(/[^A-Za-z0-9\+\/]/g, ""), nInLen = sB64Enc.length,
    nOutLen = nBlockBytes ? Math.ceil((nInLen * 3 + 1 >> 2) / nBlockBytes) * nBlockBytes : nInLen * 3 + 1 >> 2, taBytes = new Uint8Array(nOutLen);

  for (var nMod3, nMod4, nUint24 = 0, nOutIdx = 0, nInIdx = 0; nInIdx < nInLen; nInIdx++) {
    nMod4 = nInIdx & 3;
    nUint24 |= StringView.b64ToUint6(sB64Enc.charCodeAt(nInIdx)) << 18 - 6 * nMod4;
    if (nMod4 === 3 || nInLen - nInIdx === 1) {
      for (nMod3 = 0; nMod3 < 3 && nOutIdx < nOutLen; nMod3++, nOutIdx++) {
        taBytes[nOutIdx] = nUint24 >>> (16 >>> nMod3 & 24) & 255;
      }
      nUint24 = 0;

    }
  }

  return taBytes;

};

StringView.makeFromBase64 = function (sB64Inpt, sEncoding, nByteOffset, nLength) {

  var oInput, sEncType = sEncoding || StringView.prototype.encoding;

  switch (sEncType.toString()) {
    case "UTF-16":
      oInput = StringView.base64ToBytes(sB64Inpt, 2).buffer;
      break;
    case "UTF-32":
      oInput = StringView.base64ToBytes(sB64Inpt, 4).buffer;
      break;
    default:
      oInput = StringView.base64ToBytes(sB64Inpt);
  }

  return new StringView(oInput, sEncType, nByteOffset, nLength);

};

/* DEFAULT VALUES */

StringView.prototype.encoding = "UTF-8"; /* Default encoding... */

/* INSTANCES METHODS */

StringView.prototype.makeIndex = function (nEndOffsetChr, nSkipOffsetIdx) {

  var

    taTarget = this.rawData, nChrEnd, nIdxEnd = 0, nRawLength = taTarget.length,
    nStartIdx = nSkipOffsetIdx || 0, nStopAtChr = isNaN(nEndOffsetChr) ? Infinity : nEndOffsetChr;

  if (nEndOffsetChr + 1 > taTarget.length) { throw new RangeError("StringView.prototype.makeIndex - The offset can\'t be major than the length of the array - 1."); }

  switch (this.encoding) {

    case "UTF-8":

      var nPart;

      for (nChrEnd = nStartIdx; nIdxEnd < nRawLength && nChrEnd < nStopAtChr; nChrEnd++) {
        nPart = taTarget[nIdxEnd];
        nIdxEnd += nPart > 251 && nPart < 254 && nIdxEnd + 5 < nRawLength ? 6
          : nPart > 247 && nPart < 252 && nIdxEnd + 4 < nRawLength ? 5
          : nPart > 239 && nPart < 248 && nIdxEnd + 3 < nRawLength ? 4
          : nPart > 223 && nPart < 240 && nIdxEnd + 2 < nRawLength ? 3
          : nPart > 191 && nPart < 224 && nIdxEnd + 1 < nRawLength ? 2
          : 1;
      }

      break;

    case "UTF-16":

      for (nChrEnd = nStartIdx; nIdxEnd < nRawLength && nChrEnd < nStopAtChr; nChrEnd++) {
        nIdxEnd += taTarget[nIdxEnd] > 0xD7BF /* 55231 */ && nIdxEnd + 1 < taTarget.length ? 2 : 1;
      }

      break;

    default:

      nIdxEnd = nChrEnd = isFinite(nEndOffsetChr) ? nEndOffsetChr : nRawLength - 1;

  }

  if (nEndOffsetChr) { return nIdxEnd; }

  return nChrEnd;

};

StringView.prototype.toBase64 = function (bWholeBuffer) {

  return bWholeBuffer ?
    StringView.bytesToBase64(
      this.rawData.constructor === Uint8Array ?
        this.bufferView
      :
        new Uint8Array(this.buffer)
    )
  :
    StringView.bytesToBase64(
      this.rawData.constructor === Uint8Array ?
        this.rawData
      :
        new Uint8Array(
          this.buffer,
          this.rawData.byteOffset,
          this.rawData.constructor === Uint16Array ?
            this.rawData.length << 1
          :
            this.rawData.length << 2
        )
    );

};

StringView.prototype.subview = function (nCharOffset /* optional */, nCharLength /* optional */) {

  var

    nRawLen, nCharStart, nCharStop, bVariableLen = this.encoding === "UTF-8" || this.encoding === "UTF-16",
    nByteOffset = nCharOffset, taSuperset = this.rawData, nStringLength, nTableLen = taSuperset.length;

  if (nTableLen === 0) {
    return new StringView(this.buffer, this.encoding);
  }

  nStringLength = bVariableLen ? this.makeIndex() : nTableLen;
  nCharStart = nCharOffset ? Math.max((nStringLength + nCharOffset) % nStringLength, 0) : 0;
  nCharStop = Number.isInteger(nCharLength) ? Math.min(Math.max(nCharLength, 0) + nCharStart, nStringLength) : nStringLength;

  if (nCharStart === 0 && nCharStop === nStringLength) {
    return this;
  }

  if (bVariableLen) {
    nByteOffset = this.makeIndex(nCharStart);
    nRawLen = this.makeIndex(nCharStop, nByteOffset);
  } else {
    nByteOffset = nCharStart;
    nRawLen = nCharStop - nCharStart;
  }

  if (this.encoding === "UTF-16") {
    nByteOffset <<= 1;
  } else if (this.encoding === "UTF-32") {
    nByteOffset <<= 2;
  }

  return new StringView(this.buffer, this.encoding, nByteOffset, nRawLen);

};

StringView.prototype.forEachChar = function (fCallback, oThat, nChrOffset, nChrLen) {

  var aSource = this.rawData, nRawLen, nRawIdx;

  if (this.encoding === "UTF-8" || this.encoding === "UTF-16") {

    var fGetInptChrSize, fGetInptChrCode;

    if (this.encoding === "UTF-8") {
      fGetInptChrSize = StringView.getUTF8CharLength;
      fGetInptChrCode = StringView.loadUTF8CharCode;
    } else if (this.encoding === "UTF-16") {
      fGetInptChrSize = StringView.getUTF16CharLength;
      fGetInptChrCode = StringView.loadUTF16CharCode;
    }

    nRawIdx = isFinite(nChrOffset) ? this.makeIndex(nChrOffset) : 0;
    nRawLen = isFinite(nChrLen) ? this.makeIndex(nChrOffset + nChrLen, nRawIdx) : aSource.length;

    for (var nChrCode, nChrIdx = 0; nRawIdx < nRawLen; nChrIdx++) {
      nChrCode = fGetInptChrCode(aSource, nRawIdx);
      fCallback.call(oThat || null, nChrCode, nChrIdx, nRawIdx, aSource);
      nRawIdx += fGetInptChrSize(nChrCode);
    }

  } else {

    nRawIdx = isFinite(nChrOffset) ? nChrOffset : 0;
    nRawLen = isFinite(nChrLen) ? nChrLen + nRawIdx : aSource.length;

    for (nRawIdx; nRawIdx < nRawLen; nRawIdx++) {
      fCallback.call(oThat || null, aSource[nRawIdx], nRawIdx, nRawIdx, aSource);
    }

  }

};

StringView.prototype.valueOf = StringView.prototype.toString = function () {

  var taTable = this.rawData;

  if (this.encoding !== "UTF-8" && this.encoding !== "UTF-16") {
    /* ASCII, UTF-32 or BinaryString to DOMString */
    return String.fromCharCode.apply(null, taTable);
  }

  var fGetCode, fGetIncr, sView = "";

  if (this.encoding === "UTF-8") {
    fGetIncr = StringView.getUTF8CharLength;
    fGetCode = StringView.loadUTF8CharCode;
  } else if (this.encoding === "UTF-16") {
    fGetIncr = StringView.getUTF16CharLength;
    fGetCode = StringView.loadUTF16CharCode;
  }

  for (var nChr, nLen = taTable.length, nIdx = 0; nIdx < nLen; nIdx += fGetIncr(nChr)) {
    nChr = fGetCode(taTable, nIdx);
    sView += String.fromCharCode(nChr);
  }

  return sView;

};

Manual

Methods overview

Constructor
stringView new StringView(stringView input[, DOMString encoding[, unsigned int startOffset[, unsigned int length]]]);
stringView new StringView(DOMString input[, DOMString encoding[, unsigned int startOffset[, unsigned int length]]]);
stringView new StringView(unsigned int input[, DOMString encoding[, unsigned int startOffset[, unsigned int length]]]);
stringView new StringView(arrayBuffer input[, DOMString encoding[, unsigned int startOffset[, unsigned int length]]]);
stringView new StringView(arrayBufferView input[, DOMString encoding[, unsigned int startOffset[, unsigned int length]]]);
stringView new StringView(array input[, DOMString encoding[, unsigned int startOffset[, unsigned int length]]]);
Constructor's methods
stringView StringView.makeFromBase64(DOMString base64String[, DOMString encoding][, byteOffset][, length])
Other constructor's methods
DOMString StringView.bytesToBase64(uint8Array uint8Array);
uint8Array StringView.base64ToBytes(DOMString base64String[, char charSize]);
unsigned int StringView.loadUTF8CharCode(arrayBufferView typedArray, unsigned int index);
void StringView.putUTF8CharCode(arrayBufferView typedArray, unsigned int charCode, unsigned int index);
unsigned char StringView.getUTF8CharLength(unsigned int charCode);
unsigned int StringView.loadUTF16CharCode(arrayBufferView typedArray, unsigned int index);
void StringView.putUTF16CharCode(arrayBufferView typedArray, unsigned int charCode, unsigned int index);
unsigned char StringView.getUTF16CharLength(unsigned int charCode);
unsigned char StringView.b64ToUint6(unsigned char charCode);
unsigned char StringView.uint6ToB64(unsigned char uint6);
Instances' methods
unsigned int stringView.makeIndex([unsigned int endOffsetCharacter][, unsigned int skipOffsetIndex]);
DOMString stringView.toBase64([boolean wholeBuffer]);
stringView stringView.subview(unsigned int characterOffset[, unsigned int charactersLength]);
void stringView.forEachChar(function callback[, object thisObject[, unsigned int characterOffset[, unsigned int charactersLength]]]);
DOMString stringView.valueOf();
DOMString stringView.toString();

Properties overview

Attribute Type Description
encoding
{{ReadOnlyInline()}}
DOMString A string expressing the encoding type. For possible values see here.
buffer
{{ReadOnlyInline()}}
arrayBuffer The buffer to be shared between stringView.rawData and stringView.bufferView view references.
rawData
{{ReadOnlyInline()}}
arrayBufferView An arrayBufferView containing the representation of the string as array of 8-bit, 16-bit or 32-bit integers (depeding on the choosen encoding).
bufferView
{{ReadOnlyInline()}}
arrayBufferView An arrayBufferView containing the representation of the whole buffer as array of 8-bit, 16-bit or 32-bit integers (depeding on the choosen encoding).

Constructor

Syntax

new StringView(input[, encoding[, startOffset[, length]]])

Description

Create a new string-like object based upon an ArrayBuffer.

Arguments

input (required)
The argument upon which will be constructed the stringView. It can be: If it is a number it will become the length of the new stringView; elsewhere it will become its content. The following table shows the behaviour of the StringView constructor.
input class stringView.buffer stringView.rawData stringView.bufferView
StringView A new arrayBuffer will be created. Object reference to stringView.bufferView or a new arrayBufferView of stringView.buffer will be created (depending on startOffset and length arguments passed). A new arrayBufferView of stringView.buffer will be created.
DOMString A new arrayBuffer will be created. Object reference to stringView.bufferView or a new arrayBufferView of stringView.buffer will be created (depending on startOffset and length arguments passed). A new arrayBufferView of stringView.buffer will be created.
Number A new arrayBuffer will be created. Object reference to stringView.bufferView. A new arrayBufferView of stringView.buffer will be created.
ArrayBuffer Object reference to input.buffer. Object reference to stringView.bufferView or a new arrayBufferView of stringView.buffer will be created (depending on startOffset and length arguments passed). A new arrayBufferView of stringView.buffer will be created.
ArrayBufferView Object reference to input.buffer. Object reference to input or a new arrayBufferView of the buffer input.buffer (depending on many factors regarding the position of the focused parts). Object reference to input or a new arrayBufferView of the buffer input.buffer (depending on many factors regarding the position of the focused parts).
other ordered object (like Array, collections, etc.) A new arrayBuffer will be created. Object reference to stringView.bufferView or a new arrayBufferView of stringView.buffer will be created (depending on startOffset and length arguments passed). A new arrayBufferView of stringView.buffer will be created.
encoding (optional)
A string expressing the encoding type. Possible values are:
  • UTF-8 (default)
  • UTF-16
  • UTF-32
  • Another custom string. In this case it will threated as ASCII ISO/IEC 8859-15 during conversion to and/or from string. However it is usable also for binary strings.
If not specified (or specified as null) it will considered as UTF-8.
startOffset (optional)
A number expressing:
  • The start offset of the new stringView in bytes if the input argument is an arrayBuffer.
  • The start offset of the new stringView as index if the input argument is a typed array or other ordered object,
  • The start offset of the new stringView in characters if the input argument is a stringView or a string.
If not specified (or specified as null) it will become 0.
length (optional)

A number expressing the length in characters of the new stringView. If not specified it will taken the length of the input.

Examples

var myStringView1 = new StringView("Hello world!"); // UTF-8

alert(myStringView) // "Hello world!"

var myStringView2 = new StringView(myStringView1, "UTF-16");

alert(myStringView1.buffer.byteLength); // 12
alert(myStringView2.buffer.byteLength); // 24

StringView constructor's methods

makeFromBase64()
Syntax
StringView.makeFromBase64(base64String[, encoding][, byteOffset][, length])
Description
Returns a new instance of StringView constructed decoding a given base64-encoded string.
Arguments
base64String (required)
A base64-encoded string which will be decoded and copied into the new stringView object.
encoding (optional)
A string expressing the encoding type. For possible values see here.
byteOffset (optional)
A number expressing the start offset in bytes of the new stringView. If not specified (or specified as null) it will considered as 0.
length (optional)
A number expressing the length in characters of the new stringView. If not specified it will taken the length of the input.
Examples
var myStringView = StringView.makeFromBase64("SGVsbG8gd29ybGQh");
alert(myStringView) // "Hello world!"

This function is useful in order to pass binary data containing strings. See also this example.

StringView instances' properties

encoding
A string expressing the encoding type. For possible values see here.
buffer

The buffer to be shared between stringView.rawData and stringView.bufferView view references.

rawData

An arrayBufferView containing the representation of the string as array of 8-bit, 16-bit or 32-bit integers (depeding on the choosen encoding).

bufferView

An arrayBufferView containing the representation of the whole buffer as array of 8-bit, 16-bit or 32-bit integers (depeding on the choosen encoding).

StringView instances' methods

makeIndex()
Syntax
stringView.makeIndex([endOffsetCharacter][, skipOffsetIndex])
Description
If the endOffsetCharacter argument is a number it will be token as character position and makeIndex() will return the real index of that position. If the endOffsetCharacter argument is omitted, makeIndex() will return the length in characters (ASCII or UTF-encoded) of the stringView object.
Arguments
endOffsetCharacter (optional)
A number expressing the position in characters of the index of stringView.rawData to be returned.
skipOffsetIndex (optional)
A number expressing the position as index of the characters parts to skip.
Examples
var myStringView = new StringView("\u6432\u6432\u6432\u6432");
alert(myStringView.makeIndex()) // 4
alert(myStringView.makeIndex(2)) // 6

stringView.makeIndex() is a powerful method. Here is a typical use of stringView.makeIndex() within a cycle:

var myStringView = new StringView("䍧

Revision Source

<p>{{draft}}</p>
<p>The aims of this library are:</p>
<ul>
  <li>creating a <strong><a href="http://en.wikipedia.org/wiki/C_%28programming_language%29">C</a>-like interface for strings</strong> (i.e. array of characters codes — an<a href="/en-US/docs/Web/JavaScript/Typed_arrays/ArrayBufferView"> <code>ArrayBufferView</code></a> in JavaScript) based upon the JavaScript <a href="/en-US/docs/Web/JavaScript/Typed_arrays/ArrayBuffer"><code>ArrayBuffer</code></a> interface,</li>
  <li>creating an <strong>highly scalable</strong> library, that anyone can extend by adding methods to the object <code>StringView.prototype</code>,</li>
  <li>creating a collection of methods for such string-like objects (since now: <code>stringView</code>s) which <strong>work strictly on arrays of numbers</strong> rather than on creating new immutable JavaScript strings,</li>
  <li><strong>working with other Unicode encodings</strong> different from default JavaScript's UTF-16 {{domxref("DOMString")}}s,</li>
</ul>
<h2 id="Introduction">Introduction</h2>
<p>As web applications become more and more powerful, adding features such as audio and video manipulation, access to raw data using WebSockets, and so forth, it has become clear that there are times when it would be helpful for JavaScript code to be able to quickly and easily manipulate raw binary data. In the past, this had to be simulated by treating the raw data as a <a href="https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/String" title="JavaScript/Reference/Global Objects/String">string</a> and using the <a href="https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/String/charCodeAt" title="JavaScript/Reference/Global Objects/String/charCodeAt"><code>charCodeAt()</code></a> method to read the bytes from the data buffer.</p>
<p>However, this is slow and error-prone, due to the need for multiple conversions (especially if the binary data is not actually byte-format data, but, for example, 32-bit integers or floats).</p>
<p><a href="/en-US/docs/Web/JavaScript/Typed_arrays" title="/en-US/docs/Web/JavaScript/Typed_arrays">JavaScript typed arrays</a> provide a mechanism for accessing raw binary data much more efficiently. The <code>StringView</code> constructor is one level above typed arrays.</p>
<h2 id="The_code">The code</h2>
<p><strong>stringview.js</strong></p>
<div style="height: 400px; margin-bottom: 12px; overflow: auto;">
  <pre class="brush: js">
"use strict";

/*\
|*|
|*|&nbsp; :: Number.isInteger() polyfill ::
|*|
|*|&nbsp; https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger
|*|
\*/

if (!Number.isInteger) {
&nbsp; Number.isInteger = function isInteger (nVal) {
&nbsp;&nbsp;&nbsp; return typeof nVal === "number" &amp;&amp; isFinite(nVal) &amp;&amp; nVal &gt; -9007199254740992 &amp;&amp; nVal &lt; 9007199254740992 &amp;&amp; Math.floor(nVal) === nVal;
&nbsp; };
}


/*\
|*|
|*|&nbsp; StringView - Mozilla Developer Network - revision #2
|*|
|*|&nbsp; https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays/StringView
|*|&nbsp; https://developer.mozilla.org/User:fusionchess
|*|
|*|&nbsp; This framework is released under the GNU Public License, version 3 or later.
|*|&nbsp; http://www.gnu.org/licenses/gpl-3.0-standalone.html
|*|
\*/

function StringView (vInput, sEncoding /* optional (default: UTF-8) */, nOffset /* optional */, nLength /* optional */) {

&nbsp; var fTAView, aWhole, aRaw, fPutOutptCode, fGetOutptChrSize, nInptLen, nStartIdx = isFinite(nOffset) ? nOffset : 0, nTranscrType = 15;

&nbsp; if (sEncoding) { this.encoding = sEncoding.toString(); }

&nbsp; encSwitch: switch (this.encoding) {
&nbsp;&nbsp;&nbsp; case "UTF-8":
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fPutOutptCode = StringView.putUTF8CharCode;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fGetOutptChrSize = StringView.getUTF8CharLength;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fTAView = Uint8Array;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break encSwitch;
&nbsp;&nbsp;&nbsp; case "UTF-16":
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fPutOutptCode = StringView.putUTF16CharCode;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fGetOutptChrSize = StringView.getUTF16CharLength;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fTAView = Uint16Array;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break encSwitch;
&nbsp;&nbsp;&nbsp; case "UTF-32":
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fTAView = Uint32Array;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nTranscrType &amp;= 14;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break encSwitch;
&nbsp;&nbsp;&nbsp; default:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* case "ASCII", or case "BinaryString" or unknown cases */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fTAView = Uint8Array;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nTranscrType &amp;= 14;
&nbsp; }

&nbsp; typeSwitch: switch (typeof vInput) {
&nbsp;&nbsp;&nbsp; case "string":
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* the input argument is a primitive string: a new buffer will be created. */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nTranscrType &amp;= 7;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break typeSwitch;
&nbsp;&nbsp;&nbsp; case "object":
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; classSwitch: switch (vInput.constructor) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case StringView:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* the input argument is a stringView: a new buffer will be created. */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nTranscrType &amp;= 3;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break typeSwitch;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case String:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* the input argument is an objectified string: a new buffer will be created. */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nTranscrType &amp;= 7;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break typeSwitch;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case ArrayBuffer:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* the input argument is an arrayBuffer: the buffer will be shared. */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; aWhole = new fTAView(vInput);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nInptLen = this.encoding === "UTF-32" ?
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; vInput.byteLength &gt;&gt;&gt; 2
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : this.encoding === "UTF-16" ?
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; vInput.byteLength &gt;&gt;&gt; 1
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; vInput.byteLength;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; aRaw = nStartIdx === 0 &amp;&amp; (!isFinite(nLength) || nLength === nInptLen) ?
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; aWhole
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : new fTAView(vInput, nStartIdx, !isFinite(nLength) ? nInptLen - nStartIdx : nLength);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break typeSwitch;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case Uint32Array:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case Uint16Array:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case Uint8Array:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* the input argument is a typedArray: the buffer, and possibly the array itself, will be shared. */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fTAView = vInput.constructor;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nInptLen = vInput.length;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; aWhole = vInput.byteOffset === 0 &amp;&amp; vInput.length === (
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fTAView === Uint32Array ?
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; vInput.buffer.byteLength &gt;&gt;&gt; 2
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : fTAView === Uint16Array ?
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; vInput.buffer.byteLength &gt;&gt;&gt; 1
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; vInput.buffer.byteLength
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ) ? vInput : new fTAView(vInput.buffer);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; aRaw = nStartIdx === 0 &amp;&amp; (!isFinite(nLength) || nLength === nInptLen) ?
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; vInput
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : vInput.subarray(nStartIdx, isFinite(nLength) ? nStartIdx + nLength : nInptLen);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break typeSwitch;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; default:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* the input argument is an array or another serializable object: a new typedArray will be created. */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; aWhole = new fTAView(vInput);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nInptLen = aWhole.length;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; aRaw = nStartIdx === 0 &amp;&amp; (!isFinite(nLength) || nLength === nInptLen) ?
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; aWhole
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : aWhole.subarray(nStartIdx, isFinite(nLength) ? nStartIdx + nLength : nInptLen);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break typeSwitch;
&nbsp;&nbsp;&nbsp; default:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* the input argument is a number, a boolean or a function: a new typedArray will be created. */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; aWhole = aRaw = new fTAView(Number(vInput) || 0);

&nbsp; }

&nbsp; if (nTranscrType &lt; 8) {

&nbsp;&nbsp;&nbsp; var vSource, nOutptLen, nCharStart, nCharEnd, nEndIdx, fGetInptChrSize, fGetInptChrCode;


&nbsp;&nbsp;&nbsp; if (nTranscrType &amp; 4) { /* input is string */

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; vSource = vInput;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nOutptLen = nInptLen = vSource.length;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nTranscrType ^= this.encoding === "UTF-32" ? 0 : 2;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* ...or...: nTranscrType ^= Number(this.encoding !== "UTF-32") &lt;&lt; 1; */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nStartIdx = nCharStart = nOffset ? Math.max((nOutptLen + nOffset) % nOutptLen, 0) : 0;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nEndIdx = nCharEnd = (Number.isInteger(nLength) ? Math.min(Math.max(nLength, 0) + nStartIdx, nOutptLen) : nOutptLen) - 1;

&nbsp;&nbsp;&nbsp; } else { /* input is stringView */

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; vSource = vInput.rawData;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nInptLen = vInput.makeIndex();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nStartIdx = nCharStart = nOffset ? Math.max((nInptLen + nOffset) % nInptLen, 0) : 0;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nOutptLen = Number.isInteger(nLength) ? Math.min(Math.max(nLength, 0), nInptLen - nCharStart) : nInptLen;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nEndIdx = nCharEnd = nOutptLen + nCharStart;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (vInput.encoding === "UTF-8") {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fGetInptChrSize = StringView.getUTF8CharLength;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fGetInptChrCode = StringView.loadUTF8CharCode;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else if (vInput.encoding === "UTF-16") {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fGetInptChrSize = StringView.getUTF16CharLength;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fGetInptChrCode = StringView.loadUTF16CharCode;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nTranscrType &amp;= 1;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp; if (nOutptLen === 0 || nTranscrType &lt; 4 &amp;&amp; vSource.encoding === this.encoding &amp;&amp; nCharStart === 0 &amp;&amp; nOutptLen === nInptLen) {

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* the encoding is the same, the length too and the offset is 0... or the input is empty! */

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nTranscrType = 7;

&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp; conversionSwitch: switch (nTranscrType) {

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 0:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* both the source and the new StringView have a fixed-length encoding... */

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; aWhole = new fTAView(nOutptLen);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (var nOutptIdx = 0; nOutptIdx &lt; nOutptLen; aWhole[nOutptIdx] = vSource[nStartIdx + nOutptIdx++]);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break conversionSwitch;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 1:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* the source has a fixed-length encoding but the new StringView has a variable-length encoding... */

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* mapping... */

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nOutptLen = 0;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (var nInptIdx = nStartIdx; nInptIdx &lt; nEndIdx; nInptIdx++) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nOutptLen += fGetOutptChrSize(vSource[nInptIdx]);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; aWhole = new fTAView(nOutptLen);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* transcription of the source... */

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (var nInptIdx = nStartIdx, nOutptIdx = 0; nOutptIdx &lt; nOutptLen; nInptIdx++) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nOutptIdx = fPutOutptCode(aWhole, vSource[nInptIdx], nOutptIdx);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break conversionSwitch;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 2:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* the source has a variable-length encoding but the new StringView has a fixed-length encoding... */

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* mapping... */

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nStartIdx = 0;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var nChrCode;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (nChrIdx = 0; nChrIdx &lt; nCharStart; nChrIdx++) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nChrCode = fGetInptChrCode(vSource, nStartIdx);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nStartIdx += fGetInptChrSize(nChrCode);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; aWhole = new fTAView(nOutptLen);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* transcription of the source... */

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (var nInptIdx = nStartIdx, nOutptIdx = 0; nOutptIdx &lt; nOutptLen; nInptIdx += fGetInptChrSize(nChrCode), nOutptIdx++) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nChrCode = fGetInptChrCode(vSource, nInptIdx);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; aWhole[nOutptIdx] = nChrCode;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break conversionSwitch;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 3:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* both the source and the new StringView have a variable-length encoding... */

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* mapping... */

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nOutptLen = 0;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var nChrCode;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (var nChrIdx = 0, nInptIdx = 0; nChrIdx &lt; nCharEnd; nInptIdx += fGetInptChrSize(nChrCode)) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nChrCode = fGetInptChrCode(vSource, nInptIdx);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (nChrIdx === nCharStart) { nStartIdx = nInptIdx; }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (++nChrIdx &gt; nCharStart) { nOutptLen += fGetOutptChrSize(nChrCode); }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; aWhole = new fTAView(nOutptLen);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* transcription... */

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (var nInptIdx = nStartIdx, nOutptIdx = 0; nOutptIdx &lt; nOutptLen; nInptIdx += fGetInptChrSize(nChrCode)) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nChrCode = fGetInptChrCode(vSource, nInptIdx);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nOutptIdx = fPutOutptCode(aWhole, nChrCode, nOutptIdx);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break conversionSwitch;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 4:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* DOMString to ASCII or BinaryString or other unknown encodings */

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; aWhole = new fTAView(nOutptLen);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* transcription... */

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (var nIdx = 0; nIdx &lt; nOutptLen; nIdx++) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; aWhole[nIdx] = vSource.charCodeAt(nIdx) &amp; 0xff;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break conversionSwitch;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 5:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* DOMString to UTF-8 or to UTF-16 */

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* mapping... */

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nOutptLen = 0;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (var nMapIdx = 0; nMapIdx &lt; nInptLen; nMapIdx++) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (nMapIdx === nCharStart) { nStartIdx = nOutptLen; }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nOutptLen += fGetOutptChrSize(vSource.charCodeAt(nMapIdx));
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (nMapIdx === nCharEnd) { nEndIdx = nOutptLen; }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; aWhole = new fTAView(nOutptLen);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* transcription... */

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (var nOutptIdx = 0, nChrIdx = 0; nOutptIdx &lt; nOutptLen; nChrIdx++) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nOutptIdx = fPutOutptCode(aWhole, vSource.charCodeAt(nChrIdx), nOutptIdx);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break conversionSwitch;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 6:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* DOMString to UTF-32 */

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; aWhole = new fTAView(nOutptLen);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* transcription... */

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (var nIdx = 0; nIdx &lt; nOutptLen; nIdx++) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; aWhole[nIdx] = vSource.charCodeAt(nIdx);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break conversionSwitch;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 7:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; aWhole = new fTAView(nOutptLen ? vSource : 0);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break conversionSwitch;

&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp; aRaw = nTranscrType &gt; 3 &amp;&amp; (nStartIdx &gt; 0 || nEndIdx &lt; aWhole.length - 1) ? aWhole.subarray(nStartIdx, nEndIdx) : aWhole;

&nbsp; }

&nbsp; this.buffer = aWhole.buffer;
&nbsp; this.bufferView = aWhole;
&nbsp; this.rawData = aRaw;

&nbsp; Object.freeze(this);

}

/* CONSTRUCTOR METHODS */

StringView.loadUTF8CharCode = function (aChars, nIdx) {

&nbsp; var nLen = aChars.length, nPart = aChars[nIdx];

&nbsp; return nPart &gt; 251 &amp;&amp; nPart &lt; 254 &amp;&amp; nIdx + 5 &lt; nLen ?
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* (nPart - 252 &lt;&lt; 32) is not possible in ECMAScript! So...: */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* six bytes */ (nPart - 252) * 1073741824 + (aChars[nIdx + 1] - 128 &lt;&lt; 24) + (aChars[nIdx + 2] - 128 &lt;&lt; 18) + (aChars[nIdx + 3] - 128 &lt;&lt; 12) + (aChars[nIdx + 4] - 128 &lt;&lt; 6) + aChars[nIdx + 5] - 128
&nbsp;&nbsp;&nbsp; : nPart &gt; 247 &amp;&amp; nPart &lt; 252 &amp;&amp; nIdx + 4 &lt; nLen ?
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* five bytes */ (nPart - 248 &lt;&lt; 24) + (aChars[nIdx + 1] - 128 &lt;&lt; 18) + (aChars[nIdx + 2] - 128 &lt;&lt; 12) + (aChars[nIdx + 3] - 128 &lt;&lt; 6) + aChars[nIdx + 4] - 128
&nbsp;&nbsp;&nbsp; : nPart &gt; 239 &amp;&amp; nPart &lt; 248 &amp;&amp; nIdx + 3 &lt; nLen ?
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* four bytes */(nPart - 240 &lt;&lt; 18) + (aChars[nIdx + 1] - 128 &lt;&lt; 12) + (aChars[nIdx + 2] - 128 &lt;&lt; 6) + aChars[nIdx + 3] - 128
&nbsp;&nbsp;&nbsp; : nPart &gt; 223 &amp;&amp; nPart &lt; 240 &amp;&amp; nIdx + 2 &lt; nLen ?
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* three bytes */ (nPart - 224 &lt;&lt; 12) + (aChars[nIdx + 1] - 128 &lt;&lt; 6) + aChars[nIdx + 2] - 128
&nbsp;&nbsp;&nbsp; : nPart &gt; 191 &amp;&amp; nPart &lt; 224 &amp;&amp; nIdx + 1 &lt; nLen ?
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* two bytes */ (nPart - 192 &lt;&lt; 6) + aChars[nIdx + 1] - 128
&nbsp;&nbsp;&nbsp; :
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* one byte */ nPart;

};

StringView.putUTF8CharCode = function (aTarget, nChar, nPutAt) {

&nbsp; var nIdx = nPutAt;

&nbsp; if (nChar &lt; 0x80 /* 128 */) {
&nbsp;&nbsp;&nbsp; /* one byte */
&nbsp;&nbsp;&nbsp; aTarget[nIdx++] = nChar;
&nbsp; } else if (nChar &lt; 0x800 /* 2048 */) {
&nbsp;&nbsp;&nbsp; /* two bytes */
&nbsp;&nbsp;&nbsp; aTarget[nIdx++] = 0xc0 /* 192 */ + (nChar &gt;&gt;&gt; 6);
&nbsp;&nbsp;&nbsp; aTarget[nIdx++] = 0x80 /* 128 */ + (nChar &amp; 0x3f /* 63 */);
&nbsp; } else if (nChar &lt; 0x10000 /* 65536 */) {
&nbsp;&nbsp;&nbsp; /* three bytes */
&nbsp;&nbsp;&nbsp; aTarget[nIdx++] = 0xe0 /* 224 */ + (nChar &gt;&gt;&gt; 12);
&nbsp;&nbsp;&nbsp; aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar &gt;&gt;&gt; 6) &amp; 0x3f /* 63 */);
&nbsp;&nbsp;&nbsp; aTarget[nIdx++] = 0x80 /* 128 */ + (nChar &amp; 0x3f /* 63 */);
&nbsp; } else if (nChar &lt; 0x200000 /* 2097152 */) {
&nbsp;&nbsp;&nbsp; /* four bytes */
&nbsp;&nbsp;&nbsp; aTarget[nIdx++] = 0xf0 /* 240 */ + (nChar &gt;&gt;&gt; 18);
&nbsp;&nbsp;&nbsp; aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar &gt;&gt;&gt; 12) &amp; 0x3f /* 63 */);
&nbsp;&nbsp;&nbsp; aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar &gt;&gt;&gt; 6) &amp; 0x3f /* 63 */);
&nbsp;&nbsp;&nbsp; aTarget[nIdx++] = 0x80 /* 128 */ + (nChar &amp; 0x3f /* 63 */);
&nbsp; } else if (nChar &lt; 0x4000000 /* 67108864 */) {
&nbsp;&nbsp;&nbsp; /* five bytes */
&nbsp;&nbsp;&nbsp; aTarget[nIdx++] = 0xf8 /* 248 */ + (nChar &gt;&gt;&gt; 24);
&nbsp;&nbsp;&nbsp; aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar &gt;&gt;&gt; 18) &amp; 0x3f /* 63 */);
&nbsp;&nbsp;&nbsp; aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar &gt;&gt;&gt; 12) &amp; 0x3f /* 63 */);
&nbsp;&nbsp;&nbsp; aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar &gt;&gt;&gt; 6) &amp; 0x3f /* 63 */);
&nbsp;&nbsp;&nbsp; aTarget[nIdx++] = 0x80 /* 128 */ + (nChar &amp; 0x3f /* 63 */);
&nbsp; } else /* if (nChar &lt;= 0x7fffffff) */ { /* 2147483647 */
&nbsp;&nbsp;&nbsp; /* six bytes */
&nbsp;&nbsp;&nbsp; aTarget[nIdx++] = 0xfc /* 252 */ + /* (nChar &gt;&gt;&gt; 32) is not possible in ECMAScript! So...: */ (nChar / 1073741824);
&nbsp;&nbsp;&nbsp; aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar &gt;&gt;&gt; 24) &amp; 0x3f /* 63 */);
&nbsp;&nbsp;&nbsp; aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar &gt;&gt;&gt; 18) &amp; 0x3f /* 63 */);
&nbsp;&nbsp;&nbsp; aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar &gt;&gt;&gt; 12) &amp; 0x3f /* 63 */);
&nbsp;&nbsp;&nbsp; aTarget[nIdx++] = 0x80 /* 128 */ + ((nChar &gt;&gt;&gt; 6) &amp; 0x3f /* 63 */);
&nbsp;&nbsp;&nbsp; aTarget[nIdx++] = 0x80 /* 128 */ + (nChar &amp; 0x3f /* 63 */);
&nbsp; }

&nbsp; return nIdx;

};

StringView.getUTF8CharLength = function (nChar) {
&nbsp; return nChar &lt; 0x80 ? 1 : nChar &lt; 0x800 ? 2 : nChar &lt; 0x10000 ? 3 : nChar &lt; 0x200000 ? 4 : nChar &lt; 0x4000000 ? 5 : 6;
};

StringView.loadUTF16CharCode = function (aChars, nIdx) {

&nbsp; /* UTF-16 to DOMString decoding algorithm */
&nbsp; var nFrstChr = aChars[nIdx];

&nbsp; return nFrstChr &gt; 0xD7BF /* 55231 */ &amp;&amp; nIdx + 1 &lt; aChars.length ?
&nbsp;&nbsp;&nbsp; (nFrstChr - 0xD800 /* 55296 */ &lt;&lt; 10) + aChars[nIdx + 1] + 0x2400 /* 9216 */
&nbsp;&nbsp;&nbsp; : nFrstChr;

};

StringView.putUTF16CharCode = function (aTarget, nChar, nPutAt) {

&nbsp; var nIdx = nPutAt;

&nbsp; if (nChar &lt; 0x10000 /* 65536 */) {
&nbsp;&nbsp;&nbsp; /* one double-byte */
&nbsp;&nbsp;&nbsp; aTarget[nIdx++] = nChar;
&nbsp; } else {
&nbsp;&nbsp;&nbsp; /* two double-bytes */
&nbsp;&nbsp;&nbsp; aTarget[nIdx++] = 0xD7C0 /* 55232 */ + (nChar &gt;&gt; 10);
&nbsp;&nbsp;&nbsp; aTarget[nIdx++] = 0xDC00 /* 56320 */ + (nChar &amp; 0x3FF /* 1023 */);
&nbsp; }

&nbsp; return nIdx;

};

StringView.getUTF16CharLength = function (nChar) {
&nbsp; return nChar &lt; 0x10000 ? 1 : 2;
};

/* Array of bytes to base64 string decoding */

StringView.b64ToUint6 = function (nChr) {

&nbsp; return nChr &gt; 64 &amp;&amp; nChr &lt; 91 ?
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nChr - 65
&nbsp;&nbsp;&nbsp; : nChr &gt; 96 &amp;&amp; nChr &lt; 123 ?
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nChr - 71
&nbsp;&nbsp;&nbsp; : nChr &gt; 47 &amp;&amp; nChr &lt; 58 ?
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nChr + 4
&nbsp;&nbsp;&nbsp; : nChr === 43 ?
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 62
&nbsp;&nbsp;&nbsp; : nChr === 47 ?
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 63
&nbsp;&nbsp;&nbsp; :
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0;

};

StringView.uint6ToB64 = function (nUint6) {

&nbsp; return nUint6 &lt; 26 ?
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nUint6 + 65
&nbsp;&nbsp;&nbsp; : nUint6 &lt; 52 ?
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nUint6 + 71
&nbsp;&nbsp;&nbsp; : nUint6 &lt; 62 ?
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nUint6 - 4
&nbsp;&nbsp;&nbsp; : nUint6 === 62 ?
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 43
&nbsp;&nbsp;&nbsp; : nUint6 === 63 ?
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 47
&nbsp;&nbsp;&nbsp; :
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 65;

};

/* Base64 string to array encoding */

StringView.bytesToBase64 = function (taBytes) {

&nbsp; var sB64Enc = "";

&nbsp; for (var nMod3, nLen = taBytes.length, nUint24 = 0, nIdx = 0; nIdx &lt; nLen; nIdx++) {
&nbsp;&nbsp;&nbsp; nMod3 = nIdx % 3;
&nbsp;&nbsp;&nbsp; if (nIdx &gt; 0 &amp;&amp; (nIdx * 4 / 3) % 76 === 0) { sB64Enc += "\r\n"; }
&nbsp;&nbsp;&nbsp; nUint24 |= taBytes[nIdx] &lt;&lt; (16 &gt;&gt;&gt; nMod3 &amp; 24);
&nbsp;&nbsp;&nbsp; if (nMod3 === 2 || taBytes.length - nIdx === 1) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sB64Enc += String.fromCharCode(StringView.uint6ToB64(nUint24 &gt;&gt;&gt; 18 &amp; 63), StringView.uint6ToB64(nUint24 &gt;&gt;&gt; 12 &amp; 63), StringView.uint6ToB64(nUint24 &gt;&gt;&gt; 6 &amp; 63), StringView.uint6ToB64(nUint24 &amp; 63));
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nUint24 = 0;
&nbsp;&nbsp;&nbsp; }
&nbsp; }

&nbsp; return sB64Enc.replace(/A(?=A$|$)/g, "=");

};


StringView.base64ToBytes = function (sBase64, nBlockBytes) {

&nbsp; var
&nbsp;&nbsp;&nbsp; sB64Enc = sBase64.replace(/[^A-Za-z0-9\+\/]/g, ""), nInLen = sB64Enc.length,
&nbsp;&nbsp;&nbsp; nOutLen = nBlockBytes ? Math.ceil((nInLen * 3 + 1 &gt;&gt; 2) / nBlockBytes) * nBlockBytes : nInLen * 3 + 1 &gt;&gt; 2, taBytes = new Uint8Array(nOutLen);

&nbsp; for (var nMod3, nMod4, nUint24 = 0, nOutIdx = 0, nInIdx = 0; nInIdx &lt; nInLen; nInIdx++) {
&nbsp;&nbsp;&nbsp; nMod4 = nInIdx &amp; 3;
&nbsp;&nbsp;&nbsp; nUint24 |= StringView.b64ToUint6(sB64Enc.charCodeAt(nInIdx)) &lt;&lt; 18 - 6 * nMod4;
&nbsp;&nbsp;&nbsp; if (nMod4 === 3 || nInLen - nInIdx === 1) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (nMod3 = 0; nMod3 &lt; 3 &amp;&amp; nOutIdx &lt; nOutLen; nMod3++, nOutIdx++) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; taBytes[nOutIdx] = nUint24 &gt;&gt;&gt; (16 &gt;&gt;&gt; nMod3 &amp; 24) &amp; 255;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nUint24 = 0;

&nbsp;&nbsp;&nbsp; }
&nbsp; }

&nbsp; return taBytes;

};

StringView.makeFromBase64 = function (sB64Inpt, sEncoding, nByteOffset, nLength) {

&nbsp; var oInput, sEncType = sEncoding || StringView.prototype.encoding;

&nbsp; switch (sEncType.toString()) {
&nbsp;&nbsp;&nbsp; case "UTF-16":
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; oInput = StringView.base64ToBytes(sB64Inpt, 2).buffer;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;
&nbsp;&nbsp;&nbsp; case "UTF-32":
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; oInput = StringView.base64ToBytes(sB64Inpt, 4).buffer;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;
&nbsp;&nbsp;&nbsp; default:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; oInput = StringView.base64ToBytes(sB64Inpt);
&nbsp; }

&nbsp; return new StringView(oInput, sEncType, nByteOffset, nLength);

};

/* DEFAULT VALUES */

StringView.prototype.encoding = "UTF-8"; /* Default encoding... */

/* INSTANCES METHODS */

StringView.prototype.makeIndex = function (nEndOffsetChr, nSkipOffsetIdx) {

&nbsp; var

&nbsp;&nbsp;&nbsp; taTarget = this.rawData, nChrEnd, nIdxEnd = 0, nRawLength = taTarget.length,
&nbsp;&nbsp;&nbsp; nStartIdx = nSkipOffsetIdx || 0, nStopAtChr = isNaN(nEndOffsetChr) ? Infinity : nEndOffsetChr;

&nbsp; if (nEndOffsetChr + 1 &gt; taTarget.length) { throw new RangeError("StringView.prototype.makeIndex - The offset can\'t be major than the length of the array - 1."); }

&nbsp; switch (this.encoding) {

&nbsp;&nbsp;&nbsp; case "UTF-8":

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var nPart;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (nChrEnd = nStartIdx; nIdxEnd &lt; nRawLength &amp;&amp; nChrEnd &lt; nStopAtChr; nChrEnd++) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nPart = taTarget[nIdxEnd];
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nIdxEnd += nPart &gt; 251 &amp;&amp; nPart &lt; 254 &amp;&amp; nIdxEnd + 5 &lt; nRawLength ? 6
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : nPart &gt; 247 &amp;&amp; nPart &lt; 252 &amp;&amp; nIdxEnd + 4 &lt; nRawLength ? 5
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : nPart &gt; 239 &amp;&amp; nPart &lt; 248 &amp;&amp; nIdxEnd + 3 &lt; nRawLength ? 4
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : nPart &gt; 223 &amp;&amp; nPart &lt; 240 &amp;&amp; nIdxEnd + 2 &lt; nRawLength ? 3
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : nPart &gt; 191 &amp;&amp; nPart &lt; 224 &amp;&amp; nIdxEnd + 1 &lt; nRawLength ? 2
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 1;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;

&nbsp;&nbsp;&nbsp; case "UTF-16":

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (nChrEnd = nStartIdx; nIdxEnd &lt; nRawLength &amp;&amp; nChrEnd &lt; nStopAtChr; nChrEnd++) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nIdxEnd += taTarget[nIdxEnd] &gt; 0xD7BF /* 55231 */ &amp;&amp; nIdxEnd + 1 &lt; taTarget.length ? 2 : 1;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;

&nbsp;&nbsp;&nbsp; default:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nIdxEnd = nChrEnd = isFinite(nEndOffsetChr) ? nEndOffsetChr : nRawLength - 1;

&nbsp; }

&nbsp; if (nEndOffsetChr) { return nIdxEnd; }

&nbsp; return nChrEnd;

};

StringView.prototype.toBase64 = function (bWholeBuffer) {

&nbsp; return bWholeBuffer ?
&nbsp;&nbsp;&nbsp; StringView.bytesToBase64(
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.rawData.constructor === Uint8Array ?
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.bufferView
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new Uint8Array(this.buffer)
&nbsp;&nbsp;&nbsp; )
&nbsp; :
&nbsp;&nbsp;&nbsp; StringView.bytesToBase64(
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.rawData.constructor === Uint8Array ?
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.rawData
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new Uint8Array(
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.buffer,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.rawData.byteOffset,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.rawData.constructor === Uint16Array ?
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.rawData.length &lt;&lt; 1
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.rawData.length &lt;&lt; 2
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; )
&nbsp;&nbsp;&nbsp; );

};

StringView.prototype.subview = function (nCharOffset /* optional */, nCharLength /* optional */) {

&nbsp; var

&nbsp;&nbsp;&nbsp; nRawLen, nCharStart, nCharStop, bVariableLen = this.encoding === "UTF-8" || this.encoding === "UTF-16",
&nbsp;&nbsp;&nbsp; nByteOffset = nCharOffset, taSuperset = this.rawData, nStringLength, nTableLen = taSuperset.length;

&nbsp; if (nTableLen === 0) {
&nbsp;&nbsp;&nbsp; return new StringView(this.buffer, this.encoding);
&nbsp; }

&nbsp; nStringLength = bVariableLen ? this.makeIndex() : nTableLen;
&nbsp; nCharStart = nCharOffset ? Math.max((nStringLength + nCharOffset) % nStringLength, 0) : 0;
&nbsp; nCharStop = Number.isInteger(nCharLength) ? Math.min(Math.max(nCharLength, 0) + nCharStart, nStringLength) : nStringLength;

&nbsp; if (nCharStart === 0 &amp;&amp; nCharStop === nStringLength) {
&nbsp;&nbsp;&nbsp; return this;
&nbsp; }

&nbsp; if (bVariableLen) {
&nbsp;&nbsp;&nbsp; nByteOffset = this.makeIndex(nCharStart);
&nbsp;&nbsp;&nbsp; nRawLen = this.makeIndex(nCharStop, nByteOffset);
&nbsp; } else {
&nbsp;&nbsp;&nbsp; nByteOffset = nCharStart;
&nbsp;&nbsp;&nbsp; nRawLen = nCharStop - nCharStart;
&nbsp; }

&nbsp; if (this.encoding === "UTF-16") {
&nbsp;&nbsp;&nbsp; nByteOffset &lt;&lt;= 1;
&nbsp; } else if (this.encoding === "UTF-32") {
&nbsp;&nbsp;&nbsp; nByteOffset &lt;&lt;= 2;
&nbsp; }

&nbsp; return new StringView(this.buffer, this.encoding, nByteOffset, nRawLen);

};

StringView.prototype.forEachChar = function (fCallback, oThat, nChrOffset, nChrLen) {

&nbsp; var aSource = this.rawData, nRawLen, nRawIdx;

&nbsp; if (this.encoding === "UTF-8" || this.encoding === "UTF-16") {

&nbsp;&nbsp;&nbsp; var fGetInptChrSize, fGetInptChrCode;

&nbsp;&nbsp;&nbsp; if (this.encoding === "UTF-8") {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fGetInptChrSize = StringView.getUTF8CharLength;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fGetInptChrCode = StringView.loadUTF8CharCode;
&nbsp;&nbsp;&nbsp; } else if (this.encoding === "UTF-16") {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fGetInptChrSize = StringView.getUTF16CharLength;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fGetInptChrCode = StringView.loadUTF16CharCode;
&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp; nRawIdx = isFinite(nChrOffset) ? this.makeIndex(nChrOffset) : 0;
&nbsp;&nbsp;&nbsp; nRawLen = isFinite(nChrLen) ? this.makeIndex(nChrOffset + nChrLen, nRawIdx) : aSource.length;

&nbsp;&nbsp;&nbsp; for (var nChrCode, nChrIdx = 0; nRawIdx &lt; nRawLen; nChrIdx++) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nChrCode = fGetInptChrCode(aSource, nRawIdx);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fCallback.call(oThat || null, nChrCode, nChrIdx, nRawIdx, aSource);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nRawIdx += fGetInptChrSize(nChrCode);
&nbsp;&nbsp;&nbsp; }

&nbsp; } else {

&nbsp;&nbsp;&nbsp; nRawIdx = isFinite(nChrOffset) ? nChrOffset : 0;
&nbsp;&nbsp;&nbsp; nRawLen = isFinite(nChrLen) ? nChrLen + nRawIdx : aSource.length;

&nbsp;&nbsp;&nbsp; for (nRawIdx; nRawIdx &lt; nRawLen; nRawIdx++) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fCallback.call(oThat || null, aSource[nRawIdx], nRawIdx, nRawIdx, aSource);
&nbsp;&nbsp;&nbsp; }

&nbsp; }

};

StringView.prototype.valueOf = StringView.prototype.toString = function () {

&nbsp; var taTable = this.rawData;

&nbsp; if (this.encoding !== "UTF-8" &amp;&amp; this.encoding !== "UTF-16") {
&nbsp;&nbsp;&nbsp; /* ASCII, UTF-32 or BinaryString to DOMString */
&nbsp;&nbsp;&nbsp; return String.fromCharCode.apply(null, taTable);
&nbsp; }

&nbsp; var fGetCode, fGetIncr, sView = "";

&nbsp; if (this.encoding === "UTF-8") {
&nbsp;&nbsp;&nbsp; fGetIncr = StringView.getUTF8CharLength;
&nbsp;&nbsp;&nbsp; fGetCode = StringView.loadUTF8CharCode;
&nbsp; } else if (this.encoding === "UTF-16") {
&nbsp;&nbsp;&nbsp; fGetIncr = StringView.getUTF16CharLength;
&nbsp;&nbsp;&nbsp; fGetCode = StringView.loadUTF16CharCode;
&nbsp; }

&nbsp; for (var nChr, nLen = taTable.length, nIdx = 0; nIdx &lt; nLen; nIdx += fGetIncr(nChr)) {
&nbsp;&nbsp;&nbsp; nChr = fGetCode(taTable, nIdx);
&nbsp;&nbsp;&nbsp; sView += String.fromCharCode(nChr);
&nbsp; }

&nbsp; return sView;

};</pre>
</div>
<h2 id="Manual">Manual</h2>
<h3 id="Methods_overview">Methods overview</h3>
<table class="standard-table">
  <tbody>
    <tr>
      <th>Constructor</th>
    </tr>
    <tr>
      <td><code>stringView new StringView(stringView input[, DOMString encoding[, unsigned int startOffset[, unsigned int length]]]);</code><br />
        <code>stringView new StringView(DOMString input[, DOMString encoding[, unsigned int startOffset[, unsigned int length]]]);</code><br />
        <code>stringView new StringView(unsigned int input[, DOMString encoding[, unsigned int startOffset[, unsigned int length]]]);</code><br />
        <code>stringView new StringView(arrayBuffer input[, DOMString encoding[, unsigned int startOffset[, unsigned int length]]]);</code><br />
        <code>stringView new StringView(arrayBufferView input[, DOMString encoding[, unsigned int startOffset[, unsigned int length]]]);</code><br />
        <code>stringView new StringView(array input[, DOMString encoding[, unsigned int startOffset[, unsigned int length]]]);</code></td>
    </tr>
    <tr>
      <th>Constructor's methods</th>
    </tr>
    <tr>
      <td><code>stringView StringView.<a href="#StringView.makeFromBase64%28%29">makeFromBase64</a>(DOMString base64String[, DOMString encoding][, byteOffset][, length])</code></td>
    </tr>
    <tr>
      <th>Other constructor's methods</th>
    </tr>
    <tr>
      <td><code>DOMString StringView.<a href="#StringView.base64ToBytes%28%29">bytesToBase64</a>(</code><code>uint8Array </code><code>uint8Array);</code></td>
    </tr>
    <tr>
      <td><code>uint8Array StringView.<a href="#StringView.base64ToBytes%28%29">base64ToBytes</a>(DOMString base64String[, char charSize]);</code></td>
    </tr>
    <tr>
      <td><code>unsigned int StringView.<a href="#StringView.loadUTF8CharCode%28%29">loadUTF8CharCode</a>(arrayBufferView typedArray, unsigned int index);</code></td>
    </tr>
    <tr>
      <td><code>void StringView.<a href="#StringView.putUTF8CharCode%28%29">putUTF8CharCode</a>(arrayBufferView typedArray, unsigned int charCode, unsigned int index);</code></td>
    </tr>
    <tr>
      <td><code>unsigned char StringView.<a href="#StringView.getUTF8CharLength%28%29">getUTF8CharLength</a>(unsigned int charCode);</code></td>
    </tr>
    <tr>
      <td><code>unsigned int StringView.<a href="#StringView.loadUTF16CharCode%28%29">loadUTF16CharCode</a>(arrayBufferView typedArray, unsigned int index);</code></td>
    </tr>
    <tr>
      <td><code>void StringView.<a href="#StringView.putUTF16CharCode%28%29">putUTF16CharCode</a>(arrayBufferView typedArray, unsigned int charCode, unsigned int index);</code></td>
    </tr>
    <tr>
      <td><code>unsigned char StringView.<a href="#StringView.getUTF16CharLength%28%29">getUTF16CharLength</a>(unsigned int charCode);</code></td>
    </tr>
    <tr>
      <td><code>unsigned char StringView.<a href="#StringView.b64ToUint6%28%29">b64ToUint6</a>(unsigned char charCode);</code></td>
    </tr>
    <tr>
      <td><code>unsigned char StringView.<a href="#StringView.uint6ToB64%28%29">uint6ToB64</a>(unsigned char uint6);</code></td>
    </tr>
    <tr>
      <th>Instances' methods</th>
    </tr>
    <tr>
      <td><code>unsigned int stringView.<a href="#StringView.prototype.makeIndex%28%29">makeIndex</a>([unsigned int endOffsetCharacter][, unsigned int skipOffsetIndex]);</code></td>
    </tr>
    <tr>
      <td><code>DOMString stringView.<a href="#StringView.prototype.toBase64%28%29">toBase64</a>([boolean wholeBuffer]);</code></td>
    </tr>
    <tr>
      <td><code>stringView stringView.<a href="#StringView.prototype.subview%28%29">subview</a>(unsigned int characterOffset[, unsigned int charactersLength]);</code></td>
    </tr>
    <tr>
      <td><code>void stringView.<a href="#StringView.prototype.forEachChar%28%29">forEachChar</a>(function callback[, object thisObject[, unsigned int characterOffset[, unsigned int charactersLength]]]);</code></td>
    </tr>
    <tr>
      <td><code>DOMString stringView.<a href="#StringView.prototype.valueOf%28%29">valueOf</a>();</code></td>
    </tr>
    <tr>
      <td><code>DOMString stringView.<a href="#StringView.prototype.toString%28%29">toString</a>();</code></td>
    </tr>
  </tbody>
</table>
<h3 id="Properties_overview">Properties overview</h3>
<table class="standard-table">
  <tbody>
    <tr>
      <th>Attribute</th>
      <th>Type</th>
      <th>Description</th>
    </tr>
    <tr>
      <td><a href="#StringView.prototype.encoding"><code>encoding</code></a><br />
        {{ReadOnlyInline()}}</td>
      <td><code>DOMString</code></td>
      <td>A <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/String">string</a> expressing the encoding type. For possible values <a href="#encoding_values">see here</a>.</td>
    </tr>
    <tr>
      <td><a href="#StringView.prototype.buffer"><code>buffer</code></a><br />
        {{ReadOnlyInline()}}</td>
      <td><code>arrayBuffer</code></td>
      <td>The buffer to be shared between <code>stringView.</code><a href="#StringView.prototype.rawData"><code>rawData</code></a> and <code>stringView.</code><a href="#StringView.prototype.bufferView"><code>bufferView</code></a> view references.</td>
    </tr>
    <tr>
      <td><a href="#StringView.prototype.rawData"><code>rawData</code></a><br />
        {{ReadOnlyInline()}}</td>
      <td><code>arrayBufferView</code></td>
      <td>An <a href="/en-US/docs/Web/JavaScript/Typed_arrays/ArrayBufferView">arrayBufferView</a> containing the representation of the string as array of 8-bit, 16-bit or 32-bit integers (depeding on the choosen encoding).</td>
    </tr>
    <tr>
      <td><a href="#StringView.prototype.bufferView"><code>bufferView</code></a><br />
        {{ReadOnlyInline()}}</td>
      <td><code>arrayBufferView</code></td>
      <td>An <a href="/en-US/docs/Web/JavaScript/Typed_arrays/ArrayBufferView">arrayBufferView</a> containing the representation of <strong>the whole buffer</strong> as array of 8-bit, 16-bit or 32-bit integers (depeding on the choosen encoding).</td>
    </tr>
  </tbody>
</table>
<h3 id="Constructor">Constructor</h3>
<h4 id="Syntax">Syntax</h4>
<pre class="syntaxbox">
new StringView(<em>input</em>[, <em>encoding</em>[, <em>startOffset</em>[, <em>length</em>]]])</pre>
<h4 id="Description">Description</h4>
<p>Create a new <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/String">string</a>-like object based upon an <a href="/en-US/docs/Web/JavaScript/Typed_arrays/ArrayBuffer"><code>ArrayBuffer</code></a>.</p>
<h4 id="Arguments">Arguments</h4>
<dl>
  <dt>
    <code>input</code> (required)</dt>
  <dd>
    The argument upon which will be constructed the <code>stringView</code>. It can be:
    <ul>
      <li>another stringView,</li>
      <li>a <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/String">string</a>,</li>
      <li>a <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number">number</a>,</li>
      <li>an <a href="/en-US/docs/Web/JavaScript/Typed_arrays/ArrayBuffer"><code>arrayBuffer</code></a>,</li>
      <li>a <a href="/en-US/docs/Web/JavaScript/Typed_arrays">typed array</a> of <a href="/en-US/docs/Web/JavaScript/Typed_arrays/Uint8Array">uint8Array</a>, <a href="/en-US/docs/Web/JavaScript/Typed_arrays/Uint16Array">uint16Array</a> or <a href="/en-US/docs/Web/JavaScript/Typed_arrays/Uint32Array">uint32Array</a> subclass,</li>
      <li>any other kind of ordered object (like <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array">arrays</a>, collections, etc.)</li>
    </ul>
    If it is a number it will become the <em>length</em> of the new <code>stringView</code>; elsewhere it will become its <em>content</em>. The following table shows the behaviour of the <code>StringView</code> constructor.<br />
    <table class="standard-table">
      <thead>
        <tr>
          <th><code>input</code> class</th>
          <th><code>stringView.buffer</code></th>
          <th><code>stringView.rawData</code></th>
          <th><code>stringView.bufferView</code></th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td><code>StringView</code></td>
          <td>A new arrayBuffer will be created.</td>
          <td>Object reference to <code>stringView.bufferView</code> or a new arrayBufferView of <code>stringView.buffer</code> will be created (depending on <code>startOffset</code> and <code>length</code> arguments passed).</td>
          <td>A new arrayBufferView of <code>stringView.buffer</code> will be created.</td>
        </tr>
        <tr>
          <td><a href="/en-US/docs/Web/API/DOMString"><code>DOMString</code></a></td>
          <td>A new arrayBuffer will be created.</td>
          <td>Object reference to <code>stringView.bufferView</code> or a new arrayBufferView of <code>stringView.buffer</code> will be created (depending on <code>startOffset</code> and <code>length</code> arguments passed).</td>
          <td>A new arrayBufferView of <code>stringView.buffer</code> will be created.</td>
        </tr>
        <tr>
          <td><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number"><code>Number</code></a></td>
          <td>A new arrayBuffer will be created.</td>
          <td>Object reference to <code>stringView.bufferView</code>.</td>
          <td>A new arrayBufferView of <code>stringView.buffer</code> will be created.</td>
        </tr>
        <tr>
          <td><a href="/en-US/docs/Web/JavaScript/Typed_arrays/ArrayBuffer"><code>ArrayBuffer</code></a></td>
          <td>Object reference to <code>input.buffer</code>.</td>
          <td>Object reference to <code>stringView.bufferView</code> or a new arrayBufferView of <code>stringView.buffer</code> will be created (depending on <code>startOffset</code> and <code>length</code> arguments passed).</td>
          <td>A new arrayBufferView of <code>stringView.buffer</code> will be created.</td>
        </tr>
        <tr>
          <td><a href="/en-US/docs/Web/JavaScript/Typed_arrays/ArrayBufferView"><code>ArrayBufferView</code></a></td>
          <td>Object reference to <code>input.buffer</code>.</td>
          <td>Object reference to <code>input</code> or a new arrayBufferView of the buffer <code>input.buffer</code> (depending on many factors regarding the position of the focused parts).</td>
          <td>Object reference to <code>input</code> or a new arrayBufferView of the buffer <code>input.buffer</code> (depending on many factors regarding the position of the focused parts).</td>
        </tr>
        <tr>
          <td>other ordered object (like <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array"><code>Array</code></a>, collections, etc.)</td>
          <td>A new arrayBuffer will be created.</td>
          <td>Object reference to <code>stringView.bufferView</code> or a new arrayBufferView of <code>stringView.buffer</code> will be created (depending on <code>startOffset</code> and <code>length</code> arguments passed).</td>
          <td>A new arrayBufferView of <code>stringView.buffer</code> will be created.</td>
        </tr>
      </tbody>
    </table>
  </dd>
  <dt id="encoding_values">
    <code>encoding</code> <em>(optional)</em></dt>
  <dd>
    A <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/String">string</a> expressing the encoding type. Possible values are:
    <ul>
      <li><code>UTF-8</code> (default)</li>
      <li><code>UTF-16</code></li>
      <li><code>UTF-32</code></li>
      <li>Another custom string. In this case it will threated as <a href="http://en.wikipedia.org/wiki/ISO/IEC_8859-15"><code>ASCII ISO/IEC 8859-15</code></a> during conversion to and/or from string. However it is usable also for <a href="/en-US/docs/Web/API/DOMString/Binary">binary strings</a>.</li>
    </ul>
    If not specified (or specified as <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/null"><code>null</code></a>) it will considered as <code>UTF-8</code>.</dd>
  <dt>
    <code>startOffset</code> <em>(optional)</em></dt>
  <dd>
    A <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number">number</a> expressing:
    <ul>
      <li>The start offset of the new <code>stringView</code> <strong>in bytes</strong> if the input argument is an <a href="/en-US/docs/Web/JavaScript/Typed_arrays/ArrayBuffer"><code>arrayBuffer</code></a>.</li>
      <li>The start offset of the new <code>stringView</code> <em>as index</em> if the input argument is a <a href="/en-US/docs/Web/JavaScript/Typed_arrays">typed array</a> or other ordered object,</li>
      <li>The start offset of the new <code>stringView</code> <strong>in characters</strong> if the input argument is a <code>stringView</code> or a <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/String">string</a>.</li>
    </ul>
    If not specified (or specified as <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/null"><code>null</code></a>) it will become <code>0</code>.</dd>
  <dt>
    <code>length</code> <em>(optional)</em></dt>
</dl>
<p>A <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number">number</a> expressing the length<strong> in characters</strong> of the new <code>stringView</code>. If not specified it will taken the length of the input.</p>
<h4 id="Examples">Examples</h4>
<pre class="brush: js">
var myStringView1 = new StringView("Hello world!"); // UTF-8

alert(myStringView) // "Hello world!"

var myStringView2 = new StringView(myStringView1, "UTF-16");

alert(myStringView1.buffer.byteLength); // 12
alert(myStringView2.buffer.byteLength); // 24
</pre>
<h3 id="StringView_constructor's_methods"><code>StringView</code> constructor's methods</h3>
<dl>
  <dt id="StringView.makeFromBase64()">
    <code>makeFromBase64()</code></dt>
  <dd>
    <dl>
      <dt>
        Syntax</dt>
      <dd>
        <pre class="syntaxbox">
StringView.makeFromBase64(<em>base64String</em>[, <em>encoding</em>][, <em>byteOffset</em>][, <em>length</em>])</pre>
      </dd>
      <dt>
        Description</dt>
      <dd>
        Returns a new instance of <code>StringView</code> constructed decoding a given <a href="/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding"><em>base64</em>-encoded string</a>.</dd>
      <dt>
        Arguments</dt>
      <dd>
        <dl>
          <dt>
            <code>base64String</code> (required)</dt>
          <dd>
            A <a href="/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding"><em>base64</em>-encoded string</a> which will be decoded and copied into the new <code>stringView</code> object.</dd>
          <dt>
            <code>encoding</code> <em>(optional)</em></dt>
          <dd>
            A <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/String">string</a> expressing the encoding type. For possible values <a href="#encoding_values">see here</a>.</dd>
          <dt>
            <code>byteOffset</code> <em>(optional)</em></dt>
          <dd>
            A <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number">number</a> expressing the start offset <strong>in bytes</strong> of the new <code>stringView</code>. If not specified (or specified as <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/null"><code>null</code></a>) it will considered as <code>0</code>.</dd>
          <dt>
            <code>length</code> <em>(optional)</em></dt>
          <dd>
            A <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number">number</a> expressing the length<strong> in characters</strong> of the new <code>stringView</code>. If not specified it will taken the length of the input.</dd>
        </dl>
      </dd>
      <dt>
        Examples</dt>
      <dd>
        <pre class="brush: js">
var myStringView = StringView.makeFromBase64("SGVsbG8gd29ybGQh");
alert(myStringView) // "Hello world!"</pre>
      </dd>
    </dl>
    <p>This function is useful in order to pass binary data containing strings. See also <a href="#Edit_an_ASCII_part_contained_within_a_binary_file" title="#Edit_an_ASCII_part_contained_within_a_binary_file">this example</a>.</p>
  </dd>
</dl>
<h3 id="StringView_instances'_properties"><code>StringView</code> instances' properties</h3>
<dl>
  <dt id="StringView.prototype.encoding">
    <code>encoding</code></dt>
  <dd>
    A <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/String">string</a> expressing the encoding type. For possible values <a href="#encoding_values">see here</a>.</dd>
  <dt id="StringView.prototype.buffer">
    <code>buffer</code></dt>
  <dd>
    <p>The buffer to be shared between <code>stringView.</code><a href="#StringView.prototype.rawData"><code>rawData</code></a> and <code>stringView.</code><a href="#StringView.prototype.bufferView"><code>bufferView</code></a> view references.</p>
  </dd>
  <dt id="StringView.prototype.rawData">
    <code>rawData</code></dt>
  <dd>
    <p>An <a href="/en-US/docs/Web/JavaScript/Typed_arrays/ArrayBufferView">arrayBufferView</a> containing the representation of the string as array of 8-bit, 16-bit or 32-bit integers (depeding on the choosen encoding).</p>
  </dd>
  <dt id="StringView.prototype.bufferView">
    <code>bufferView</code></dt>
  <dd>
    <p>An <a href="/en-US/docs/Web/JavaScript/Typed_arrays/ArrayBufferView">arrayBufferView</a> containing the representation of <strong>the whole buffer</strong> as array of 8-bit, 16-bit or 32-bit integers (depeding on the choosen encoding).</p>
  </dd>
</dl>
<h3 id="StringView_instances'_methods"><code>StringView</code> instances' methods</h3>
<dl>
  <dt id="StringView.prototype.makeIndex()">
    <code>makeIndex()</code></dt>
  <dd>
    <dl>
      <dt>
        Syntax</dt>
      <dd>
        <pre class="syntaxbox">
stringView.makeIndex([<em>endOffsetCharacter</em>][, <em>skipOffsetIndex</em>])
</pre>
      </dd>
      <dt>
        Description</dt>
      <dd>
        If the <code>endOffsetCharacter</code> argument is a number it will be token as character position and <code>makeIndex()</code> will return the real index of that position. If the <code>endOffsetCharacter argument is omitted,</code> <code>makeIndex()</code> will return the length <strong>in characters</strong> (ASCII or UTF-encoded) of the <code>stringView</code> object.</dd>
      <dt>
        Arguments</dt>
      <dd>
        <dl>
          <dt>
            <code>endOffsetCharacter</code> <em>(optional)</em></dt>
          <dd>
            A <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number">number</a> expressing the position <strong>in characters</strong> of the index of <code>stringView.rawData</code> to be returned.</dd>
          <dt>
            <code>skipOffsetIndex</code> <em>(optional)</em></dt>
          <dd>
            A <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number">number</a> expressing the position <strong>as index</strong> of the characters parts to skip.</dd>
        </dl>
      </dd>
      <dt>
        Examples</dt>
      <dd>
        <pre class="brush: js">
var myStringView = new StringView("\u6432\u6432\u6432\u6432");
alert(myStringView.makeIndex()) // 4
alert(myStringView.makeIndex(2)) // 6</pre>
      </dd>
    </dl>
    <p><code>stringView.makeIndex()</code> is a powerful method. Here is a typical use of <code>stringView.makeIndex()</code> within a cycle:</p>
    <pre class="brush: js">
var myStringView = new StringView("䍧
Revert to this revision