Skip to content

Commit

Permalink
Merge pull request #13303 from Snuffleupagus/BaseStream
Browse files Browse the repository at this point in the history
Add an abstract base-class, which all the various Stream implementations inherit from
  • Loading branch information
timvandermeij authored May 1, 2021
2 parents af4dc55 + 2ac4ad3 commit f6f3351
Show file tree
Hide file tree
Showing 23 changed files with 1,481 additions and 1,425 deletions.
98 changes: 98 additions & 0 deletions src/core/ascii_85_stream.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/* Copyright 2012 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { DecodeStream } from "./decode_stream.js";
import { isWhiteSpace } from "./core_utils.js";

class Ascii85Stream extends DecodeStream {
constructor(str, maybeLength) {
// Most streams increase in size when decoded, but Ascii85 streams
// typically shrink by ~20%.
if (maybeLength) {
maybeLength = 0.8 * maybeLength;
}
super(maybeLength);

this.str = str;
this.dict = str.dict;
this.input = new Uint8Array(5);
}

readBlock() {
const TILDA_CHAR = 0x7e; // '~'
const Z_LOWER_CHAR = 0x7a; // 'z'
const EOF = -1;

const str = this.str;

let c = str.getByte();
while (isWhiteSpace(c)) {
c = str.getByte();
}

if (c === EOF || c === TILDA_CHAR) {
this.eof = true;
return;
}

const bufferLength = this.bufferLength;
let buffer, i;

// special code for z
if (c === Z_LOWER_CHAR) {
buffer = this.ensureBuffer(bufferLength + 4);
for (i = 0; i < 4; ++i) {
buffer[bufferLength + i] = 0;
}
this.bufferLength += 4;
} else {
const input = this.input;
input[0] = c;
for (i = 1; i < 5; ++i) {
c = str.getByte();
while (isWhiteSpace(c)) {
c = str.getByte();
}

input[i] = c;

if (c === EOF || c === TILDA_CHAR) {
break;
}
}
buffer = this.ensureBuffer(bufferLength + i - 1);
this.bufferLength += i - 1;

// partial ending;
if (i < 5) {
for (; i < 5; ++i) {
input[i] = 0x21 + 84;
}
this.eof = true;
}
let t = 0;
for (i = 0; i < 5; ++i) {
t = t * 85 + (input[i] - 0x21);
}

for (i = 3; i >= 0; --i) {
buffer[bufferLength + i] = t & 0xff;
t >>= 8;
}
}
}
}

export { Ascii85Stream };
79 changes: 79 additions & 0 deletions src/core/ascii_hex_stream.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/* Copyright 2012 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { DecodeStream } from "./decode_stream.js";

class AsciiHexStream extends DecodeStream {
constructor(str, maybeLength) {
// Most streams increase in size when decoded, but AsciiHex streams shrink
// by 50%.
if (maybeLength) {
maybeLength = 0.5 * maybeLength;
}
super(maybeLength);

this.str = str;
this.dict = str.dict;

this.firstDigit = -1;
}

readBlock() {
const UPSTREAM_BLOCK_SIZE = 8000;
const bytes = this.str.getBytes(UPSTREAM_BLOCK_SIZE);
if (!bytes.length) {
this.eof = true;
return;
}

const maxDecodeLength = (bytes.length + 1) >> 1;
const buffer = this.ensureBuffer(this.bufferLength + maxDecodeLength);
let bufferLength = this.bufferLength;

let firstDigit = this.firstDigit;
for (const ch of bytes) {
let digit;
if (ch >= /* '0' = */ 0x30 && ch <= /* '9' = */ 0x39) {
digit = ch & 0x0f;
} else if (
(ch >= /* 'A' = */ 0x41 && ch <= /* 'Z' = */ 0x46) ||
(ch >= /* 'a' = */ 0x61 && ch <= /* 'z' = */ 0x66)
) {
digit = (ch & 0x0f) + 9;
} else if (ch === /* '>' = */ 0x3e) {
this.eof = true;
break;
} else {
// Probably whitespace, ignoring.
continue;
}
if (firstDigit < 0) {
firstDigit = digit;
} else {
buffer[bufferLength++] = (firstDigit << 4) | digit;
firstDigit = -1;
}
}
if (firstDigit >= 0 && this.eof) {
// incomplete byte
buffer[bufferLength++] = firstDigit << 4;
firstDigit = -1;
}
this.firstDigit = firstDigit;
this.bufferLength = bufferLength;
}
}

export { AsciiHexStream };
106 changes: 106 additions & 0 deletions src/core/base_stream.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/* Copyright 2021 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { shadow, unreachable } from "../shared/util.js";

class BaseStream {
constructor() {
if (this.constructor === BaseStream) {
unreachable("Cannot initialize BaseStream.");
}
}

// eslint-disable-next-line getter-return
get length() {
unreachable("Abstract getter `length` accessed");
}

// eslint-disable-next-line getter-return
get isEmpty() {
unreachable("Abstract getter `isEmpty` accessed");
}

get isDataLoaded() {
return shadow(this, "isDataLoaded", true);
}

getByte() {
unreachable("Abstract method `getByte` called");
}

getBytes(length, forceClamped = false) {
unreachable("Abstract method `getBytes` called");
}

peekByte() {
const peekedByte = this.getByte();
if (peekedByte !== -1) {
this.pos--;
}
return peekedByte;
}

peekBytes(length, forceClamped = false) {
const bytes = this.getBytes(length, forceClamped);
this.pos -= bytes.length;
return bytes;
}

getUint16() {
const b0 = this.getByte();
const b1 = this.getByte();
if (b0 === -1 || b1 === -1) {
return -1;
}
return (b0 << 8) + b1;
}

getInt32() {
const b0 = this.getByte();
const b1 = this.getByte();
const b2 = this.getByte();
const b3 = this.getByte();
return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3;
}

getByteRange(begin, end) {
unreachable("Abstract method `getByteRange` called");
}

skip(n) {
this.pos += n || 1;
}

reset() {
unreachable("Abstract method `reset` called");
}

moveStart() {
unreachable("Abstract method `moveStart` called");
}

makeSubStream(start, length, dict = null) {
unreachable("Abstract method `makeSubStream` called");
}

/**
* @returns {Array | null}
*/
getBaseStreams() {
return null;
}
}

export { BaseStream };
2 changes: 1 addition & 1 deletion src/core/ccitt_stream.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

import { Dict, isDict } from "./primitives.js";
import { CCITTFaxDecoder } from "./ccitt.js";
import { DecodeStream } from "./stream.js";
import { DecodeStream } from "./decode_stream.js";

class CCITTFaxStream extends DecodeStream {
constructor(str, maybeLength, params) {
Expand Down
Loading

0 comments on commit f6f3351

Please sign in to comment.