node-postgres/lib/types/arrayParser.js

93 lines
2.1 KiB
JavaScript

function ArrayParser(source, converter) {
this.source = source;
this.converter = converter;
this.pos = 0;
this.entries = [];
this.recorded = [];
this.dimension = 0;
if (!this.converter) {
this.converter = function(entry) {
return entry;
};
}
}
ArrayParser.prototype.eof = function() {
return this.pos >= this.source.length;
};
ArrayParser.prototype.nextChar = function() {
var c;
if ((c = this.source[this.pos++]) === "\\") {
return {
char: this.source[this.pos++],
escaped: true
};
} else {
return {
char: c,
escaped: false
};
}
};
ArrayParser.prototype.record = function(c) {
return this.recorded.push(c);
};
ArrayParser.prototype.newEntry = function(includeEmpty) {
var entry;
if (this.recorded.length > 0 || includeEmpty) {
entry = this.recorded.join("");
if (entry === "NULL" && !includeEmpty) {
entry = null;
}
if (entry !== null) {
entry = this.converter(entry);
}
this.entries.push(entry);
this.recorded = [];
}
};
ArrayParser.prototype.parse = function(nested) {
var c, p, quote;
if (nested === null) {
nested = false;
}
quote = false;
while (!this.eof()) {
c = this.nextChar();
if (c.char === "{" && !quote) {
this.dimension++;
if (this.dimension > 1) {
p = new ArrayParser(this.source.substr(this.pos - 1), this.converter);
this.entries.push(p.parse(true));
this.pos += p.pos - 2;
}
} else if (c.char === "}" && !quote) {
this.dimension--;
if (this.dimension === 0) {
this.newEntry();
if (nested) {
return this.entries;
}
}
} else if (c.char === '"' && !c.escaped) {
if (quote) {
this.newEntry(true);
}
quote = !quote;
} else if (c.char === ',' && !quote) {
this.newEntry();
} else {
this.record(c.char);
}
}
if (this.dimension !== 0) {
throw "array dimension not balanced";
}
return this.entries;
};
module.exports = {
create: function(source, converter){
return new ArrayParser(source, converter);
}
};