Path: blob/trunk/third_party/closure/goog/net/streams/base64streamdecoder.js
1865 views
// Copyright 2016 The Closure Library Authors. All Rights Reserved.1//2// Licensed under the Apache License, Version 2.0 (the "License");3// you may not use this file except in compliance with the License.4// You may obtain a copy of the License at5//6// http://www.apache.org/licenses/LICENSE-2.07//8// Unless required by applicable law or agreed to in writing, software9// distributed under the License is distributed on an "AS-IS" BASIS,10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.11// See the License for the specific language governing permissions and12// limitations under the License.1314/**15* @fileoverview A base64 stream decoder.16*17* Base64 encoding bytes in the buffer will be decoded and delivered in a batch.18* - Decodes input string in 4-character groups.19* - Accepts both normal and websafe characters (see {@link goog.crypt.base64}).20* - Whitespaces are skipped.21* - Further input after padding characters are decoded normally. Padding22* characters are simply treated as 6 input bits (like other characters),23* and has no more semantics meaning to the decoder.24*25*/2627goog.provide('goog.net.streams.Base64StreamDecoder');2829goog.require('goog.asserts');30goog.require('goog.crypt.base64');3132goog.scope(function() {333435/**36* Base64 stream decoder.37*38* @constructor39* @struct40* @final41* @package42*/43goog.net.streams.Base64StreamDecoder = function() {44/**45* If the input stream is still valid.46* @private {boolean}47*/48this.isInputValid_ = true;4950/**51* The current position in the streamed data that has been processed, i.e.52* the position right before {@code leftoverInput_}.53* @private {number}54*/55this.streamPos_ = 0;5657/**58* The leftover characters when grouping input characters into four.59* @private {string}60*/61this.leftoverInput_ = '';62};636465var Decoder = goog.net.streams.Base64StreamDecoder;666768/**69* Checks if the decoder has aborted due to invalid input.70*71* @return {boolean} true if the input is still valid.72*/73Decoder.prototype.isInputValid = function() {74return this.isInputValid_;75};767778/**79* @param {string} input The current input string to be processed80* @param {string} errorMsg Additional error message81* @throws {!Error} Throws an error indicating where the stream is broken82* @private83*/84Decoder.prototype.error_ = function(input, errorMsg) {85this.isInputValid_ = false;86throw Error(87'The stream is broken @' + this.streamPos_ + '. Error: ' + errorMsg +88'. With input:\n' + input);89};909192/**93* Decodes the input stream.94*95* @param {string} input The next part of input stream96* @return {?Array<number>} decoded bytes in an array, or null if needs more97* input data to decode any new bytes98* @throws {!Error} Throws an error message if the input is invalid99*/100Decoder.prototype.decode = function(input) {101goog.asserts.assertString(input);102103if (!this.isInputValid_) {104this.error_(input, 'stream already broken');105}106107this.leftoverInput_ += input;108109var groups = Math.floor(this.leftoverInput_.length / 4);110if (groups == 0) {111return null;112}113114try {115var result = goog.crypt.base64.decodeStringToByteArray(116this.leftoverInput_.substr(0, groups * 4));117} catch (e) {118this.error_(this.leftoverInput_, e.message);119}120121this.streamPos_ += groups * 4;122this.leftoverInput_ = this.leftoverInput_.substr(groups * 4);123return result;124};125126127}); // goog.scope128129130