StringView

  • Revision slug: Mozilla/Add-ons/Code_snippets/StringView
  • Revision title: StringView
  • Revision id: 504199
  • Created:
  • Creator: wbamberg
  • Is current revision? No
  • Comment Moved From Code_snippets/StringView to Mozilla/Add-ons/Code_snippets/StringView

Revision Content

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 extensible 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 #6
|*|
|*|  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'S 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 element */
    aTarget[nIdx++] = nChar;
  } else {
    /* two elements */
    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 (aBytes) {

  var sB64Enc = "";

  for (var nMod3, nLen = aBytes.length, nUint24 = 0, nIdx = 0; nIdx < nLen; nIdx++) {
    nMod3 = nIdx % 3;
    if (nIdx > 0 && (nIdx * 4 / 3) % 76 === 0) { sB64Enc += "\r\n"; }
    nUint24 |= aBytes[nIdx] << (16 >>> nMod3 & 24);
    if (nMod3 === 2 || aBytes.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, aBytes = 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++) {
        aBytes[nOutIdx] = nUint24 >>> (16 >>> nMod3 & 24) & 255;
      }
      nUint24 = 0;
    }
  }

  return aBytes;

};

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

  return new StringView(sEncoding === "UTF-16" || sEncoding === "UTF-32" ? StringView.base64ToBytes(sB64Inpt, sEncoding === "UTF-16" ? 2 : 4).buffer : StringView.base64ToBytes(sB64Inpt), sEncoding, nByteOffset, nLength);

};

/* DEFAULT VALUES */

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

/* INSTANCES' METHODS */

StringView.prototype.makeIndex = function (nChrLength, nStartFrom) {

  var

    aTarget = this.rawData, nChrEnd, nRawLength = aTarget.length,
    nStartIdx = nStartFrom || 0, nIdxEnd = nStartIdx, nStopAtChr = isNaN(nChrLength) ? Infinity : nChrLength;

  if (nChrLength + 1 > aTarget.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 = 0; nIdxEnd < nRawLength && nChrEnd < nStopAtChr; nChrEnd++) {
        nPart = aTarget[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 += aTarget[nIdxEnd] > 0xD7BF /* 55231 */ && nIdxEnd + 1 < aTarget.length ? 2 : 1;
      }

      break;

    default:

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

  }

  if (nChrLength) { return nIdxEnd; }

  return nChrEnd;

};

StringView.prototype.toBase64 = function (bWholeBuffer) {

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

};

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

  var

    nChrLen, nCharStart, nStrLen, bVariableLen = this.encoding === "UTF-8" || this.encoding === "UTF-16",
    nStartOffset = nCharOffset, nStringLength, nRawLen = this.rawData.length;

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

  nStringLength = bVariableLen ? this.makeIndex() : nRawLen;
  nCharStart = nCharOffset ? Math.max((nStringLength + nCharOffset) % nStringLength, 0) : 0;
  nStrLen = Number.isInteger(nCharLength) ? Math.max(nCharLength, 0) + nCharStart > nStringLength ? nStringLength - nCharStart : nCharLength : nStringLength;

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

  if (bVariableLen) {
    nStartOffset = this.makeIndex(nCharStart);
    nChrLen = this.makeIndex(nStrLen, nStartOffset) - nStartOffset;
  } else {
    nStartOffset = nCharStart;
    nChrLen = nStrLen - nCharStart;
  }

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

  return new StringView(this.buffer, this.encoding, nStartOffset, nChrLen);

};

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

  var aSource = this.rawData, nRawEnd, 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;
    nRawEnd = isFinite(nChrLen) ? this.makeIndex(nChrLen, nRawIdx) : aSource.length;

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

  } else {

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

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

  }

};

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

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

  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 = this.rawData.length, nIdx = 0; nIdx < nLen; nIdx += fGetIncr(nChr)) {
    nChr = fGetCode(this.rawData, nIdx);
    sView += String.fromCharCode(nChr);
  }

  return sView;

};

Manual

Methods overview

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

Properties overview

Attribute Type Description
encoding
{{ReadOnlyInline()}}
DOMString A string expressing the encoding type. For actually supported 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 (depending on the chosen encoding).
bufferView
{{ReadOnlyInline()}}
arrayBufferView An arrayBufferView containing the representation of the whole buffer as array of 8-bit, 16-bit, or 32-bit integers (depending on the chosen 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 behavior 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 be treated 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 be 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 in raw elements if the input argument is a typed array or other ordered object
  • The start offset of the new stringView in codepoints 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 in codepoints the length of the new stringView if the input argument is a string or a stringView, or in raw elements if the input is a typed array, an arrayBuffer or any other kind of ordered object (like Array, collections, etc.). If not specified it will take the length of the input. It never can be major than the length of the input. If you want to see how create a stringView bigger than its content, please, see this note.

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 be considered as 0.
length (optional)
A number expressing the length in codepoints of the new stringView. If not specified it will take 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 (depending on the chosen encoding).

bufferView

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

StringView instances' methods

makeIndex()
Syntax
stringView.makeIndex([charactersLength[, startFrom]])
Description
If the charactersLength argument is a number it will be taken as codepoints length and makeIndex() will return the index in elements of that position starting from 0. If the startFrom argument is passed the analysis will be done starting from it. If the charactersLength argument is omitted, makeIndex() will return the length in codepoints (ASCII or UTF-encoded) of the stringView object.
Arguments
charactersLength (optional)
A number expressing the distance in codepoints from startFrom of the index of stringView.rawData to be returned.
startFrom (optional)
A number expressing the position in raw elements of the characters parts to skip. If omitted it will be considered as 0.
Examples
var myStringView = new StringView("\u6432\u6432\u6432\u6432");
alert(myStringView.makeIndex()) // 4
alert(myStringView.makeIndex(2)) // 6

…using the startFrom argument…

var myStringView = StringView.makeFromBase64("5Lit5paHIGVzcGHDsW9sIEVuZ2xpc2gg4KS54KS/4KSo4KWN4KSm4KWAINin2YTYudix2KjZitipIHBvcnR1Z3XDqnMg4Kas4Ka+4KaC4Kay4Ka+INGA0YPRgdGB0LrQuNC5IOaXpeacrOiqniDgqKrgqbDgqJzgqL7gqKzgqY==");

alert(myStringView);

/* Get the Hindi subview... */
var mySubview1 = myStringView.subview(19, 6);

/* Get the Hindi subview passing an uint8Array as argument... */

var nHindiStart = myStringView.makeIndex(19);
var nHindiEnd = myStringView.makeIndex(6, nHindiStart);
var mySubview2 = new StringView(myStringView.rawData.subarray(nHindiStart, nHindiEnd), "UTF-8");

alert(mySubview1.rawData.length); // 18
alert(mySubview2.rawData.length); // 18

See also: stringView.forEachChar().

Performance note: Each invocation of stringView.makeIndex() runs a cycle for all characters contained in the stringView object between startFrom and startFrom + charactersLength. Dont't use stringView.makeIndex() in a cycle as if it were a normal length property. For custom cycles, look at the example proposed here.
toBase64()
Syntax
stringView.toBase64([wholeBuffer])
Description
Returns a base64-encoded string corresponding to the stringView or to its buffer.
Arguments
wholeBuffer (optional)
A boolean expressing whether the returned base64-encoded string will correspond to the whole buffer (true) or to the stringView (false or omitted).
Examples
var myStringView = new StringView("\u6432\u6432\u6432\u6432");
alert(StringView.makeFromBase64(myStringView.toBase64())) // 搲搲搲搲

See also: Base64 encoding and decoding.

subview()
Syntax
stringView.subview(characterOffset[, charactersLength])
Description
Returns a new stringView object which will share the same buffer. Arguments characterOffset and charactersLength will be treated as in String.prototype.substr(characterOffset[, charactersLength) (see). If you want to create a new stringView object cloning without sharing the same buffer, look at this table.
Arguments
characterOffset (optional)
A number expressing (in codepoints) the location at which to begin extracting characters.
charactersLength (optional)
A number expressing (in codepoints) the location at which to stop extracting characters.
Examples
var myStringView1 = new StringView("Hello world!");
var myStringView2 = myStringView1.subview(3, 7);
alert(myStringView2); // "lo worl"
As was explained above, characterOffset is a character index. The index of the first character is 0, and the index of the last character is 1 less than the length of the stringView. subview begins extracting characters at characterOffset and collects charactersLength characters (unless it reaches the end of the string first, in which case it will return fewer).
  • If characterOffset is positive and is greater than or equal to the length of the string, substr returns an empty string.
  • If characterOffset is negative, substr uses it as a character index from the end of the string. If characterOffset is negative and abs(start) is larger than the length of the string, substr uses 0 as the start index.
  • If charactersLength is 0 or negative, substr returns an empty string. If charactersLength is omitted, substr extracts characters to the end of the string.
forEachChar()
Syntax
stringView.forEachChar(callback[, thisObject[, characterOffset[, charactersLength]]])
Description
Repeatedly invokes a function for each character of the stringView.
Arguments
callback (required)
A function to be invoked for each character. It will be called with four arguments, expressing respectively:
charCode
A number expressing the Unicode representation of the actual character (codepoint).
characterOffset
A number expressing the position, in codepoints, of the passed character.
rawOffset
A number expressing the position, in codepoints parts, of the passed character.
rawDataArray
The array containing the raw data of the stringView.
It will look something like this: callback.call(thisObject, charCode, characterOffset, rawOffset, rawDataArray). If the encoding is a fixed-length Unicode encoding, characterOffset and rawOffset will be the same number.
thisObject (optional)
The this object upon which will be executed the callback function.
characterOffset (optional)
A number expressing (in codepoints) the location at which to begin executing the callback function.
charactersLength (optional)
A number expressing (in codepoints) the number of invocations of the callback function.
Examples
function myCallback (charCode, characterOffset, rawOffset /*, rawDataArray */) {
  this.appendChild(document.createTextNode("char #" + characterOffset + ", raw index: " + rawOffset + ", character: " + String.fromCharCode(charCode)));
  this.appendChild(document.createElement("br"));
}

(new StringView("\u4367\uD889\uDE54\u4343\u5431")).forEachChar(myCallback, document.body);
Note: stringView.forEachChar() executes a complete cycle through all characters in the stringView between characterOffset and characterOffset + charactersLength. If you want to build a custom cycle through a variable-length-encoded stringView (UTF-8, UTF-16), you can use a code like the following, which does not make use of stringView.forEachChar(). If the encoding is a fixed-length one (ASCII, UTF-32, etc.), you can do a normal cycle upon the stringView.rawData array.
var myStringView = new StringView("\u4367\uD889\uDE54\u4343\u5431 – Hello world!"); // an UTF-8-encoded stringView...

alert(myStringView);

for (var nChrCode, nLen = myStringView.rawData.length, nRawIdx = 0, nChrIdx = 0; nRawIdx < nLen; nRawIdx += StringView.getUTF8CharLength(nChrCode), nChrIdx++) {

  nChrCode = StringView.loadUTF8CharCode(myStringView.rawData, nRawIdx);

  /* Do something with each character... */
  alert(String.fromCharCode(nChrCode));

}
Note: For UTF-16, replace getUTF8CharLength() and loadUTF8CharCode() methods respectively with getUTF16CharLength() and loadUTF16CharCode().

See also: stringView.makeIndex() and its note.

valueOf()
Syntax
stringView.valueOf()
Description
Converts stringView's content into string and returns it.
Arguments
none
No arguments expected.
Examples
alert((new StringView("Hello world!")).valueOf() === "Hello world!"); // true

JavaScript calls the stringView.valueOf() method to convert an object to a primitive value. You rarely need to invoke the stringView.valueOf() method yourself; JavaScript automatically invokes it when encountering an object where a primitive value is expected.

toString()
Syntax
stringView.toString()
Description
Converts stringView's content into string and returns it.
Arguments
none
No arguments expected.
Examples
alert((new StringView("Hello world!")).toString() === "Hello world!"); // true

The stringView.toString() method is automatically called when the object is to be represented as a text value or when an object is referred to in a manner in which a string is expected.

Appendix: other StringView constructor's methods (utilities)

bytesToBase64()
Syntax
StringView.bytesToBase64(uint8Array)
Description
Converts an array of bytes (a typed array of Uint8Array subclass) into a base64-encoded string.
Arguments
typedArray (required)
The Uint8Array of bytes to encode to base64.
Examples
alert(StringView.bytesToBase64([72,101,108,108,111,32,119,111,114,108,100,33])); // "SGVsbG8gd29ybGQh"

StringView.bytesToBase64() is useful to encode an UTF-8 string to base64. See this article for other stuff.

base64ToBytes()
Syntax
StringView.base64ToBytes(base64String[, regSize])
Description
Decode a base64 string to an array of bytes and return it. The returned array will be a typed array of Uint8Array subclass.
Arguments
base64String (required)
The string to decode from base64.
regSize (optional)
The number of bytes of which the length must result in a multiple (1 or omitted for ASCII, binary strings or UTF-8-encoded strings, 2 for UTF-16 strings, 4 for UTF-32 strings).
Examples
alert(String.fromCharCode.apply(null, StringView.base64ToBytes("SGVsbG8gd29ybGQh"))); // "Hello world!"

StringView.base64ToBytes() is a generic utility useful also for binary data. If you want to pass the StringView.base64ToBytes(base64String[, regSize]).buffer property to an ArrayBufferView subclass different from Uint8Array, you should make use of the regSize argument.

loadUTF8CharCode()
Syntax
StringView.loadUTF8CharCode(typedArray, index)
Description
Returns the single codepoint at the given location from an array of UTF-8-encoded elements. An UTF-8-encoded codepoint can occupy up to six elements. This function will recompose all these parts into a codepoint.
Arguments
typedArray (required)
A typed array containing the UTF-8 encoded elements.
index (required)
The location to be read.
Examples
var myStringView = new StringView("Hello world!"); // an UTF-8 stringView...
alert(StringView.loadUTF8CharCode(myStringView.rawData, 6)); // 119, which is the character code for "w"
StringView.loadUTF8CharCode() is mainly for internal use and generally is of little utility.
putUTF8CharCode()
Syntax
StringView.putUTF8CharCode(typedArray, charCode, index)
Description
Write a single codepoint at the given position into a typed array. A single UTF-8-encoded codepoint can occupy many elements (up to six). This function will split it into the needed parts and will write them. Returns undefined.
Arguments
typedArray (required)
A typed array containing the UTF-8 encoded elements.
charCode (required)
A number expressing the Unicode representation of a character (codepoint).
index (required)
The location to be overwritten.
Examples
var myStringView = new StringView("Hello world!"); // an UTF-8 stringView...
StringView.putUTF8CharCode(myStringView.rawData, "_".charCodeAt(0), 5)
alert(myStringView); // "Hello_world!"

StringView.putUTF8CharCode() is mainly for internal use and generally is of little utility.

getUTF8CharLength()
Syntax
StringView.getUTF8CharLength(charCode)
Description
Returns the number of elements occupied by an UTF-8-encoded codepoint.
Arguments
charCode (required)
A number expressing the Unicode representation of a character (codepoint).
Examples
alert(StringView.getUTF8CharLength("C".charCodeAt(0))); // "C" occupies 1 UTF-8-encoded element...
alert(StringView.getUTF8CharLength("⁈".charCodeAt(0))); // "⁈" occupies 3 UTF-8-encoded elements...

StringView.getUTF8CharLength() is mainly for internal use and generally is of little utility.

loadUTF16CharCode()
Syntax
StringView.loadUTF16CharCode(typedArray, index)
Description
Returns the single codepoint at the given location from an array of UTF-16-encoded elements. An UTF-16 codepoint can occupy up to two UTF-16-encoded elements. This function will recompose all these parts into a codepoint.
Arguments
typedArray (required)
A typed array containing the UTF-16 encoded elements.
index (required)
The location to be read.
Examples
var myStringView = new StringView("Hello world!", "UTF-16"); // an UTF-16 stringView...
alert(StringView.loadUTF16CharCode(myStringView.rawData, 6)); // 119, which is the character code of "w"

StringView.loadUTF16CharCode() is mainly for internal use and generally is of little utility.

putUTF16CharCode()
Syntax
StringView.putUTF16CharCode(typedArray, charCode, index)
Description
Write a single codepoint at the given position into a typed array. A single UTF-16-encoded codepoint can occupy up to two UTF-16-encoded elements. This function will split it into the needed parts and will write them. Returns undefined.
Arguments
typedArray (required)
A typed array containing the UTF-16 encoded elements.
charCode (required)
A number expressing the Unicode representation of a character (codepoint).
index (required)
The location to be overwritten.
Examples
var myStringView = new StringView("Hello world!", "UTF-16"); // an UTF-16 stringView...
StringView.putUTF16CharCode(myStringView.rawData, "_".charCodeAt(0), 5)
alert(myStringView); // "Hello_world!"

StringView.putUTF16CharCode() is mainly for internal use and generally is of little utility.

getUTF16CharLength()
Syntax
StringView.getUTF16CharLength(charCode)
Description
Returns the number of elements occupied by an UTF-16-encoded codepoint.
Arguments
charCode (required)
A number expressing the Unicode representation of a character (codepoint).
Examples
alert("\uD950\uDF21"); // 0x64321
alert(StringView.b64ToUint6(0x64321)); // "\uD950\uDF21" occupies 2 UTF-16-encoded elements...

StringView.getUTF16CharLength() is mainly for internal use and generally is of little utility.

b64ToUint6()
Syntax
StringView.b64ToUint6(charCode)
Description
Returns the 6-bit number corresponding to the given base64 character code.
Arguments
charCode (required)
A number expressing a base64 character code.
Examples
alert(StringView.b64ToUint6("B".charCodeAt(0))); // "B" stands for 1 in base64 encoding...
StringView.b64ToUint6() is mainly for internal use and generally is of little utility.
uint6ToB64()
Syntax
StringView.uint6ToB64(uint6)
Description
Returns the base64 character code corresponding to the given 6-bit number.
Arguments
uint6 (required)
A 6-bit unsigned number (0 = uint6 < 64).
Examples
alert(String.fromCharCode(StringView.uint6ToB64(1))); // 1 is represented by "B" in base64 encoding...

StringView.uint6ToB64() is mainly for internal use and generally is of little utility.

Advanced examples

Edit an ASCII part contained within a binary file

Let's compile this C program:

#include <stdio.h>

int main () {
    printf("Hello world!\n");
    return 0;
}

In a 64-bit machine it will result an output like the following first alert. Let's try to translate the "Hello world!" string into the italian "Ciao mondo!!"

var swHelloWorld = StringView.makeFromBase64("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AwAAAAAAAAAAAAAAAAAAAAAAAAAYGAAAAAAAAD4CAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAQAAAkAAAAAAAAAAAAAAAAAAAAAAAAMAAgAcAkAAAAAAAAAAAAAAAAAAAAAAAAMAAwA8AkAAAAAAAAAAAAAAAAAAAAAAAAMABABgAkAAAAAAAAAAAAAAAAAAAAAAAAMABQCAAkAAAAAAAAAAAAAAAAAAAAAAAAMABgDgAkAAAAAAAAAAAAAAAAAAAAAAAAMABwAeA0AAAAAAAAAAAAAAAAAAAAAAAAMACAAoA0AAAAAAAAAAAAAAAAAAAAAAAAMACQBIA0AAAAAAAAAAAAAAAAAAAAAAAAMACgBgA0AAAAAAAAAAAAAAAAAAAAAAAAMACwCoA0AAAAAAAAAAAAAAAAAAAAAAAAMADADQA0AAAAAAAAAAAAAAAAAAAAAAAAMADQAQBEAAAAAAAAAAAAAAAAAAAAAAAAMADgCUBUAAAAAAAAAAAAAAAAAAAAAAAAMADwCgBUAAAAAAAAAAAAAAAAAAAAAAAAMAEAC0BUAAAAAAAAAAAAAAAAAAAAAAAAMAEQDoBUAAAAAAAAAAAAAAAAAAAAAAAAMAEgDgBmAAAAAAAAAAAAAAAAAAAAAAAAMAEwDoBmAAAAAAAAAAAAAAAAAAAAAAAAMAFADwBmAAAAAAAAAAAAAAAAAAAAAAAAMAFQD4BmAAAAAAAAAAAAAAAAAAAAAAAAMAFgDICGAAAAAAAAAAAAAAAAAAAAAAAAMAFwDQCGAAAAAAAAAAAAAAAAAAAAAAAAMAGAAACWAAAAAAAAAAAAAAAAAAAAAAAAMAGQAQCWAAAAAAAAAAAAAAAAAAAAAAAAMAGgAAAAAAAAAAAAAAAAAAAAAAAQAAAAQA8f8AAAAAAAAAAAAAAAAAAAAAAAAAAAQA8f8AAAAAAAAAAAAAAAAAAAAACAAAAAQA8f8AAAAAAAAAAAAAAAAAAAAAEwAAAAEAFADwBmAAAAAAAAAAAAAAAAAAIAAAAAIADQBABEAAAAAAAAAAAAAAAAAANQAAAAIADQBwBEAAAAAAAAAAAAAAAAAASAAAAAIADQCwBEAAAAAAAAAAAAAAAAAAXgAAAAEAGQAQCWAAAAAAAAEAAAAAAAAAbQAAAAEAEwDoBmAAAAAAAAAAAAAAAAAAlAAAAAIADQDQBEAAAAAAAAAAAAAAAAAAoAAAAAEAEgDgBmAAAAAAAAAAAAAAAAAAvwAAAAQA8f8AAAAAAAAAAAAAAAAAAAAACAAAAAQA8f8AAAAAAAAAAAAAAAAAAAAAxwAAAAEAEQDYBkAAAAAAAAAAAAAAAAAA1QAAAAEAFADwBmAAAAAAAAAAAAAAAAAAAAAAAAQA8f8AAAAAAAAAAAAAAAAAAAAA4QAAAAAAEgDoBmAAAAAAAAAAAAAAAAAA8gAAAAEAFQD4BmAAAAAAAAAAAAAAAAAA+wAAAAAAEgDgBmAAAAAAAAAAAAAAAAAADgEAAAEAFwDQCGAAAAAAAAAAAAAAAAAAJAEAABIADQCQBUAAAAAAAAIAAAAAAAAANAEAACAAAAAAAAAAAAAAAAAAAAAAAAAAUAEAACAAGAAACWAAAAAAAAAAAAAAAAAAWwEAABIAAAAAAAAAAAAAAAAAAAAAAAAAbQEAABAAGAAQCWAAAAAAAAAAAAAAAAAAdAEAABIADgCUBUAAAAAAAAAAAAAAAAAAegEAABIAAAAAAAAAAAAAAAAAAAAAAAAAmQEAABAAGAAACWAAAAAAAAAAAAAAAAAApgEAACAAAAAAAAAAAAAAAAAAAAAAAAAAtQEAABECGAAICWAAAAAAAAAAAAAAAAAAwgEAABEADwCgBUAAAAAAAAQAAAAAAAAA0QEAABIADQAgBUAAAAAAAGUAAAAAAAAA4QEAABAAGQAYCWAAAAAAAAAAAAAAAAAA5gEAABIADQAQBEAAAAAAAAAAAAAAAAAA7QEAABAAGQAQCWAAAAAAAAAAAAAAAAAA+QEAABIADQAABUAAAAAAABUAAAAAAAAA/gEAACAAAAAAAAAAAAAAAAAAAAAAAAAAEgIAABECGAAQCWAAAAAAAAAAAAAAAAAAHgIAACAAAAAAAAAAAAAAAAAAAAAAAAAAOAIAABIACwCoA0AAAAAAAAAAAAAAAAAAAGluaXQuYwBjcnRzdHVmZi5jAF9fSkNSX0xJU1RfXwBkZXJlZ2lzdGVyX3RtX2Nsb25lcwByZWdpc3Rlcl90bV9jbG9uZXMAX19kb19nbG9iYWxfZHRvcnNfYXV4AGNvbXBsZXRlZC42MzU5AF9fZG9fZ2xvYmFsX2R0b3JzX2F1eF9maW5pX2FycmF5X2VudHJ5AGZyYW1lX2R1bW15AF9fZnJhbWVfZHVtbXlfaW5pdF9hcnJheV9lbnRyeQBoZWxsby5jAF9fRlJBTUVfRU5EX18AX19KQ1JfRU5EX18AX19pbml0X2FycmF5X2VuZABfRFlOQU1JQwBfX2luaXRfYXJyYXlfc3RhcnQAX0dMT0JBTF9PRkZTRVRfVEFCTEVfAF9fbGliY19jc3VfZmluaQBfSVRNX2RlcmVnaXN0ZXJUTUNsb25lVGFibGUAZGF0YV9zdGFydABwdXRzQEBHTElCQ18yLjIuNQBfZWRhdGEAX2ZpbmkAX19saWJjX3N0YXJ0X21haW5AQEdMSUJDXzIuMi41AF9fZGF0YV9zdGFydABfX2dtb25fc3RhcnRfXwBfX2Rzb19oYW5kbGUAX0lPX3N0ZGluX3VzZWQAX19saWJjX2NzdV9pbml0AF9lbmQAX3N0YXJ0AF9fYnNzX3N0YXJ0AG1haW4AX0p2X1JlZ2lzdGVyQ2xhc3NlcwBfX1RNQ19FTkRfXwBfSVRNX3JlZ2lzdGVyVE1DbG9uZVRhYmxlAF9pbml0AA==", "ASCII", 1444, 12);

alert(String.fromCharCode.apply(null, swHelloWorld.bufferView)); // swHelloWorld.buffer contains the whole file
alert(swHelloWorld); // "Hello world"

/* traslating "Hello world" into italian... */

swHelloWorld.rawData.set((new StringView("Ciao mondo!!", "ASCII")).rawData);

/* download the new executable file... */

location.assign(URL.createObjectURL(new Blob([swHelloWorld.buffer], { "type": "application\/x-executable" })));
Note: The executable above has been compiled with GNU GCC 4.8.1 running on a 64-bit machine with Arch GNU/Linux.

Glossary

Element
An item of the backing array (whether Uint8Array, Uint16Array, Uint32Array, etc.)
Codepoint
An unique number for each Unicode character. It is rappresented by a collection of 1-6 uint8 elements for UTF-8, 1-2 uint16 elements for UTF-16, 1 uint32 element for UCS4, 1 uint8 element for ASCII, or something else.
Byte
A collection of 8 bits.
NULL codepoint
The character whose codepoint is equal to 0 ('\0').

Notes

  • When you include the script stringview.js into a page, no other variables than StringView itself will be added to the global scope.
  • StringView is an highly extensible library, that anyone can extend by adding methods to the object StringView.prototype.
    For example, imagine you want to create a method similar to string.replace(), but for stringView objects. Maybe you should want to solve a situation like the following:
    var oMyStringView = new StringView("Hello,&nbsp;strange&nbsp;people!"); // UTF-8
    var oMyRegExp = new CLikeRegExp("&nbsp;", "g");
    
    alert(oMyStringView.replace(oMyRegExp, " ")); // "Hello, strange people!\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"
    
    /* stringView.replace() will be different from string.replace() because it act also on the source: */
    alert(oMyStringView); // "Hello, strange people!\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"
    As you can see, the previous example needs you to create two new algorithms: the CLikeRegExp() constructor – a constructor of C-like regular expression objects – and StringView.prototype.replace() – the new method, able to act on stringView instances. Well, just include stringview.js to your scope and work on them in another script:
    /* A constructor of C-like regular expression objects... */
    function CLikeRegExp (sRegExp, sFlags) {
        /**
        *  [...]
        *
        *  CONSTRUCTOR CODE HERE!
        **/
    }
    
    /* A "replace" method for StringView... */
    StringView.prototype.replace = function (oCLikeRegExp, sWith) {
        /**
        *  [...]
        *
        *  METHOD CODE HERE!
        **/
    };
  • If you want to create a stringView inside a bigger empty buffer, like in the following C line
    /* myBuffer: 12 character followed by 1012 NULLs... */
    char myBuffer[1024] = "Hello world!";
    you should do something like this:
    var myBuffer = new StringView(1024);
    /* myBuffer: 12 character followed by 1012 NULLs... */
    var myContent = new StringView("Hello world!");
    myBuffer.rawData.set(myContent.rawData, myContent.rawData.length);
  • StringView is a constructor and a collection of methods whose aim is to work strictly on arrays of numbers rather than on creating new immutable JavaScript strings. Keep it in mind when you try to extend its prototype.
  • Since stringView, unlike C strings, has a length property, there are no reasons to add a NULL codepoint ('\0') after the termination of a string.
  • StringView has been proposed as strawman for ES6 on ECMAScript Bugs. Everyone can partecipate in the discussion at bug 1557.

See also

Revision Source

<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 extensible</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 #6
|*|
|*|&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'S 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 element */
&nbsp;&nbsp;&nbsp; aTarget[nIdx++] = nChar;
&nbsp; } else {
&nbsp;&nbsp;&nbsp; /* two elements */
&nbsp;&nbsp;&nbsp; aTarget[nIdx++] = 0xD7C0 /* 55232 */ + (nChar &gt;&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 (aBytes) {

&nbsp; var sB64Enc = "";

&nbsp; for (var nMod3, nLen = aBytes.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 |= aBytes[nIdx] &lt;&lt; (16 &gt;&gt;&gt; nMod3 &amp; 24);
&nbsp;&nbsp;&nbsp; if (nMod3 === 2 || aBytes.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;&gt; 2) / nBlockBytes) * nBlockBytes : nInLen * 3 + 1 &gt;&gt;&gt; 2, aBytes = 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; aBytes[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 aBytes;

};

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

&nbsp; return new StringView(sEncoding === "UTF-16" || sEncoding === "UTF-32" ? StringView.base64ToBytes(sB64Inpt, sEncoding === "UTF-16" ? 2 : 4).buffer : StringView.base64ToBytes(sB64Inpt), sEncoding, nByteOffset, nLength);

};

/* DEFAULT VALUES */

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

/* INSTANCES' METHODS */

StringView.prototype.makeIndex = function (nChrLength, nStartFrom) {

&nbsp; var

&nbsp;&nbsp;&nbsp; aTarget = this.rawData, nChrEnd, nRawLength = aTarget.length,
&nbsp;&nbsp;&nbsp; nStartIdx = nStartFrom || 0, nIdxEnd = nStartIdx, nStopAtChr = isNaN(nChrLength) ? Infinity : nChrLength;

&nbsp; if (nChrLength + 1 &gt; aTarget.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 = 0; nIdxEnd &lt; nRawLength &amp;&amp; nChrEnd &lt; nStopAtChr; nChrEnd++) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nPart = aTarget[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 += aTarget[nIdxEnd] &gt; 0xD7BF /* 55231 */ &amp;&amp; nIdxEnd + 1 &lt; aTarget.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(nChrLength) ? nChrLength : nRawLength - 1;

&nbsp; }

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

&nbsp; return nChrEnd;

};

StringView.prototype.toBase64 = function (bWholeBuffer) {

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

};

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

&nbsp; var

&nbsp;&nbsp;&nbsp; nChrLen, nCharStart, nStrLen, bVariableLen = this.encoding === "UTF-8" || this.encoding === "UTF-16",
&nbsp;&nbsp;&nbsp; nStartOffset = nCharOffset, nStringLength, nRawLen = this.rawData.length;

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

&nbsp; nStringLength = bVariableLen ? this.makeIndex() : nRawLen;
&nbsp; nCharStart = nCharOffset ? Math.max((nStringLength + nCharOffset) % nStringLength, 0) : 0;
&nbsp; nStrLen = Number.isInteger(nCharLength) ? Math.max(nCharLength, 0) + nCharStart &gt; nStringLength ? nStringLength - nCharStart : nCharLength : nStringLength;

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

&nbsp; if (bVariableLen) {
&nbsp;&nbsp;&nbsp; nStartOffset = this.makeIndex(nCharStart);
&nbsp;&nbsp;&nbsp; nChrLen = this.makeIndex(nStrLen, nStartOffset) - nStartOffset;
&nbsp; } else {
&nbsp;&nbsp;&nbsp; nStartOffset = nCharStart;
&nbsp;&nbsp;&nbsp; nChrLen = nStrLen - nCharStart;
&nbsp; }

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

&nbsp; return new StringView(this.buffer, this.encoding, nStartOffset, nChrLen);

};

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

&nbsp; var aSource = this.rawData, nRawEnd, 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; nRawEnd = isFinite(nChrLen) ? this.makeIndex(nChrLen, nRawIdx) : aSource.length;

&nbsp;&nbsp;&nbsp; for (var nChrCode, nChrIdx = 0; nRawIdx &lt; nRawEnd; 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; nRawEnd = isFinite(nChrLen) ? nChrLen + nRawIdx : aSource.length;

&nbsp;&nbsp;&nbsp; for (nRawIdx; nRawIdx &lt; nRawEnd; 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; 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, this.rawData);
&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 = this.rawData.length, nIdx = 0; nIdx &lt; nLen; nIdx += fGetIncr(nChr)) {
&nbsp;&nbsp;&nbsp; nChr = fGetCode(this.rawData, 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 <a href="#Constructor" title="#Constructor">StringView</a>(stringView input, optional DOMString encoding, optional unsigned long startOffset, optional unsigned long length);</code><br />
    <code>stringView new <a href="#Constructor" title="#Constructor">StringView</a>(DOMString input, optional DOMString encoding, optional unsigned long startOffset, optional unsigned long length);</code><br />
    <code>stringView new <a href="#Constructor" title="#Constructor">StringView</a>(unsigned long input);</code><br />
    <code>stringView new <a href="#Constructor" title="#Constructor">StringView</a>(arrayBuffer input, optional DOMString encoding, optional unsigned long byteOffset, optional unsigned long length);</code><br />
    <code>stringView new <a href="#Constructor" title="#Constructor">StringView</a>(arrayBufferView input, optional DOMString encoding, optional unsigned long startOffset, optional unsigned long length);</code><br />
    <code>stringView new <a href="#Constructor" title="#Constructor">StringView</a>(array input, optional DOMString encoding, optional unsigned long startOffset, optional unsigned long 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, optional DOMString encoding, optional unsigned long byteOffset, optional unsigned long 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, optional unsigned char charSize);</code></td>
  </tr>
  <tr>
   <td><code>unsigned long StringView.<a href="#StringView.loadUTF8CharCode%28%29">loadUTF8CharCode</a>(arrayBufferView typedArray, unsigned long index);</code></td>
  </tr>
  <tr>
   <td><code>void StringView.<a href="#StringView.putUTF8CharCode%28%29">putUTF8CharCode</a>(arrayBufferView typedArray, unsigned long charCode, unsigned long index);</code></td>
  </tr>
  <tr>
   <td><code>unsigned char StringView.<a href="#StringView.getUTF8CharLength%28%29">getUTF8CharLength</a>(unsigned long charCode);</code></td>
  </tr>
  <tr>
   <td><code>unsigned long StringView.<a href="#StringView.loadUTF16CharCode%28%29">loadUTF16CharCode</a>(arrayBufferView typedArray, unsigned long index);</code></td>
  </tr>
  <tr>
   <td><code>void StringView.<a href="#StringView.putUTF16CharCode%28%29">putUTF16CharCode</a>(arrayBufferView typedArray, unsigned long charCode, unsigned long index);</code></td>
  </tr>
  <tr>
   <td><code>unsigned char StringView.<a href="#StringView.getUTF16CharLength%28%29">getUTF16CharLength</a>(unsigned long 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 long stringView.<a href="#StringView.prototype.makeIndex%28%29">makeIndex</a>(optional unsigned long charactersLength, optional unsigned long startFrom);</code></td>
  </tr>
  <tr>
   <td><code>DOMString stringView.<a href="#StringView.prototype.toBase64%28%29">toBase64</a>(optional boolean wholeBuffer);</code></td>
  </tr>
  <tr>
   <td><code>stringView stringView.<a href="#StringView.prototype.subview%28%29">subview</a>(unsigned long characterOffset, optional unsigned long charactersLength);</code></td>
  </tr>
  <tr>
   <td><code>void stringView.<a href="#StringView.prototype.forEachChar%28%29">forEachChar</a>(function callback, optional object thisObject, optional unsigned long characterOffset, optional unsigned long 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 actually supported 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 (depending on the chosen 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 (depending on the chosen 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 behavior of the <code>StringView</code> constructor.<br />
  <table class="standard-table" id="stringview_behaviour">
   <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 be treated 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 be 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 <a href="#glossary_byte" title="Byte - glossary">bytes</a></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> <strong>in raw <a href="#glossary_element" title="Element - glossary">elements</a></strong> 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 <a href="#glossary_codepoint" title="Codepoint - glossary">codepoints</a></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 <strong>in <a href="#glossary_codepoint" title="Codepoint - glossary">codepoints</a></strong> the length of the new <code>stringView</code> if the <code>input</code> argument is a <code>string</code> or a <code>stringView</code>, or <strong>in raw <a href="#glossary_element" title="Element - glossary">elements</a></strong> if the input is a <a href="/en-US/docs/Web/JavaScript/Typed_arrays">typed array</a>, an <a href="/en-US/docs/Web/JavaScript/Typed_arrays/ArrayBuffer"><code>arrayBuffer</code></a> or any other kind of ordered object (like <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array"><code>Array</code></a>, collections, etc.). If not specified it will take the length of the input. <strong>It never can be major than the length of the input</strong>. If you want to see how create a stringView bigger than its content, please, see <a href="#note_about_length">this note</a>.</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 <a href="#glossary_byte" title="Byte - glossary">bytes</a></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 be 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 <a href="#glossary_codepoint" title="Codepoint - glossary">codepoints</a></strong> of the new <code>stringView</code>. If not specified it will take 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 (depending on the chosen 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 (depending on the chosen 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>charactersLength</em>[, <em>startFrom</em>]])
</pre>
   </dd>
   <dt>
    Description</dt>
   <dd>
    If the <code>charactersLength</code> argument is a number it will be taken <strong>as <a href="#glossary_codepoint" title="Codepoint - glossary">codepoints</a> length</strong> and <code>makeIndex()</code> will return the index <strong>in <a href="#glossary_element" title="Element - glossary">elements</a></strong> of that position starting from 0. If the <code>startFrom</code> argument is passed the analysis will be done starting from it. If the <code>charactersLength</code> argument is omitted, <code>makeIndex()</code> will return the length <strong>in <a href="#glossary_codepoint" title="Codepoint - glossary">codepoints</a></strong> (ASCII or UTF-encoded) of the <code>stringView</code> object.</dd>
   <dt>
    Arguments</dt>
   <dd>
    <dl>
     <dt>
      <code>charactersLength</code> <em>(optional)</em></dt>
     <dd>
      A <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number">number</a> expressing the distance <strong>in <a href="#glossary_codepoint" title="Codepoint - glossary">codepoints</a></strong> from <code>startFrom</code> of the index of <code>stringView.rawData</code> to be returned.</dd>
     <dt>
      <code>startFrom</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 raw&nbsp;<a href="#glossary_element" title="Element - glossary">elements</a></strong> of the characters parts to skip. If omitted it will be considered as <code>0</code>.</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>
    <p>…using the <code>startFrom</code> argument…</p>
    <pre class="brush: js">
var myStringView = StringView.makeFromBase64("5Lit5paHIGVzcGHDsW9sIEVuZ2xpc2gg4KS54KS/4KSo4KWN4KSm4KWAINin2YTYudix2KjZitipIHBvcnR1Z3XDqnMg4Kas4Ka+4KaC4Kay4Ka+INGA0YPRgdGB0LrQuNC5IOaXpeacrOiqniDgqKrgqbDgqJzgqL7gqKzgqY==");

alert(myStringView);

/* Get the Hindi subview... */
var mySubview1 = myStringView.subview(19, 6);

/* Get the Hindi subview passing an uint8Array as argument... */

var nHindiStart = myStringView.makeIndex(19);
var nHindiEnd = myStringView.makeIndex(6, nHindiStart);
var mySubview2 = new StringView(myStringView.rawData.subarray(nHindiStart, nHindiEnd), "UTF-8");

alert(mySubview1.rawData.length); // 18
alert(mySubview2.rawData.length); // 18</pre>
   </dd>
  </dl>
  <p>See also: <a href="#StringView.prototype.forEachChar%28%29" title="#StringView.prototype.forEachChar%28%29"><code>stringView.forEachChar()</code></a>.</p>
  <div class="note" id="makeIndex()_note">
   <strong>Performance note:</strong> Each invocation of <code>stringView.makeIndex()</code> runs a cycle for all characters contained in the <code>stringView</code> object between <code>startFrom</code> and <code>startFrom</code> + <code>charactersLength</code>. <strong>Dont't use <code>stringView.makeIndex()</code> in a cycle as if it were a normal <code>length</code> property.</strong> For custom cycles, look at the example proposed <a href="#forEachChar%28%29_note" title="#forEachChar%28%29_note">here</a>.</div>
 </dd>
 <dt id="StringView.prototype.toBase64()">
  <code>toBase64()</code></dt>
 <dd>
  <dl>
   <dt>
    Syntax</dt>
   <dd>
    <pre class="syntaxbox">
stringView.toBase64([<em>wholeBuffer</em>])</pre>
   </dd>
   <dt>
    Description</dt>
   <dd>
    Returns a <a href="/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding"><em>base64</em>-encoded string</a> corresponding to the <code>stringView</code> or to its buffer.</dd>
   <dt>
    Arguments</dt>
   <dd>
    <dl>
     <dt>
      <code>wholeBuffer</code> <em>(optional)</em></dt>
     <dd>
      A <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean">boolean</a> expressing whether the returned <em>base64</em>-encoded string will correspond to the whole buffer (<code>true</code>) or to the stringView (<code>false</code> or omitted).</dd>
    </dl>
   </dd>
   <dt>
    Examples</dt>
   <dd>
    <pre class="brush: js">
var myStringView = new StringView("\u6432\u6432\u6432\u6432");
alert(StringView.makeFromBase64(myStringView.toBase64())) // 搲搲搲搲</pre>
   </dd>
  </dl>
  <p>See also: <a href="/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding" title="/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding">Base64 encoding and decoding</a>.</p>
 </dd>
 <dt id="StringView.prototype.subview()">
  <code>subview()</code></dt>
 <dd>
  <dl>
   <dt>
    Syntax</dt>
   <dd>
    <pre class="syntaxbox">
stringView.subview(<em>characterOffset</em>[, <em>charactersLength</em>])</pre>
   </dd>
   <dt>
    Description</dt>
   <dd>
    Returns a new <code>stringView</code> object <strong>which will share the same buffer</strong>. Arguments <code>characterOffset</code> and <code>charactersLength</code> will be treated as in <code>String.prototype.substr(<em>characterOffset</em>[, <em>charactersLength</em>)</code> (<a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substr">see</a>). If you want to create a new <code>stringView</code> object <em>cloning without sharing</em> the same buffer, look at <a href="#stringview_behaviour" title="#stringview_behaviour">this table</a>.</dd>
   <dt>
    Arguments</dt>
   <dd>
    <dl>
     <dt>
      <code>characterOffset</code> <em>(optional)</em></dt>
     <dd>
      A <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number">number</a> expressing (<strong>in <a href="#glossary_codepoint" title="Codepoint - glossary">codepoints</a></strong>) the location at which to begin extracting characters.</dd>
     <dt>
      <code>charactersLength</code> <em>(optional)</em></dt>
     <dd>
      A <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number">number</a> expressing (<strong>in <a href="#glossary_codepoint" title="Codepoint - glossary">codepoints</a></strong>) the location at which to stop extracting characters.</dd>
    </dl>
   </dd>
   <dt>
    Examples</dt>
   <dd>
    <pre class="brush: js">
var myStringView1 = new StringView("Hello world!");
var myStringView2 = myStringView1.subview(3, 7);
alert(myStringView2); // "lo worl"</pre>
   </dd>
  </dl>
  As was explained above, <code>characterOffset</code> is a character index. The index of the first character is 0, and the index of the last character is 1 less than the length of the <code>stringView.</code> <code>subview</code> begins extracting characters at <code>characterOffset</code> and collects <code>charactersLength</code> characters (unless it reaches the end of the string first, in which case it will return fewer).
  <ul>
   <li>If <code>characterOffset</code> is positive and is greater than or equal to the length of the string, <code>substr</code> returns an empty string.</li>
   <li>If <code>characterOffset</code> is negative, <code>substr</code> uses it as a character index from the end of the string. If <code>characterOffset</code> is negative and <code>abs(start)</code> is larger than the length of the string, <code>substr</code> uses 0 as the start index.</li>
   <li>If <code>charactersLength</code> is 0 or negative, <code>substr</code> returns an empty string. If <code>charactersLength</code> is omitted, <code>substr</code> extracts characters to the end of the string.</li>
  </ul>
 </dd>
 <dt id="StringView.prototype.forEachChar()">
  <code>forEachChar()</code></dt>
 <dd>
  <dl>
   <dt>
    Syntax</dt>
   <dd>
    <pre class="syntaxbox">
stringView.forEachChar(<em>callback</em>[, <em>thisObject</em>[, <em>characterOffset</em>[, <em>charactersLength</em>]]])</pre>
   </dd>
   <dt>
    Description</dt>
   <dd>
    Repeatedly invokes a function for each character of the <code>stringView</code>.</dd>
   <dt>
    Arguments</dt>
   <dd>
    <dl>
     <dt>
      <code>callback</code> (required)</dt>
     <dd>
      A <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function">function</a> to be invoked for each character. It will be called with four arguments, expressing respectively:
      <dl>
       <dt>
        <code>charCode</code></dt>
       <dd>
        A <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number">number</a> expressing the Unicode representation of the actual character (<em><a href="#glossary_codepoint" title="Codepoint - glossary">codepoint</a></em>).</dd>
       <dt>
        <code>characterOffset</code></dt>
       <dd>
        A <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number">number</a> expressing the position, <strong>in <a href="#glossary_codepoint" title="Codepoint - glossary">codepoints</a></strong>, of the passed character.</dd>
       <dt>
        <code>rawOffset</code></dt>
       <dd>
        A <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number">number</a> expressing the position, <strong>in <a href="#glossary_codepoint" title="Codepoint - glossary">codepoints</a> parts</strong>, of the passed character.</dd>
       <dt>
        <code>rawDataArray</code></dt>
       <dd>
        The array containing the raw data of the <code>stringView</code>.</dd>
      </dl>
      It will look something like this: <code>callback.call(<em>thisObject</em>, <em>charCode</em>, <em>characterOffset</em>, <em>rawOffset</em>, <em>rawDataArray</em>)</code>. If the encoding is a fixed-length Unicode encoding, <code>characterOffset</code> and <code>rawOffset</code> will be the same number.</dd>
     <dt>
      <code>thisObject</code> <em>(optional)</em></dt>
     <dd>
      The <a href="/en-US/docs/Web/JavaScript/Reference/Operators/this"><code>this</code> object</a> upon which will be executed the <code>callback</code> function.</dd>
     <dt>
      <code>characterOffset</code> <em>(optional)</em></dt>
     <dd>
      A <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number">number</a> expressing (<strong>in <a href="#glossary_codepoint" title="Codepoint - glossary">codepoints</a></strong>) the location at which to begin executing the <code>callback</code> function.</dd>
     <dt>
      <code>charactersLength</code> <em>(optional)</em></dt>
     <dd>
      A <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number">number</a> expressing (<strong>in <a href="#glossary_codepoint" title="Codepoint - glossary">codepoints</a></strong>) the number of invocations of the <code>callback</code> function.</dd>
    </dl>
   </dd>
   <dt>
    Examples</dt>
   <dd>
    <pre class="brush: js">
function myCallback (charCode, characterOffset, rawOffset /*, rawDataArray */) {
&nbsp; this.appendChild(document.createTextNode("char #" + characterOffset + ", raw index: " + rawOffset + ", character: " + String.fromCharCode(charCode)));
&nbsp; this.appendChild(document.createElement("br"));
}

(new StringView("\u4367\uD889\uDE54\u4343\u5431")).forEachChar(myCallback, document.body);</pre>
   </dd>
  </dl>
  <div class="note" id="forEachChar()_note">
   <strong>Note:</strong> <code>stringView.forEachChar()</code> executes <strong>a complete cycle</strong> through <em>all</em> characters in the <code>stringView</code> between <code>characterOffset</code> and <code>characterOffset</code> + <code>charactersLength</code>. If you want to build a custom cycle through a variable-length-encoded&nbsp;<code>stringView</code> (<code>UTF-8</code>, <code>UTF-16</code>), you can use a code like the following, which does not make use of <code>stringView.forEachChar()</code>. If the encoding is a fixed-length one (<code>ASCII</code>, <code>UTF-32</code>, etc.), you can do a normal cycle upon the <code>stringView.rawData</code> array.</div>
  <pre class="brush: js">
var myStringView = new StringView("\u4367\uD889\uDE54\u4343\u5431 – Hello world!"); // an UTF-8-encoded stringView...

alert(myStringView);

for (var nChrCode, nLen = myStringView.rawData.length, nRawIdx = 0, nChrIdx = 0; nRawIdx &lt; nLen; nRawIdx += StringView.getUTF8CharLength(nChrCode), nChrIdx++) {

&nbsp; nChrCode = StringView.loadUTF8CharCode(myStringView.rawData, nRawIdx);

&nbsp; /* Do something with each character... */
&nbsp; alert(String.fromCharCode(nChrCode));

}</pre>
  <div class="note">
   <strong>Note:</strong> For <code>UTF-16</code>, replace <code>getUTF8CharLength()</code> and <code>loadUTF8CharCode()</code> methods respectively with <code>getUTF16CharLength()</code> and <code>loadUTF16CharCode()</code>.</div>
  <p>See also: <a href="#StringView.prototype.makeIndex%28%29" title="#StringView.prototype.makeIndex%28%29"><code>stringView.makeIndex()</code></a> and <a href="#makeIndex%28%29_note" title="#makeIndex%28%29_note">its note</a>.</p>
 </dd>
 <dt id="StringView.prototype.valueOf()">
  <code>valueOf()</code></dt>
 <dd>
  <dl>
   <dt>
    Syntax</dt>
   <dd>
    <pre class="syntaxbox">
stringView.valueOf()
</pre>
   </dd>
   <dt>
    Description</dt>
   <dd>
    Converts <code>stringView</code>'s content into string and returns it.</dd>
   <dt>
    Arguments</dt>
   <dd>
    <dl>
     <dt>
      <em>none</em></dt>
     <dd>
      <em>No arguments expected.</em></dd>
    </dl>
   </dd>
   <dt>
    Examples</dt>
   <dd>
    <pre class="brush: js">
alert((new StringView("Hello world!")).valueOf() === "Hello world!"); // true</pre>
   </dd>
  </dl>
  <p>JavaScript calls the <code>stringView.valueOf()</code> method to convert an object to a primitive value. You rarely need to invoke the <code>stringView.valueOf()</code> method yourself; JavaScript automatically invokes it when encountering an object where a primitive value is expected.</p>
 </dd>
 <dt id="StringView.prototype.toString()">
  <code>toString()</code></dt>
 <dd>
  <dl>
   <dt>
    Syntax</dt>
   <dd>
    <pre class="syntaxbox">
stringView.toString()</pre>
   </dd>
   <dt>
    Description</dt>
   <dd>
    Converts <code>stringView</code>'s content into string and returns it.</dd>
   <dt>
    Arguments</dt>
   <dd>
    <dl>
     <dt>
      <em>none</em></dt>
     <dd>
      <em>No arguments expected.</em></dd>
    </dl>
   </dd>
   <dt>
    Examples</dt>
   <dd>
    <pre class="brush: js">
alert((new StringView("Hello world!")).toString() === "Hello world!"); // true</pre>
   </dd>
  </dl>
  <p>The <code>stringView.toString()</code> method is automatically called when the object is to be represented as a text value or when an object is referred to in a manner in which a string is expected.</p>
 </dd>
</dl>
<h3 id="Appendix.3A_other_StringView_constructor's_methods_(utilities)">Appendix: other <code>StringView</code> constructor's methods (utilities)</h3>
<dl>
 <dt id="StringView.bytesToBase64()">
  <code>bytesToBase64()</code></dt>
 <dd>
  <dl>
   <dt>
    Syntax</dt>
   <dd>
    <pre class="syntaxbox">
StringView.bytesToBase64(<em>uint8Array</em>)</pre>
   </dd>
   <dt>
    Description</dt>
   <dd>
    Converts an array of <a href="#glossary_byte" title="Byte - glossary">bytes</a> (a <a href="/en-US/docs/Web/JavaScript/Typed_arrays">typed array</a> of <a href="/en-US/docs/Web/JavaScript/Typed_arrays/Uint8Array"><code>Uint8Array</code></a> subclass) into a <a href="/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding"><em>base64</em></a>-encoded string.</dd>
   <dt>
    Arguments</dt>
   <dd>
    <dl>
     <dt>
      <code>typedArray</code> (required)</dt>
     <dd>
      The <a href="/en-US/docs/Web/JavaScript/Typed_arrays/Uint8Array"><code>Uint8Array</code></a> of <a href="#glossary_byte" title="Byte - glossary">bytes</a> to encode to <a href="/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding"><em>base64</em></a>.</dd>
    </dl>
   </dd>
   <dt>
    Examples</dt>
   <dd>
    <pre class="brush: js">
alert(StringView.bytesToBase64([72,101,108,108,111,32,119,111,114,108,100,33])); // "SGVsbG8gd29ybGQh"</pre>
   </dd>
  </dl>
  <p><code>StringView.bytesToBase64()</code> is useful to encode an UTF-8 string to <a href="/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding"><em>base64</em></a>. See <a href="/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding">this article</a> for other stuff.</p>
 </dd>
 <dt id="StringView.base64ToBytes()">
  <code>base64ToBytes()</code></dt>
 <dd>
  <dl>
   <dt>
    Syntax</dt>
   <dd>
    <pre class="syntaxbox">
StringView.base64ToBytes(<em>base64String</em>[, <em>regSize</em>])
</pre>
   </dd>
   <dt>
    Description</dt>
   <dd>
    Decode a <a href="/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding"><em>base64</em></a> string to an array of <a href="#glossary_byte" title="Byte - glossary">bytes</a> and return it. The returned array will be a <a href="/en-US/docs/Web/JavaScript/Typed_arrays">typed array</a> of <a href="/en-US/docs/Web/JavaScript/Typed_arrays/Uint8Array"><code>Uint8Array</code></a> subclass.</dd>
   <dt>
    Arguments</dt>
   <dd>
    <dl>
     <dt>
      <code>base64String</code> (required)</dt>
     <dd>
      The <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/String">string</a> to decode from <a href="/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding"><em>base64</em></a>.</dd>
     <dt>
      <code>regSize</code> <em>(optional)</em></dt>
     <dd>
      The <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number">number</a> of <a href="#glossary_byte" title="Byte - glossary">bytes</a> of which the length must result in a multiple (<code>1</code> or omitted for ASCII, <a href="/en-US/docs/Web/API/DOMString/Binary">binary strings</a> or UTF-8-encoded strings, <code>2</code> for UTF-16 strings, <code>4</code> for UTF-32 strings).</dd>
    </dl>
   </dd>
   <dt>
    Examples</dt>
   <dd>
    <pre class="brush: js">
alert(String.fromCharCode.apply(null, StringView.base64ToBytes("SGVsbG8gd29ybGQh"))); // "Hello world!"</pre>
   </dd>
  </dl>
  <p><code>StringView.base64ToBytes()</code> is a generic utility useful also for binary data. If you want to pass the <code>StringView.base64ToBytes(<em>base64String</em>[, <em>regSize</em>]).buffer</code> property to an <a href="/en-US/docs/Web/JavaScript/Typed_arrays/ArrayBufferView"><code>ArrayBufferView</code></a> subclass different from <a href="/en-US/docs/Web/JavaScript/Typed_arrays/Uint8Array">Uint8Array</a>, <strong>you should make use of the <code>regSize</code> argument</strong>.</p>
 </dd>
 <dt id="StringView.loadUTF8CharCode()">
  <code>loadUTF8CharCode()</code></dt>
 <dd>
  <dl>
   <dt>
    Syntax</dt>
   <dd>
    <pre class="syntaxbox">
StringView.loadUTF8CharCode(<em>typedArray</em>, <em>index</em>)</pre>
   </dd>
   <dt>
    Description</dt>
   <dd>
    Returns the single <a href="#glossary_codepoint" title="Codepoint - glossary">codepoint</a> at the given location from an array of UTF-8-encoded <a href="#glossary_element" title="Element - glossary">elements</a>. An UTF-8-encoded codepoint can occupy up to six elements. This function will recompose all these parts into a codepoint.</dd>
   <dt>
    Arguments</dt>
   <dd>
    <dl>
     <dt>
      <code>typedArray</code> (required)</dt>
     <dd>
      A <a href="/en-US/docs/Web/JavaScript/Typed_arrays">typed array</a> containing the UTF-8 encoded <a href="#glossary_element" title="Element - glossary">elements</a>.</dd>
     <dt>
      <code>index</code> (required)</dt>
     <dd>
      The location to be read.</dd>
    </dl>
   </dd>
   <dt>
    Examples</dt>
   <dd>
    <pre class="brush: js">
var myStringView = new StringView("Hello world!"); // an UTF-8 stringView...
alert(StringView.loadUTF8CharCode(myStringView.rawData, 6)); // 119, which is the character code for "w"</pre>
   </dd>
  </dl>
  <code>StringView.loadUTF8CharCode()</code> is mainly for internal use and generally is of little utility.</dd>
 <dt id="StringView.putUTF8CharCode()">
  <code>putUTF8CharCode()</code></dt>
 <dd>
  <dl>
   <dt>
    Syntax</dt>
   <dd>
    <pre class="syntaxbox">
StringView.putUTF8CharCode(<em>typedArray</em>, <em>charCode</em>, <em>index</em>)
</pre>
   </dd>
   <dt>
    Description</dt>
   <dd>
    Write a single <a href="#glossary_codepoint" title="Codepoint - glossary">codepoint</a> at the given position into a <a href="/en-US/docs/Web/JavaScript/Typed_arrays">typed array</a>. A single UTF-8-encoded codepoint can occupy many <a href="#glossary_element" title="Element - glossary">elements</a> (up to six). This function will split it into the needed parts and will write them. Returns <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined"><code>undefined</code></a>.</dd>
   <dt>
    Arguments</dt>
   <dd>
    <dl>
     <dt>
      <code>typedArray</code> (required)</dt>
     <dd>
      A <a href="/en-US/docs/Web/JavaScript/Typed_arrays">typed array</a> containing the UTF-8 encoded <a href="#glossary_element" title="Element - glossary">elements</a>.</dd>
     <dt>
      <code>charCode</code> (required)</dt>
     <dd>
      A <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number">number</a> expressing the Unicode representation of a character (<em><a href="#glossary_codepoint" title="Codepoint - glossary">codepoint</a></em>).</dd>
     <dt>
      <code>index</code> (required)</dt>
     <dd>
      The location to be overwritten.</dd>
    </dl>
   </dd>
   <dt>
    Examples</dt>
   <dd>
    <pre class="brush: js">
var myStringView = new StringView("Hello world!"); // an UTF-8 stringView...
StringView.putUTF8CharCode(myStringView.rawData, "_".charCodeAt(0), 5)
alert(myStringView); // "Hello_world!"</pre>
   </dd>
  </dl>
  <p><code>StringView.putUTF8CharCode()</code> is mainly for internal use and generally is of little utility.</p>
 </dd>
 <dt id="StringView.getUTF8CharLength()">
  <code>getUTF8CharLength()</code></dt>
 <dd>
  <dl>
   <dt>
    Syntax</dt>
   <dd>
    <pre class="syntaxbox">
StringView.getUTF8CharLength(<em>charCode</em>)</pre>
   </dd>
   <dt>
    Description</dt>
   <dd>
    Returns the number of <a href="#glossary_element" title="Element - glossary">elements</a> occupied by an UTF-8-encoded <a href="#glossary_codepoint" title="Codepoint - glossary">codepoint</a>.</dd>
   <dt>
    Arguments</dt>
   <dd>
    <dl>
     <dt>
      <code>charCode</code> (required)</dt>
     <dd>
      A <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number">number</a> expressing the Unicode representation of a character (<em><a href="#glossary_codepoint" title="Codepoint - glossary">codepoint</a></em>).</dd>
    </dl>
   </dd>
   <dt>
    Examples</dt>
   <dd>
    <pre class="brush: js">
alert(StringView.getUTF8CharLength("C".charCodeAt(0))); // "C" occupies 1 UTF-8-encoded element...
alert(StringView.getUTF8CharLength("⁈".charCodeAt(0))); // "⁈" occupies 3 UTF-8-encoded elements...</pre>
   </dd>
  </dl>
  <p><code>StringView.getUTF8CharLength()</code> is mainly for internal use and generally is of little utility.</p>
 </dd>
 <dt id="StringView.loadUTF16CharCode()">
  <code>loadUTF16CharCode()</code></dt>
 <dd>
  <dl>
   <dt>
    Syntax</dt>
   <dd>
    <pre class="syntaxbox">
StringView.loadUTF16CharCode(<em>typedArray</em>, <em>index</em>)</pre>
   </dd>
   <dt>
    Description</dt>
   <dd>
    Returns the single <a href="#glossary_codepoint" title="Codepoint - glossary">codepoint</a> at the given location from an array of UTF-16-encoded <a href="#glossary_element" title="Element - glossary">elements</a>. An UTF-16 codepoint can occupy up to two UTF-16-encoded <a href="#glossary_element" title="Element - glossary">elements</a>. This function will recompose all these parts into a codepoint.</dd>
   <dt>
    Arguments</dt>
   <dd>
    <dl>
     <dt>
      <code>typedArray</code> (required)</dt>
     <dd>
      A <a href="/en-US/docs/Web/JavaScript/Typed_arrays">typed array</a> containing the UTF-16 encoded <a href="#glossary_element" title="Element - glossary">elements</a>.</dd>
     <dt>
      <code>index</code> (required)</dt>
     <dd>
      The location to be read.</dd>
    </dl>
   </dd>
   <dt>
    Examples</dt>
   <dd>
    <pre class="brush: js">
var myStringView = new StringView("Hello world!", "UTF-16"); // an UTF-16 stringView...
alert(StringView.loadUTF16CharCode(myStringView.rawData, 6)); // 119, which is the character code of "w"</pre>
   </dd>
  </dl>
  <p><code>StringView.loadUTF16CharCode()</code> is mainly for internal use and generally is of little utility.</p>
 </dd>
 <dt id="StringView.putUTF16CharCode()">
  <code>putUTF16CharCode()</code></dt>
 <dd>
  <dl>
   <dt>
    Syntax</dt>
   <dd>
    <pre class="syntaxbox">
StringView.putUTF16CharCode(<em>typedArray</em>, <em>charCode</em>, <em>index</em>)
</pre>
   </dd>
   <dt>
    Description</dt>
   <dd>
    Write a single <a href="#glossary_codepoint" title="Codepoint - glossary">codepoint</a> at the given position into a <a href="/en-US/docs/Web/JavaScript/Typed_arrays">typed array</a>. A single UTF-16-encoded codepoint can occupy up to two UTF-16-encoded <a href="#glossary_element" title="Element - glossary">elements</a>. This function will split it into the needed parts and will write them. Returns <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined"><code>undefined</code></a>.</dd>
   <dt>
    Arguments</dt>
   <dd>
    <dl>
     <dt>
      <code>typedArray</code> (required)</dt>
     <dd>
      A <a href="/en-US/docs/Web/JavaScript/Typed_arrays">typed array</a> containing the UTF-16 encoded <a href="#glossary_element" title="Element - glossary">elements</a>.</dd>
     <dt>
      <code>charCode</code> (required)</dt>
     <dd>
      A <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number">number</a> expressing the Unicode representation of a character (<em><a href="#glossary_codepoint" title="Codepoint - glossary">codepoint</a></em>).</dd>
     <dt>
      <code>index</code> (required)</dt>
     <dd>
      The location to be overwritten.</dd>
    </dl>
   </dd>
   <dt>
    Examples</dt>
   <dd>
    <pre class="brush: js">
var myStringView = new StringView("Hello world!", "UTF-16"); // an UTF-16 stringView...
StringView.putUTF16CharCode(myStringView.rawData, "_".charCodeAt(0), 5)
alert(myStringView); // "Hello_world!"</pre>
   </dd>
  </dl>
  <p><code>StringView.putUTF16CharCode()</code> is mainly for internal use and generally is of little utility.</p>
 </dd>
 <dt id="StringView.getUTF16CharLength()">
  <code>getUTF16CharLength()</code></dt>
 <dd>
  <dl>
   <dt>
    Syntax</dt>
   <dd>
    <pre class="syntaxbox">
StringView.getUTF16CharLength(<em>charCode</em>)
</pre>
   </dd>
   <dt>
    Description</dt>
   <dd>
    Returns the number of <a href="#glossary_element" title="Element - glossary">elements</a> occupied by an UTF-16-encoded <a href="#glossary_codepoint" title="Codepoint - glossary">codepoint</a>.</dd>
   <dt>
    Arguments</dt>
   <dd>
    <dl>
     <dt>
      <code>charCode</code> (required)</dt>
     <dd>
      A <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number">number</a> expressing the Unicode representation of a character (<em><a href="#glossary_codepoint" title="Codepoint - glossary">codepoint</a></em>).</dd>
    </dl>
   </dd>
   <dt>
    Examples</dt>
   <dd>
    <pre class="brush: js">
alert("\uD950\uDF21"); // 0x64321
alert(StringView.b64ToUint6(0x64321)); // "\uD950\uDF21" occupies 2 UTF-16-encoded elements...</pre>
   </dd>
  </dl>
  <p><code>StringView.getUTF16CharLength()</code> is mainly for internal use and generally is of little utility.</p>
 </dd>
 <dt id="StringView.b64ToUint6()">
  <code>b64ToUint6()</code></dt>
 <dd>
  <dl>
   <dt>
    Syntax</dt>
   <dd>
    <pre class="syntaxbox">
StringView.b64ToUint6(<em>charCode</em>)
</pre>
   </dd>
   <dt>
    Description</dt>
   <dd>
    Returns the 6-bit <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number">number</a> corresponding to the given <a href="/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding"><em>base64</em></a> character code.</dd>
   <dt>
    Arguments</dt>
   <dd>
    <dl>
     <dt>
      <code>charCode</code> (required)</dt>
     <dd>
      A <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number">number</a> expressing a <a href="/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding"><em>base64</em></a> character code.</dd>
    </dl>
   </dd>
   <dt>
    Examples</dt>
   <dd>
    <pre class="brush: js">
alert(StringView.b64ToUint6("B".charCodeAt(0))); // "B" stands for 1 in base64 encoding...</pre>
   </dd>
  </dl>
  <code>StringView.b64ToUint6()</code> is mainly for internal use and generally is of little utility.</dd>
 <dt id="StringView.uint6ToB64()">
  <code>uint6ToB64()</code></dt>
 <dd>
  <dl>
   <dt>
    Syntax</dt>
   <dd>
    <pre class="syntaxbox">
StringView.uint6ToB64(<em>uint6</em>)</pre>
   </dd>
   <dt>
    Description</dt>
   <dd>
    Returns the <a href="/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding"><em>base64</em></a> character code corresponding to the given 6-bit <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number">number</a>.</dd>
   <dt>
    Arguments</dt>
   <dd>
    <dl>
     <dt>
      <code>uint6</code> (required)</dt>
     <dd>
      A 6-bit unsigned <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number">number</a> (0 = <code>uint6</code> &lt; 64).</dd>
    </dl>
   </dd>
   <dt>
    Examples</dt>
   <dd>
    <pre class="brush: js">
alert(String.fromCharCode(StringView.uint6ToB64(1))); // 1 is represented by "B" in base64 encoding...</pre>
   </dd>
  </dl>
  <p><code>StringView.uint6ToB64()</code> is mainly for internal use and generally is of little utility.</p>
 </dd>
</dl>
<h3 id="Advanced_examples">Advanced examples</h3>
<h4 id="Edit_an_ASCII_part_contained_within_a_binary_file">Edit an ASCII part contained within a binary file</h4>
<p>Let's compile this <a href="http://en.wikipedia.org/wiki/C_%28programming_language%29">C</a> program:</p>
<pre class="brush: c">
#include &lt;stdio.h&gt;

int main () {
&nbsp;&nbsp; &nbsp;printf("Hello world!\n");
&nbsp;&nbsp; &nbsp;return 0;
}</pre>
<p>In a 64-bit machine it will result an output like the following first <code>alert</code>. Let's try to translate the <code>"Hello world!"</code> string into the italian <code>"Ciao mondo!!"</code>…</p>
<pre class="brush: js">
var swHelloWorld = StringView.makeFromBase64("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AwAAAAAAAAAAAAAAAAAAAAAAAAAYGAAAAAAAAD4CAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAQAAAkAAAAAAAAAAAAAAAAAAAAAAAAMAAgAcAkAAAAAAAAAAAAAAAAAAAAAAAAMAAwA8AkAAAAAAAAAAAAAAAAAAAAAAAAMABABgAkAAAAAAAAAAAAAAAAAAAAAAAAMABQCAAkAAAAAAAAAAAAAAAAAAAAAAAAMABgDgAkAAAAAAAAAAAAAAAAAAAAAAAAMABwAeA0AAAAAAAAAAAAAAAAAAAAAAAAMACAAoA0AAAAAAAAAAAAAAAAAAAAAAAAMACQBIA0AAAAAAAAAAAAAAAAAAAAAAAAMACgBgA0AAAAAAAAAAAAAAAAAAAAAAAAMACwCoA0AAAAAAAAAAAAAAAAAAAAAAAAMADADQA0AAAAAAAAAAAAAAAAAAAAAAAAMADQAQBEAAAAAAAAAAAAAAAAAAAAAAAAMADgCUBUAAAAAAAAAAAAAAAAAAAAAAAAMADwCgBUAAAAAAAAAAAAAAAAAAAAAAAAMAEAC0BUAAAAAAAAAAAAAAAAAAAAAAAAMAEQDoBUAAAAAAAAAAAAAAAAAAAAAAAAMAEgDgBmAAAAAAAAAAAAAAAAAAAAAAAAMAEwDoBmAAAAAAAAAAAAAAAAAAAAAAAAMAFADwBmAAAAAAAAAAAAAAAAAAAAAAAAMAFQD4BmAAAAAAAAAAAAAAAAAAAAAAAAMAFgDICGAAAAAAAAAAAAAAAAAAAAAAAAMAFwDQCGAAAAAAAAAAAAAAAAAAAAAAAAMAGAAACWAAAAAAAAAAAAAAAAAAAAAAAAMAGQAQCWAAAAAAAAAAAAAAAAAAAAAAAAMAGgAAAAAAAAAAAAAAAAAAAAAAAQAAAAQA8f8AAAAAAAAAAAAAAAAAAAAAAAAAAAQA8f8AAAAAAAAAAAAAAAAAAAAACAAAAAQA8f8AAAAAAAAAAAAAAAAAAAAAEwAAAAEAFADwBmAAAAAAAAAAAAAAAAAAIAAAAAIADQBABEAAAAAAAAAAAAAAAAAANQAAAAIADQBwBEAAAAAAAAAAAAAAAAAASAAAAAIADQCwBEAAAAAAAAAAAAAAAAAAXgAAAAEAGQAQCWAAAAAAAAEAAAAAAAAAbQAAAAEAEwDoBmAAAAAAAAAAAAAAAAAAlAAAAAIADQDQBEAAAAAAAAAAAAAAAAAAoAAAAAEAEgDgBmAAAAAAAAAAAAAAAAAAvwAAAAQA8f8AAAAAAAAAAAAAAAAAAAAACAAAAAQA8f8AAAAAAAAAAAAAAAAAAAAAxwAAAAEAEQDYBkAAAAAAAAAAAAAAAAAA1QAAAAEAFADwBmAAAAAAAAAAAAAAAAAAAAAAAAQA8f8AAAAAAAAAAAAAAAAAAAAA4QAAAAAAEgDoBmAAAAAAAAAAAAAAAAAA8gAAAAEAFQD4BmAAAAAAAAAAAAAAAAAA+wAAAAAAEgDgBmAAAAAAAAAAAAAAAAAADgEAAAEAFwDQCGAAAAAAAAAAAAAAAAAAJAEAABIADQCQBUAAAAAAAAIAAAAAAAAANAEAACAAAAAAAAAAAAAAAAAAAAAAAAAAUAEAACAAGAAACWAAAAAAAAAAAAAAAAAAWwEAABIAAAAAAAAAAAAAAAAAAAAAAAAAbQEAABAAGAAQCWAAAAAAAAAAAAAAAAAAdAEAABIADgCUBUAAAAAAAAAAAAAAAAAAegEAABIAAAAAAAAAAAAAAAAAAAAAAAAAmQEAABAAGAAACWAAAAAAAAAAAAAAAAAApgEAACAAAAAAAAAAAAAAAAAAAAAAAAAAtQEAABECGAAICWAAAAAAAAAAAAAAAAAAwgEAABEADwCgBUAAAAAAAAQAAAAAAAAA0QEAABIADQAgBUAAAAAAAGUAAAAAAAAA4QEAABAAGQAYCWAAAAAAAAAAAAAAAAAA5gEAABIADQAQBEAAAAAAAAAAAAAAAAAA7QEAABAAGQAQCWAAAAAAAAAAAAAAAAAA+QEAABIADQAABUAAAAAAABUAAAAAAAAA/gEAACAAAAAAAAAAAAAAAAAAAAAAAAAAEgIAABECGAAQCWAAAAAAAAAAAAAAAAAAHgIAACAAAAAAAAAAAAAAAAAAAAAAAAAAOAIAABIACwCoA0AAAAAAAAAAAAAAAAAAAGluaXQuYwBjcnRzdHVmZi5jAF9fSkNSX0xJU1RfXwBkZXJlZ2lzdGVyX3RtX2Nsb25lcwByZWdpc3Rlcl90bV9jbG9uZXMAX19kb19nbG9iYWxfZHRvcnNfYXV4AGNvbXBsZXRlZC42MzU5AF9fZG9fZ2xvYmFsX2R0b3JzX2F1eF9maW5pX2FycmF5X2VudHJ5AGZyYW1lX2R1bW15AF9fZnJhbWVfZHVtbXlfaW5pdF9hcnJheV9lbnRyeQBoZWxsby5jAF9fRlJBTUVfRU5EX18AX19KQ1JfRU5EX18AX19pbml0X2FycmF5X2VuZABfRFlOQU1JQwBfX2luaXRfYXJyYXlfc3RhcnQAX0dMT0JBTF9PRkZTRVRfVEFCTEVfAF9fbGliY19jc3VfZmluaQBfSVRNX2RlcmVnaXN0ZXJUTUNsb25lVGFibGUAZGF0YV9zdGFydABwdXRzQEBHTElCQ18yLjIuNQBfZWRhdGEAX2ZpbmkAX19saWJjX3N0YXJ0X21haW5AQEdMSUJDXzIuMi41AF9fZGF0YV9zdGFydABfX2dtb25fc3RhcnRfXwBfX2Rzb19oYW5kbGUAX0lPX3N0ZGluX3VzZWQAX19saWJjX2NzdV9pbml0AF9lbmQAX3N0YXJ0AF9fYnNzX3N0YXJ0AG1haW4AX0p2X1JlZ2lzdGVyQ2xhc3NlcwBfX1RNQ19FTkRfXwBfSVRNX3JlZ2lzdGVyVE1DbG9uZVRhYmxlAF9pbml0AA==", "ASCII", 1444, 12);

alert(String.fromCharCode.apply(null, swHelloWorld.bufferView)); // swHelloWorld.buffer contains the whole file
alert(swHelloWorld); // "Hello world"

/* traslating "Hello world" into italian... */

swHelloWorld.rawData.set((new StringView("Ciao mondo!!", "ASCII")).rawData);

/* download the new executable file... */

location.assign(URL.createObjectURL(new Blob([swHelloWorld.buffer], { "type": "application\/x-executable" })));</pre>
<div class="note">
 <strong>Note:</strong> The executable above has been compiled with <a href="http://gcc.gnu.org/gcc-4.8/" title="http://gcc.gnu.org/gcc-4.8/">GNU GCC 4.8.1</a> running on a 64-bit machine with <a href="https://www.archlinux.org/" title="https://www.archlinux.org/">Arch GNU/Linux</a>.</div>
<h2 id="Glossary">Glossary</h2>
<dl>
 <dt id="glossary_element">
  Element</dt>
 <dd>
  An item of the backing array (whether <a href="/en-US/docs/Web/JavaScript/Typed_arrays/Uint8Array"><code>Uint8Array</code></a>, <a href="/en-US/docs/Web/JavaScript/Typed_arrays/Uint16Array"><code>Uint16Array</code></a>, <a href="/en-US/docs/Web/JavaScript/Typed_arrays/Uint32Array"><code>Uint32Array</code></a>, etc.)</dd>
 <dt id="glossary_codepoint">
  Codepoint</dt>
 <dd>
  An unique number for each Unicode character. It is rappresented by a collection of 1-6 <code>uint8</code> <a href="#glossary_element" title="Element - glossary">elements</a> for <code>UTF-8</code>, 1-2 <code>uint16</code> <a href="#glossary_element" title="Element - glossary">elements</a> for <code>UTF-16</code>, 1 <code>uint32</code> <a href="#glossary_element" title="Element - glossary">element</a> for <code>UCS4</code>, 1 <code>uint8</code> <a href="#glossary_element" title="Element - glossary">element</a> for <code>ASCII</code>, or something else.</dd>
 <dt id="glossary_byte">
  Byte</dt>
 <dd>
  A collection of 8 <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators" title="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators">bits</a>.</dd>
 <dt id="glossary_null_codepoint">
  <code>NULL</code> codepoint</dt>
 <dd>
  The character whose <a href="#glossary_codepoint">codepoint</a> is equal to <code>0</code> (<code>'\0'</code>).</dd>
</dl>
<h2 id="Notes">Notes</h2>
<ul>
 <li>When you include the script <strong>stringview.js</strong> into a page, <strong>no other variables than <code>StringView</code> itself will be added to the global scope</strong>.</li>
 <li><code>StringView</code> is an <strong>highly extensible</strong> library, that anyone can extend by adding methods to the object <code>StringView.prototype</code>.<br />
  For example, imagine you want to create a method similar to <code>string.replace()</code>, but for <code>stringView</code> objects. Maybe you should want to solve a situation like the following:
  <pre class="brush: js">
var oMyStringView = new StringView("Hello,&amp;nbsp;strange&amp;nbsp;people!"); // UTF-8
var oMyRegExp = new CLikeRegExp("&amp;nbsp;", "g");

alert(oMyStringView.replace(oMyRegExp, " ")); // "Hello, strange people!\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"

/* stringView.replace() will be different from string.replace() because it act also on the source: */
alert(oMyStringView); // "Hello, strange people!\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"</pre>
  As you can see, the previous example needs you to create two new algorithms: the <code>CLikeRegExp()</code> constructor – a constructor of C-like regular expression objects – and <code>StringView.prototype.replace()</code> – the new method, able to act on <code>stringView</code> instances. Well, just include <strong>stringview.js</strong> to your scope and work on them in another script:
  <pre class="brush: js">
/* A constructor of C-like regular expression objects... */
function CLikeRegExp (sRegExp, sFlags) {
&nbsp;&nbsp; &nbsp;/**
&nbsp;&nbsp; &nbsp;*&nbsp; [...]
&nbsp;&nbsp; &nbsp;*
&nbsp;&nbsp; &nbsp;*&nbsp; CONSTRUCTOR CODE HERE!
&nbsp;&nbsp; &nbsp;**/
}

/* A "replace" method for StringView... */
StringView.prototype.replace = function (oCLikeRegExp, sWith) {
&nbsp;&nbsp; &nbsp;/**
&nbsp;&nbsp; &nbsp;*&nbsp; [...]
&nbsp;&nbsp; &nbsp;*
&nbsp;&nbsp; &nbsp;*&nbsp; METHOD CODE HERE!
&nbsp;&nbsp; &nbsp;**/
};</pre>
 </li>
 <li id="note_about_length">If you want to create a <code>stringView</code> inside a <em>bigger</em> empty buffer, like in the following <a href="http://en.wikipedia.org/wiki/C_%28programming_language%29">C</a> line
  <pre class="brush: c">
/* myBuffer: 12 character followed by 1012 NULLs... */
char myBuffer[1024] = "Hello world!";</pre>
  you should do something like this:
  <pre class="brush: js">
var myBuffer = new StringView(1024);
/* myBuffer: 12 character followed by 1012 NULLs... */
var myContent = new StringView("Hello world!");
myBuffer.rawData.set(myContent.rawData, myContent.rawData.length);</pre>
 </li>
 <li><code>StringView</code> is a constructor and a collection of methods <strong>whose aim is <em>to work strictly on arrays of numbers</em></strong> rather than on creating new immutable JavaScript strings. Keep it in mind when you try to extend its <code>prototype</code>.</li>
 <li>Since <code>stringView</code>, unlike <a href="http://en.wikipedia.org/wiki/C_%28programming_language%29">C</a> strings, has a <code>length</code> property, there are no reasons to add a <a href="#glossary_null_codepoint"><code>NULL</code> codepoint</a> (<code>'\0'</code>) after the termination of a string.</li>
 <li><code>StringView</code> has been proposed as <em>strawman</em> for <a href="http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts">ES6</a> on <strong>ECMAScript Bugs</strong>. Everyone can partecipate in the discussion at <a class="external" href="http://bugs.ecmascript.org/show_bug.cgi?id=1557" title="Bug 1557 — StringView – a proposal for a native typed arrays API ">bug&nbsp;1557</a>.</li>
</ul>
<h2 id="See_also">See also</h2>
<ul>
 <li><a href="/en-US/docs/Web/JavaScript/Typed_arrays/ArrayBuffer"><code>ArrayBuffer</code></a></li>
 <li><a href="/en-US/docs/Web/JavaScript/Typed_arrays">Typed arrays</a></li>
 <li><a href="/en-US/docs/Web/JavaScript/Typed_arrays/ArrayBufferView"><code>ArrayBufferView</code></a></li>
 <li><a href="/en-US/docs/Web/JavaScript/Typed_arrays/Uint8Array"><code>Uint8Array</code></a>, <a href="/en-US/docs/Web/JavaScript/Typed_arrays/Uint16Array"><code>Uint16Array</code></a>, <a href="/en-US/docs/Web/JavaScript/Typed_arrays/Uint32Array"><code>Uint32Array</code></a></li>
 <li><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/String"><code>String</code></a></li>
 <li><a href="/en-US/docs/Web/API/DOMString"><code>DOMString</code></a></li>
 <li><a href="/en-US/docs/Web/API/DOMString/Binary">Binary string</a></li>
 <li><a href="/en-US/docs/Web/JavaScript/Typed_arrays/DataView" title="/en-US/docs/Web/JavaScript/Typed_arrays/DataView"><code>DataView</code></a></li>
 <li><a href="/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding" title="/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding">Base64 encoding and decoding</a></li>
 <li><a href="http://en.wikipedia.org/wiki/Unicode" title="http://en.wikipedia.org/wiki/Unicode">Wikipidia article about Unicode</a></li>
</ul>
Revert to this revision