From 8cb44e3cf37667f4f1d93bd8a68205ed3a43f5ed Mon Sep 17 00:00:00 2001 From: brianc Date: Fri, 15 Oct 2010 00:24:58 -0500 Subject: [PATCH] substantial refactoring of the parser --- lib/parser.js | 111 +++++++++++++++++---------------------- test/unit/test-helper.js | 1 + 2 files changed, 48 insertions(+), 64 deletions(-) diff --git a/lib/parser.js b/lib/parser.js index 8fc57e7d..b7f0fba1 100644 --- a/lib/parser.js +++ b/lib/parser.js @@ -8,94 +8,81 @@ p.setBuffer = function(buffer) { var remaining = this.lastBuffer.length - this.lastOffset; var combinedBuffer = new Buffer(buffer.length + remaining); this.lastBuffer.copy(combinedBuffer, 0, this.lastOffset); - this.lastBuffer = false; buffer.copy(combinedBuffer, remaining, 0); - this.buffer = combinedBuffer; - this.offset = 0; - return; + buffer = combinedBuffer; } this.buffer = buffer; this.offset = 0; }; +var messageNames = { + R: 'authenticationOk', + S: 'parameterStatus', + K: 'backendKeyData', + C: 'commandComplete', + Z: 'readyForQuery', + T: 'rowDescription', + D: 'dataRow', + E: 'error' +}; + p.parseMessage = function() { - if(this.buffer.length == this.offset) { - //clean packet - nothing left for next buffer - return false; - } var remaining = this.buffer.length - this.offset - 1; - var messageID = this.buffer[this.offset]; - var length = this.peekInt32(this.offset + 1); - if(remaining < 5 || remaining < length) { + if(remaining < 5) { + //cannot read id + length without at least 5 bytes + //just abort the read now this.lastBuffer = this.buffer; this.lastOffset = this.offset; + return; + } + var id = this.readChar(); + var message = { + id: id, + name: messageNames[id], + length: this.parseInt32() + }; + + if(remaining < message.length) { + this.lastBuffer = this.buffer; + //rewind the last 5 bytes we read + this.lastOffset = this.offset-5; return false; } - return this["parse"+messageID](); + return this["parse"+message.id](message); }; -//parse 'R' message -p.parse82 = function() { - var type = this.buffer[this.offset++]; - var length = this.parseLength(); - if(length == 8) { +p.parseR = function(msg) { + if(msg.length == 8) { this.offset += 4; - return { - name: 'authenticationOk', - id: 'R', - length: length - } + return msg; } - throw new Error("Unknown AuthenticatinOk message type"); + throw new Error("Unknown authenticatinOk message type"); }; -//parse 'S' message -p.parse83 = function(buffer) { - var msg = this.parseStart('parameterStatus'); +p.parseS = function(msg) { msg.parameterName = this.parseCString(); msg.parameterValue = this.parseCString(); return msg; }; -//parse 'K' message -p.parse75 = function() { - var msg = this.parseStart('backendKeyData'); +p.parseK = function(msg) { msg.processID = this.parseInt32(); msg.secretKey = this.parseInt32(); return msg; }; -//parse 'C' message -p.parse67 = function() { - var msg = this.parseStart('commandComplete'); +p.parseC = function(msg) { msg.text = this.parseCString(); return msg; }; -//parses common start of message packets -p.parseStart = function(name) { - return { - name: name, - id: this.readChar(), - length: this.parseInt32() - } -}; - -p.readChar = function() { - return Buffer([this.buffer[this.offset++]]).toString('utf8'); -}; - -//parse 'Z' message -p.parse90 = function() { - var msg = this.parseStart('readyForQuery'); +p.parseZ = function(msg) { msg.status = this.readChar(); return msg; }; -//parse 'T' message -p.parse84 = function() { - var msg = this.parseStart('rowDescription'); +p.parseT = function(msg) { msg.fieldCount = this.parseInt16(); var fields = []; for(var i = 0; i < msg.fieldCount; i++){ @@ -106,7 +93,7 @@ p.parse84 = function() { }; p.parseField = function() { - var row = { + var field = { name: this.parseCString(), tableID: this.parseInt32(), columnID: this.parseInt16(), @@ -115,12 +102,10 @@ p.parseField = function() { dataTypeModifier: this.parseInt32(), format: this.parseInt16() == 0 ? 'text' : 'binary' }; - return row; + return field; }; -//parse 'D' message -p.parse68 = function() { - var msg = this.parseStart('dataRow'); +p.parseD = function(msg) { var fieldCount = this.parseInt16(); var fields = []; for(var i = 0; i < fieldCount; i++) { @@ -132,9 +117,7 @@ p.parse68 = function() { return msg; }; -//parse 'E' message -p.parse69 = function() { - var msg = this.parseStart('error'); +p.parseE = function(msg) { var fields = {}; var fieldType = this.readString(1); while(fieldType != '\0') { @@ -156,6 +139,9 @@ p.parse69 = function() { return msg; }; +p.readChar = function() { + return Buffer([this.buffer[this.offset++]]).toString('utf8'); +}; p.parseInt32 = function() { var value = this.peekInt32(); @@ -174,11 +160,8 @@ p.peekInt32 = function(offset) { p.parseInt16 = function() { - return ((this.buffer[this.offset++] << 8) + (this.buffer[this.offset++] << 0)); -}; - -p.parseLength = function() { - return this.parseInt32(); + return ((this.buffer[this.offset++] << 8) + + (this.buffer[this.offset++] << 0)); }; p.readString = function(length) { diff --git a/test/unit/test-helper.js b/test/unit/test-helper.js index 36ecfd19..8674ac4c 100644 --- a/test/unit/test-helper.js +++ b/test/unit/test-helper.js @@ -53,6 +53,7 @@ test = function(name, action) { global.TEST_RESULTS.testCount++; action(); }catch(e) { + console.log(''); console.log(name); throw e; }