Browse Source

Split out Stream functionality

Andreas Gal 14 years ago
parent
commit
d3f3e611c3
  1. 136
      pdf.js

136
pdf.js

@ -20,6 +20,44 @@ var HashMap = (function() {
return constructor; return constructor;
})(); })();
var Stream = (function() {
function constructor(arrayBuffer) {
this.bytes = Uint8Array(arrayBuffer);
this.pos = 0;
}
constructor.prototype = {
reset: function() {
this.pos = 0;
},
lookChar: function() {
var bytes = this.bytes;
if (this.pos >= bytes.length)
return EOF;
return String.fromCharCode(bytes[this.pos]);
},
getChar: function() {
var ch = this.lookChar();
this.pos++;
return ch;
},
putBack: function() {
this.pos--;
},
skipChar: function() {
this.pos++;
},
moveStart: function(delta) {
this.bytes = Uint8Array(arrayBuffer, delta);
this.pos -= delta;
}
};
constructor.EOF = -1;
return constructor;
});
var Obj = (function() { var Obj = (function() {
function constructor(type, value) { function constructor(type, value) {
this.type = type; this.type = type;
@ -62,11 +100,8 @@ var Obj = (function() {
})(); })();
var Lexer = (function() { var Lexer = (function() {
const EOF = -1; function constructor(stream) {
this.stream = stream;
function constructor(bytes) {
this.bytes = bytes;
this.pos = 0;
} }
// A '1' in this array means the character is white space. A '1' or // A '1' in this array means the character is white space. A '1' or
@ -106,29 +141,14 @@ var Lexer = (function() {
constructor.prototype = { constructor.prototype = {
error: function(msg) { error: function(msg) {
}, // TODO
lookChar: function() {
var bytes = this.bytes;
if (this.pos >= bytes.length)
return EOF;
return String.fromCharCode(bytes[this.pos]);
},
getChar: function() {
var ch = this.lookChar();
this.pos++;
return ch;
},
putBack: function() {
this.pos--;
},
skipChar: function() {
this.pos++;
}, },
getNumber: function(ch) { getNumber: function(ch) {
var floating = false; var floating = false;
var str = ch; var str = ch;
var stream = this.stream;
do { do {
ch = this.getChar(); ch = stream.getChar();
if (ch == "." && !floating) { if (ch == "." && !floating) {
str += ch; str += ch;
floating = true; floating = true;
@ -142,7 +162,7 @@ var Lexer = (function() {
floating = true; floating = true;
} else { } else {
// put back the last character, it doesn't belong to us // put back the last character, it doesn't belong to us
this.putBack(); stream.putBack();
break; break;
} }
} while (true); } while (true);
@ -166,8 +186,9 @@ var Lexer = (function() {
var numParent = 1; var numParent = 1;
var done = false; var done = false;
var str = ch; var str = ch;
var stream = this.stream;
do { do {
switch (ch = this.getChar()) { switch (ch = stream.getChar()) {
case EOF: case EOF:
this.error("Unterminated string"); this.error("Unterminated string");
done = true; done = true;
@ -184,7 +205,7 @@ var Lexer = (function() {
} }
break; break;
case '\\': case '\\':
switch (ch = this.getChar()) { switch (ch = stream.getChar()) {
case 'n': case 'n':
str += '\n'; str += '\n';
break; break;
@ -208,23 +229,22 @@ var Lexer = (function() {
case '0': case '1': case '2': case '3': case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7': case '4': case '5': case '6': case '7':
var x = ch - '0'; var x = ch - '0';
ch = this.lookChar(); ch = stream.lookChar();
if (ch >= '0' && ch <= '7') { if (ch >= '0' && ch <= '7') {
this.getChar(); this.getChar();
x = (x << 3) + (x - '0'); x = (x << 3) + (x - '0');
ch = this.lookChar(); ch = stream.lookChar();
if (ch >= '0' && ch <= '7') { if (ch >= '0' && ch <= '7') {
getChar(); stream.getChar();
x = (x << 3) + (x - '0'); x = (x << 3) + (x - '0');
} }
} }
str += String.fromCharCode(x); str += String.fromCharCode(x);
break; break;
case '\r': case '\r':
ch = this.lookChar(); ch = stream.lookChar();
if (ch == '\n') { if (ch == '\n')
this.getChar(); stream.getChar();
}
break; break;
case '\n': case '\n':
break; break;
@ -248,14 +268,15 @@ var Lexer = (function() {
}, },
getName: function(ch) { getName: function(ch) {
var str = ""; var str = "";
while ((ch = this.lookChar()) != EOF && !specialChars[ch.toCharCode()]) { var stream = this.stream;
this.getChar(); while ((ch = stream.lookChar()) != EOF && !specialChars[ch.toCharCode()]) {
stream.getChar();
if (ch == "#") { if (ch == "#") {
ch = this.lookChar(); ch = stream.lookChar();
var x = ToHexDigit(ch); var x = ToHexDigit(ch);
if (x != -1) { if (x != -1) {
this.getChar(); stream.getChar();
var x2 = ToHexDigit(this.getChar()); var x2 = ToHexDigit(stream.getChar());
if (x2 == -1) if (x2 == -1)
this.error("Illegal digit in hex char in name"); this.error("Illegal digit in hex char in name");
str += String.fromCharCode((x << 4) | x2); str += String.fromCharCode((x << 4) | x2);
@ -273,8 +294,9 @@ var Lexer = (function() {
}, },
getHexString: function(ch) { getHexString: function(ch) {
var str = ""; var str = "";
var stream = this.stream;
while (1) { while (1) {
ch = this.getChar(); ch = stream.getChar();
if (ch == '>') { if (ch == '>') {
break; break;
} else if (ch == EOF) { } else if (ch == EOF) {
@ -295,9 +317,10 @@ var Lexer = (function() {
getObj: function() { getObj: function() {
// skip whitespace and comments // skip whitespace and comments
var comment = false; var comment = false;
var stream = this.stream;
while (true) { while (true) {
var ch; var ch;
if ((ch = this.getChar()) == EOF) if ((ch = stream.getChar()) == EOF)
return new Obj(Object.EOF); return new Obj(Object.EOF);
if (comment) { if (comment) {
if (ch == '\r' || ch == '\n') if (ch == '\r' || ch == '\n')
@ -325,18 +348,18 @@ var Lexer = (function() {
return new Obj(Obj.Cmd, ch); return new Obj(Obj.Cmd, ch);
// hex string or dict punctuation // hex string or dict punctuation
case '<': case '<':
ch = this.lookChar(); ch = stream.lookChar();
if (ch == '<') { if (ch == '<') {
// dict punctuation // dict punctuation
this.getChar(); stream.getChar();
return new Obj(Obj.Cmd, ch); return new Obj(Obj.Cmd, ch);
} }
return this.getHexString(ch); return this.getHexString(ch);
// dict punctuation // dict punctuation
case '>': case '>':
ch = this.lookChar(); ch = stream.lookChar();
if (ch == '>') { if (ch == '>') {
this.getChar(); stream.getChar();
return new Obj(Obj.Cmd, ch); return new Obj(Obj.Cmd, ch);
} }
// fall through // fall through
@ -349,8 +372,8 @@ var Lexer = (function() {
// command // command
var str = ch; var str = ch;
while ((ch = this.lookChar()) != EOF && !specialChars[ch.toCharCode()]) { while ((ch = stream.lookChar()) != EOF && !specialChars[ch.toCharCode()]) {
getChar(); stream.getChar();
if (str.length == 128) { if (str.length == 128) {
error("Command token too long"); error("Command token too long");
break; break;
@ -475,8 +498,8 @@ var Parser = (function() {
})(); })();
var Linearization = (function () { var Linearization = (function () {
function constructor(bytes) { function constructor(stream) {
this.parser = new Parser(new Lexer(bytes), false); this.parser = new Parser(new Lexer(stream), false);
var obj1 = this.parser.getObj(); var obj1 = this.parser.getObj();
var obj2 = this.parser.getObj(); var obj2 = this.parser.getObj();
var obj3 = this.parser.getObj(); var obj3 = this.parser.getObj();
@ -547,8 +570,8 @@ var Linearization = (function () {
})(); })();
var PDFDoc = (function () { var PDFDoc = (function () {
function constructor(arrayBuffer) { function constructor(stream) {
this.setup(arrayBuffer); this.setup(stream);
} }
constructor.prototype = { constructor.prototype = {
@ -576,20 +599,23 @@ var PDFDoc = (function () {
}, },
// Find the header, remove leading garbage and setup the stream // Find the header, remove leading garbage and setup the stream
// starting from the header. // starting from the header.
checkHeader: function(arrayBuffer) { checkHeader: function(stream) {
const headerSearchSize = 1024; const headerSearchSize = 1024;
var stream = new Uint8Array(arrayBuffer); stream.reset();
var skip = 0; var skip = 0;
var header = "%PDF-"; var header = "%PDF-";
while (skip < headerSearchSize) { while (skip < headerSearchSize) {
for (var i = 0; i < header.length; ++i) stream.setPos(skip);
if (this.stream[skip+i] != header.charCodeAt(i)) for (var i = 0; i < header.length; ++i) {
if (stream.getChar() != header.charCodeAt(i))
break; break;
}
// Found the header, trim off any garbage before it. // Found the header, trim off any garbage before it.
if (i == header.length) { if (i == header.length) {
this.stream = new Uint8Array(arrayBuffer, skip); stream.moveStart(skip);
return; return;
} }
} }

Loading…
Cancel
Save