diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..f8fab8c --- /dev/null +++ b/package-lock.json @@ -0,0 +1,13 @@ +{ + "name": "turtle-validator", + "version": "1.0.1", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "n3": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/n3/-/n3-0.11.2.tgz", + "integrity": "sha512-ICSiOmFLbZ4gI35+4H3e2vYGHDC944WZkCa1iVNRAx/mRZESEevQNFhfHaui/lhqynoZYvBVDNjM/2Tfd3TICQ==" + } + } +} diff --git a/package.json b/package.json index f9febd4..09e6313 100644 --- a/package.json +++ b/package.json @@ -1,16 +1,17 @@ { "name": "turtle-validator", - "version": "1.0.1", + "version": "1.0.2", "description": "This command line tool validates Turtle documents and does XSD datatype checks", - "main": "TurtleValidator.js", + "main": "lib/validator.js", "bin": { "ttl": "./TurtleValidator.js" }, "dependencies": { - "n3": "^0.4.0" + "n3": "^0.11.x" }, "devDependencies": {}, "scripts": { + "build": "browserify lib/validator.js -o public/js/ttl.js", "test": "echo \"Error: no test specified\" && exit 1" }, "repository": { diff --git a/public/js/ttl.js b/public/js/ttl.js index eda3328..6b4e654 100644 --- a/public/js/ttl.js +++ b/public/js/ttl.js @@ -1,4 +1,2760 @@ (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o\\"\{\}\|\^\`]/; + +// ## Constructor +function N3Lexer(options) { + if (!(this instanceof N3Lexer)) + return new N3Lexer(options); + options = options || {}; + + // In line mode (N-Triples or N-Quads), only simple features may be parsed + if (options.lineMode) { + // Don't tokenize special literals + this._tripleQuotedString = this._number = this._boolean = /$0^/; + // Swap the tokenize method for a restricted version + var self = this; + this._tokenize = this.tokenize; + this.tokenize = function (input, callback) { + this._tokenize(input, function (error, token) { + if (!error && /^(?:IRI|blank|literal|langcode|typeIRI|\.|eof)$/.test(token.type)) + callback && callback(error, token); + else + callback && callback(error || self._syntaxError(token.type, callback = null)); + }); + }; + } + // Enable N3 functionality by default + this._n3Mode = options.n3 !== false; + // Disable comment tokens by default + this._comments = !!options.comments; +} + +N3Lexer.prototype = { + // ## Regular expressions + // It's slightly faster to have these as properties than as in-scope variables + + _iri: /^<((?:[^ <>{}\\]|\\[uU])+)>[ \t]*/, // IRI with escape sequences; needs sanity check after unescaping + _unescapedIri: /^<([^\x00-\x20<>\\"\{\}\|\^\`]*)>[ \t]*/, // IRI without escape sequences; no unescaping + _unescapedString: /^"[^"\\\r\n]+"/, // non-empty string without escape sequences + _singleQuotedString: /^"(?:[^"\\\r\n]|\\.)*"(?=[^"])|^'(?:[^'\\\r\n]|\\.)*'(?=[^'])/, + _tripleQuotedString: /^""("[^"\\]*(?:(?:\\.|"(?!""))[^"\\]*)*")""|^''('[^'\\]*(?:(?:\\.|'(?!''))[^'\\]*)*')''/, + _langcode: /^@([a-z]+(?:-[a-z0-9]+)*)(?=[^a-z0-9\-])/i, + _prefix: /^((?:[A-Za-z\xc0-\xd6\xd8-\xf6\xf8-\u02ff\u0370-\u037d\u037f-\u1fff\u200c\u200d\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff])(?:\.?[\-0-9A-Z_a-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u037f-\u1fff\u200c\u200d\u203f\u2040\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff])*)?:(?=[#\s<])/, + _prefixed: /^((?:[A-Za-z\xc0-\xd6\xd8-\xf6\xf8-\u02ff\u0370-\u037d\u037f-\u1fff\u200c\u200d\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff])(?:\.?[\-0-9A-Z_a-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u037f-\u1fff\u200c\u200d\u203f\u2040\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff])*)?:((?:(?:[0-:A-Z_a-z\xc0-\xd6\xd8-\xf6\xf8-\u02ff\u0370-\u037d\u037f-\u1fff\u200c\u200d\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff]|%[0-9a-fA-F]{2}|\\[!#-\/;=?\-@_~])(?:(?:[\.\-0-:A-Z_a-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u037f-\u1fff\u200c\u200d\u203f\u2040\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff]|%[0-9a-fA-F]{2}|\\[!#-\/;=?\-@_~])*(?:[\-0-:A-Z_a-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u037f-\u1fff\u200c\u200d\u203f\u2040\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff]|%[0-9a-fA-F]{2}|\\[!#-\/;=?\-@_~]))?)?)(?:[ \t]+|(?=\.?[,;!\^\s#()\[\]\{\}"'<]))/, + _variable: /^\?(?:(?:[A-Z_a-z\xc0-\xd6\xd8-\xf6\xf8-\u02ff\u0370-\u037d\u037f-\u1fff\u200c\u200d\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff])(?:[\-0-:A-Z_a-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u037f-\u1fff\u200c\u200d\u203f\u2040\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff])*)(?=[.,;!\^\s#()\[\]\{\}"'<])/, + _blank: /^_:((?:[0-9A-Z_a-z\xc0-\xd6\xd8-\xf6\xf8-\u02ff\u0370-\u037d\u037f-\u1fff\u200c\u200d\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff])(?:\.?[\-0-9A-Z_a-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u037f-\u1fff\u200c\u200d\u203f\u2040\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff])*)(?:[ \t]+|(?=\.?[,;:\s#()\[\]\{\}"'<]))/, + _number: /^[\-+]?(?:\d+\.?\d*([eE](?:[\-\+])?\d+)|\d*\.?\d+)(?=\.?[,;:\s#()\[\]\{\}"'<])/, + _boolean: /^(?:true|false)(?=[.,;\s#()\[\]\{\}"'<])/, + _keyword: /^@[a-z]+(?=[\s#<:])/i, + _sparqlKeyword: /^(?:PREFIX|BASE|GRAPH)(?=[\s#<])/i, + _shortPredicates: /^a(?=\s+|<)/, + _newline: /^[ \t]*(?:#[^\n\r]*)?(?:\r\n|\n|\r)[ \t]*/, + _comment: /#([^\n\r]*)/, + _whitespace: /^[ \t]+/, + _endOfFile: /^(?:#[^\n\r]*)?$/, + + // ## Private methods + + // ### `_tokenizeToEnd` tokenizes as for as possible, emitting tokens through the callback + _tokenizeToEnd: function (callback, inputFinished) { + // Continue parsing as far as possible; the loop will return eventually + var input = this._input, outputComments = this._comments; + while (true) { + // Count and skip whitespace lines + var whiteSpaceMatch, comment; + while (whiteSpaceMatch = this._newline.exec(input)) { + // Try to find a comment + if (outputComments && (comment = this._comment.exec(whiteSpaceMatch[0]))) + callback(null, { line: this._line, type: 'comment', value: comment[1], prefix: '' }); + // Advance the input + input = input.substr(whiteSpaceMatch[0].length, input.length); + this._line++; + } + // Skip whitespace on current line + if (whiteSpaceMatch = this._whitespace.exec(input)) + input = input.substr(whiteSpaceMatch[0].length, input.length); + + // Stop for now if we're at the end + if (this._endOfFile.test(input)) { + // If the input is finished, emit EOF + if (inputFinished) { + // Try to find a final comment + if (outputComments && (comment = this._comment.exec(input))) + callback(null, { line: this._line, type: 'comment', value: comment[1], prefix: '' }); + callback(input = null, { line: this._line, type: 'eof', value: '', prefix: '' }); + } + return this._input = input; + } + + // Look for specific token types based on the first character + var line = this._line, type = '', value = '', prefix = '', + firstChar = input[0], match = null, matchLength = 0, unescaped, inconclusive = false; + switch (firstChar) { + case '^': + // We need at least 3 tokens lookahead to distinguish ^^ and ^^pre:fixed + if (input.length < 3) + break; + // Try to match a type + else if (input[1] === '^') { + this._previousMarker = '^^'; + // Move to type IRI or prefixed name + input = input.substr(2); + if (input[0] !== '<') { + inconclusive = true; + break; + } + } + // If no type, it must be a path expression + else { + if (this._n3Mode) { + matchLength = 1; + type = '^'; + } + break; + } + // Fall through in case the type is an IRI + case '<': + // Try to find a full IRI without escape sequences + if (match = this._unescapedIri.exec(input)) + type = 'IRI', value = match[1]; + // Try to find a full IRI with escape sequences + else if (match = this._iri.exec(input)) { + unescaped = this._unescape(match[1]); + if (unescaped === null || illegalIriChars.test(unescaped)) + return reportSyntaxError(this); + type = 'IRI', value = unescaped; + } + // Try to find a backwards implication arrow + else if (this._n3Mode && input.length > 1 && input[1] === '=') + type = 'inverse', matchLength = 2, value = 'http://www.w3.org/2000/10/swap/log#implies'; + break; + + case '_': + // Try to find a blank node. Since it can contain (but not end with) a dot, + // we always need a non-dot character before deciding it is a blank node. + // Therefore, try inserting a space if we're at the end of the input. + if ((match = this._blank.exec(input)) || + inputFinished && (match = this._blank.exec(input + ' '))) + type = 'blank', prefix = '_', value = match[1]; + break; + + case '"': + case "'": + // Try to find a non-empty double-quoted literal without escape sequences + if (match = this._unescapedString.exec(input)) + type = 'literal', value = match[0]; + // Try to find any other literal wrapped in a pair of single or double quotes + else if (match = this._singleQuotedString.exec(input)) { + unescaped = this._unescape(match[0]); + if (unescaped === null) + return reportSyntaxError(this); + type = 'literal', value = unescaped.replace(/^'|'$/g, '"'); + } + // Try to find a literal wrapped in three pairs of single or double quotes + else if (match = this._tripleQuotedString.exec(input)) { + unescaped = match[1] || match[2]; + // Count the newlines and advance line counter + this._line += unescaped.split(/\r\n|\r|\n/).length - 1; + unescaped = this._unescape(unescaped); + if (unescaped === null) + return reportSyntaxError(this); + type = 'literal', value = unescaped.replace(/^'|'$/g, '"'); + } + break; + + case '?': + // Try to find a variable + if (this._n3Mode && (match = this._variable.exec(input))) + type = 'var', value = match[0]; + break; + + case '@': + // Try to find a language code + if (this._previousMarker === 'literal' && (match = this._langcode.exec(input))) + type = 'langcode', value = match[1]; + // Try to find a keyword + else if (match = this._keyword.exec(input)) + type = match[0]; + break; + + case '.': + // Try to find a dot as punctuation + if (input.length === 1 ? inputFinished : (input[1] < '0' || input[1] > '9')) { + type = '.'; + matchLength = 1; + break; + } + // Fall through to numerical case (could be a decimal dot) + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '+': + case '-': + // Try to find a number. Since it can contain (but not end with) a dot, + // we always need a non-dot character before deciding it is a number. + // Therefore, try inserting a space if we're at the end of the input. + if (match = this._number.exec(input) || + inputFinished && (match = this._number.exec(input + ' '))) { + type = 'literal'; + value = '"' + match[0] + '"^^http://www.w3.org/2001/XMLSchema#' + + (match[1] ? 'double' : (/^[+\-]?\d+$/.test(match[0]) ? 'integer' : 'decimal')); + } + break; + + case 'B': + case 'b': + case 'p': + case 'P': + case 'G': + case 'g': + // Try to find a SPARQL-style keyword + if (match = this._sparqlKeyword.exec(input)) + type = match[0].toUpperCase(); + else + inconclusive = true; + break; + + case 'f': + case 't': + // Try to match a boolean + if (match = this._boolean.exec(input)) + type = 'literal', value = '"' + match[0] + '"^^http://www.w3.org/2001/XMLSchema#boolean'; + else + inconclusive = true; + break; + + case 'a': + // Try to find an abbreviated predicate + if (match = this._shortPredicates.exec(input)) + type = 'abbreviation', value = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type'; + else + inconclusive = true; + break; + + case '=': + // Try to find an implication arrow or equals sign + if (this._n3Mode && input.length > 1) { + type = 'abbreviation'; + if (input[1] !== '>') + matchLength = 1, value = 'http://www.w3.org/2002/07/owl#sameAs'; + else + matchLength = 2, value = 'http://www.w3.org/2000/10/swap/log#implies'; + } + break; + + case '!': + if (!this._n3Mode) + break; + case ',': + case ';': + case '[': + case ']': + case '(': + case ')': + case '{': + case '}': + // The next token is punctuation + matchLength = 1; + type = firstChar; + break; + + default: + inconclusive = true; + } + + // Some first characters do not allow an immediate decision, so inspect more + if (inconclusive) { + // Try to find a prefix + if ((this._previousMarker === '@prefix' || this._previousMarker === 'PREFIX') && + (match = this._prefix.exec(input))) + type = 'prefix', value = match[1] || ''; + // Try to find a prefixed name. Since it can contain (but not end with) a dot, + // we always need a non-dot character before deciding it is a prefixed name. + // Therefore, try inserting a space if we're at the end of the input. + else if ((match = this._prefixed.exec(input)) || + inputFinished && (match = this._prefixed.exec(input + ' '))) + type = 'prefixed', prefix = match[1] || '', value = this._unescape(match[2]); + } + + // A type token is special: it can only be emitted after an IRI or prefixed name is read + if (this._previousMarker === '^^') { + switch (type) { + case 'prefixed': type = 'type'; break; + case 'IRI': type = 'typeIRI'; break; + default: type = ''; + } + } + + // What if nothing of the above was found? + if (!type) { + // We could be in streaming mode, and then we just wait for more input to arrive. + // Otherwise, a syntax error has occurred in the input. + // One exception: error on an unaccounted linebreak (= not inside a triple-quoted literal). + if (inputFinished || (!/^'''|^"""/.test(input) && /\n|\r/.test(input))) + return reportSyntaxError(this); + else + return this._input = input; + } + + // Emit the parsed token + var token = { line: line, type: type, value: value, prefix: prefix }; + callback(null, token); + this.previousToken = token; + this._previousMarker = type; + // Advance to next part to tokenize + input = input.substr(matchLength || match[0].length, input.length); + } + + // Signals the syntax error through the callback + function reportSyntaxError(self) { callback(self._syntaxError(/^\S*/.exec(input)[0])); } + }, + + // ### `_unescape` replaces N3 escape codes by their corresponding characters + _unescape: function (item) { + try { + return item.replace(escapeSequence, function (sequence, unicode4, unicode8, escapedChar) { + var charCode; + if (unicode4) { + charCode = parseInt(unicode4, 16); + if (isNaN(charCode)) throw new Error(); // can never happen (regex), but helps performance + return fromCharCode(charCode); + } + else if (unicode8) { + charCode = parseInt(unicode8, 16); + if (isNaN(charCode)) throw new Error(); // can never happen (regex), but helps performance + if (charCode <= 0xFFFF) return fromCharCode(charCode); + return fromCharCode(0xD800 + ((charCode -= 0x10000) / 0x400), 0xDC00 + (charCode & 0x3FF)); + } + else { + var replacement = escapeReplacements[escapedChar]; + if (!replacement) + throw new Error(); + return replacement; + } + }); + } + catch (error) { return null; } + }, + + // ### `_syntaxError` creates a syntax error for the given issue + _syntaxError: function (issue) { + this._input = null; + var err = new Error('Unexpected "' + issue + '" on line ' + this._line + '.'); + err.context = { + token: undefined, + line: this._line, + previousToken: this.previousToken, + }; + return err; + }, + + + // ## Public methods + + // ### `tokenize` starts the transformation of an N3 document into an array of tokens. + // The input can be a string or a stream. + tokenize: function (input, callback) { + var self = this; + this._line = 1; + + // If the input is a string, continuously emit tokens through the callback until the end + if (typeof input === 'string') { + this._input = input; + // If a callback was passed, asynchronously call it + if (typeof callback === 'function') + immediately(function () { self._tokenizeToEnd(callback, true); }); + // If no callback was passed, tokenize synchronously and return + else { + var tokens = [], error; + this._tokenizeToEnd(function (e, t) { e ? (error = e) : tokens.push(t); }, true); + if (error) throw error; + return tokens; + } + } + // Otherwise, the input must be a stream + else { + this._input = ''; + if (typeof input.setEncoding === 'function') + input.setEncoding('utf8'); + // Adds the data chunk to the buffer and parses as far as possible + input.on('data', function (data) { + if (self._input !== null) { + self._input += data; + self._tokenizeToEnd(callback, false); + } + }); + // Parses until the end + input.on('end', function () { + if (self._input !== null) + self._tokenizeToEnd(callback, true); + }); + input.on('error', callback); + } + }, +}; + +// ## Exports +module.exports = N3Lexer; + +},{}],4:[function(require,module,exports){ +// **N3Parser** parses N3 documents. +var N3Lexer = require('./N3Lexer'); + +var RDF_PREFIX = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', + RDF_NIL = RDF_PREFIX + 'nil', + RDF_FIRST = RDF_PREFIX + 'first', + RDF_REST = RDF_PREFIX + 'rest'; + +var QUANTIFIERS_GRAPH = 'urn:n3:quantifiers'; + +var absoluteIRI = /^[a-z][a-z0-9+.-]*:/i, + schemeAuthority = /^(?:([a-z][a-z0-9+.-]*:))?(?:\/\/[^\/]*)?/i, + dotSegments = /(?:^|\/)\.\.?(?:$|[\/#?])/; + +// The next ID for new blank nodes +var blankNodePrefix = 0, blankNodeCount = 0; + +// ## Constructor +function N3Parser(options) { + if (!(this instanceof N3Parser)) + return new N3Parser(options); + this._contextStack = []; + this._graph = null; + + // Set the document IRI + options = options || {}; + this._setBase(options.documentIRI); + + // Set supported features depending on the format + var format = (typeof options.format === 'string') ? + options.format.match(/\w*$/)[0].toLowerCase() : '', + isTurtle = format === 'turtle', isTriG = format === 'trig', + isNTriples = /triple/.test(format), isNQuads = /quad/.test(format), + isN3 = this._n3Mode = /n3/.test(format), + isLineMode = isNTriples || isNQuads; + if (!(this._supportsNamedGraphs = !(isTurtle || isN3))) + this._readPredicateOrNamedGraph = this._readPredicate; + this._supportsQuads = !(isTurtle || isTriG || isNTriples || isN3); + // Disable relative IRIs in N-Triples or N-Quads mode + if (isLineMode) { + this._base = ''; + this._resolveIRI = function (token) { + this._error('Disallowed relative IRI', token); + return this._callback = noop, this._subject = null; + }; + } + this._blankNodePrefix = typeof options.blankNodePrefix !== 'string' ? '' : + '_:' + options.blankNodePrefix.replace(/^_:/, ''); + this._lexer = options.lexer || new N3Lexer({ lineMode: isLineMode, n3: isN3 }); + // Disable explicit quantifiers by default + this._explicitQuantifiers = !!options.explicitQuantifiers; +} + +// ## Private class methods + +// ### `_resetBlankNodeIds` restarts blank node identification +N3Parser._resetBlankNodeIds = function () { + blankNodePrefix = blankNodeCount = 0; +}; + +N3Parser.prototype = { + // ## Private methods + + // ### `_setBase` sets the base IRI to resolve relative IRIs + _setBase: function (baseIRI) { + if (!baseIRI) + this._base = null; + else { + // Remove fragment if present + var fragmentPos = baseIRI.indexOf('#'); + if (fragmentPos >= 0) + baseIRI = baseIRI.substr(0, fragmentPos); + // Set base IRI and its components + this._base = baseIRI; + this._basePath = baseIRI.indexOf('/') < 0 ? baseIRI : + baseIRI.replace(/[^\/?]*(?:\?.*)?$/, ''); + baseIRI = baseIRI.match(schemeAuthority); + this._baseRoot = baseIRI[0]; + this._baseScheme = baseIRI[1]; + } + }, + + // ### `_saveContext` stores the current parsing context + // when entering a new scope (list, blank node, formula) + _saveContext: function (type, graph, subject, predicate, object) { + var n3Mode = this._n3Mode; + this._contextStack.push({ + subject: subject, predicate: predicate, object: object, + graph: graph, type: type, + inverse: n3Mode ? this._inversePredicate : false, + blankPrefix: n3Mode ? this._prefixes._ : '', + quantified: n3Mode ? this._quantified : null, + }); + // The settings below only apply to N3 streams + if (n3Mode) { + // Every new scope resets the predicate direction + this._inversePredicate = false; + // In N3, blank nodes are scoped to a formula + // (using a dot as separator, as a blank node label cannot start with it) + this._prefixes._ = this._graph + '.'; + // Quantifiers are scoped to a formula + this._quantified = Object.create(this._quantified); + } + }, + + // ### `_restoreContext` restores the parent context + // when leaving a scope (list, blank node, formula) + _restoreContext: function () { + var context = this._contextStack.pop(), n3Mode = this._n3Mode; + this._subject = context.subject; + this._predicate = context.predicate; + this._object = context.object; + this._graph = context.graph; + // The settings below only apply to N3 streams + if (n3Mode) { + this._inversePredicate = context.inverse; + this._prefixes._ = context.blankPrefix; + this._quantified = context.quantified; + } + }, + + // ### `_readInTopContext` reads a token when in the top context + _readInTopContext: function (token) { + switch (token.type) { + // If an EOF token arrives in the top context, signal that we're done + case 'eof': + if (this._graph !== null) + return this._error('Unclosed graph', token); + delete this._prefixes._; + return this._callback(null, null, this._prefixes); + // It could be a prefix declaration + case 'PREFIX': + this._sparqlStyle = true; + case '@prefix': + return this._readPrefix; + // It could be a base declaration + case 'BASE': + this._sparqlStyle = true; + case '@base': + return this._readBaseIRI; + // It could be a graph + case '{': + if (this._supportsNamedGraphs) { + this._graph = ''; + this._subject = null; + return this._readSubject; + } + case 'GRAPH': + if (this._supportsNamedGraphs) + return this._readNamedGraphLabel; + // Otherwise, the next token must be a subject + default: + return this._readSubject(token); + } + }, + + // ### `_readEntity` reads an IRI, prefixed name, blank node, or variable + _readEntity: function (token, quantifier) { + var value; + switch (token.type) { + // Read a relative or absolute IRI + case 'IRI': + case 'typeIRI': + value = (this._base === null || absoluteIRI.test(token.value)) ? + token.value : this._resolveIRI(token); + break; + // Read a blank node or prefixed name + case 'type': + case 'blank': + case 'prefixed': + var prefix = this._prefixes[token.prefix]; + if (prefix === undefined) + return this._error('Undefined prefix "' + token.prefix + ':"', token); + value = prefix + token.value; + break; + // Read a variable + case 'var': + return token.value; + // Everything else is not an entity + default: + return this._error('Expected entity but got ' + token.type, token); + } + // In N3 mode, replace the entity if it is quantified + if (!quantifier && this._n3Mode && (value in this._quantified)) + value = this._quantified[value]; + return value; + }, + + // ### `_readSubject` reads a triple's subject + _readSubject: function (token) { + this._predicate = null; + switch (token.type) { + case '[': + // Start a new triple with a new blank node as subject + this._saveContext('blank', this._graph, + this._subject = '_:b' + blankNodeCount++, null, null); + return this._readBlankNodeHead; + case '(': + // Start a new list + this._saveContext('list', this._graph, RDF_NIL, null, null); + this._subject = null; + return this._readListItem; + case '{': + // Start a new formula + if (!this._n3Mode) + return this._error('Unexpected graph', token); + this._saveContext('formula', this._graph, + this._graph = '_:b' + blankNodeCount++, null, null); + return this._readSubject; + case '}': + // No subject; the graph in which we are reading is closed instead + return this._readPunctuation(token); + case '@forSome': + if (!this._n3Mode) + return this._error('Unexpected "@forSome"', token); + this._subject = null; + this._predicate = 'http://www.w3.org/2000/10/swap/reify#forSome'; + this._quantifiedPrefix = '_:b'; + return this._readQuantifierList; + case '@forAll': + if (!this._n3Mode) + return this._error('Unexpected "@forAll"', token); + this._subject = null; + this._predicate = 'http://www.w3.org/2000/10/swap/reify#forAll'; + this._quantifiedPrefix = '?b-'; + return this._readQuantifierList; + default: + // Read the subject entity + if ((this._subject = this._readEntity(token)) === undefined) + return; + // In N3 mode, the subject might be a path + if (this._n3Mode) + return this._getPathReader(this._readPredicateOrNamedGraph); + } + + // The next token must be a predicate, + // or, if the subject was actually a graph IRI, a named graph + return this._readPredicateOrNamedGraph; + }, + + // ### `_readPredicate` reads a triple's predicate + _readPredicate: function (token) { + var type = token.type; + switch (type) { + case 'inverse': + this._inversePredicate = true; + case 'abbreviation': + this._predicate = token.value; + break; + case '.': + case ']': + case '}': + // Expected predicate didn't come, must have been trailing semicolon + if (this._predicate === null) + return this._error('Unexpected ' + type, token); + this._subject = null; + return type === ']' ? this._readBlankNodeTail(token) : this._readPunctuation(token); + case ';': + // Additional semicolons can be safely ignored + return this._predicate !== null ? this._readPredicate : + this._error('Expected predicate but got ;', token); + case 'blank': + if (!this._n3Mode) + return this._error('Disallowed blank node as predicate', token); + default: + if ((this._predicate = this._readEntity(token)) === undefined) + return; + } + // The next token must be an object + return this._readObject; + }, + + // ### `_readObject` reads a triple's object + _readObject: function (token) { + switch (token.type) { + case 'literal': + this._object = token.value; + return this._readDataTypeOrLang; + case '[': + // Start a new triple with a new blank node as subject + this._saveContext('blank', this._graph, this._subject, this._predicate, + this._subject = '_:b' + blankNodeCount++); + return this._readBlankNodeHead; + case '(': + // Start a new list + this._saveContext('list', this._graph, this._subject, this._predicate, RDF_NIL); + this._subject = null; + return this._readListItem; + case '{': + // Start a new formula + if (!this._n3Mode) + return this._error('Unexpected graph', token); + this._saveContext('formula', this._graph, this._subject, this._predicate, + this._graph = '_:b' + blankNodeCount++); + return this._readSubject; + default: + // Read the object entity + if ((this._object = this._readEntity(token)) === undefined) + return; + // In N3 mode, the object might be a path + if (this._n3Mode) + return this._getPathReader(this._getContextEndReader()); + } + return this._getContextEndReader(); + }, + + // ### `_readPredicateOrNamedGraph` reads a triple's predicate, or a named graph + _readPredicateOrNamedGraph: function (token) { + return token.type === '{' ? this._readGraph(token) : this._readPredicate(token); + }, + + // ### `_readGraph` reads a graph + _readGraph: function (token) { + if (token.type !== '{') + return this._error('Expected graph but got ' + token.type, token); + // The "subject" we read is actually the GRAPH's label + this._graph = this._subject, this._subject = null; + return this._readSubject; + }, + + // ### `_readBlankNodeHead` reads the head of a blank node + _readBlankNodeHead: function (token) { + if (token.type === ']') { + this._subject = null; + return this._readBlankNodeTail(token); + } + else { + this._predicate = null; + return this._readPredicate(token); + } + }, + + // ### `_readBlankNodeTail` reads the end of a blank node + _readBlankNodeTail: function (token) { + if (token.type !== ']') + return this._readBlankNodePunctuation(token); + + // Store blank node triple + if (this._subject !== null) + this._triple(this._subject, this._predicate, this._object, this._graph); + + // Restore the parent context containing this blank node + var empty = this._predicate === null; + this._restoreContext(); + // If the blank node was the subject, continue reading the predicate + if (this._object === null) + // If the blank node was empty, it could be a named graph label + return empty ? this._readPredicateOrNamedGraph : this._readPredicateAfterBlank; + // If the blank node was the object, restore previous context and read punctuation + else + return this._getContextEndReader(); + }, + + // ### `_readPredicateAfterBlank` reads a predicate after an anonymous blank node + _readPredicateAfterBlank: function (token) { + // If a dot follows a blank node in top context, there is no predicate + if (token.type === '.' && !this._contextStack.length) { + this._subject = null; // cancel the current triple + return this._readPunctuation(token); + } + return this._readPredicate(token); + }, + + // ### `_readListItem` reads items from a list + _readListItem: function (token) { + var item = null, // The item of the list + list = null, // The list itself + prevList = this._subject, // The previous list that contains this list + stack = this._contextStack, // The stack of parent contexts + parent = stack[stack.length - 1], // The parent containing the current list + next = this._readListItem, // The next function to execute + itemComplete = true; // Whether the item has been read fully + + switch (token.type) { + case '[': + // Stack the current list triple and start a new triple with a blank node as subject + this._saveContext('blank', this._graph, list = '_:b' + blankNodeCount++, + RDF_FIRST, this._subject = item = '_:b' + blankNodeCount++); + next = this._readBlankNodeHead; + break; + case '(': + // Stack the current list triple and start a new list + this._saveContext('list', this._graph, list = '_:b' + blankNodeCount++, + RDF_FIRST, RDF_NIL); + this._subject = null; + break; + case ')': + // Closing the list; restore the parent context + this._restoreContext(); + // If this list is contained within a parent list, return the membership triple here. + // This will be ` rdf:first .`. + if (stack.length !== 0 && stack[stack.length - 1].type === 'list') + this._triple(this._subject, this._predicate, this._object, this._graph); + // Was this list the parent's subject? + if (this._predicate === null) { + // The next token is the predicate + next = this._readPredicate; + // No list tail if this was an empty list + if (this._subject === RDF_NIL) + return next; + } + // The list was in the parent context's object + else { + next = this._getContextEndReader(); + // No list tail if this was an empty list + if (this._object === RDF_NIL) + return next; + } + // Close the list by making the head nil + list = RDF_NIL; + break; + case 'literal': + item = token.value; + itemComplete = false; // Can still have a datatype or language + next = this._readListItemDataTypeOrLang; + break; + default: + if ((item = this._readEntity(token)) === undefined) + return; + } + + // Create a new blank node if no item head was assigned yet + if (list === null) + this._subject = list = '_:b' + blankNodeCount++; + + // Is this the first element of the list? + if (prevList === null) { + // This list is either the subject or the object of its parent + if (parent.predicate === null) + parent.subject = list; + else + parent.object = list; + } + else { + // Continue the previous list with the current list + this._triple(prevList, RDF_REST, list, this._graph); + } + // Add the item's value + if (item !== null) { + // In N3 mode, the item might be a path + if (this._n3Mode && (token.type === 'IRI' || token.type === 'prefixed')) { + // Create a new context to add the item's path + this._saveContext('item', this._graph, list, RDF_FIRST, item); + this._subject = item, this._predicate = null; + // _readPath will restore the context and output the item + return this._getPathReader(this._readListItem); + } + // Output the item if it is complete + if (itemComplete) + this._triple(list, RDF_FIRST, item, this._graph); + // Otherwise, save it for completion + else + this._object = item; + } + return next; + }, + + // ### `_readDataTypeOrLang` reads an _optional_ data type or language + _readDataTypeOrLang: function (token) { + return this._completeLiteral(token, false); + }, + + // ### `_readListItemDataTypeOrLang` reads an _optional_ data type or language in a list + _readListItemDataTypeOrLang: function (token) { + return this._completeLiteral(token, true); + }, + + // ### `_completeLiteral` completes the object with a data type or language + _completeLiteral: function (token, listItem) { + var suffix = false; + switch (token.type) { + // Add a "^^type" suffix for types (IRIs and blank nodes) + case 'type': + case 'typeIRI': + suffix = true; + this._object += '^^' + this._readEntity(token); + break; + // Add an "@lang" suffix for language tags + case 'langcode': + suffix = true; + this._object += '@' + token.value.toLowerCase(); + break; + } + // If this literal was part of a list, write the item + // (we could also check the context stack, but passing in a flag is faster) + if (listItem) + this._triple(this._subject, RDF_FIRST, this._object, this._graph); + // Continue with the rest of the input + if (suffix) + return this._getContextEndReader(); + else { + this._readCallback = this._getContextEndReader(); + return this._readCallback(token); + } + }, + + // ### `_readFormulaTail` reads the end of a formula + _readFormulaTail: function (token) { + if (token.type !== '}') + return this._readPunctuation(token); + + // Store the last triple of the formula + if (this._subject !== null) + this._triple(this._subject, this._predicate, this._object, this._graph); + + // Restore the parent context containing this formula + this._restoreContext(); + // If the formula was the subject, continue reading the predicate. + // If the formula was the object, read punctuation. + return this._object === null ? this._readPredicate : this._getContextEndReader(); + }, + + // ### `_readPunctuation` reads punctuation between triples or triple parts + _readPunctuation: function (token) { + var next, subject = this._subject, graph = this._graph, + inversePredicate = this._inversePredicate; + switch (token.type) { + // A closing brace ends a graph + case '}': + if (this._graph === null) + return this._error('Unexpected graph closing', token); + if (this._n3Mode) + return this._readFormulaTail(token); + this._graph = null; + // A dot just ends the statement, without sharing anything with the next + case '.': + this._subject = null; + next = this._contextStack.length ? this._readSubject : this._readInTopContext; + if (inversePredicate) this._inversePredicate = false; + break; + // Semicolon means the subject is shared; predicate and object are different + case ';': + next = this._readPredicate; + break; + // Comma means both the subject and predicate are shared; the object is different + case ',': + next = this._readObject; + break; + default: + // An entity means this is a quad (only allowed if not already inside a graph) + if (this._supportsQuads && this._graph === null && (graph = this._readEntity(token)) !== undefined) { + next = this._readQuadPunctuation; + break; + } + return this._error('Expected punctuation to follow "' + this._object + '"', token); + } + // A triple has been completed now, so return it + if (subject !== null) { + var predicate = this._predicate, object = this._object; + if (!inversePredicate) + this._triple(subject, predicate, object, graph); + else + this._triple(object, predicate, subject, graph); + } + return next; + }, + + // ### `_readBlankNodePunctuation` reads punctuation in a blank node + _readBlankNodePunctuation: function (token) { + var next; + switch (token.type) { + // Semicolon means the subject is shared; predicate and object are different + case ';': + next = this._readPredicate; + break; + // Comma means both the subject and predicate are shared; the object is different + case ',': + next = this._readObject; + break; + default: + return this._error('Expected punctuation to follow "' + this._object + '"', token); + } + // A triple has been completed now, so return it + this._triple(this._subject, this._predicate, this._object, this._graph); + return next; + }, + + // ### `_readQuadPunctuation` reads punctuation after a quad + _readQuadPunctuation: function (token) { + if (token.type !== '.') + return this._error('Expected dot to follow quad', token); + return this._readInTopContext; + }, + + // ### `_readPrefix` reads the prefix of a prefix declaration + _readPrefix: function (token) { + if (token.type !== 'prefix') + return this._error('Expected prefix to follow @prefix', token); + this._prefix = token.value; + return this._readPrefixIRI; + }, + + // ### `_readPrefixIRI` reads the IRI of a prefix declaration + _readPrefixIRI: function (token) { + if (token.type !== 'IRI') + return this._error('Expected IRI to follow prefix "' + this._prefix + ':"', token); + var prefixIRI = this._readEntity(token); + this._prefixes[this._prefix] = prefixIRI; + this._prefixCallback(this._prefix, prefixIRI); + return this._readDeclarationPunctuation; + }, + + // ### `_readBaseIRI` reads the IRI of a base declaration + _readBaseIRI: function (token) { + if (token.type !== 'IRI') + return this._error('Expected IRI to follow base declaration', token); + this._setBase(this._base === null || absoluteIRI.test(token.value) ? + token.value : this._resolveIRI(token)); + return this._readDeclarationPunctuation; + }, + + // ### `_readNamedGraphLabel` reads the label of a named graph + _readNamedGraphLabel: function (token) { + switch (token.type) { + case 'IRI': + case 'blank': + case 'prefixed': + return this._readSubject(token), this._readGraph; + case '[': + return this._readNamedGraphBlankLabel; + default: + return this._error('Invalid graph label', token); + } + }, + + // ### `_readNamedGraphLabel` reads a blank node label of a named graph + _readNamedGraphBlankLabel: function (token) { + if (token.type !== ']') + return this._error('Invalid graph label', token); + this._subject = '_:b' + blankNodeCount++; + return this._readGraph; + }, + + // ### `_readDeclarationPunctuation` reads the punctuation of a declaration + _readDeclarationPunctuation: function (token) { + // SPARQL-style declarations don't have punctuation + if (this._sparqlStyle) { + this._sparqlStyle = false; + return this._readInTopContext(token); + } + + if (token.type !== '.') + return this._error('Expected declaration to end with a dot', token); + return this._readInTopContext; + }, + + // Reads a list of quantified symbols from a @forSome or @forAll statement + _readQuantifierList: function (token) { + var entity; + switch (token.type) { + case 'IRI': + case 'prefixed': + if ((entity = this._readEntity(token, true)) !== undefined) + break; + default: + return this._error('Unexpected ' + token.type, token); + } + // Without explicit quantifiers, map entities to a quantified entity + if (!this._explicitQuantifiers) + this._quantified[entity] = this._quantifiedPrefix + blankNodeCount++; + // With explicit quantifiers, output the reified quantifier + else { + // If this is the first item, start a new quantifier list + if (this._subject === null) + this._triple(this._graph || '', this._predicate, + this._subject = '_:b' + blankNodeCount++, QUANTIFIERS_GRAPH); + // Otherwise, continue the previous list + else + this._triple(this._subject, RDF_REST, + this._subject = '_:b' + blankNodeCount++, QUANTIFIERS_GRAPH); + // Output the list item + this._triple(this._subject, RDF_FIRST, entity, QUANTIFIERS_GRAPH); + } + return this._readQuantifierPunctuation; + }, + + // Reads punctuation from a @forSome or @forAll statement + _readQuantifierPunctuation: function (token) { + // Read more quantifiers + if (token.type === ',') + return this._readQuantifierList; + // End of the quantifier list + else { + // With explicit quantifiers, close the quantifier list + if (this._explicitQuantifiers) { + this._triple(this._subject, RDF_REST, RDF_NIL, QUANTIFIERS_GRAPH); + this._subject = null; + } + // Read a dot + this._readCallback = this._getContextEndReader(); + return this._readCallback(token); + } + }, + + // ### `_getPathReader` reads a potential path and then resumes with the given function + _getPathReader: function (afterPath) { + this._afterPath = afterPath; + return this._readPath; + }, + + // ### `_readPath` reads a potential path + _readPath: function (token) { + switch (token.type) { + // Forward path + case '!': return this._readForwardPath; + // Backward path + case '^': return this._readBackwardPath; + // Not a path; resume reading where we left off + default: + var stack = this._contextStack, parent = stack.length && stack[stack.length - 1]; + // If we were reading a list item, we still need to output it + if (parent && parent.type === 'item') { + // The list item is the remaining subejct after reading the path + var item = this._subject; + // Switch back to the context of the list + this._restoreContext(); + // Output the list item + this._triple(this._subject, RDF_FIRST, item, this._graph); + } + return this._afterPath(token); + } + }, + + // ### `_readForwardPath` reads a '!' path + _readForwardPath: function (token) { + var subject, predicate, object = '_:b' + blankNodeCount++; + // The next token is the predicate + if ((predicate = this._readEntity(token)) === undefined) + return; + // If we were reading a subject, replace the subject by the path's object + if (this._predicate === null) + subject = this._subject, this._subject = object; + // If we were reading an object, replace the subject by the path's object + else + subject = this._object, this._object = object; + // Emit the path's current triple and read its next section + this._triple(subject, predicate, object, this._graph); + return this._readPath; + }, + + // ### `_readBackwardPath` reads a '^' path + _readBackwardPath: function (token) { + var subject = '_:b' + blankNodeCount++, predicate, object; + // The next token is the predicate + if ((predicate = this._readEntity(token)) === undefined) + return; + // If we were reading a subject, replace the subject by the path's subject + if (this._predicate === null) + object = this._subject, this._subject = subject; + // If we were reading an object, replace the subject by the path's subject + else + object = this._object, this._object = subject; + // Emit the path's current triple and read its next section + this._triple(subject, predicate, object, this._graph); + return this._readPath; + }, + + // ### `_getContextEndReader` gets the next reader function at the end of a context + _getContextEndReader: function () { + var contextStack = this._contextStack; + if (!contextStack.length) + return this._readPunctuation; + + switch (contextStack[contextStack.length - 1].type) { + case 'blank': + return this._readBlankNodeTail; + case 'list': + return this._readListItem; + case 'formula': + return this._readFormulaTail; + } + }, + + // ### `_triple` emits a triple through the callback + _triple: function (subject, predicate, object, graph) { + this._callback(null, + { subject: subject, predicate: predicate, object: object, graph: graph || '' }); + }, + + // ### `_error` emits an error message through the callback + _error: function (message, token) { + var err = new Error(message + ' on line ' + token.line + '.'); + err.context = { + token: token, + line: token.line, + previousToken: this._lexer.previousToken, + }; + this._callback(err); + }, + + // ### `_resolveIRI` resolves a relative IRI token against the base path, + // assuming that a base path has been set and that the IRI is indeed relative + _resolveIRI: function (token) { + var iri = token.value; + switch (iri[0]) { + // An empty relative IRI indicates the base IRI + case undefined: return this._base; + // Resolve relative fragment IRIs against the base IRI + case '#': return this._base + iri; + // Resolve relative query string IRIs by replacing the query string + case '?': return this._base.replace(/(?:\?.*)?$/, iri); + // Resolve root-relative IRIs at the root of the base IRI + case '/': + // Resolve scheme-relative IRIs to the scheme + return (iri[1] === '/' ? this._baseScheme : this._baseRoot) + this._removeDotSegments(iri); + // Resolve all other IRIs at the base IRI's path + default: + return this._removeDotSegments(this._basePath + iri); + } + }, + + // ### `_removeDotSegments` resolves './' and '../' path segments in an IRI as per RFC3986 + _removeDotSegments: function (iri) { + // Don't modify the IRI if it does not contain any dot segments + if (!dotSegments.test(iri)) + return iri; + + // Start with an imaginary slash before the IRI in order to resolve trailing './' and '../' + var result = '', length = iri.length, i = -1, pathStart = -1, segmentStart = 0, next = '/'; + + while (i < length) { + switch (next) { + // The path starts with the first slash after the authority + case ':': + if (pathStart < 0) { + // Skip two slashes before the authority + if (iri[++i] === '/' && iri[++i] === '/') + // Skip to slash after the authority + while ((pathStart = i + 1) < length && iri[pathStart] !== '/') + i = pathStart; + } + break; + // Don't modify a query string or fragment + case '?': + case '#': + i = length; + break; + // Handle '/.' or '/..' path segments + case '/': + if (iri[i + 1] === '.') { + next = iri[++i + 1]; + switch (next) { + // Remove a '/.' segment + case '/': + result += iri.substring(segmentStart, i - 1); + segmentStart = i + 1; + break; + // Remove a trailing '/.' segment + case undefined: + case '?': + case '#': + return result + iri.substring(segmentStart, i) + iri.substr(i + 1); + // Remove a '/..' segment + case '.': + next = iri[++i + 1]; + if (next === undefined || next === '/' || next === '?' || next === '#') { + result += iri.substring(segmentStart, i - 2); + // Try to remove the parent path from result + if ((segmentStart = result.lastIndexOf('/')) >= pathStart) + result = result.substr(0, segmentStart); + // Remove a trailing '/..' segment + if (next !== '/') + return result + '/' + iri.substr(i + 1); + segmentStart = i + 1; + } + } + } + } + next = iri[++i]; + } + return result + iri.substring(segmentStart); + }, + + // ## Public methods + + // ### `parse` parses the N3 input and emits each parsed triple through the callback + parse: function (input, tripleCallback, prefixCallback) { + var self = this; + // The read callback is the next function to be executed when a token arrives. + // We start reading in the top context. + this._readCallback = this._readInTopContext; + this._sparqlStyle = false; + this._prefixes = Object.create(null); + this._prefixes._ = this._blankNodePrefix || '_:b' + blankNodePrefix++ + '_'; + this._prefixCallback = prefixCallback || noop; + this._inversePredicate = false; + this._quantified = Object.create(null); + + // Parse synchronously if no triple callback is given + if (!tripleCallback) { + var triples = [], error; + this._callback = function (e, t) { e ? (error = e) : t && triples.push(t); }; + this._lexer.tokenize(input).every(function (token) { + return self._readCallback = self._readCallback(token); + }); + if (error) throw error; + return triples; + } + + // Parse asynchronously otherwise, executing the read callback when a token arrives + this._callback = tripleCallback; + this._lexer.tokenize(input, function (error, token) { + if (error !== null) + self._callback(error), self._callback = noop; + else if (self._readCallback) + self._readCallback = self._readCallback(token); + }); + }, +}; + +// The empty function +function noop() {} + +// ## Exports +module.exports = N3Parser; + +},{"./N3Lexer":3}],5:[function(require,module,exports){ +// **N3Store** objects store N3 triples by graph in memory. + +var expandPrefixedName = require('./N3Util').expandPrefixedName; + +// ## Constructor +function N3Store(triples, options) { + if (!(this instanceof N3Store)) + return new N3Store(triples, options); + + // The number of triples is initially zero + this._size = 0; + // `_graphs` contains subject, predicate, and object indexes per graph + this._graphs = Object.create(null); + // `_ids` maps entities such as `http://xmlns.com/foaf/0.1/name` to numbers, + // saving memory by using only numbers as keys in `_graphs` + this._id = 0; + this._ids = Object.create(null); + this._ids['><'] = 0; // dummy entry, so the first actual key is non-zero + this._entities = Object.create(null); // inverse of `_ids` + // `_blankNodeIndex` is the index of the last automatically named blank node + this._blankNodeIndex = 0; + + // Shift parameters if `triples` is not given + if (!options && triples && !triples[0]) + options = triples, triples = null; + options = options || {}; + + // Add triples and prefixes if passed + this._prefixes = Object.create(null); + if (options.prefixes) + this.addPrefixes(options.prefixes); + if (triples) + this.addTriples(triples); +} + +N3Store.prototype = { + // ## Public properties + + // ### `size` returns the number of triples in the store + get size() { + // Return the triple count if if was cached + var size = this._size; + if (size !== null) + return size; + + // Calculate the number of triples by counting to the deepest level + size = 0; + var graphs = this._graphs, subjects, subject; + for (var graphKey in graphs) + for (var subjectKey in (subjects = graphs[graphKey].subjects)) + for (var predicateKey in (subject = subjects[subjectKey])) + size += Object.keys(subject[predicateKey]).length; + return this._size = size; + }, + + // ## Private methods + + // ### `_addToIndex` adds a triple to a three-layered index. + // Returns if the index has changed, if the entry did not already exist. + _addToIndex: function (index0, key0, key1, key2) { + // Create layers as necessary + var index1 = index0[key0] || (index0[key0] = {}); + var index2 = index1[key1] || (index1[key1] = {}); + // Setting the key to _any_ value signals the presence of the triple + var existed = key2 in index2; + if (!existed) + index2[key2] = null; + return !existed; + }, + + // ### `_removeFromIndex` removes a triple from a three-layered index + _removeFromIndex: function (index0, key0, key1, key2) { + // Remove the triple from the index + var index1 = index0[key0], index2 = index1[key1], key; + delete index2[key2]; + + // Remove intermediary index layers if they are empty + for (key in index2) return; + delete index1[key1]; + for (key in index1) return; + delete index0[key0]; + }, + + // ### `_findInIndex` finds a set of triples in a three-layered index. + // The index base is `index0` and the keys at each level are `key0`, `key1`, and `key2`. + // Any of these keys can be undefined, which is interpreted as a wildcard. + // `name0`, `name1`, and `name2` are the names of the keys at each level, + // used when reconstructing the resulting triple + // (for instance: _subject_, _predicate_, and _object_). + // Finally, `graph` will be the graph of the created triples. + // If `callback` is given, each result is passed through it + // and iteration halts when it returns truthy for any triple. + // If instead `array` is given, each result is added to the array. + _findInIndex: function (index0, key0, key1, key2, name0, name1, name2, graph, callback, array) { + var tmp, index1, index2, varCount = !key0 + !key1 + !key2, + // depending on the number of variables, keys or reverse index are faster + entityKeys = varCount > 1 ? Object.keys(this._ids) : this._entities; + + // If a key is specified, use only that part of index 0. + if (key0) (tmp = index0, index0 = {})[key0] = tmp[key0]; + for (var value0 in index0) { + var entity0 = entityKeys[value0]; + + if (index1 = index0[value0]) { + // If a key is specified, use only that part of index 1. + if (key1) (tmp = index1, index1 = {})[key1] = tmp[key1]; + for (var value1 in index1) { + var entity1 = entityKeys[value1]; + + if (index2 = index1[value1]) { + // If a key is specified, use only that part of index 2, if it exists. + var values = key2 ? (key2 in index2 ? [key2] : []) : Object.keys(index2); + // Create triples for all items found in index 2. + for (var l = values.length - 1; l >= 0; l--) { + var result = { subject: '', predicate: '', object: '', graph: graph }; + result[name0] = entity0; + result[name1] = entity1; + result[name2] = entityKeys[values[l]]; + if (array) + array.push(result); + else if (callback(result)) + return true; + } + } + } + } + } + return array; + }, + + // ### `_loop` executes the callback on all keys of index 0 + _loop: function (index0, callback) { + for (var key0 in index0) + callback(key0); + }, + + // ### `_loopByKey0` executes the callback on all keys of a certain entry in index 0 + _loopByKey0: function (index0, key0, callback) { + var index1, key1; + if (index1 = index0[key0]) { + for (key1 in index1) + callback(key1); + } + }, + + // ### `_loopByKey1` executes the callback on given keys of all entries in index 0 + _loopByKey1: function (index0, key1, callback) { + var key0, index1; + for (key0 in index0) { + index1 = index0[key0]; + if (index1[key1]) + callback(key0); + } + }, + + // ### `_loopBy2Keys` executes the callback on given keys of certain entries in index 2 + _loopBy2Keys: function (index0, key0, key1, callback) { + var index1, index2, key2; + if ((index1 = index0[key0]) && (index2 = index1[key1])) { + for (key2 in index2) + callback(key2); + } + }, + + // ### `_countInIndex` counts matching triples in a three-layered index. + // The index base is `index0` and the keys at each level are `key0`, `key1`, and `key2`. + // Any of these keys can be undefined, which is interpreted as a wildcard. + _countInIndex: function (index0, key0, key1, key2) { + var count = 0, tmp, index1, index2; + + // If a key is specified, count only that part of index 0 + if (key0) (tmp = index0, index0 = {})[key0] = tmp[key0]; + for (var value0 in index0) { + if (index1 = index0[value0]) { + // If a key is specified, count only that part of index 1 + if (key1) (tmp = index1, index1 = {})[key1] = tmp[key1]; + for (var value1 in index1) { + if (index2 = index1[value1]) { + // If a key is specified, count the triple if it exists + if (key2) (key2 in index2) && count++; + // Otherwise, count all triples + else count += Object.keys(index2).length; + } + } + } + } + return count; + }, + + // ### `_getGraphs` returns an array with the given graph, + // or all graphs if the argument is null or undefined. + _getGraphs: function (graph) { + if (!isString(graph)) + return this._graphs; + var graphs = {}; + graphs[graph] = this._graphs[graph]; + return graphs; + }, + + // ### `_uniqueEntities` returns a function that accepts an entity ID + // and passes the corresponding entity to callback if it hasn't occurred before. + _uniqueEntities: function (callback) { + var uniqueIds = Object.create(null), entities = this._entities; + return function (id) { + if (!(id in uniqueIds)) { + uniqueIds[id] = true; + callback(entities[id]); + } + }; + }, + + // ## Public methods + + // ### `addTriple` adds a new N3 triple to the store. + // Returns if the triple index has changed, if the triple did not already exist. + addTriple: function (subject, predicate, object, graph) { + // Shift arguments if a triple object is given instead of components + if (!predicate) + graph = subject.graph, object = subject.object, + predicate = subject.predicate, subject = subject.subject; + + // Find the graph that will contain the triple + graph = graph || ''; + var graphItem = this._graphs[graph]; + // Create the graph if it doesn't exist yet + if (!graphItem) { + graphItem = this._graphs[graph] = { subjects: {}, predicates: {}, objects: {} }; + // Freezing a graph helps subsequent `add` performance, + // and properties will never be modified anyway + Object.freeze(graphItem); + } + + // Since entities can often be long IRIs, we avoid storing them in every index. + // Instead, we have a separate index that maps entities to numbers, + // which are then used as keys in the other indexes. + var ids = this._ids; + var entities = this._entities; + subject = ids[subject] || (ids[entities[++this._id] = subject] = this._id); + predicate = ids[predicate] || (ids[entities[++this._id] = predicate] = this._id); + object = ids[object] || (ids[entities[++this._id] = object] = this._id); + + var changed = this._addToIndex(graphItem.subjects, subject, predicate, object); + this._addToIndex(graphItem.predicates, predicate, object, subject); + this._addToIndex(graphItem.objects, object, subject, predicate); + + // The cached triple count is now invalid + this._size = null; + return changed; + }, + + // ### `addTriples` adds multiple N3 triples to the store + addTriples: function (triples) { + for (var i = triples.length - 1; i >= 0; i--) + this.addTriple(triples[i]); + }, + + // ### `addPrefix` adds support for querying with the given prefix + addPrefix: function (prefix, iri) { + this._prefixes[prefix] = iri; + }, + + // ### `addPrefixes` adds support for querying with the given prefixes + addPrefixes: function (prefixes) { + for (var prefix in prefixes) + this.addPrefix(prefix, prefixes[prefix]); + }, + + // ### `removeTriple` removes an N3 triple from the store if it exists + removeTriple: function (subject, predicate, object, graph) { + // Shift arguments if a triple object is given instead of components + if (!predicate) + graph = subject.graph, object = subject.object, + predicate = subject.predicate, subject = subject.subject; + graph = graph || ''; + + // Find internal identifiers for all components + // and verify the triple exists. + var graphItem, ids = this._ids, graphs = this._graphs, subjects, predicates; + if (!(subject = ids[subject]) || !(predicate = ids[predicate]) || + !(object = ids[object]) || !(graphItem = graphs[graph]) || + !(subjects = graphItem.subjects[subject]) || + !(predicates = subjects[predicate]) || + !(object in predicates)) + return false; + + // Remove it from all indexes + this._removeFromIndex(graphItem.subjects, subject, predicate, object); + this._removeFromIndex(graphItem.predicates, predicate, object, subject); + this._removeFromIndex(graphItem.objects, object, subject, predicate); + if (this._size !== null) this._size--; + + // Remove the graph if it is empty + for (subject in graphItem.subjects) return true; + delete graphs[graph]; + return true; + }, + + // ### `removeTriples` removes multiple N3 triples from the store + removeTriples: function (triples) { + for (var i = triples.length - 1; i >= 0; i--) + this.removeTriple(triples[i]); + }, + + // ### `getTriples` returns an array of triples matching a pattern, expanding prefixes as necessary. + // Setting any field to `undefined` or `null` indicates a wildcard. + getTriples: function (subject, predicate, object, graph) { + var prefixes = this._prefixes; + return this.getTriplesByIRI( + expandPrefixedName(subject, prefixes), + expandPrefixedName(predicate, prefixes), + expandPrefixedName(object, prefixes), + expandPrefixedName(graph, prefixes) + ); + }, + + // ### `getTriplesByIRI` returns an array of triples matching a pattern. + // Setting any field to `undefined` or `null` indicates a wildcard. + getTriplesByIRI: function (subject, predicate, object, graph) { + var quads = [], graphs = this._getGraphs(graph), content, + ids = this._ids, subjectId, predicateId, objectId; + + // Translate IRIs to internal index keys. + if (isString(subject) && !(subjectId = ids[subject]) || + isString(predicate) && !(predicateId = ids[predicate]) || + isString(object) && !(objectId = ids[object])) + return quads; + + for (var graphId in graphs) { + // Only if the specified graph contains triples, there can be results + if (content = graphs[graphId]) { + // Choose the optimal index, based on what fields are present + if (subjectId) { + if (objectId) + // If subject and object are given, the object index will be the fastest + this._findInIndex(content.objects, objectId, subjectId, predicateId, + 'object', 'subject', 'predicate', graphId, null, quads); + else + // If only subject and possibly predicate are given, the subject index will be the fastest + this._findInIndex(content.subjects, subjectId, predicateId, null, + 'subject', 'predicate', 'object', graphId, null, quads); + } + else if (predicateId) + // If only predicate and possibly object are given, the predicate index will be the fastest + this._findInIndex(content.predicates, predicateId, objectId, null, + 'predicate', 'object', 'subject', graphId, null, quads); + else if (objectId) + // If only object is given, the object index will be the fastest + this._findInIndex(content.objects, objectId, null, null, + 'object', 'subject', 'predicate', graphId, null, quads); + else + // If nothing is given, iterate subjects and predicates first + this._findInIndex(content.subjects, null, null, null, + 'subject', 'predicate', 'object', graphId, null, quads); + } + } + return quads; + }, + + // ### `countTriples` returns the number of triples matching a pattern, expanding prefixes as necessary. + // Setting any field to `undefined` or `null` indicates a wildcard. + countTriples: function (subject, predicate, object, graph) { + var prefixes = this._prefixes; + return this.countTriplesByIRI( + expandPrefixedName(subject, prefixes), + expandPrefixedName(predicate, prefixes), + expandPrefixedName(object, prefixes), + expandPrefixedName(graph, prefixes) + ); + }, + + // ### `countTriplesByIRI` returns the number of triples matching a pattern. + // Setting any field to `undefined` or `null` indicates a wildcard. + countTriplesByIRI: function (subject, predicate, object, graph) { + var count = 0, graphs = this._getGraphs(graph), content, + ids = this._ids, subjectId, predicateId, objectId; + + // Translate IRIs to internal index keys. + if (isString(subject) && !(subjectId = ids[subject]) || + isString(predicate) && !(predicateId = ids[predicate]) || + isString(object) && !(objectId = ids[object])) + return 0; + + for (var graphId in graphs) { + // Only if the specified graph contains triples, there can be results + if (content = graphs[graphId]) { + // Choose the optimal index, based on what fields are present + if (subject) { + if (object) + // If subject and object are given, the object index will be the fastest + count += this._countInIndex(content.objects, objectId, subjectId, predicateId); + else + // If only subject and possibly predicate are given, the subject index will be the fastest + count += this._countInIndex(content.subjects, subjectId, predicateId, objectId); + } + else if (predicate) { + // If only predicate and possibly object are given, the predicate index will be the fastest + count += this._countInIndex(content.predicates, predicateId, objectId, subjectId); + } + else { + // If only object is possibly given, the object index will be the fastest + count += this._countInIndex(content.objects, objectId, subjectId, predicateId); + } + } + } + return count; + }, + + // ### `forEach` executes the callback on all triples. + // Setting any field to `undefined` or `null` indicates a wildcard. + forEach: function (callback, subject, predicate, object, graph) { + var prefixes = this._prefixes; + this.forEachByIRI( + callback, + expandPrefixedName(subject, prefixes), + expandPrefixedName(predicate, prefixes), + expandPrefixedName(object, prefixes), + expandPrefixedName(graph, prefixes) + ); + }, + + // ### `forEachByIRI` executes the callback on all triples. + // Setting any field to `undefined` or `null` indicates a wildcard. + forEachByIRI: function (callback, subject, predicate, object, graph) { + this.someByIRI(function (quad) { + callback(quad); + return false; + }, subject, predicate, object, graph); + }, + + // ### `every` executes the callback on all triples, + // and returns `true` if it returns truthy for all them. + // Setting any field to `undefined` or `null` indicates a wildcard. + every: function (callback, subject, predicate, object, graph) { + var prefixes = this._prefixes; + return this.everyByIRI( + callback, + expandPrefixedName(subject, prefixes), + expandPrefixedName(predicate, prefixes), + expandPrefixedName(object, prefixes), + expandPrefixedName(graph, prefixes) + ); + }, + + // ### `everyByIRI` executes the callback on all triples, + // and returns `true` if it returns truthy for all them. + // Setting any field to `undefined` or `null` indicates a wildcard. + everyByIRI: function (callback, subject, predicate, object, graph) { + var some = false; + var every = !this.someByIRI(function (quad) { + some = true; + return !callback(quad); + }, subject, predicate, object, graph); + return some && every; + }, + + // ### `some` executes the callback on all triples, + // and returns `true` if it returns truthy for any of them. + // Setting any field to `undefined` or `null` indicates a wildcard. + some: function (callback, subject, predicate, object, graph) { + var prefixes = this._prefixes; + return this.someByIRI( + callback, + expandPrefixedName(subject, prefixes), + expandPrefixedName(predicate, prefixes), + expandPrefixedName(object, prefixes), + expandPrefixedName(graph, prefixes) + ); + }, + + // ### `someByIRI` executes the callback on all triples, + // and returns `true` if it returns truthy for any of them. + // Setting any field to `undefined` or `null` indicates a wildcard. + someByIRI: function (callback, subject, predicate, object, graph) { + var graphs = this._getGraphs(graph), content, + ids = this._ids, subjectId, predicateId, objectId; + + // Translate IRIs to internal index keys. + if (isString(subject) && !(subjectId = ids[subject]) || + isString(predicate) && !(predicateId = ids[predicate]) || + isString(object) && !(objectId = ids[object])) + return false; + + for (var graphId in graphs) { + // Only if the specified graph contains triples, there can be result + if (content = graphs[graphId]) { + // Choose the optimal index, based on what fields are present + if (subjectId) { + if (objectId) { + // If subject and object are given, the object index will be the fastest + if (this._findInIndex(content.objects, objectId, subjectId, predicateId, + 'object', 'subject', 'predicate', graphId, callback, null)) + return true; + } + else + // If only subject and possibly predicate are given, the subject index will be the fastest + if (this._findInIndex(content.subjects, subjectId, predicateId, null, + 'subject', 'predicate', 'object', graphId, callback, null)) + return true; + } + else if (predicateId) { + // If only predicate and possibly object are given, the predicate index will be the fastest + if (this._findInIndex(content.predicates, predicateId, objectId, null, + 'predicate', 'object', 'subject', graphId, callback, null)) { + return true; + } + } + else if (objectId) { + // If only object is given, the object index will be the fastest + if (this._findInIndex(content.objects, objectId, null, null, + 'object', 'subject', 'predicate', graphId, callback, null)) { + return true; + } + } + else + // If nothing is given, iterate subjects and predicates first + if (this._findInIndex(content.subjects, null, null, null, + 'subject', 'predicate', 'object', graphId, callback, null)) { + return true; + } + } + } + return false; + }, + + // ### `getSubjects` returns all subjects that match the pattern. + // Setting any field to `undefined` or `null` indicates a wildcard. + getSubjects: function (predicate, object, graph) { + var prefixes = this._prefixes; + return this.getSubjectsByIRI( + expandPrefixedName(predicate, prefixes), + expandPrefixedName(object, prefixes), + expandPrefixedName(graph, prefixes) + ); + }, + + // ### `getSubjectsByIRI` returns all subjects that match the pattern. + // Setting any field to `undefined` or `null` indicates a wildcard. + getSubjectsByIRI: function (predicate, object, graph) { + var results = []; + this.forSubjectsByIRI(function (s) { results.push(s); }, predicate, object, graph); + return results; + }, + + // ### `forSubjects` executes the callback on all subjects that match the pattern. + // Setting any field to `undefined` or `null` indicates a wildcard. + forSubjects: function (callback, predicate, object, graph) { + var prefixes = this._prefixes; + this.forSubjectsByIRI( + callback, + expandPrefixedName(predicate, prefixes), + expandPrefixedName(object, prefixes), + expandPrefixedName(graph, prefixes) + ); + }, + + // ### `forSubjectsByIRI` executes the callback on all subjects that match the pattern. + // Setting any field to `undefined` or `null` indicates a wildcard. + forSubjectsByIRI: function (callback, predicate, object, graph) { + var ids = this._ids, graphs = this._getGraphs(graph), content, predicateId, objectId; + callback = this._uniqueEntities(callback); + + // Translate IRIs to internal index keys. + if (isString(predicate) && !(predicateId = ids[predicate]) || + isString(object) && !(objectId = ids[object])) + return; + + for (graph in graphs) { + // Only if the specified graph contains triples, there can be results + if (content = graphs[graph]) { + // Choose optimal index based on which fields are wildcards + if (predicateId) { + if (objectId) + // If predicate and object are given, the POS index is best. + this._loopBy2Keys(content.predicates, predicateId, objectId, callback); + else + // If only predicate is given, the SPO index is best. + this._loopByKey1(content.subjects, predicateId, callback); + } + else if (objectId) + // If only object is given, the OSP index is best. + this._loopByKey0(content.objects, objectId, callback); + else + // If no params given, iterate all the subjects + this._loop(content.subjects, callback); + } + } + }, + + // ### `getPredicates` returns all predicates that match the pattern. + // Setting any field to `undefined` or `null` indicates a wildcard. + getPredicates: function (subject, object, graph) { + var prefixes = this._prefixes; + return this.getPredicatesByIRI( + expandPrefixedName(subject, prefixes), + expandPrefixedName(object, prefixes), + expandPrefixedName(graph, prefixes) + ); + }, + + // ### `getPredicatesByIRI` returns all predicates that match the pattern. + // Setting any field to `undefined` or `null` indicates a wildcard. + getPredicatesByIRI: function (subject, object, graph) { + var results = []; + this.forPredicatesByIRI(function (p) { results.push(p); }, subject, object, graph); + return results; + }, + + // ### `forPredicates` executes the callback on all predicates that match the pattern. + // Setting any field to `undefined` or `null` indicates a wildcard. + forPredicates: function (callback, subject, object, graph) { + var prefixes = this._prefixes; + this.forPredicatesByIRI( + callback, + expandPrefixedName(subject, prefixes), + expandPrefixedName(object, prefixes), + expandPrefixedName(graph, prefixes) + ); + }, + + // ### `forPredicatesByIRI` executes the callback on all predicates that match the pattern. + // Setting any field to `undefined` or `null` indicates a wildcard. + forPredicatesByIRI: function (callback, subject, object, graph) { + var ids = this._ids, graphs = this._getGraphs(graph), content, subjectId, objectId; + callback = this._uniqueEntities(callback); + + // Translate IRIs to internal index keys. + if (isString(subject) && !(subjectId = ids[subject]) || + isString(object) && !(objectId = ids[object])) + return; + + for (graph in graphs) { + // Only if the specified graph contains triples, there can be results + if (content = graphs[graph]) { + // Choose optimal index based on which fields are wildcards + if (subjectId) { + if (objectId) + // If subject and object are given, the OSP index is best. + this._loopBy2Keys(content.objects, objectId, subjectId, callback); + else + // If only subject is given, the SPO index is best. + this._loopByKey0(content.subjects, subjectId, callback); + } + else if (objectId) + // If only object is given, the POS index is best. + this._loopByKey1(content.predicates, objectId, callback); + else + // If no params given, iterate all the predicates. + this._loop(content.predicates, callback); + } + } + }, + + // ### `getObjects` returns all objects that match the pattern. + // Setting any field to `undefined` or `null` indicates a wildcard. + getObjects: function (subject, predicate, graph) { + var prefixes = this._prefixes; + return this.getObjectsByIRI( + expandPrefixedName(subject, prefixes), + expandPrefixedName(predicate, prefixes), + expandPrefixedName(graph, prefixes) + ); + }, + + // ### `getObjectsByIRI` returns all objects that match the pattern. + // Setting any field to `undefined` or `null` indicates a wildcard. + getObjectsByIRI: function (subject, predicate, graph) { + var results = []; + this.forObjectsByIRI(function (o) { results.push(o); }, subject, predicate, graph); + return results; + }, + + // ### `forObjects` executes the callback on all objects that match the pattern. + // Setting any field to `undefined` or `null` indicates a wildcard. + forObjects: function (callback, subject, predicate, graph) { + var prefixes = this._prefixes; + this.forObjectsByIRI( + callback, + expandPrefixedName(subject, prefixes), + expandPrefixedName(predicate, prefixes), + expandPrefixedName(graph, prefixes) + ); + }, + + // ### `forObjectsByIRI` executes the callback on all objects that match the pattern. + // Setting any field to `undefined` or `null` indicates a wildcard. + forObjectsByIRI: function (callback, subject, predicate, graph) { + var ids = this._ids, graphs = this._getGraphs(graph), content, subjectId, predicateId; + callback = this._uniqueEntities(callback); + + // Translate IRIs to internal index keys. + if (isString(subject) && !(subjectId = ids[subject]) || + isString(predicate) && !(predicateId = ids[predicate])) + return; + + for (graph in graphs) { + // Only if the specified graph contains triples, there can be results + if (content = graphs[graph]) { + // Choose optimal index based on which fields are wildcards + if (subjectId) { + if (predicateId) + // If subject and predicate are given, the SPO index is best. + this._loopBy2Keys(content.subjects, subjectId, predicateId, callback); + else + // If only subject is given, the OSP index is best. + this._loopByKey1(content.objects, subjectId, callback); + } + else if (predicateId) + // If only predicate is given, the POS index is best. + this._loopByKey0(content.predicates, predicateId, callback); + else + // If no params given, iterate all the objects. + this._loop(content.objects, callback); + } + } + }, + + // ### `getGraphs` returns all graphs that match the pattern. + // Setting any field to `undefined` or `null` indicates a wildcard. + getGraphs: function (subject, predicate, object) { + var prefixes = this._prefixes; + return this.getGraphsByIRI( + expandPrefixedName(subject, prefixes), + expandPrefixedName(predicate, prefixes), + expandPrefixedName(object, prefixes) + ); + }, + + // ### `getGraphsByIRI` returns all graphs that match the pattern. + // Setting any field to `undefined` or `null` indicates a wildcard. + getGraphsByIRI: function (subject, predicate, object) { + var results = []; + this.forGraphsByIRI(function (g) { results.push(g); }, subject, predicate, object); + return results; + }, + + // ### `forGraphs` executes the callback on all graphs that match the pattern. + // Setting any field to `undefined` or `null` indicates a wildcard. + forGraphs: function (callback, subject, predicate, object) { + var prefixes = this._prefixes; + this.forGraphsByIRI( + callback, + expandPrefixedName(subject, prefixes), + expandPrefixedName(predicate, prefixes), + expandPrefixedName(object, prefixes) + ); + }, + + // ### `forGraphsByIRI` executes the callback on all graphs that match the pattern. + // Setting any field to `undefined` or `null` indicates a wildcard. + forGraphsByIRI: function (callback, subject, predicate, object) { + for (var graph in this._graphs) { + this.someByIRI(function (quad) { + callback(quad.graph); + return true; // Halt iteration of some() + }, subject, predicate, object, graph); + } + }, + + // ### `createBlankNode` creates a new blank node, returning its name + createBlankNode: function (suggestedName) { + var name, index; + // Generate a name based on the suggested name + if (suggestedName) { + name = suggestedName = '_:' + suggestedName, index = 1; + while (this._ids[name]) + name = suggestedName + index++; + } + // Generate a generic blank node name + else { + do { name = '_:b' + this._blankNodeIndex++; } + while (this._ids[name]); + } + // Add the blank node to the entities, avoiding the generation of duplicates + this._ids[name] = ++this._id; + this._entities[this._id] = name; + return name; + }, +}; + +// Determines whether the argument is a string +function isString(s) { + return typeof s === 'string' || s instanceof String; +} + +// ## Exports +module.exports = N3Store; + +},{"./N3Util":8}],6:[function(require,module,exports){ +// **N3StreamParser** parses an N3 stream into a triple stream. +var Transform = require('stream').Transform, + util = require('util'), + N3Parser = require('./N3Parser.js'); + +// ## Constructor +function N3StreamParser(options) { + if (!(this instanceof N3StreamParser)) + return new N3StreamParser(options); + + // Initialize Transform base class + Transform.call(this, { decodeStrings: true }); + this._readableState.objectMode = true; + + // Set up parser + var self = this, parser = new N3Parser(options), onData, onEnd; + // Pass dummy stream to obtain `data` and `end` callbacks + parser.parse({ + on: function (event, cb) { + switch (event) { + case 'data': onData = cb; break; + case 'end': onEnd = cb; break; + } + }, + }, + // Handle triples by pushing them down the pipeline + function (error, t) { error && self.emit('error', error) || t && self.push(t); }, + // Emit prefixes through the `prefix` event + function (prefix, uri) { self.emit('prefix', prefix, uri); }); + + // Implement Transform methods through parser callbacks + this._transform = function (chunk, encoding, done) { onData(chunk); done(); }; + this._flush = function (done) { onEnd(); done(); }; +} +util.inherits(N3StreamParser, Transform); + +// ## Exports +module.exports = N3StreamParser; + +},{"./N3Parser.js":4,"stream":33,"util":38}],7:[function(require,module,exports){ +// **N3StreamWriter** serializes a triple stream into an N3 stream. +var Transform = require('stream').Transform, + util = require('util'), + N3Writer = require('./N3Writer.js'); + +// ## Constructor +function N3StreamWriter(options) { + if (!(this instanceof N3StreamWriter)) + return new N3StreamWriter(options); + + // Initialize Transform base class + Transform.call(this, { encoding: 'utf8' }); + this._writableState.objectMode = true; + + // Set up writer with a dummy stream object + var self = this; + var writer = new N3Writer({ + write: function (chunk, encoding, callback) { self.push(chunk); callback && callback(); }, + end: function (callback) { self.push(null); callback && callback(); }, + }, options); + + // Implement Transform methods on top of writer + this._transform = function (triple, encoding, done) { writer.addTriple(triple, done); }; + this._flush = function (done) { writer.end(done); }; +} +util.inherits(N3StreamWriter, Transform); + +// ## Exports +module.exports = N3StreamWriter; + +},{"./N3Writer.js":9,"stream":33,"util":38}],8:[function(require,module,exports){ +// **N3Util** provides N3 utility functions. + +var Xsd = 'http://www.w3.org/2001/XMLSchema#'; +var XsdString = Xsd + 'string'; +var XsdInteger = Xsd + 'integer'; +var XsdDouble = Xsd + 'double'; +var XsdBoolean = Xsd + 'boolean'; +var RdfLangString = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString'; + +var N3Util = { + // Tests whether the given entity (triple object) represents an IRI in the N3 library + isIRI: function (entity) { + if (typeof entity !== 'string') + return false; + else if (entity.length === 0) + return true; + else { + var firstChar = entity[0]; + return firstChar !== '"' && firstChar !== '_'; + } + }, + + // Tests whether the given entity (triple object) represents a literal in the N3 library + isLiteral: function (entity) { + return typeof entity === 'string' && entity[0] === '"'; + }, + + // Tests whether the given entity (triple object) represents a blank node in the N3 library + isBlank: function (entity) { + return typeof entity === 'string' && entity.substr(0, 2) === '_:'; + }, + + // Tests whether the given entity represents the default graph + isDefaultGraph: function (entity) { + return !entity; + }, + + // Tests whether the given triple is in the default graph + inDefaultGraph: function (triple) { + return !triple.graph; + }, + + // Gets the string value of a literal in the N3 library + getLiteralValue: function (literal) { + var match = /^"([^]*)"/.exec(literal); + if (!match) + throw new Error(literal + ' is not a literal'); + return match[1]; + }, + + // Gets the type of a literal in the N3 library + getLiteralType: function (literal) { + var match = /^"[^]*"(?:\^\^([^"]+)|(@)[^@"]+)?$/.exec(literal); + if (!match) + throw new Error(literal + ' is not a literal'); + return match[1] || (match[2] ? RdfLangString : XsdString); + }, + + // Gets the language of a literal in the N3 library + getLiteralLanguage: function (literal) { + var match = /^"[^]*"(?:@([^@"]+)|\^\^[^"]+)?$/.exec(literal); + if (!match) + throw new Error(literal + ' is not a literal'); + return match[1] ? match[1].toLowerCase() : ''; + }, + + // Tests whether the given entity (triple object) represents a prefixed name + isPrefixedName: function (entity) { + return typeof entity === 'string' && /^[^:\/"']*:[^:\/"']+$/.test(entity); + }, + + // Expands the prefixed name to a full IRI (also when it occurs as a literal's type) + expandPrefixedName: function (prefixedName, prefixes) { + var match = /(?:^|"\^\^)([^:\/#"'\^_]*):[^\/]*$/.exec(prefixedName), prefix, base, index; + if (match) + prefix = match[1], base = prefixes[prefix], index = match.index; + if (base === undefined) + return prefixedName; + + // The match index is non-zero when expanding a literal's type + return index === 0 ? base + prefixedName.substr(prefix.length + 1) + : prefixedName.substr(0, index + 3) + + base + prefixedName.substr(index + prefix.length + 4); + }, + + // Creates an IRI in N3.js representation + createIRI: function (iri) { + return iri && iri[0] === '"' ? N3Util.getLiteralValue(iri) : iri; + }, + + // Creates a literal in N3.js representation + createLiteral: function (value, modifier) { + if (!modifier) { + switch (typeof value) { + case 'boolean': + modifier = XsdBoolean; + break; + case 'number': + if (isFinite(value)) + modifier = value % 1 === 0 ? XsdInteger : XsdDouble; + else { + modifier = XsdDouble; + if (!isNaN(value)) + value = value > 0 ? 'INF' : '-INF'; + } + break; + default: + return '"' + value + '"'; + } + } + return '"' + value + + (/^[a-z]+(-[a-z0-9]+)*$/i.test(modifier) ? '"@' + modifier.toLowerCase() + : '"^^' + modifier); + }, + + // Creates a function that prepends the given IRI to a local name + prefix: function (iri) { + return N3Util.prefixes({ '': iri })(''); + }, + + // Creates a function that allows registering and expanding prefixes + prefixes: function (defaultPrefixes) { + // Add all of the default prefixes + var prefixes = Object.create(null); + for (var prefix in defaultPrefixes) + processPrefix(prefix, defaultPrefixes[prefix]); + + // Registers a new prefix (if an IRI was specified) + // or retrieves a function that expands an existing prefix (if no IRI was specified) + function processPrefix(prefix, iri) { + // Create a new prefix if an IRI is specified or the prefix doesn't exist + if (iri || !(prefix in prefixes)) { + var cache = Object.create(null); + iri = iri || ''; + // Create a function that expands the prefix + prefixes[prefix] = function (localName) { + return cache[localName] || (cache[localName] = iri + localName); + }; + } + return prefixes[prefix]; + } + return processPrefix; + }, +}; + +// ## Exports +module.exports = N3Util; + +},{}],9:[function(require,module,exports){ +// **N3Writer** writes N3 documents. + +// Matches a literal as represented in memory by the N3 library +var N3LiteralMatcher = /^"([^]*)"(?:\^\^(.+)|@([\-a-z]+))?$/i; + +// rdf:type predicate (for 'a' abbreviation) +var RDF_PREFIX = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', + RDF_TYPE = RDF_PREFIX + 'type'; + +// Characters in literals that require escaping +var escape = /["\\\t\n\r\b\f\u0000-\u0019\ud800-\udbff]/, + escapeAll = /["\\\t\n\r\b\f\u0000-\u0019]|[\ud800-\udbff][\udc00-\udfff]/g, + escapedCharacters = { + '\\': '\\\\', '"': '\\"', '\t': '\\t', + '\n': '\\n', '\r': '\\r', '\b': '\\b', '\f': '\\f', + }; + +// ## Constructor +function N3Writer(outputStream, options) { + if (!(this instanceof N3Writer)) + return new N3Writer(outputStream, options); + + // Shift arguments if the first argument is not a stream + if (outputStream && typeof outputStream.write !== 'function') + options = outputStream, outputStream = null; + options = options || {}; + + // If no output stream given, send the output as string through the end callback + if (!outputStream) { + var output = ''; + this._outputStream = { + write: function (chunk, encoding, done) { output += chunk; done && done(); }, + end: function (done) { done && done(null, output); }, + }; + this._endStream = true; + } + else { + this._outputStream = outputStream; + this._endStream = options.end === undefined ? true : !!options.end; + } + + // Initialize writer, depending on the format + this._subject = null; + if (!(/triple|quad/i).test(options.format)) { + this._graph = ''; + this._prefixIRIs = Object.create(null); + options.prefixes && this.addPrefixes(options.prefixes); + } + else { + this._writeTriple = this._writeTripleLine; + } +} + +N3Writer.prototype = { + // ## Private methods + + // ### `_write` writes the argument to the output stream + _write: function (string, callback) { + this._outputStream.write(string, 'utf8', callback); + }, + + // ### `_writeTriple` writes the triple to the output stream + _writeTriple: function (subject, predicate, object, graph, done) { + try { + // Write the graph's label if it has changed + if (this._graph !== graph) { + // Close the previous graph and start the new one + this._write((this._subject === null ? '' : (this._graph ? '\n}\n' : '.\n')) + + (graph ? this._encodeIriOrBlankNode(graph) + ' {\n' : '')); + this._subject = null; + // Don't treat identical blank nodes as repeating graphs + this._graph = graph[0] !== '[' ? graph : ']'; + } + // Don't repeat the subject if it's the same + if (this._subject === subject) { + // Don't repeat the predicate if it's the same + if (this._predicate === predicate) + this._write(', ' + this._encodeObject(object), done); + // Same subject, different predicate + else + this._write(';\n ' + + this._encodePredicate(this._predicate = predicate) + ' ' + + this._encodeObject(object), done); + } + // Different subject; write the whole triple + else + this._write((this._subject === null ? '' : '.\n') + + this._encodeSubject(this._subject = subject) + ' ' + + this._encodePredicate(this._predicate = predicate) + ' ' + + this._encodeObject(object), done); + } + catch (error) { done && done(error); } + }, + + // ### `_writeTripleLine` writes the triple or quad to the output stream as a single line + _writeTripleLine: function (subject, predicate, object, graph, done) { + // Write the triple without prefixes + delete this._prefixMatch; + try { this._write(this.tripleToString(subject, predicate, object, graph), done); } + catch (error) { done && done(error); } + }, + + // ### `tripleToString` serializes a triple or quad as a string + tripleToString: function (subject, predicate, object, graph) { + return this._encodeIriOrBlankNode(subject) + ' ' + + this._encodeIriOrBlankNode(predicate) + ' ' + + this._encodeObject(object) + + (graph ? ' ' + this._encodeIriOrBlankNode(graph) + '.\n' : '.\n'); + }, + + // ### `triplesToString` serializes an array of triples or quads as a string + triplesToString: function (triples) { + return triples.map(function (t) { + return this.tripleToString(t.subject, t.predicate, t.object, t.graph); + }, this).join(''); + }, + + // ### `_encodeIriOrBlankNode` represents an IRI or blank node + _encodeIriOrBlankNode: function (entity) { + // A blank node or list is represented as-is + var firstChar = entity[0]; + if (firstChar === '[' || firstChar === '(' || firstChar === '_' && entity[1] === ':') + return entity; + // Escape special characters + if (escape.test(entity)) + entity = entity.replace(escapeAll, characterReplacer); + // Try to represent the IRI as prefixed name + var prefixMatch = this._prefixRegex.exec(entity); + return !prefixMatch ? '<' + entity + '>' : + (!prefixMatch[1] ? entity : this._prefixIRIs[prefixMatch[1]] + prefixMatch[2]); + }, + + // ### `_encodeLiteral` represents a literal + _encodeLiteral: function (value, type, language) { + // Escape special characters + if (escape.test(value)) + value = value.replace(escapeAll, characterReplacer); + // Write the literal, possibly with type or language + if (language) + return '"' + value + '"@' + language; + else if (type) + return '"' + value + '"^^' + this._encodeIriOrBlankNode(type); + else + return '"' + value + '"'; + }, + + // ### `_encodeSubject` represents a subject + _encodeSubject: function (subject) { + if (subject[0] === '"') + throw new Error('A literal as subject is not allowed: ' + subject); + // Don't treat identical blank nodes as repeating subjects + if (subject[0] === '[') + this._subject = ']'; + return this._encodeIriOrBlankNode(subject); + }, + + // ### `_encodePredicate` represents a predicate + _encodePredicate: function (predicate) { + if (predicate[0] === '"') + throw new Error('A literal as predicate is not allowed: ' + predicate); + return predicate === RDF_TYPE ? 'a' : this._encodeIriOrBlankNode(predicate); + }, + + // ### `_encodeObject` represents an object + _encodeObject: function (object) { + // Represent an IRI or blank node + if (object[0] !== '"') + return this._encodeIriOrBlankNode(object); + // Represent a literal + var match = N3LiteralMatcher.exec(object); + if (!match) throw new Error('Invalid literal: ' + object); + return this._encodeLiteral(match[1], match[2], match[3]); + }, + + // ### `_blockedWrite` replaces `_write` after the writer has been closed + _blockedWrite: function () { + throw new Error('Cannot write because the writer has been closed.'); + }, + + // ### `addTriple` adds the triple to the output stream + addTriple: function (subject, predicate, object, graph, done) { + // The triple was given as a triple object, so shift parameters + if (object === undefined) + this._writeTriple(subject.subject, subject.predicate, subject.object, + subject.graph || '', predicate); + // The optional `graph` parameter was not provided + else if (typeof graph !== 'string') + this._writeTriple(subject, predicate, object, '', graph); + // The `graph` parameter was provided + else + this._writeTriple(subject, predicate, object, graph, done); + }, + + // ### `addTriples` adds the triples to the output stream + addTriples: function (triples) { + for (var i = 0; i < triples.length; i++) + this.addTriple(triples[i]); + }, + + // ### `addPrefix` adds the prefix to the output stream + addPrefix: function (prefix, iri, done) { + var prefixes = {}; + prefixes[prefix] = iri; + this.addPrefixes(prefixes, done); + }, + + // ### `addPrefixes` adds the prefixes to the output stream + addPrefixes: function (prefixes, done) { + // Add all useful prefixes + var prefixIRIs = this._prefixIRIs, hasPrefixes = false; + for (var prefix in prefixes) { + // Verify whether the prefix can be used and does not exist yet + var iri = prefixes[prefix]; + if (/[#\/]$/.test(iri) && prefixIRIs[iri] !== (prefix += ':')) { + hasPrefixes = true; + prefixIRIs[iri] = prefix; + // Finish a possible pending triple + if (this._subject !== null) { + this._write(this._graph ? '\n}\n' : '.\n'); + this._subject = null, this._graph = ''; + } + // Write prefix + this._write('@prefix ' + prefix + ' <' + iri + '>.\n'); + } + } + // Recreate the prefix matcher + if (hasPrefixes) { + var IRIlist = '', prefixList = ''; + for (var prefixIRI in prefixIRIs) { + IRIlist += IRIlist ? '|' + prefixIRI : prefixIRI; + prefixList += (prefixList ? '|' : '') + prefixIRIs[prefixIRI]; + } + IRIlist = IRIlist.replace(/[\]\/\(\)\*\+\?\.\\\$]/g, '\\$&'); + this._prefixRegex = new RegExp('^(?:' + prefixList + ')[^\/]*$|' + + '^(' + IRIlist + ')([a-zA-Z][\\-_a-zA-Z0-9]*)$'); + } + // End a prefix block with a newline + this._write(hasPrefixes ? '\n' : '', done); + }, + + // ### `blank` creates a blank node with the given content + blank: function (predicate, object) { + var children = predicate, child, length; + // Empty blank node + if (predicate === undefined) + children = []; + // Blank node passed as blank("predicate", "object") + else if (typeof predicate === 'string') + children = [{ predicate: predicate, object: object }]; + // Blank node passed as blank({ predicate: predicate, object: object }) + else if (!('length' in predicate)) + children = [predicate]; + + switch (length = children.length) { + // Generate an empty blank node + case 0: + return '[]'; + // Generate a non-nested one-triple blank node + case 1: + child = children[0]; + if (child.object[0] !== '[') + return '[ ' + this._encodePredicate(child.predicate) + ' ' + + this._encodeObject(child.object) + ' ]'; + // Generate a multi-triple or nested blank node + default: + var contents = '['; + // Write all triples in order + for (var i = 0; i < length; i++) { + child = children[i]; + // Write only the object is the predicate is the same as the previous + if (child.predicate === predicate) + contents += ', ' + this._encodeObject(child.object); + // Otherwise, write the predicate and the object + else { + contents += (i ? ';\n ' : '\n ') + + this._encodePredicate(child.predicate) + ' ' + + this._encodeObject(child.object); + predicate = child.predicate; + } + } + return contents + '\n]'; + } + }, + + // ### `list` creates a list node with the given content + list: function (elements) { + var length = elements && elements.length || 0, contents = new Array(length); + for (var i = 0; i < length; i++) + contents[i] = this._encodeObject(elements[i]); + return '(' + contents.join(' ') + ')'; + }, + + // ### `_prefixRegex` matches a prefixed name or IRI that begins with one of the added prefixes + _prefixRegex: /$0^/, + + // ### `end` signals the end of the output stream + end: function (done) { + // Finish a possible pending triple + if (this._subject !== null) { + this._write(this._graph ? '\n}\n' : '.\n'); + this._subject = null; + } + // Disallow further writing + this._write = this._blockedWrite; + + // Try to end the underlying stream, ensuring done is called exactly one time + var singleDone = done && function (error, result) { singleDone = null, done(error, result); }; + if (this._endStream) { + try { return this._outputStream.end(singleDone); } + catch (error) { /* error closing stream */ } + } + singleDone && singleDone(); + }, +}; + +// Replaces a character by its escaped version +function characterReplacer(character) { + // Replace a single character by its escaped version + var result = escapedCharacters[character]; + if (result === undefined) { + // Replace a single character with its 4-bit unicode escape sequence + if (character.length === 1) { + result = character.charCodeAt(0).toString(16); + result = '\\u0000'.substr(0, 6 - result.length) + result; + } + // Replace a surrogate pair with its 8-bit unicode escape sequence + else { + result = ((character.charCodeAt(0) - 0xD800) * 0x400 + + character.charCodeAt(1) + 0x2400).toString(16); + result = '\\U00000000'.substr(0, 10 - result.length) + result; + } + } + return result; +} + +// ## Exports +module.exports = N3Writer; + +},{}],10:[function(require,module,exports){ 'use strict' exports.byteLength = byteLength @@ -114,9 +2870,9 @@ function fromByteArray (uint8) { return parts.join('') } -},{}],2:[function(require,module,exports){ +},{}],11:[function(require,module,exports){ -},{}],3:[function(require,module,exports){ +},{}],12:[function(require,module,exports){ (function (global){ 'use strict'; @@ -228,8 +2984,7 @@ exports.allocUnsafeSlow = function allocUnsafeSlow(size) { } }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"buffer":4}],4:[function(require,module,exports){ -(function (global){ +},{"buffer":13}],13:[function(require,module,exports){ /*! * The buffer module from node.js, for the browser. * @@ -242,80 +2997,57 @@ exports.allocUnsafeSlow = function allocUnsafeSlow(size) { var base64 = require('base64-js') var ieee754 = require('ieee754') -var isArray = require('isarray') exports.Buffer = Buffer exports.SlowBuffer = SlowBuffer exports.INSPECT_MAX_BYTES = 50 +var K_MAX_LENGTH = 0x7fffffff +exports.kMaxLength = K_MAX_LENGTH + /** * If `Buffer.TYPED_ARRAY_SUPPORT`: * === true Use Uint8Array implementation (fastest) - * === false Use Object implementation (most compatible, even IE6) + * === false Print warning and recommend using `buffer` v4.x which has an Object + * implementation (most compatible, even IE6) * * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, * Opera 11.6+, iOS 4.2+. * - * Due to various browser bugs, sometimes the Object implementation will be used even - * when the browser supports typed arrays. - * - * Note: - * - * - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances, - * See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438. - * - * - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function. - * - * - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of - * incorrect length in some situations. - - * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they - * get the Object implementation, which is slower but behaves correctly. + * We report that the browser does not support typed arrays if the are not subclassable + * using __proto__. Firefox 4-29 lacks support for adding new properties to `Uint8Array` + * (See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438). IE 10 lacks support + * for __proto__ and has a buggy typed array implementation. */ -Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined - ? global.TYPED_ARRAY_SUPPORT - : typedArraySupport() +Buffer.TYPED_ARRAY_SUPPORT = typedArraySupport() -/* - * Export kMaxLength after typed array support is determined. - */ -exports.kMaxLength = kMaxLength() +if (!Buffer.TYPED_ARRAY_SUPPORT && typeof console !== 'undefined' && + typeof console.error === 'function') { + console.error( + 'This browser lacks typed array (Uint8Array) support which is required by ' + + '`buffer` v5.x. Use `buffer` v4.x if you require old browser support.' + ) +} function typedArraySupport () { + // Can typed array instances can be augmented? try { var arr = new Uint8Array(1) arr.__proto__ = {__proto__: Uint8Array.prototype, foo: function () { return 42 }} - return arr.foo() === 42 && // typed array instances can be augmented - typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray` - arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray` + return arr.foo() === 42 } catch (e) { return false } } -function kMaxLength () { - return Buffer.TYPED_ARRAY_SUPPORT - ? 0x7fffffff - : 0x3fffffff -} - -function createBuffer (that, length) { - if (kMaxLength() < length) { +function createBuffer (length) { + if (length > K_MAX_LENGTH) { throw new RangeError('Invalid typed array length') } - if (Buffer.TYPED_ARRAY_SUPPORT) { - // Return an augmented `Uint8Array` instance, for best performance - that = new Uint8Array(length) - that.__proto__ = Buffer.prototype - } else { - // Fallback: Return an object instance of the Buffer class - if (that === null) { - that = new Buffer(length) - } - that.length = length - } - - return that + // Return an augmented `Uint8Array` instance + var buf = new Uint8Array(length) + buf.__proto__ = Buffer.prototype + return buf } /** @@ -329,10 +3061,6 @@ function createBuffer (that, length) { */ function Buffer (arg, encodingOrOffset, length) { - if (!Buffer.TYPED_ARRAY_SUPPORT && !(this instanceof Buffer)) { - return new Buffer(arg, encodingOrOffset, length) - } - // Common case. if (typeof arg === 'number') { if (typeof encodingOrOffset === 'string') { @@ -340,33 +3068,38 @@ function Buffer (arg, encodingOrOffset, length) { 'If encoding is specified then the first argument must be a string' ) } - return allocUnsafe(this, arg) + return allocUnsafe(arg) } - return from(this, arg, encodingOrOffset, length) + return from(arg, encodingOrOffset, length) +} + +// Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97 +if (typeof Symbol !== 'undefined' && Symbol.species && + Buffer[Symbol.species] === Buffer) { + Object.defineProperty(Buffer, Symbol.species, { + value: null, + configurable: true, + enumerable: false, + writable: false + }) } Buffer.poolSize = 8192 // not used by this implementation -// TODO: Legacy, not needed anymore. Remove in next major version. -Buffer._augment = function (arr) { - arr.__proto__ = Buffer.prototype - return arr -} - -function from (that, value, encodingOrOffset, length) { +function from (value, encodingOrOffset, length) { if (typeof value === 'number') { throw new TypeError('"value" argument must not be a number') } - if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) { - return fromArrayBuffer(that, value, encodingOrOffset, length) + if (value instanceof ArrayBuffer) { + return fromArrayBuffer(value, encodingOrOffset, length) } if (typeof value === 'string') { - return fromString(that, value, encodingOrOffset) + return fromString(value, encodingOrOffset) } - return fromObject(that, value) + return fromObject(value) } /** @@ -378,21 +3111,13 @@ function from (that, value, encodingOrOffset, length) { * Buffer.from(arrayBuffer[, byteOffset[, length]]) **/ Buffer.from = function (value, encodingOrOffset, length) { - return from(null, value, encodingOrOffset, length) + return from(value, encodingOrOffset, length) } -if (Buffer.TYPED_ARRAY_SUPPORT) { - Buffer.prototype.__proto__ = Uint8Array.prototype - Buffer.__proto__ = Uint8Array - if (typeof Symbol !== 'undefined' && Symbol.species && - Buffer[Symbol.species] === Buffer) { - // Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97 - Object.defineProperty(Buffer, Symbol.species, { - value: null, - configurable: true - }) - } -} +// Note: Change prototype *after* Buffer.from is defined to workaround Chrome bug: +// https://github.com/feross/buffer/pull/148 +Buffer.prototype.__proto__ = Uint8Array.prototype +Buffer.__proto__ = Uint8Array function assertSize (size) { if (typeof size !== 'number') { @@ -402,20 +3127,20 @@ function assertSize (size) { } } -function alloc (that, size, fill, encoding) { +function alloc (size, fill, encoding) { assertSize(size) if (size <= 0) { - return createBuffer(that, size) + return createBuffer(size) } if (fill !== undefined) { // Only pay attention to encoding if it's a string. This // prevents accidentally sending in a number that would // be interpretted as a start offset. return typeof encoding === 'string' - ? createBuffer(that, size).fill(fill, encoding) - : createBuffer(that, size).fill(fill) + ? createBuffer(size).fill(fill, encoding) + : createBuffer(size).fill(fill) } - return createBuffer(that, size) + return createBuffer(size) } /** @@ -423,34 +3148,28 @@ function alloc (that, size, fill, encoding) { * alloc(size[, fill[, encoding]]) **/ Buffer.alloc = function (size, fill, encoding) { - return alloc(null, size, fill, encoding) + return alloc(size, fill, encoding) } -function allocUnsafe (that, size) { +function allocUnsafe (size) { assertSize(size) - that = createBuffer(that, size < 0 ? 0 : checked(size) | 0) - if (!Buffer.TYPED_ARRAY_SUPPORT) { - for (var i = 0; i < size; ++i) { - that[i] = 0 - } - } - return that + return createBuffer(size < 0 ? 0 : checked(size) | 0) } /** * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance. * */ Buffer.allocUnsafe = function (size) { - return allocUnsafe(null, size) + return allocUnsafe(size) } /** * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance. */ Buffer.allocUnsafeSlow = function (size) { - return allocUnsafe(null, size) + return allocUnsafe(size) } -function fromString (that, string, encoding) { +function fromString (string, encoding) { if (typeof encoding !== 'string' || encoding === '') { encoding = 'utf8' } @@ -460,32 +3179,30 @@ function fromString (that, string, encoding) { } var length = byteLength(string, encoding) | 0 - that = createBuffer(that, length) + var buf = createBuffer(length) - var actual = that.write(string, encoding) + var actual = buf.write(string, encoding) if (actual !== length) { // Writing a hex string, for example, that contains invalid characters will // cause everything after the first invalid character to be ignored. (e.g. // 'abxxcd' will be treated as 'ab') - that = that.slice(0, actual) + buf = buf.slice(0, actual) } - return that + return buf } -function fromArrayLike (that, array) { +function fromArrayLike (array) { var length = array.length < 0 ? 0 : checked(array.length) | 0 - that = createBuffer(that, length) + var buf = createBuffer(length) for (var i = 0; i < length; i += 1) { - that[i] = array[i] & 255 + buf[i] = array[i] & 255 } - return that + return buf } -function fromArrayBuffer (that, array, byteOffset, length) { - array.byteLength // this throws if `array` is not a valid ArrayBuffer - +function fromArrayBuffer (array, byteOffset, length) { if (byteOffset < 0 || array.byteLength < byteOffset) { throw new RangeError('\'offset\' is out of bounds') } @@ -494,49 +3211,43 @@ function fromArrayBuffer (that, array, byteOffset, length) { throw new RangeError('\'length\' is out of bounds') } + var buf if (byteOffset === undefined && length === undefined) { - array = new Uint8Array(array) + buf = new Uint8Array(array) } else if (length === undefined) { - array = new Uint8Array(array, byteOffset) + buf = new Uint8Array(array, byteOffset) } else { - array = new Uint8Array(array, byteOffset, length) + buf = new Uint8Array(array, byteOffset, length) } - if (Buffer.TYPED_ARRAY_SUPPORT) { - // Return an augmented `Uint8Array` instance, for best performance - that = array - that.__proto__ = Buffer.prototype - } else { - // Fallback: Return an object instance of the Buffer class - that = fromArrayLike(that, array) - } - return that + // Return an augmented `Uint8Array` instance + buf.__proto__ = Buffer.prototype + return buf } -function fromObject (that, obj) { +function fromObject (obj) { if (Buffer.isBuffer(obj)) { var len = checked(obj.length) | 0 - that = createBuffer(that, len) + var buf = createBuffer(len) - if (that.length === 0) { - return that + if (buf.length === 0) { + return buf } - obj.copy(that, 0, 0, len) - return that + obj.copy(buf, 0, 0, len) + return buf } if (obj) { - if ((typeof ArrayBuffer !== 'undefined' && - obj.buffer instanceof ArrayBuffer) || 'length' in obj) { + if (ArrayBuffer.isView(obj) || 'length' in obj) { if (typeof obj.length !== 'number' || isnan(obj.length)) { - return createBuffer(that, 0) + return createBuffer(0) } - return fromArrayLike(that, obj) + return fromArrayLike(obj) } - if (obj.type === 'Buffer' && isArray(obj.data)) { - return fromArrayLike(that, obj.data) + if (obj.type === 'Buffer' && Array.isArray(obj.data)) { + return fromArrayLike(obj.data) } } @@ -544,11 +3255,11 @@ function fromObject (that, obj) { } function checked (length) { - // Note: cannot use `length < kMaxLength()` here because that fails when + // Note: cannot use `length < K_MAX_LENGTH` here because that fails when // length is NaN (which is otherwise coerced to zero.) - if (length >= kMaxLength()) { + if (length >= K_MAX_LENGTH) { throw new RangeError('Attempt to allocate Buffer larger than maximum ' + - 'size: 0x' + kMaxLength().toString(16) + ' bytes') + 'size: 0x' + K_MAX_LENGTH.toString(16) + ' bytes') } return length | 0 } @@ -561,7 +3272,7 @@ function SlowBuffer (length) { } Buffer.isBuffer = function isBuffer (b) { - return !!(b != null && b._isBuffer) + return b != null && b._isBuffer === true } Buffer.compare = function compare (a, b) { @@ -607,7 +3318,7 @@ Buffer.isEncoding = function isEncoding (encoding) { } Buffer.concat = function concat (list, length) { - if (!isArray(list)) { + if (!Array.isArray(list)) { throw new TypeError('"list" argument must be an Array of Buffers') } @@ -640,8 +3351,7 @@ function byteLength (string, encoding) { if (Buffer.isBuffer(string)) { return string.length } - if (typeof ArrayBuffer !== 'undefined' && typeof ArrayBuffer.isView === 'function' && - (ArrayBuffer.isView(string) || string instanceof ArrayBuffer)) { + if (ArrayBuffer.isView(string) || string instanceof ArrayBuffer) { return string.byteLength } if (typeof string !== 'string') { @@ -751,8 +3461,12 @@ function slowToString (encoding, start, end) { } } -// The property is used by `Buffer.isBuffer` and `is-buffer` (in Safari 5-7) to detect -// Buffer instances. +// This property is used by `Buffer.isBuffer` (and the `is-buffer` npm package) +// to detect a Buffer instance. It's not possible to use `instanceof Buffer` +// reliably in a browserify context because there could be multiple different +// copies of the 'buffer' package in use. This method works even for Buffer +// instances that were created from another copy of the `buffer` package. +// See: https://github.com/feross/buffer/issues/154 Buffer.prototype._isBuffer = true function swap (b, n, m) { @@ -799,7 +3513,7 @@ Buffer.prototype.swap64 = function swap64 () { } Buffer.prototype.toString = function toString () { - var length = this.length | 0 + var length = this.length if (length === 0) return '' if (arguments.length === 0) return utf8Slice(this, 0, length) return slowToString.apply(this, arguments) @@ -932,8 +3646,7 @@ function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) { return arrayIndexOf(buffer, val, byteOffset, encoding, dir) } else if (typeof val === 'number') { val = val & 0xFF // Search for a byte value [0-255] - if (Buffer.TYPED_ARRAY_SUPPORT && - typeof Uint8Array.prototype.indexOf === 'function') { + if (typeof Uint8Array.prototype.indexOf === 'function') { if (dir) { return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset) } else { @@ -1074,15 +3787,14 @@ Buffer.prototype.write = function write (string, offset, length, encoding) { offset = 0 // Buffer#write(string, offset[, length][, encoding]) } else if (isFinite(offset)) { - offset = offset | 0 + offset = offset >>> 0 if (isFinite(length)) { - length = length | 0 + length = length >>> 0 if (encoding === undefined) encoding = 'utf8' } else { encoding = length length = undefined } - // legacy write(string, encoding, offset, length) - remove in v0.13 } else { throw new Error( 'Buffer.write(string, encoding, offset[, length]) is no longer supported' @@ -1281,7 +3993,7 @@ function utf16leSlice (buf, start, end) { var bytes = buf.slice(start, end) var res = '' for (var i = 0; i < bytes.length; i += 2) { - res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256) + res += String.fromCharCode(bytes[i] + (bytes[i + 1] * 256)) } return res } @@ -1307,18 +4019,9 @@ Buffer.prototype.slice = function slice (start, end) { if (end < start) end = start - var newBuf - if (Buffer.TYPED_ARRAY_SUPPORT) { - newBuf = this.subarray(start, end) - newBuf.__proto__ = Buffer.prototype - } else { - var sliceLen = end - start - newBuf = new Buffer(sliceLen, undefined) - for (var i = 0; i < sliceLen; ++i) { - newBuf[i] = this[i + start] - } - } - + var newBuf = this.subarray(start, end) + // Return an augmented `Uint8Array` instance + newBuf.__proto__ = Buffer.prototype return newBuf } @@ -1331,8 +4034,8 @@ function checkOffset (offset, ext, length) { } Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) { - offset = offset | 0 - byteLength = byteLength | 0 + offset = offset >>> 0 + byteLength = byteLength >>> 0 if (!noAssert) checkOffset(offset, byteLength, this.length) var val = this[offset] @@ -1346,8 +4049,8 @@ Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) } Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) { - offset = offset | 0 - byteLength = byteLength | 0 + offset = offset >>> 0 + byteLength = byteLength >>> 0 if (!noAssert) { checkOffset(offset, byteLength, this.length) } @@ -1362,21 +4065,25 @@ Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) } Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) { + offset = offset >>> 0 if (!noAssert) checkOffset(offset, 1, this.length) return this[offset] } Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) { + offset = offset >>> 0 if (!noAssert) checkOffset(offset, 2, this.length) return this[offset] | (this[offset + 1] << 8) } Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) { + offset = offset >>> 0 if (!noAssert) checkOffset(offset, 2, this.length) return (this[offset] << 8) | this[offset + 1] } Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) { + offset = offset >>> 0 if (!noAssert) checkOffset(offset, 4, this.length) return ((this[offset]) | @@ -1386,6 +4093,7 @@ Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) { } Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) { + offset = offset >>> 0 if (!noAssert) checkOffset(offset, 4, this.length) return (this[offset] * 0x1000000) + @@ -1395,8 +4103,8 @@ Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) { } Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) { - offset = offset | 0 - byteLength = byteLength | 0 + offset = offset >>> 0 + byteLength = byteLength >>> 0 if (!noAssert) checkOffset(offset, byteLength, this.length) var val = this[offset] @@ -1413,8 +4121,8 @@ Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) { } Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) { - offset = offset | 0 - byteLength = byteLength | 0 + offset = offset >>> 0 + byteLength = byteLength >>> 0 if (!noAssert) checkOffset(offset, byteLength, this.length) var i = byteLength @@ -1431,24 +4139,28 @@ Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) { } Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) { + offset = offset >>> 0 if (!noAssert) checkOffset(offset, 1, this.length) if (!(this[offset] & 0x80)) return (this[offset]) return ((0xff - this[offset] + 1) * -1) } Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) { + offset = offset >>> 0 if (!noAssert) checkOffset(offset, 2, this.length) var val = this[offset] | (this[offset + 1] << 8) return (val & 0x8000) ? val | 0xFFFF0000 : val } Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) { + offset = offset >>> 0 if (!noAssert) checkOffset(offset, 2, this.length) var val = this[offset + 1] | (this[offset] << 8) return (val & 0x8000) ? val | 0xFFFF0000 : val } Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) { + offset = offset >>> 0 if (!noAssert) checkOffset(offset, 4, this.length) return (this[offset]) | @@ -1458,6 +4170,7 @@ Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) { } Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) { + offset = offset >>> 0 if (!noAssert) checkOffset(offset, 4, this.length) return (this[offset] << 24) | @@ -1467,21 +4180,25 @@ Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) { } Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) { + offset = offset >>> 0 if (!noAssert) checkOffset(offset, 4, this.length) return ieee754.read(this, offset, true, 23, 4) } Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) { + offset = offset >>> 0 if (!noAssert) checkOffset(offset, 4, this.length) return ieee754.read(this, offset, false, 23, 4) } Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) { + offset = offset >>> 0 if (!noAssert) checkOffset(offset, 8, this.length) return ieee754.read(this, offset, true, 52, 8) } Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) { + offset = offset >>> 0 if (!noAssert) checkOffset(offset, 8, this.length) return ieee754.read(this, offset, false, 52, 8) } @@ -1494,8 +4211,8 @@ function checkInt (buf, value, offset, ext, max, min) { Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) { value = +value - offset = offset | 0 - byteLength = byteLength | 0 + offset = offset >>> 0 + byteLength = byteLength >>> 0 if (!noAssert) { var maxBytes = Math.pow(2, 8 * byteLength) - 1 checkInt(this, value, offset, byteLength, maxBytes, 0) @@ -1513,8 +4230,8 @@ Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) { value = +value - offset = offset | 0 - byteLength = byteLength | 0 + offset = offset >>> 0 + byteLength = byteLength >>> 0 if (!noAssert) { var maxBytes = Math.pow(2, 8 * byteLength) - 1 checkInt(this, value, offset, byteLength, maxBytes, 0) @@ -1532,89 +4249,57 @@ Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) { value = +value - offset = offset | 0 + offset = offset >>> 0 if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0) - if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) this[offset] = (value & 0xff) return offset + 1 } -function objectWriteUInt16 (buf, value, offset, littleEndian) { - if (value < 0) value = 0xffff + value + 1 - for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; ++i) { - buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>> - (littleEndian ? i : 1 - i) * 8 - } -} - Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) { value = +value - offset = offset | 0 + offset = offset >>> 0 if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value & 0xff) - this[offset + 1] = (value >>> 8) - } else { - objectWriteUInt16(this, value, offset, true) - } + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) return offset + 2 } Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) { value = +value - offset = offset | 0 + offset = offset >>> 0 if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value >>> 8) - this[offset + 1] = (value & 0xff) - } else { - objectWriteUInt16(this, value, offset, false) - } + this[offset] = (value >>> 8) + this[offset + 1] = (value & 0xff) return offset + 2 } -function objectWriteUInt32 (buf, value, offset, littleEndian) { - if (value < 0) value = 0xffffffff + value + 1 - for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; ++i) { - buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff - } -} - Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) { value = +value - offset = offset | 0 + offset = offset >>> 0 if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset + 3] = (value >>> 24) - this[offset + 2] = (value >>> 16) - this[offset + 1] = (value >>> 8) - this[offset] = (value & 0xff) - } else { - objectWriteUInt32(this, value, offset, true) - } + this[offset + 3] = (value >>> 24) + this[offset + 2] = (value >>> 16) + this[offset + 1] = (value >>> 8) + this[offset] = (value & 0xff) return offset + 4 } Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) { value = +value - offset = offset | 0 + offset = offset >>> 0 if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value >>> 24) - this[offset + 1] = (value >>> 16) - this[offset + 2] = (value >>> 8) - this[offset + 3] = (value & 0xff) - } else { - objectWriteUInt32(this, value, offset, false) - } + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = (value & 0xff) return offset + 4 } Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) { value = +value - offset = offset | 0 + offset = offset >>> 0 if (!noAssert) { - var limit = Math.pow(2, 8 * byteLength - 1) + var limit = Math.pow(2, (8 * byteLength) - 1) checkInt(this, value, offset, byteLength, limit - 1, -limit) } @@ -1635,9 +4320,9 @@ Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, no Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) { value = +value - offset = offset | 0 + offset = offset >>> 0 if (!noAssert) { - var limit = Math.pow(2, 8 * byteLength - 1) + var limit = Math.pow(2, (8 * byteLength) - 1) checkInt(this, value, offset, byteLength, limit - 1, -limit) } @@ -1658,9 +4343,8 @@ Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, no Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { value = +value - offset = offset | 0 + offset = offset >>> 0 if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80) - if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) if (value < 0) value = 0xff + value + 1 this[offset] = (value & 0xff) return offset + 1 @@ -1668,58 +4352,42 @@ Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { value = +value - offset = offset | 0 + offset = offset >>> 0 if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value & 0xff) - this[offset + 1] = (value >>> 8) - } else { - objectWriteUInt16(this, value, offset, true) - } + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) return offset + 2 } Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { value = +value - offset = offset | 0 + offset = offset >>> 0 if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value >>> 8) - this[offset + 1] = (value & 0xff) - } else { - objectWriteUInt16(this, value, offset, false) - } + this[offset] = (value >>> 8) + this[offset + 1] = (value & 0xff) return offset + 2 } Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { value = +value - offset = offset | 0 + offset = offset >>> 0 if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value & 0xff) - this[offset + 1] = (value >>> 8) - this[offset + 2] = (value >>> 16) - this[offset + 3] = (value >>> 24) - } else { - objectWriteUInt32(this, value, offset, true) - } + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + this[offset + 2] = (value >>> 16) + this[offset + 3] = (value >>> 24) return offset + 4 } Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { value = +value - offset = offset | 0 + offset = offset >>> 0 if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) if (value < 0) value = 0xffffffff + value + 1 - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value >>> 24) - this[offset + 1] = (value >>> 16) - this[offset + 2] = (value >>> 8) - this[offset + 3] = (value & 0xff) - } else { - objectWriteUInt32(this, value, offset, false) - } + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = (value & 0xff) return offset + 4 } @@ -1729,6 +4397,8 @@ function checkIEEE754 (buf, value, offset, ext, max, min) { } function writeFloat (buf, value, offset, littleEndian, noAssert) { + value = +value + offset = offset >>> 0 if (!noAssert) { checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) } @@ -1745,6 +4415,8 @@ Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) } function writeDouble (buf, value, offset, littleEndian, noAssert) { + value = +value + offset = offset >>> 0 if (!noAssert) { checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) } @@ -1793,7 +4465,7 @@ Buffer.prototype.copy = function copy (target, targetStart, start, end) { for (i = len - 1; i >= 0; --i) { target[i + targetStart] = this[i + start] } - } else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) { + } else if (len < 1000) { // ascending copy from start for (i = 0; i < len; ++i) { target[i + targetStart] = this[i + start] @@ -1862,7 +4534,7 @@ Buffer.prototype.fill = function fill (val, start, end, encoding) { } else { var bytes = Buffer.isBuffer(val) ? val - : utf8ToBytes(new Buffer(val, encoding).toString()) + : new Buffer(val, encoding) var len = bytes.length for (i = 0; i < end - start; ++i) { this[i + start] = bytes[i % len] @@ -1875,7 +4547,7 @@ Buffer.prototype.fill = function fill (val, start, end, encoding) { // HELPER FUNCTIONS // ================ -var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g +var INVALID_BASE64_RE = /[^+/0-9A-Za-z-_]/g function base64clean (str) { // Node strips out invalid characters like \n and \t from the string, base64-js does not @@ -2020,8 +4692,7 @@ function isnan (val) { return val !== val // eslint-disable-line no-self-compare } -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"base64-js":1,"ieee754":7,"isarray":10}],5:[function(require,module,exports){ +},{"base64-js":10,"ieee754":16}],14:[function(require,module,exports){ (function (Buffer){ // Copyright Joyent, Inc. and other Node contributors. // @@ -2132,7 +4803,7 @@ function objectToString(o) { } }).call(this,{"isBuffer":require("../../is-buffer/index.js")}) -},{"../../is-buffer/index.js":9}],6:[function(require,module,exports){ +},{"../../is-buffer/index.js":18}],15:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -2436,7 +5107,7 @@ function isUndefined(arg) { return arg === void 0; } -},{}],7:[function(require,module,exports){ +},{}],16:[function(require,module,exports){ exports.read = function (buffer, offset, isLE, mLen, nBytes) { var e, m var eLen = nBytes * 8 - mLen - 1 @@ -2522,7 +5193,7 @@ exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { buffer[offset + i - d] |= s * 128 } -},{}],8:[function(require,module,exports){ +},{}],17:[function(require,module,exports){ if (typeof Object.create === 'function') { // implementation from standard node.js 'util' module module.exports = function inherits(ctor, superCtor) { @@ -2547,7 +5218,7 @@ if (typeof Object.create === 'function') { } } -},{}],9:[function(require,module,exports){ +},{}],18:[function(require,module,exports){ /*! * Determine if an object is a Buffer * @@ -2570,14 +5241,14 @@ function isSlowBuffer (obj) { return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0)) } -},{}],10:[function(require,module,exports){ +},{}],19:[function(require,module,exports){ var toString = {}.toString; module.exports = Array.isArray || function (arr) { return toString.call(arr) == '[object Array]'; }; -},{}],11:[function(require,module,exports){ +},{}],20:[function(require,module,exports){ (function (process){ 'use strict'; @@ -2624,7 +5295,7 @@ function nextTick(fn, arg1, arg2, arg3) { } }).call(this,require('_process')) -},{"_process":12}],12:[function(require,module,exports){ +},{"_process":21}],21:[function(require,module,exports){ // shim for using process in browser var process = module.exports = {}; @@ -2806,10 +5477,10 @@ process.chdir = function (dir) { }; process.umask = function() { return 0; }; -},{}],13:[function(require,module,exports){ +},{}],22:[function(require,module,exports){ module.exports = require("./lib/_stream_duplex.js") -},{"./lib/_stream_duplex.js":14}],14:[function(require,module,exports){ +},{"./lib/_stream_duplex.js":23}],23:[function(require,module,exports){ // a duplex stream is just a stream that is both readable and writable. // Since JS doesn't have multiple prototypal inheritance, this class // prototypally inherits from Readable, and then parasitically from @@ -2885,7 +5556,7 @@ function forEach(xs, f) { f(xs[i], i); } } -},{"./_stream_readable":16,"./_stream_writable":18,"core-util-is":5,"inherits":8,"process-nextick-args":11}],15:[function(require,module,exports){ +},{"./_stream_readable":25,"./_stream_writable":27,"core-util-is":14,"inherits":17,"process-nextick-args":20}],24:[function(require,module,exports){ // a passthrough stream. // basically just the most minimal sort of Transform stream. // Every written chunk gets output as-is. @@ -2912,7 +5583,7 @@ function PassThrough(options) { PassThrough.prototype._transform = function (chunk, encoding, cb) { cb(null, chunk); }; -},{"./_stream_transform":17,"core-util-is":5,"inherits":8}],16:[function(require,module,exports){ +},{"./_stream_transform":26,"core-util-is":14,"inherits":17}],25:[function(require,module,exports){ (function (process){ 'use strict'; @@ -3856,7 +6527,7 @@ function indexOf(xs, x) { return -1; } }).call(this,require('_process')) -},{"./_stream_duplex":14,"./internal/streams/BufferList":19,"_process":12,"buffer":4,"buffer-shims":3,"core-util-is":5,"events":6,"inherits":8,"isarray":10,"process-nextick-args":11,"string_decoder/":25,"util":2}],17:[function(require,module,exports){ +},{"./_stream_duplex":23,"./internal/streams/BufferList":28,"_process":21,"buffer":13,"buffer-shims":12,"core-util-is":14,"events":15,"inherits":17,"isarray":19,"process-nextick-args":20,"string_decoder/":34,"util":11}],26:[function(require,module,exports){ // a transform stream is a readable/writable stream where you do // something with the data. Sometimes it's called a "filter", // but that's not a great name for it, since that implies a thing where @@ -4039,7 +6710,7 @@ function done(stream, er, data) { return stream.push(null); } -},{"./_stream_duplex":14,"core-util-is":5,"inherits":8}],18:[function(require,module,exports){ +},{"./_stream_duplex":23,"core-util-is":14,"inherits":17}],27:[function(require,module,exports){ (function (process){ // A bit simpler than readable streams. // Implement an async ._write(chunk, encoding, cb), and it'll handle all @@ -4596,7 +7267,7 @@ function CorkedRequest(state) { }; } }).call(this,require('_process')) -},{"./_stream_duplex":14,"_process":12,"buffer":4,"buffer-shims":3,"core-util-is":5,"events":6,"inherits":8,"process-nextick-args":11,"util-deprecate":26}],19:[function(require,module,exports){ +},{"./_stream_duplex":23,"_process":21,"buffer":13,"buffer-shims":12,"core-util-is":14,"events":15,"inherits":17,"process-nextick-args":20,"util-deprecate":35}],28:[function(require,module,exports){ 'use strict'; var Buffer = require('buffer').Buffer; @@ -4661,10 +7332,10 @@ BufferList.prototype.concat = function (n) { } return ret; }; -},{"buffer":4,"buffer-shims":3}],20:[function(require,module,exports){ +},{"buffer":13,"buffer-shims":12}],29:[function(require,module,exports){ module.exports = require("./lib/_stream_passthrough.js") -},{"./lib/_stream_passthrough.js":15}],21:[function(require,module,exports){ +},{"./lib/_stream_passthrough.js":24}],30:[function(require,module,exports){ (function (process){ var Stream = (function (){ try { @@ -4684,13 +7355,13 @@ if (!process.browser && process.env.READABLE_STREAM === 'disable' && Stream) { } }).call(this,require('_process')) -},{"./lib/_stream_duplex.js":14,"./lib/_stream_passthrough.js":15,"./lib/_stream_readable.js":16,"./lib/_stream_transform.js":17,"./lib/_stream_writable.js":18,"_process":12}],22:[function(require,module,exports){ +},{"./lib/_stream_duplex.js":23,"./lib/_stream_passthrough.js":24,"./lib/_stream_readable.js":25,"./lib/_stream_transform.js":26,"./lib/_stream_writable.js":27,"_process":21}],31:[function(require,module,exports){ module.exports = require("./lib/_stream_transform.js") -},{"./lib/_stream_transform.js":17}],23:[function(require,module,exports){ +},{"./lib/_stream_transform.js":26}],32:[function(require,module,exports){ module.exports = require("./lib/_stream_writable.js") -},{"./lib/_stream_writable.js":18}],24:[function(require,module,exports){ +},{"./lib/_stream_writable.js":27}],33:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -4819,7 +7490,7 @@ Stream.prototype.pipe = function(dest, options) { return dest; }; -},{"events":6,"inherits":8,"readable-stream/duplex.js":13,"readable-stream/passthrough.js":20,"readable-stream/readable.js":21,"readable-stream/transform.js":22,"readable-stream/writable.js":23}],25:[function(require,module,exports){ +},{"events":15,"inherits":17,"readable-stream/duplex.js":22,"readable-stream/passthrough.js":29,"readable-stream/readable.js":30,"readable-stream/transform.js":31,"readable-stream/writable.js":32}],34:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -5042,7 +7713,7 @@ function base64DetectIncompleteChar(buffer) { this.charLength = this.charReceived ? 3 : 0; } -},{"buffer":4}],26:[function(require,module,exports){ +},{"buffer":13}],35:[function(require,module,exports){ (function (global){ /** @@ -5113,16 +7784,16 @@ function config (name) { } }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],27:[function(require,module,exports){ -arguments[4][8][0].apply(exports,arguments) -},{"dup":8}],28:[function(require,module,exports){ +},{}],36:[function(require,module,exports){ +arguments[4][17][0].apply(exports,arguments) +},{"dup":17}],37:[function(require,module,exports){ module.exports = function isBuffer(arg) { return arg && typeof arg === 'object' && typeof arg.copy === 'function' && typeof arg.fill === 'function' && typeof arg.readUInt8 === 'function'; } -},{}],29:[function(require,module,exports){ +},{}],38:[function(require,module,exports){ (function (process,global){ // Copyright Joyent, Inc. and other Node contributors. // @@ -5712,2013 +8383,4 @@ function hasOwnProperty(obj, prop) { } }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./support/isBuffer":28,"_process":12,"inherits":27}],30:[function(require,module,exports){ -var N3 = require('n3'), - N3Util = N3.Util; - -var validate = function (turtleStream, callback) { - var parser = N3.Parser(); - var errorCount = 0, warningCount = 0; - var regexp = { - 'dateTime' : /^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[0-1]|0[1-9]|[1-2][0-9])?T(2[0-3]|[0-1][0-9]):([0-5][0-9]):([0-5][0-9])(\.[0-9]+)??(Z|[+-](?:2[0-3]|[0-1][0-9]):[0-5][0-9])?$/, - 'double' : /[-+]?\d*([.]\d+)?/, - 'float' : /[-+]?\d*[.]\d+/, - 'int' : /^[-+]?(0|[1-9]\d*)$/ - }; - - var feedback = { warnings : [], errors : []}; - - parser.parse(turtleStream, function(error, triple, prefixes) { - if (error) { - feedback.errors.push(error); - } - - if (triple) { - if (N3Util.isLiteral(triple.object)) { - var value = N3Util.getLiteralValue(triple.object); - var type = N3Util.getLiteralType(triple.object); - - type = type.replace('http://www.w3.org/2001/XMLSchema#', ''); - if (regexp[type] && !regexp[type].test(value)) { - feedback.warnings.push('WARNING: xsd:', type, 'does not validate for literal. {', triple.subject, triple.predicate, triple.object, '}'); - } - } - } else { - callback(feedback); - } - }); -}; - -if (typeof window !== 'undefined') { - window.validate = validate; -} - -module.exports = validate; - -},{"n3":31}],31:[function(require,module,exports){ -// Replace local require by a lazy loader -var globalRequire = require; -require = function () {}; - -// Expose submodules -var exports = module.exports = { - Lexer: require('./lib/N3Lexer'), - Parser: require('./lib/N3Parser'), - Writer: require('./lib/N3Writer'), - Store: require('./lib/N3Store'), - StreamParser: require('./lib/N3StreamParser'), - StreamWriter: require('./lib/N3StreamWriter'), - Util: require('./lib/N3Util'), -}; - -// Load submodules on first access -Object.keys(exports).forEach(function (submodule) { - Object.defineProperty(exports, submodule, { - configurable: true, - enumerable: true, - get: function () { - delete exports[submodule]; - return exports[submodule] = globalRequire('./lib/N3' + submodule); - }, - }); -}); - -},{"./lib/N3Lexer":32,"./lib/N3Parser":33,"./lib/N3Store":34,"./lib/N3StreamParser":35,"./lib/N3StreamWriter":36,"./lib/N3Util":37,"./lib/N3Writer":38}],32:[function(require,module,exports){ -// **N3Lexer** tokenizes N3 documents. -var fromCharCode = String.fromCharCode; -var immediately = typeof setImmediate === 'function' ? setImmediate : - function setImmediate(func) { setTimeout(func, 0); }; - -// Regular expression and replacement string to escape N3 strings. -// Note how we catch invalid unicode sequences separately (they will trigger an error). -var escapeSequence = /\\u([a-fA-F0-9]{4})|\\U([a-fA-F0-9]{8})|\\[uU]|\\(.)/g; -var escapeReplacements = { '\\': '\\', "'": "'", '"': '"', - 'n': '\n', 'r': '\r', 't': '\t', 'f': '\f', 'b': '\b', - '_': '_', '~': '~', '.': '.', '-': '-', '!': '!', '$': '$', '&': '&', - '(': '(', ')': ')', '*': '*', '+': '+', ',': ',', ';': ';', '=': '=', - '/': '/', '?': '?', '#': '#', '@': '@', '%': '%' }; -var illegalIriChars = /[\x00-\x20<>\\"\{\}\|\^\`]/; - -// ## Constructor -function N3Lexer(options) { - if (!(this instanceof N3Lexer)) - return new N3Lexer(options); - - // In line mode (N-Triples or N-Quads), only simple features may be parsed - if (options && options.lineMode) { - // Don't tokenize special literals - this._tripleQuotedString = this._number = this._boolean = /$0^/; - // Swap the tokenize method for a restricted version - var self = this; - this._tokenize = this.tokenize; - this.tokenize = function (input, callback) { - this._tokenize(input, function (error, token) { - if (!error && /^(?:IRI|prefixed|literal|langcode|type|\.|eof)$/.test(token.type)) - callback && callback(error, token); - else - callback && callback(error || self._syntaxError(token.type, callback = null)); - }); - }; - } -} - -N3Lexer.prototype = { - // ## Regular expressions - // It's slightly faster to have these as properties than as in-scope variables. - - _iri: /^<((?:[^>\\]|\\[uU])+)>/, // IRI with escape sequences; needs sanity check after unescaping - _unescapedIri: /^<([^\x00-\x20<>\\"\{\}\|\^\`]*)>/, // IRI without escape sequences; no unescaping - _unescapedString: /^"[^"\\]+"(?=[^"\\])/, // non-empty string without escape sequences - _singleQuotedString: /^"[^"\\]*(?:\\.[^"\\]*)*"(?=[^"\\])|^'[^'\\]*(?:\\.[^'\\]*)*'(?=[^'\\])/, - _tripleQuotedString: /^""("[^"\\]*(?:(?:\\.|"(?!""))[^"\\]*)*")""|^''('[^'\\]*(?:(?:\\.|'(?!''))[^'\\]*)*')''/, - _langcode: /^@([a-z]+(?:-[a-z0-9]+)*)(?=[^a-z0-9\-])/i, - _prefix: /^((?:[A-Za-z\xc0-\xd6\xd8-\xf6\xf8-\u02ff\u0370-\u037d\u037f-\u1fff\u200c\u200d\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff])(?:\.?[\-0-9A-Z_a-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u037f-\u1fff\u200c\u200d\u203f\u2040\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff])*)?:(?=[#\s<])/, - _prefixed: /^((?:[A-Za-z\xc0-\xd6\xd8-\xf6\xf8-\u02ff\u0370-\u037d\u037f-\u1fff\u200c\u200d\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff])(?:\.?[\-0-9A-Z_a-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u037f-\u1fff\u200c\u200d\u203f\u2040\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff])*)?:((?:(?:[0-:A-Z_a-z\xc0-\xd6\xd8-\xf6\xf8-\u02ff\u0370-\u037d\u037f-\u1fff\u200c\u200d\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff]|%[0-9a-fA-F]{2}|\\[!#-\/;=?\-@_~])(?:(?:[\.\-0-:A-Z_a-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u037f-\u1fff\u200c\u200d\u203f\u2040\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff]|%[0-9a-fA-F]{2}|\\[!#-\/;=?\-@_~])*(?:[\-0-:A-Z_a-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u037f-\u1fff\u200c\u200d\u203f\u2040\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff]|%[0-9a-fA-F]{2}|\\[!#-\/;=?\-@_~]))?)?)(?=\.?[,;\s#()\[\]\{\}"'<])/, - _blank: /^_:((?:[0-9A-Z_a-z\xc0-\xd6\xd8-\xf6\xf8-\u02ff\u0370-\u037d\u037f-\u1fff\u200c\u200d\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff])(?:\.?[\-0-9A-Z_a-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u037f-\u1fff\u200c\u200d\u203f\u2040\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff])*)(?=\.?[,;:\s#()\[\]\{\}"'<])/, - _number: /^[\-+]?(?:\d+\.?\d*([eE](?:[\-\+])?\d+)|\d*\.?\d+)(?=[.,;:\s#()\[\]\{\}"'<])/, - _boolean: /^(?:true|false)(?=[.,;:\s#()\[\]\{\}"'<])/, - _keyword: /^@[a-z]+(?=[\s#<:])/, - _sparqlKeyword: /^(?:PREFIX|BASE|GRAPH)(?=[\s#<:])/i, - _shortPredicates: /^a(?=\s+|<)/, - _newline: /^[ \t]*(?:#[^\n\r]*)?(?:\r\n|\n|\r)[ \t]*/, - _whitespace: /^[ \t]+/, - _endOfFile: /^(?:#[^\n\r]*)?$/, - - // ## Private methods - - // ### `_tokenizeToEnd` tokenizes as for as possible, emitting tokens through the callback. - _tokenizeToEnd: function (callback, inputFinished) { - // Continue parsing as far as possible; the loop will return eventually. - var input = this._input; - while (true) { - // Count and skip whitespace lines. - var whiteSpaceMatch; - while (whiteSpaceMatch = this._newline.exec(input)) - input = input.substr(whiteSpaceMatch[0].length, input.length), this._line++; - // Skip whitespace on current line. - if (whiteSpaceMatch = this._whitespace.exec(input)) - input = input.substr(whiteSpaceMatch[0].length, input.length); - - // Stop for now if we're at the end. - if (this._endOfFile.test(input)) { - // If the input is finished, emit EOF. - if (inputFinished) - callback(input = null, { line: this._line, type: 'eof', value: '', prefix: '' }); - return this._input = input; - } - - // Look for specific token types based on the first character. - var line = this._line, type = '', value = '', prefix = '', - firstChar = input[0], match = null, matchLength = 0, unescaped, inconclusive = false; - switch (firstChar) { - case '^': - // Try to match a type. - if (input.length === 1) break; - else if (input[1] !== '^') return reportSyntaxError(this); - this._prevTokenType = '^'; - // Move to type IRI or prefixed name. - input = input.substr(2); - if (input[0] !== '<') { - inconclusive = true; - break; - } - // Fall through in case the type is an IRI. - - case '<': - // Try to find a full IRI without escape sequences. - if (match = this._unescapedIri.exec(input)) - type = 'IRI', value = match[1]; - // Try to find a full IRI with escape sequences. - else if (match = this._iri.exec(input)) { - unescaped = this._unescape(match[1]); - if (unescaped === null || illegalIriChars.test(unescaped)) - return reportSyntaxError(this); - type = 'IRI', value = unescaped; - } - break; - - case '_': - // Try to find a blank node. Since it can contain (but not end with) a dot, - // we always need a non-dot character before deciding it is a prefixed name. - // Therefore, try inserting a space if we're at the end of the input. - if ((match = this._blank.exec(input)) || - inputFinished && (match = this._blank.exec(input + ' '))) - type = 'prefixed', prefix = '_', value = match[1]; - break; - - case '"': - case "'": - // Try to find a non-empty double-quoted literal without escape sequences. - if (match = this._unescapedString.exec(input)) - type = 'literal', value = match[0]; - // Try to find any other literal wrapped in a pair of single or double quotes. - else if (match = this._singleQuotedString.exec(input)) { - unescaped = this._unescape(match[0]); - if (unescaped === null) - return reportSyntaxError(this); - type = 'literal', value = unescaped.replace(/^'|'$/g, '"'); - } - // Try to find a literal wrapped in three pairs of single or double quotes. - else if (match = this._tripleQuotedString.exec(input)) { - unescaped = match[1] || match[2]; - // Count the newlines and advance line counter. - this._line += unescaped.split(/\r\n|\r|\n/).length - 1; - unescaped = this._unescape(unescaped); - if (unescaped === null) - return reportSyntaxError(this); - type = 'literal', value = unescaped.replace(/^'|'$/g, '"'); - } - break; - - case '@': - // Try to find a language code. - if (this._prevTokenType === 'literal' && (match = this._langcode.exec(input))) - type = 'langcode', value = match[1]; - // Try to find a keyword. - else if (match = this._keyword.exec(input)) - type = match[0]; - break; - - case '.': - // Try to find a dot as punctuation. - if (input.length === 1 ? inputFinished : (input[1] < '0' || input[1] > '9')) { - type = '.'; - matchLength = 1; - break; - } - // Fall through to numerical case (could be a decimal dot). - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '+': - case '-': - // Try to find a number. - if (match = this._number.exec(input)) { - type = 'literal'; - value = '"' + match[0] + '"^^http://www.w3.org/2001/XMLSchema#' + - (match[1] ? 'double' : (/^[+\-]?\d+$/.test(match[0]) ? 'integer' : 'decimal')); - } - break; - - case 'B': - case 'b': - case 'p': - case 'P': - case 'G': - case 'g': - // Try to find a SPARQL-style keyword. - if (match = this._sparqlKeyword.exec(input)) - type = match[0].toUpperCase(); - else - inconclusive = true; - break; - - case 'f': - case 't': - // Try to match a boolean. - if (match = this._boolean.exec(input)) - type = 'literal', value = '"' + match[0] + '"^^http://www.w3.org/2001/XMLSchema#boolean'; - else - inconclusive = true; - break; - - case 'a': - // Try to find an abbreviated predicate. - if (match = this._shortPredicates.exec(input)) - type = 'abbreviation', value = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type'; - else - inconclusive = true; - break; - - case ',': - case ';': - case '[': - case ']': - case '(': - case ')': - case '{': - case '}': - // The next token is punctuation - matchLength = 1; - type = firstChar; - break; - - default: - inconclusive = true; - } - - // Some first characters do not allow an immediate decision, so inspect more. - if (inconclusive) { - // Try to find a prefix. - if ((this._prevTokenType === '@prefix' || this._prevTokenType === 'PREFIX') && - (match = this._prefix.exec(input))) - type = 'prefix', value = match[1] || ''; - // Try to find a prefixed name. Since it can contain (but not end with) a dot, - // we always need a non-dot character before deciding it is a prefixed name. - // Therefore, try inserting a space if we're at the end of the input. - else if ((match = this._prefixed.exec(input)) || - inputFinished && (match = this._prefixed.exec(input + ' '))) - type = 'prefixed', prefix = match[1] || '', value = this._unescape(match[2]); - } - - // A type token is special: it can only be emitted after an IRI or prefixed name is read. - if (this._prevTokenType === '^') - type = (type === 'IRI' || type === 'prefixed') ? 'type' : ''; - - // What if nothing of the above was found? - if (!type) { - // We could be in streaming mode, and then we just wait for more input to arrive. - // Otherwise, a syntax error has occurred in the input. - // One exception: error on an unaccounted linebreak (= not inside a triple-quoted literal). - if (inputFinished || (!/^'''|^"""/.test(input) && /\n|\r/.test(input))) - return reportSyntaxError(this); - else - return this._input = input; - } - - // Emit the parsed token. - callback(null, { line: line, type: type, value: value, prefix: prefix }); - this._prevTokenType = type; - - // Advance to next part to tokenize. - input = input.substr(matchLength || match[0].length, input.length); - } - - // Signals the syntax error through the callback - function reportSyntaxError(self) { callback(self._syntaxError(/^\S*/.exec(input)[0])); } - }, - - // ### `_unescape` replaces N3 escape codes by their corresponding characters. - _unescape: function (item) { - try { - return item.replace(escapeSequence, function (sequence, unicode4, unicode8, escapedChar) { - var charCode; - if (unicode4) { - charCode = parseInt(unicode4, 16); - if (isNaN(charCode)) throw new Error(); // can never happen (regex), but helps performance - return fromCharCode(charCode); - } - else if (unicode8) { - charCode = parseInt(unicode8, 16); - if (isNaN(charCode)) throw new Error(); // can never happen (regex), but helps performance - if (charCode <= 0xFFFF) return fromCharCode(charCode); - return fromCharCode(0xD800 + ((charCode -= 0x10000) / 0x400), 0xDC00 + (charCode & 0x3FF)); - } - else { - var replacement = escapeReplacements[escapedChar]; - if (!replacement) - throw new Error(); - return replacement; - } - }); - } - catch (error) { return null; } - }, - - // ### `_syntaxError` creates a syntax error for the given issue - _syntaxError: function (issue) { - this._input = null; - return new Error('Syntax error: unexpected "' + issue + '" on line ' + this._line + '.'); - }, - - - // ## Public methods - - // ### `tokenize` starts the transformation of an N3 document into an array of tokens. - // The input can be a string or a stream. - tokenize: function (input, callback) { - var self = this; - this._line = 1; - - // If the input is a string, continuously emit tokens through the callback until the end. - if (typeof input === 'string') { - this._input = input; - immediately(function () { self._tokenizeToEnd(callback, true); }); - } - // Otherwise, the input will be streamed. - else { - this._input = ''; - - // If no input was given, it will be streamed through `addChunk` and ended with `end` - if (!input || typeof input === 'function') { - this.addChunk = addChunk; - this.end = end; - if (!callback) - callback = input; - } - // Otherwise, the input itself must be a stream - else { - if (typeof input.setEncoding === 'function') - input.setEncoding('utf8'); - input.on('data', addChunk); - input.on('end', end); - } - } - - // Adds the data chunk to the buffer and parses as far as possible - function addChunk(data) { - if (self._input !== null) { - self._input += data; - self._tokenizeToEnd(callback, false); - } - } - - // Parses until the end - function end() { - if (self._input !== null) - self._tokenizeToEnd(callback, true); - } - }, -}; - -// ## Exports - -// Export the `N3Lexer` class as a whole. -module.exports = N3Lexer; - -},{}],33:[function(require,module,exports){ -// **N3Parser** parses N3 documents. -var N3Lexer = require('./N3Lexer'); - -var RDF_PREFIX = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', - RDF_NIL = RDF_PREFIX + 'nil', - RDF_FIRST = RDF_PREFIX + 'first', - RDF_REST = RDF_PREFIX + 'rest'; - -var absoluteIRI = /^[a-z][a-z0-9+.-]*:/i, - schemeAuthority = /^(?:([a-z][a-z0-9+.-]*:))?(?:\/\/[^\/]*)?/i, - dotSegments = /(?:^|\/)\.\.?(?:$|[\/#?])/; - -// The next ID for new blank nodes -var blankNodePrefix = 0, blankNodeCount = 0; - -// ## Constructor -function N3Parser(options) { - if (!(this instanceof N3Parser)) - return new N3Parser(options); - this._tripleStack = []; - this._graph = null; - - // Set the document IRI. - options = options || {}; - this._setBase(options.documentIRI); - - // Set supported features depending on the format. - var format = (typeof options.format === 'string') && options.format.match(/\w*$/)[0].toLowerCase(), - isTurtle = format === 'turtle', isTriG = format === 'trig', - isNTriples = /triple/.test(format), isNQuads = /quad/.test(format), - isLineMode = isNTriples || isNQuads; - if (!(this._supportsNamedGraphs = !isTurtle)) - this._readPredicateOrNamedGraph = this._readPredicate; - this._supportsQuads = !(isTurtle || isTriG || isNTriples); - // Disable relative IRIs in N-Triples or N-Quads mode - if (isLineMode) { - this._base = ''; - this._resolveIRI = function (token) { - this._error('Disallowed relative IRI', token); - return this._callback = noop, this._subject = null; - }; - } - this._blankNodePrefix = typeof options.blankNodePrefix !== 'string' ? '' : - '_:' + options.blankNodePrefix.replace(/^_:/, ''); - this._lexer = options.lexer || new N3Lexer({ lineMode: isLineMode }); -} - -// ## Private class methods - -// ### `_resetBlankNodeIds` restarts blank node identification. -N3Parser._resetBlankNodeIds = function () { - blankNodePrefix = blankNodeCount = 0; -}; - -N3Parser.prototype = { - // ## Private methods - - // ### `_setBase` sets the base IRI to resolve relative IRIs. - _setBase: function (baseIRI) { - if (!baseIRI) - baseIRI = null; - else if (baseIRI.indexOf('#') >= 0) - throw new Error('Invalid base IRI ' + baseIRI); - // Set base IRI and its components - if (this._base = baseIRI) { - this._basePath = baseIRI.replace(/[^\/?]*(?:\?.*)?$/, ''); - baseIRI = baseIRI.match(schemeAuthority); - this._baseRoot = baseIRI[0]; - this._baseScheme = baseIRI[1]; - } - }, - - // ### `_readInTopContext` reads a token when in the top context. - _readInTopContext: function (token) { - switch (token.type) { - // If an EOF token arrives in the top context, signal that we're done. - case 'eof': - if (this._graph !== null) - return this._error('Unclosed graph', token); - delete this._prefixes._; - return this._callback(null, null, this._prefixes); - // It could be a prefix declaration. - case '@prefix': - this._sparqlStyle = false; - return this._readPrefix; - case 'PREFIX': - this._sparqlStyle = true; - return this._readPrefix; - // It could be a base declaration. - case '@base': - this._sparqlStyle = false; - return this._readBaseIRI; - case 'BASE': - this._sparqlStyle = true; - return this._readBaseIRI; - // It could be a graph. - case '{': - if (this._supportsNamedGraphs) { - this._graph = ''; - this._subject = null; - return this._readSubject; - } - case 'GRAPH': - if (this._supportsNamedGraphs) - return this._readNamedGraphLabel; - // Otherwise, the next token must be a subject. - default: - return this._readSubject(token); - } - }, - - // ### `_readSubject` reads a triple's subject. - _readSubject: function (token) { - this._predicate = null; - switch (token.type) { - case 'IRI': - if (this._base === null || absoluteIRI.test(token.value)) - this._subject = token.value; - else - this._subject = this._resolveIRI(token); - break; - case 'prefixed': - var prefix = this._prefixes[token.prefix]; - if (prefix === undefined) - return this._error('Undefined prefix "' + token.prefix + ':"', token); - this._subject = prefix + token.value; - break; - case '[': - // Start a new triple with a new blank node as subject. - this._subject = '_:b' + blankNodeCount++; - this._tripleStack.push({ subject: this._subject, predicate: null, object: null, type: 'blank' }); - return this._readBlankNodeHead; - case '(': - // Start a new list - this._tripleStack.push({ subject: RDF_NIL, predicate: null, object: null, type: 'list' }); - this._subject = null; - return this._readListItem; - case '}': - return this._readPunctuation(token); - default: - return this._error('Expected subject but got ' + token.type, token); - } - // The next token must be a predicate, - // or, if the subject was actually a graph IRI, a named graph. - return this._readPredicateOrNamedGraph; - }, - - // ### `_readPredicate` reads a triple's predicate. - _readPredicate: function (token) { - var type = token.type; - switch (type) { - case 'IRI': - case 'abbreviation': - if (this._base === null || absoluteIRI.test(token.value)) - this._predicate = token.value; - else - this._predicate = this._resolveIRI(token); - break; - case 'prefixed': - if (token.prefix === '_') - return this._error('Disallowed blank node as predicate', token); - var prefix = this._prefixes[token.prefix]; - if (prefix === undefined) - return this._error('Undefined prefix "' + token.prefix + ':"', token); - this._predicate = prefix + token.value; - break; - case '.': - case ']': - case '}': - // Expected predicate didn't come, must have been trailing semicolon. - if (this._predicate === null) - return this._error('Unexpected ' + type, token); - this._subject = null; - return type === ']' ? this._readBlankNodeTail(token) : this._readPunctuation(token); - case ';': - // Extra semicolons can be safely ignored - return this._readPredicate; - default: - return this._error('Expected predicate to follow "' + this._subject + '"', token); - } - // The next token must be an object. - return this._readObject; - }, - - // ### `_readObject` reads a triple's object. - _readObject: function (token) { - switch (token.type) { - case 'IRI': - if (this._base === null || absoluteIRI.test(token.value)) - this._object = token.value; - else - this._object = this._resolveIRI(token); - break; - case 'prefixed': - var prefix = this._prefixes[token.prefix]; - if (prefix === undefined) - return this._error('Undefined prefix "' + token.prefix + ':"', token); - this._object = prefix + token.value; - break; - case 'literal': - this._object = token.value; - return this._readDataTypeOrLang; - case '[': - // Start a new triple with a new blank node as subject. - var blank = '_:b' + blankNodeCount++; - this._tripleStack.push({ subject: this._subject, predicate: this._predicate, object: blank, type: 'blank' }); - this._subject = blank; - return this._readBlankNodeHead; - case '(': - // Start a new list - this._tripleStack.push({ subject: this._subject, predicate: this._predicate, object: RDF_NIL, type: 'list' }); - this._subject = null; - return this._readListItem; - default: - return this._error('Expected object to follow "' + this._predicate + '"', token); - } - return this._getTripleEndReader(); - }, - - // ### `_readPredicateOrNamedGraph` reads a triple's predicate, or a named graph. - _readPredicateOrNamedGraph: function (token) { - return token.type === '{' ? this._readGraph(token) : this._readPredicate(token); - }, - - // ### `_readGraph` reads a graph. - _readGraph: function (token) { - if (token.type !== '{') - return this._error('Expected graph but got ' + token.type, token); - // The "subject" we read is actually the GRAPH's label - this._graph = this._subject, this._subject = null; - return this._readSubject; - }, - - // ### `_readBlankNodeHead` reads the head of a blank node. - _readBlankNodeHead: function (token) { - if (token.type === ']') { - this._subject = null; - return this._readBlankNodeTail(token); - } - else { - this._predicate = null; - return this._readPredicate(token); - } - }, - - // ### `_readBlankNodeTail` reads the end of a blank node. - _readBlankNodeTail: function (token) { - if (token.type !== ']') - return this._readBlankNodePunctuation(token); - - // Store blank node triple. - if (this._subject !== null) - this._callback(null, { subject: this._subject, - predicate: this._predicate, - object: this._object, - graph: this._graph || '' }); - - // Restore parent triple that contains the blank node. - var triple = this._tripleStack.pop(); - this._subject = triple.subject; - // Was the blank node the object? - if (triple.object !== null) { - // Restore predicate and object as well, and continue by reading punctuation. - this._predicate = triple.predicate; - this._object = triple.object; - return this._getTripleEndReader(); - } - // The blank node was the subject, so continue reading the predicate. - // If the blank node didn't contain any predicates, it could also be the label of a named graph. - return this._predicate !== null ? this._readPredicate : this._readPredicateOrNamedGraph; - }, - - // ### `_readDataTypeOrLang` reads an _optional_ data type or language. - _readDataTypeOrLang: function (token) { - switch (token.type) { - case 'type': - var value; - if (token.prefix === '') { - if (this._base === null || absoluteIRI.test(token.value)) - value = token.value; - else - value = this._resolveIRI(token); - } - else { - var prefix = this._prefixes[token.prefix]; - if (prefix === undefined) - return this._error('Undefined prefix "' + token.prefix + ':"', token); - value = prefix + token.value; - } - this._object += '^^' + value; - return this._getTripleEndReader(); - case 'langcode': - this._object += '@' + token.value.toLowerCase(); - return this._getTripleEndReader(); - default: - return this._getTripleEndReader().call(this, token); - } - }, - - // ### `_readListItem` reads items from a list. - _readListItem: function (token) { - var item = null, // The actual list item. - itemHead = null, // The head of the rdf:first predicate. - prevItemHead = this._subject, // The head of the previous rdf:first predicate. - stack = this._tripleStack, // The stack of triples part of recursion (lists, blanks, etc.). - parentTriple = stack[stack.length - 1], // The triple containing the current list. - next = this._readListItem; // The next function to execute. - - switch (token.type) { - case 'IRI': - if (this._base === null || absoluteIRI.test(token.value)) - item = token.value; - else - item = this._resolveIRI(token); - break; - case 'prefixed': - var prefix = this._prefixes[token.prefix]; - if (prefix === undefined) - return this._error('Undefined prefix "' + token.prefix + ':"', token); - item = prefix + token.value; - break; - case 'literal': - item = token.value; - next = this._readDataTypeOrLang; - break; - case '[': - // Stack the current list triple and start a new triple with a blank node as subject. - itemHead = '_:b' + blankNodeCount++; - item = '_:b' + blankNodeCount++; - stack.push({ subject: itemHead, predicate: RDF_FIRST, object: item, type: 'blank' }); - this._subject = item; - next = this._readBlankNodeHead; - break; - case '(': - // Stack the current list triple and start a new list - itemHead = '_:b' + blankNodeCount++; - stack.push({ subject: itemHead, predicate: RDF_FIRST, object: RDF_NIL, type: 'list' }); - this._subject = null; - next = this._readListItem; - break; - case ')': - // Restore the parent triple. - stack.pop(); - // If this list is contained within a parent list, return the membership triple here. - // This will be ` rdf:first .`. - if (stack.length !== 0 && stack[stack.length - 1].type === 'list') - this._callback(null, { subject: parentTriple.subject, - predicate: parentTriple.predicate, - object: parentTriple.object, - graph: this._graph || '' }); - // Restore the parent triple's subject. - this._subject = parentTriple.subject; - // Was this list in the parent triple's subject? - if (parentTriple.predicate === null) { - // The next token is the predicate. - next = this._readPredicate; - // Skip writing the list tail if this was an empty list. - if (parentTriple.subject === RDF_NIL) - return next; - } - // The list was in the parent triple's object. - else { - // Restore the parent triple's predicate and object as well. - this._predicate = parentTriple.predicate; - this._object = parentTriple.object; - next = this._getTripleEndReader(); - // Skip writing the list tail if this was an empty list. - if (parentTriple.object === RDF_NIL) - return next; - } - // Close the list by making the item head nil. - itemHead = RDF_NIL; - break; - default: - return this._error('Expected list item instead of "' + token.type + '"', token); - } - - // Create a new blank node if no item head was assigned yet. - if (itemHead === null) - this._subject = itemHead = '_:b' + blankNodeCount++; - - // Is this the first element of the list? - if (prevItemHead === null) { - // This list is either the object or the subject. - if (parentTriple.object === RDF_NIL) - parentTriple.object = itemHead; - else - parentTriple.subject = itemHead; - } - else { - // The rest of the list is in the current head. - this._callback(null, { subject: prevItemHead, - predicate: RDF_REST, - object: itemHead, - graph: this._graph || '' }); - } - // Add the item's value. - if (item !== null) - this._callback(null, { subject: itemHead, - predicate: RDF_FIRST, - object: item, - graph: this._graph || '' }); - return next; - }, - - // ### `_readPunctuation` reads punctuation between triples or triple parts. - _readPunctuation: function (token) { - var next, subject = this._subject, graph = this._graph; - switch (token.type) { - // A closing brace ends a graph - case '}': - if (this._graph === null) - return this._error('Unexpected graph closing', token); - this._graph = null; - // A dot just ends the statement, without sharing anything with the next. - case '.': - this._subject = null; - next = this._readInTopContext; - break; - // Semicolon means the subject is shared; predicate and object are different. - case ';': - next = this._readPredicate; - break; - // Comma means both the subject and predicate are shared; the object is different. - case ',': - next = this._readObject; - break; - // An IRI means this is a quad (only allowed if not already inside a graph). - case 'IRI': - if (this._supportsQuads && this._graph === null) { - if (this._base === null || absoluteIRI.test(token.value)) - graph = token.value; - else - graph = this._resolveIRI(token); - subject = this._subject; - next = this._readQuadPunctuation; - break; - } - // An prefixed name means this is a quad (only allowed if not already inside a graph). - case 'prefixed': - if (this._supportsQuads && this._graph === null) { - var prefix = this._prefixes[token.prefix]; - if (prefix === undefined) - return this._error('Undefined prefix "' + token.prefix + ':"', token); - graph = prefix + token.value; - next = this._readQuadPunctuation; - break; - } - default: - return this._error('Expected punctuation to follow "' + this._object + '"', token); - } - // A triple has been completed now, so return it. - if (subject !== null) - this._callback(null, { subject: subject, - predicate: this._predicate, - object: this._object, - graph: graph || '' }); - return next; - }, - - // ### `_readBlankNodePunctuation` reads punctuation in a blank node - _readBlankNodePunctuation: function (token) { - var next; - switch (token.type) { - // Semicolon means the subject is shared; predicate and object are different. - case ';': - next = this._readPredicate; - break; - // Comma means both the subject and predicate are shared; the object is different. - case ',': - next = this._readObject; - break; - default: - return this._error('Expected punctuation to follow "' + this._object + '"', token); - } - // A triple has been completed now, so return it. - this._callback(null, { subject: this._subject, - predicate: this._predicate, - object: this._object, - graph: this._graph || '' }); - return next; - }, - - // ### `_readQuadPunctuation` reads punctuation after a quad. - _readQuadPunctuation: function (token) { - if (token.type !== '.') - return this._error('Expected dot to follow quad', token); - return this._readInTopContext; - }, - - // ### `_readPrefix` reads the prefix of a prefix declaration. - _readPrefix: function (token) { - if (token.type !== 'prefix') - return this._error('Expected prefix to follow @prefix', token); - this._prefix = token.value; - return this._readPrefixIRI; - }, - - // ### `_readPrefixIRI` reads the IRI of a prefix declaration. - _readPrefixIRI: function (token) { - if (token.type !== 'IRI') - return this._error('Expected IRI to follow prefix "' + this._prefix + ':"', token); - var prefixIRI; - if (this._base === null || absoluteIRI.test(token.value)) - prefixIRI = token.value; - else - prefixIRI = this._resolveIRI(token); - this._prefixes[this._prefix] = prefixIRI; - this._prefixCallback(this._prefix, prefixIRI); - return this._readDeclarationPunctuation; - }, - - // ### `_readBaseIRI` reads the IRI of a base declaration. - _readBaseIRI: function (token) { - if (token.type !== 'IRI') - return this._error('Expected IRI to follow base declaration', token); - try { - this._setBase(this._base === null || - absoluteIRI.test(token.value) ? token.value : this._resolveIRI(token)); - } - catch (error) { this._error(error.message, token); } - return this._readDeclarationPunctuation; - }, - - // ### `_readNamedGraphLabel` reads the label of a named graph. - _readNamedGraphLabel: function (token) { - switch (token.type) { - case 'IRI': - case 'prefixed': - return this._readSubject(token), this._readGraph; - case '[': - return this._readNamedGraphBlankLabel; - default: - return this._error('Invalid graph label', token); - } - }, - - // ### `_readNamedGraphLabel` reads a blank node label of a named graph. - _readNamedGraphBlankLabel: function (token) { - if (token.type !== ']') - return this._error('Invalid graph label', token); - this._subject = '_:b' + blankNodeCount++; - return this._readGraph; - }, - - // ### `_readDeclarationPunctuation` reads the punctuation of a declaration. - _readDeclarationPunctuation: function (token) { - // SPARQL-style declarations don't have punctuation. - if (this._sparqlStyle) - return this._readInTopContext(token); - - if (token.type !== '.') - return this._error('Expected declaration to end with a dot', token); - return this._readInTopContext; - }, - - // ### `_getTripleEndReader` gets the next reader function at the end of a triple. - _getTripleEndReader: function () { - var stack = this._tripleStack; - if (stack.length === 0) - return this._readPunctuation; - - switch (stack[stack.length - 1].type) { - case 'blank': - return this._readBlankNodeTail; - case 'list': - return this._readListItem; - } - }, - - // ### `_error` emits an error message through the callback. - _error: function (message, token) { - this._callback(new Error(message + ' at line ' + token.line + '.')); - }, - - // ### `_resolveIRI` resolves a relative IRI token against the base path, - // assuming that a base path has been set and that the IRI is indeed relative. - _resolveIRI: function (token) { - var iri = token.value; - switch (iri[0]) { - // An empty relative IRI indicates the base IRI - case undefined: return this._base; - // Resolve relative fragment IRIs against the base IRI - case '#': return this._base + iri; - // Resolve relative query string IRIs by replacing the query string - case '?': return this._base.replace(/(?:\?.*)?$/, iri); - // Resolve root-relative IRIs at the root of the base IRI - case '/': - // Resolve scheme-relative IRIs to the scheme - return (iri[1] === '/' ? this._baseScheme : this._baseRoot) + this._removeDotSegments(iri); - // Resolve all other IRIs at the base IRI's path - default: - return this._removeDotSegments(this._basePath + iri); - } - }, - - // ### `_removeDotSegments` resolves './' and '../' path segments in an IRI as per RFC3986. - _removeDotSegments: function (iri) { - // Don't modify the IRI if it does not contain any dot segments - if (!dotSegments.test(iri)) - return iri; - - // Start with an imaginary slash before the IRI in order to resolve trailing './' and '../' - var result = '', length = iri.length, i = -1, pathStart = -1, segmentStart = 0, next = '/'; - - while (i < length) { - switch (next) { - // The path starts with the first slash after the authority - case ':': - if (pathStart < 0) { - // Skip two slashes before the authority - if (iri[++i] === '/' && iri[++i] === '/') - // Skip to slash after the authority - while ((pathStart = i + 1) < length && iri[pathStart] !== '/') - i = pathStart; - } - break; - // Don't modify a query string or fragment - case '?': - case '#': - i = length; - break; - // Handle '/.' or '/..' path segments - case '/': - if (iri[i + 1] === '.') { - next = iri[++i + 1]; - switch (next) { - // Remove a '/.' segment - case '/': - result += iri.substring(segmentStart, i - 1); - segmentStart = i + 1; - break; - // Remove a trailing '/.' segment - case undefined: - case '?': - case '#': - return result + iri.substring(segmentStart, i) + iri.substr(i + 1); - // Remove a '/..' segment - case '.': - next = iri[++i + 1]; - if (next === undefined || next === '/' || next === '?' || next === '#') { - result += iri.substring(segmentStart, i - 2); - // Try to remove the parent path from result - if ((segmentStart = result.lastIndexOf('/')) >= pathStart) - result = result.substr(0, segmentStart); - // Remove a trailing '/..' segment - if (next !== '/') - return result + '/' + iri.substr(i + 1); - segmentStart = i + 1; - } - } - } - } - next = iri[++i]; - } - return result + iri.substring(segmentStart); - }, - - // ## Public methods - - // ### `parse` parses the N3 input and emits each parsed triple through the callback. - parse: function (input, tripleCallback, prefixCallback) { - // The read callback is the next function to be executed when a token arrives. - // We start reading in the top context. - this._readCallback = this._readInTopContext; - this._prefixes = Object.create(null); - this._prefixes._ = this._blankNodePrefix || '_:b' + blankNodePrefix++ + '_'; - - // If the input argument is not given, shift parameters - if (typeof input === 'function') - prefixCallback = tripleCallback, tripleCallback = input, input = null; - - // Set the triple and prefix callbacks. - this._callback = tripleCallback || noop; - this._prefixCallback = prefixCallback || noop; - - // Execute the read callback when a token arrives. - var self = this; - this._lexer.tokenize(input, function (error, token) { - if (error !== null) - self._callback(error), self._callback = noop; - else if (self._readCallback !== undefined) - self._readCallback = self._readCallback(token); - }); - - // If no input was given, it can be added with `addChunk` and ended with `end` - if (!input) { - this.addChunk = this._lexer.addChunk; - this.end = this._lexer.end; - } - }, -}; - -// The empty function -function noop() {} - -// ## Exports - -// Export the `N3Parser` class as a whole. -module.exports = N3Parser; - -},{"./N3Lexer":32}],34:[function(require,module,exports){ -// **N3Store** objects store N3 triples by graph in memory. - -var expandPrefixedName = require('./N3Util').expandPrefixedName; - -// ## Constructor -function N3Store(triples, options) { - if (!(this instanceof N3Store)) - return new N3Store(triples, options); - - // The number of triples is initially zero. - this._size = 0; - // `_graphs` contains subject, predicate, and object indexes per graph. - this._graphs = Object.create(null); - // `_entities` maps entities such as `http://xmlns.com/foaf/0.1/name` to numbers. - // This saves memory, since only the numbers have to be stored in `_graphs`. - this._entities = Object.create(null); - this._entities['><'] = 0; // Dummy entry, so the first actual key is non-zero - this._entityCount = 0; - // `_blankNodeIndex` is the index of the last created blank node that was automatically named - this._blankNodeIndex = 0; - - // Shift parameters if `triples` is not given - if (!options && triples && !triples[0]) - options = triples, triples = null; - - // Add triples and prefixes if passed - this._prefixes = Object.create(null); - if (options && options.prefixes) - this.addPrefixes(options.prefixes); - if (triples) - this.addTriples(triples); -} - -N3Store.prototype = { - // ## Public properties - - // ### `size` returns the number of triples in the store. - get size() { - // Return the triple count if if was cached. - var size = this._size; - if (size !== null) - return size; - - // Calculate the number of triples by counting to the deepest level. - var graphs = this._graphs, subjects, subject; - for (var graphKey in graphs) - for (var subjectKey in (subjects = graphs[graphKey].subjects)) - for (var predicateKey in (subject = subjects[subjectKey])) - size += Object.keys(subject[predicateKey]).length; - return this._size = size; - }, - - // ## Private methods - - // ### `_addToIndex` adds a triple to a three-layered index. - _addToIndex: function (index0, key0, key1, key2) { - // Create layers as necessary. - var index1 = index0[key0] || (index0[key0] = {}); - var index2 = index1[key1] || (index1[key1] = {}); - // Setting the key to _any_ value signalizes the presence of the triple. - index2[key2] = null; - }, - - // ### `_removeFromIndex` removes a triple from a three-layered index. - _removeFromIndex: function (index0, key0, key1, key2) { - // Remove the triple from the index. - var index1 = index0[key0], index2 = index1[key1], key; - delete index2[key2]; - - // Remove intermediary index layers if they are empty. - for (key in index2) return; - delete index1[key1]; - for (key in index1) return; - delete index0[key0]; - }, - - // ### `_findInIndex` finds a set of triples in a three-layered index. - // The index base is `index0` and the keys at each level are `key0`, `key1`, and `key2`. - // Any of these keys can be `null`, which is interpreted as a wildcard. - // `name0`, `name1`, and `name2` are the names of the keys at each level, - // used when reconstructing the resulting triple - // (for instance: _subject_, _predicate_, and _object_). - // Finally, `graph` will be the graph of the created triples. - _findInIndex: function (index0, key0, key1, key2, name0, name1, name2, graph) { - var results = [], entityKeys = Object.keys(this._entities), tmp, index1, index2; - - // If a key is specified, use only that part of index 0. - if (key0) (tmp = index0, index0 = {})[key0] = tmp[key0]; - for (var value0 in index0) { - var entity0 = entityKeys[value0]; - - if (index1 = index0[value0]) { - // If a key is specified, use only that part of index 1. - if (key1) (tmp = index1, index1 = {})[key1] = tmp[key1]; - for (var value1 in index1) { - var entity1 = entityKeys[value1]; - - if (index2 = index1[value1]) { - // If a key is specified, use only that part of index 2, if it exists. - var values = key2 ? (key2 in index2 ? [key2] : []) : Object.keys(index2); - // Create triples for all items found in index 2. - for (var l = values.length - 1; l >= 0; l--) { - var result = { subject: '', predicate: '', object: '', graph: graph }; - result[name0] = entity0; - result[name1] = entity1; - result[name2] = entityKeys[values[l]]; - results.push(result); - } - } - } - } - } - return results; - }, - - // ### `_countInIndex` counts matching triples in a three-layered index. - // The index base is `index0` and the keys at each level are `key0`, `key1`, and `key2`. - // Any of these keys can be `null`, which is interpreted as a wildcard. - _countInIndex: function (index0, key0, key1, key2) { - var count = 0, tmp, index1, index2; - - // If a key is specified, count only that part of index 0. - if (key0) (tmp = index0, index0 = {})[key0] = tmp[key0]; - for (var value0 in index0) { - if (index1 = index0[value0]) { - // If a key is specified, count only that part of index 1. - if (key1) (tmp = index1, index1 = {})[key1] = tmp[key1]; - for (var value1 in index1) { - if (index2 = index1[value1]) { - // If a key is specified, count the triple if it exists. - if (key2) (key2 in index2) && count++; - // Otherwise, count all triples. - else count += Object.keys(index2).length; - } - } - } - } - return count; - }, - - // ## Public methods - - // ### `addTriple` adds a new N3 triple to the store. - addTriple: function (subject, predicate, object, graph) { - // Shift arguments if a triple object is given instead of components - if (!predicate) - graph = subject.graph, object = subject.object, - predicate = subject.predicate, subject = subject.subject; - - // Find the graph that will contain the triple. - graph = graph || ''; - var graphItem = this._graphs[graph]; - // Create the graph if it doesn't exist yet. - if (!graphItem) { - graphItem = this._graphs[graph] = { subjects: {}, predicates: {}, objects: {} }; - // Freezing a graph helps subsequent `add` performance, - // and properties will never be modified anyway. - Object.freeze(graphItem); - } - - // Since entities can often be long IRIs, we avoid storing them in every index. - // Instead, we have a separate index that maps entities to numbers, - // which are then used as keys in the other indexes. - var entities = this._entities; - subject = entities[subject] || (entities[subject] = ++this._entityCount); - predicate = entities[predicate] || (entities[predicate] = ++this._entityCount); - object = entities[object] || (entities[object] = ++this._entityCount); - - this._addToIndex(graphItem.subjects, subject, predicate, object); - this._addToIndex(graphItem.predicates, predicate, object, subject); - this._addToIndex(graphItem.objects, object, subject, predicate); - - // The cached triple count is now invalid. - this._size = null; - }, - - // ### `addTriples` adds multiple N3 triples to the store. - addTriples: function (triples) { - for (var i = triples.length - 1; i >= 0; i--) - this.addTriple(triples[i]); - }, - - // ### `addPrefix` adds support for querying with the given prefix - addPrefix: function (prefix, iri) { - this._prefixes[prefix] = iri; - }, - - // ### `addPrefixes` adds support for querying with the given prefixes - addPrefixes: function (prefixes) { - for (var prefix in prefixes) - this.addPrefix(prefix, prefixes[prefix]); - }, - - // ### `removeTriple` removes an N3 triple from the store if it exists. - removeTriple: function (subject, predicate, object, graph) { - // Shift arguments if a triple object is given instead of components. - if (!predicate) - graph = subject.graph, object = subject.object, - predicate = subject.predicate, subject = subject.subject; - graph = graph || ''; - - // Find internal identifiers for all components. - var graphItem, entities = this._entities, graphs = this._graphs; - if (!(subject = entities[subject])) return; - if (!(predicate = entities[predicate])) return; - if (!(object = entities[object])) return; - if (!(graphItem = graphs[graph])) return; - - // Verify that the triple exists. - var subjects, predicates; - if (!(subjects = graphItem.subjects[subject])) return; - if (!(predicates = subjects[predicate])) return; - if (!(object in predicates)) return; - - // Remove it from all indexes. - this._removeFromIndex(graphItem.subjects, subject, predicate, object); - this._removeFromIndex(graphItem.predicates, predicate, object, subject); - this._removeFromIndex(graphItem.objects, object, subject, predicate); - if (this._size !== null) this._size--; - - // Remove the graph if it is empty. - for (subject in graphItem.subjects) return; - delete graphs[graph]; - }, - - // ### `removeTriples` removes multiple N3 triples from the store. - removeTriples: function (triples) { - for (var i = triples.length - 1; i >= 0; i--) - this.removeTriple(triples[i]); - }, - - // ### `find` finds a set of triples matching a pattern, expanding prefixes as necessary. - // Setting `subject`, `predicate`, or `object` to `null` means an _anything_ wildcard. - // Setting `graph` to `null` means the default graph. - find: function (subject, predicate, object, graph) { - var prefixes = this._prefixes; - return this.findByIRI( - expandPrefixedName(subject, prefixes), - expandPrefixedName(predicate, prefixes), - expandPrefixedName(object, prefixes), - expandPrefixedName(graph, prefixes) - ); - }, - - // ### `findByIRI` finds a set of triples matching a pattern. - // Setting `subject`, `predicate`, or `object` to a falsy value means an _anything_ wildcard. - // Setting `graph` to a falsy value means the default graph. - findByIRI: function (subject, predicate, object, graph) { - graph = graph || ''; - var graphItem = this._graphs[graph], entities = this._entities; - - // If the specified graph contain no triples, there are no results. - if (!graphItem) return []; - - // Translate IRIs to internal index keys. - // Optimization: if the entity doesn't exist, no triples with it exist. - if (subject && !(subject = entities[subject])) return []; - if (predicate && !(predicate = entities[predicate])) return []; - if (object && !(object = entities[object])) return []; - - // Choose the optimal index, based on what fields are present - if (subject) { - if (object) - // If subject and object are given, the object index will be the fastest. - return this._findInIndex(graphItem.objects, object, subject, predicate, - 'object', 'subject', 'predicate', graph); - else - // If only subject and possibly predicate are given, the subject index will be the fastest. - return this._findInIndex(graphItem.subjects, subject, predicate, null, - 'subject', 'predicate', 'object', graph); - } - else if (predicate) - // If only predicate and possibly object are given, the predicate index will be the fastest. - return this._findInIndex(graphItem.predicates, predicate, object, null, - 'predicate', 'object', 'subject', graph); - else if (object) - // If only object is given, the object index will be the fastest. - return this._findInIndex(graphItem.objects, object, null, null, - 'object', 'subject', 'predicate', graph); - else - // If nothing is given, iterate subjects and predicates first - return this._findInIndex(graphItem.subjects, null, null, null, - 'subject', 'predicate', 'object', graph); - }, - - // ### `count` returns the number of triples matching a pattern, expanding prefixes as necessary. - // Setting `subject`, `predicate`, or `object` to `null` means an _anything_ wildcard. - // Setting `graph` to `null` means the default graph. - count: function (subject, predicate, object, graph) { - var prefixes = this._prefixes; - return this.countByIRI( - expandPrefixedName(subject, prefixes), - expandPrefixedName(predicate, prefixes), - expandPrefixedName(object, prefixes), - expandPrefixedName(graph, prefixes) - ); - }, - - // ### `countByIRI` returns the number of triples matching a pattern. - // Setting `subject`, `predicate`, or `object` to `null` means an _anything_ wildcard. - // Setting `graph` to `null` means the default graph. - countByIRI: function (subject, predicate, object, graph) { - graph = graph || ''; - var graphItem = this._graphs[graph], entities = this._entities; - - // If the specified graph contain no triples, there are no results. - if (!graphItem) return 0; - - // Translate IRIs to internal index keys. - // Optimization: if the entity doesn't exist, no triples with it exist. - if (subject && !(subject = entities[subject])) return 0; - if (predicate && !(predicate = entities[predicate])) return 0; - if (object && !(object = entities[object])) return 0; - - // Choose the optimal index, based on what fields are present - if (subject) { - if (object) - // If subject and object are given, the object index will be the fastest. - return this._countInIndex(graphItem.objects, object, subject, predicate); - else - // If only subject and possibly predicate are given, the subject index will be the fastest. - return this._countInIndex(graphItem.subjects, subject, predicate, object); - } - else if (predicate) { - // If only predicate and possibly object are given, the predicate index will be the fastest. - return this._countInIndex(graphItem.predicates, predicate, object, subject); - } - else { - // If only object is possibly given, the object index will be the fastest. - return this._countInIndex(graphItem.objects, object, subject, predicate); - } - }, - - // ### `createBlankNode` creates a new blank node, returning its name. - createBlankNode: function (suggestedName) { - var name, index; - // Generate a name based on the suggested name - if (suggestedName) { - name = suggestedName = '_:' + suggestedName, index = 1; - while (this._entities[name]) - name = suggestedName + index++; - } - // Generate a generic blank node name - else { - do { name = '_:b' + this._blankNodeIndex++; } - while (this._entities[name]); - } - // Add the blank node to the entities, avoiding the generation of duplicates - this._entities[name] = ++this._entityCount; - return name; - }, -}; - -// ## Exports - -// Export the `N3Store` class as a whole. -module.exports = N3Store; - -},{"./N3Util":37}],35:[function(require,module,exports){ -// **N3StreamParser** parses an N3 stream into a triple stream -var Transform = require('stream').Transform, - util = require('util'), - N3Parser = require('./N3Parser.js'); - -// ## Constructor -function N3StreamParser(options) { - if (!(this instanceof N3StreamParser)) - return new N3StreamParser(options); - - // Initialize Transform base class - Transform.call(this, { decodeStrings: true }); - this._readableState.objectMode = true; - - // Set up parser - var self = this, parser = new N3Parser(options); - parser.parse( - // Handle triples by pushing them down the pipeline - function (error, triple) { - triple && self.push(triple) || - error && self.emit('error', error); - }, - // Emit prefixes through the `prefix` event - this.emit.bind(this, 'prefix')); - - // Implement Transform methods on top of parser - this._transform = function (chunk, encoding, done) { parser.addChunk(chunk); done(); }; - this._flush = function (done) { parser.end(); done(); }; -} -util.inherits(N3StreamParser, Transform); - -// ## Exports -// Export the `N3StreamParser` class as a whole. -module.exports = N3StreamParser; - -},{"./N3Parser.js":33,"stream":24,"util":29}],36:[function(require,module,exports){ -// **N3StreamWriter** serializes a triple stream into an N3 stream -var Transform = require('stream').Transform, - util = require('util'), - N3Writer = require('./N3Writer.js'); - -// ## Constructor -function N3StreamWriter(options) { - if (!(this instanceof N3StreamWriter)) - return new N3StreamWriter(options); - - // Initialize Transform base class - Transform.call(this, { encoding: 'utf8' }); - this._writableState.objectMode = true; - - // Set up writer with a dummy stream object - var self = this; - var writer = new N3Writer({ - write: function (chunk, encoding, callback) { self.push(chunk); callback && callback(); }, - end: function (callback) { self.push(null); callback && callback(); }, - }, options); - - // Implement Transform methods on top of writer - this._transform = function (triple, encoding, done) { writer.addTriple(triple, done); }; - this._flush = function (done) { writer.end(done); }; -} -util.inherits(N3StreamWriter, Transform); - -// ## Exports -// Export the `N3StreamWriter` class as a whole. -module.exports = N3StreamWriter; - -},{"./N3Writer.js":38,"stream":24,"util":29}],37:[function(require,module,exports){ -// **N3Util** provides N3 utility functions - -var Xsd = 'http://www.w3.org/2001/XMLSchema#'; -var XsdString = Xsd + 'string'; -var XsdInteger = Xsd + 'integer'; -var XsdDecimal = Xsd + 'decimal'; -var XsdBoolean = Xsd + 'boolean'; -var RdfLangString = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString'; - -var N3Util = { - // Tests whether the given entity (triple object) represents an IRI in the N3 library - isIRI: function (entity) { - if (!entity) - return entity; - var firstChar = entity[0]; - return firstChar !== '"' && firstChar !== '_'; - }, - - // Tests whether the given entity (triple object) represents a literal in the N3 library - isLiteral: function (entity) { - return entity && entity[0] === '"'; - }, - - // Tests whether the given entity (triple object) represents a blank node in the N3 library - isBlank: function (entity) { - return entity && entity.substr(0, 2) === '_:'; - }, - - // Gets the string value of a literal in the N3 library - getLiteralValue: function (literal) { - var match = /^"([^]*)"/.exec(literal); - if (!match) - throw new Error(literal + ' is not a literal'); - return match[1]; - }, - - // Gets the type of a literal in the N3 library - getLiteralType: function (literal) { - var match = /^"[^]*"(?:\^\^([^"]+)|(@)[^@"]+)?$/.exec(literal); - if (!match) - throw new Error(literal + ' is not a literal'); - return match[1] || (match[2] ? RdfLangString : XsdString); - }, - - // Gets the language of a literal in the N3 library - getLiteralLanguage: function (literal) { - var match = /^"[^]*"(?:@([^@"]+)|\^\^[^"]+)?$/.exec(literal); - if (!match) - throw new Error(literal + ' is not a literal'); - return match[1] ? match[1].toLowerCase() : ''; - }, - - // Tests whether the given entity (triple object) represents a prefixed name - isPrefixedName: function (entity) { - return entity && /^[^:\/"']*:[^:\/"']+$/.test(entity); - }, - - // Expands the prefixed name to a full IRI (also when it occurs as a literal's type) - expandPrefixedName: function (prefixedName, prefixes) { - var match = /(?:^|"\^\^)([^:\/#"'\^_]*):[^\/]*$/.exec(prefixedName), prefix, base, index; - if (match) - prefix = match[1], base = prefixes[prefix], index = match.index; - if (base === undefined) - return prefixedName; - - // The match index is non-zero when expanding a literal's type. - return index === 0 ? base + prefixedName.substr(prefix.length + 1) - : prefixedName.substr(0, index + 3) + - base + prefixedName.substr(index + prefix.length + 4); - }, - - // Creates an IRI in N3.js representation - createIRI: function (iri) { - return iri && iri[0] === '"' ? N3Util.getLiteralValue(iri) : iri; - }, - - // Creates a literal in N3.js representation - createLiteral: function (value, modifier) { - if (!modifier) { - switch (typeof value) { - case 'boolean': - modifier = XsdBoolean; - break; - case 'number': - if (isFinite(value)) { - modifier = value % 1 === 0 ? XsdInteger : XsdDecimal; - break; - } - default: - return '"' + value + '"'; - } - } - return '"' + value + - (/^[a-z]+(-[a-z0-9]+)*$/i.test(modifier) ? '"@' + modifier.toLowerCase() - : '"^^' + modifier); - }, -}; - -// Add the N3Util functions to the given object or its prototype -function addN3Util(parent, toPrototype) { - for (var name in N3Util) - if (!toPrototype) - parent[name] = N3Util[name]; - else - parent.prototype[name] = applyToThis(N3Util[name]); - - return parent; -} - -// Returns a function that applies `f` to the `this` object -function applyToThis(f) { - return function (a) { return f(this, a); }; -} - -// Expose N3Util, attaching all functions to it -module.exports = addN3Util(addN3Util); - -},{}],38:[function(require,module,exports){ -// **N3Writer** writes N3 documents. - -// Matches a literal as represented in memory by the N3 library -var N3LiteralMatcher = /^"([^]*)"(?:\^\^(.+)|@([\-a-z]+))?$/i; - -// rdf:type predicate (for 'a' abbreviation) -var RDF_PREFIX = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', - RDF_TYPE = RDF_PREFIX + 'type'; - -// Characters in literals that require escaping -var escape = /["\\\t\n\r\b\f\u0000-\u0019\ud800-\udbff]/, - escapeAll = /["\\\t\n\r\b\f\u0000-\u0019]|[\ud800-\udbff][\udc00-\udfff]/g, - escapeReplacements = { '\\': '\\\\', '"': '\\"', '\t': '\\t', - '\n': '\\n', '\r': '\\r', '\b': '\\b', '\f': '\\f' }; - -// ## Constructor -function N3Writer(outputStream, options) { - if (!(this instanceof N3Writer)) - return new N3Writer(outputStream, options); - - // Shift arguments if the first argument is not a stream - if (outputStream && typeof outputStream.write !== 'function') - options = outputStream, outputStream = null; - options = options || {}; - - // If no output stream given, send the output as string through the end callback - if (!outputStream) { - var output = ''; - this._outputStream = { - write: function (chunk, encoding, done) { output += chunk; done && done(); }, - end: function (done) { done && done(null, output); }, - }; - this._endStream = true; - } - else { - this._outputStream = outputStream; - this._endStream = options.end === undefined ? true : !!options.end; - } - - // Initialize writer, depending on the format - this._subject = null; - if (!(/triple|quad/i).test(options.format)) { - this._graph = ''; - this._prefixIRIs = Object.create(null); - options.prefixes && this.addPrefixes(options.prefixes); - } - else { - this._writeTriple = this._writeTripleLine; - } -} - -N3Writer.prototype = { - // ## Private methods - - // ### `_write` writes the argument to the output stream - _write: function (string, callback) { - this._outputStream.write(string, 'utf8', callback); - }, - - // ### `_writeTriple` writes the triple to the output stream - _writeTriple: function (subject, predicate, object, graph, done) { - try { - // Write the graph's label if it has changed - if (this._graph !== graph) { - // Close the previous graph and start the new one - this._write((this._subject === null ? '' : (this._graph ? '\n}\n' : '.\n')) + - (graph ? this._encodeIriOrBlankNode(graph) + ' {\n' : '')); - this._subject = null; - // Don't treat identical blank nodes as repeating graphs - this._graph = graph[0] !== '[' ? graph : ']'; - } - // Don't repeat the subject if it's the same - if (this._subject === subject) { - // Don't repeat the predicate if it's the same - if (this._predicate === predicate) - this._write(', ' + this._encodeObject(object), done); - // Same subject, different predicate - else - this._write(';\n ' + - this._encodePredicate(this._predicate = predicate) + ' ' + - this._encodeObject(object), done); - } - // Different subject; write the whole triple - else - this._write((this._subject === null ? '' : '.\n') + - this._encodeSubject(this._subject = subject) + ' ' + - this._encodePredicate(this._predicate = predicate) + ' ' + - this._encodeObject(object), done); - } - catch (error) { done && done(error); } - }, - - // ### `_writeTripleLine` writes the triple or quad to the output stream as a single line - _writeTripleLine: function (subject, predicate, object, graph, done) { - // Don't use prefixes - delete this._prefixMatch; - // Write the triple - try { - this._write(this._encodeIriOrBlankNode(subject) + ' ' + - this._encodeIriOrBlankNode(predicate) + ' ' + - this._encodeObject(object) + - (graph ? ' ' + this._encodeIriOrBlankNode(graph) + '.\n' : '.\n'), done); - } - catch (error) { done && done(error); } - }, - - // ### `_encodeIriOrBlankNode` represents an IRI or blank node - _encodeIriOrBlankNode: function (entity) { - // A blank node or list is represented as-is - var firstChar = entity[0]; - if (firstChar === '[' || firstChar === '(' || firstChar === '_' && entity[1] === ':') - return entity; - // Escape special characters - if (escape.test(entity)) - entity = entity.replace(escapeAll, characterReplacer); - // Try to represent the IRI as prefixed name - var prefixMatch = this._prefixRegex.exec(entity); - return !prefixMatch ? '<' + entity + '>' : - (!prefixMatch[1] ? entity : this._prefixIRIs[prefixMatch[1]] + prefixMatch[2]); - }, - - // ### `_encodeLiteral` represents a literal - _encodeLiteral: function (value, type, language) { - // Escape special characters - if (escape.test(value)) - value = value.replace(escapeAll, characterReplacer); - // Write the literal, possibly with type or language - if (language) - return '"' + value + '"@' + language; - else if (type) - return '"' + value + '"^^' + this._encodeIriOrBlankNode(type); - else - return '"' + value + '"'; - }, - - // ### `_encodeSubject` represents a subject - _encodeSubject: function (subject) { - if (subject[0] === '"') - throw new Error('A literal as subject is not allowed: ' + subject); - // Don't treat identical blank nodes as repeating subjects - if (subject[0] === '[') - this._subject = ']'; - return this._encodeIriOrBlankNode(subject); - }, - - // ### `_encodePredicate` represents a predicate - _encodePredicate: function (predicate) { - if (predicate[0] === '"') - throw new Error('A literal as predicate is not allowed: ' + predicate); - return predicate === RDF_TYPE ? 'a' : this._encodeIriOrBlankNode(predicate); - }, - - // ### `_encodeObject` represents an object - _encodeObject: function (object) { - // Represent an IRI or blank node - if (object[0] !== '"') - return this._encodeIriOrBlankNode(object); - // Represent a literal - var match = N3LiteralMatcher.exec(object); - if (!match) throw new Error('Invalid literal: ' + object); - return this._encodeLiteral(match[1], match[2], match[3]); - }, - - // ### `_blockedWrite` replaces `_write` after the writer has been closed - _blockedWrite: function () { - throw new Error('Cannot write because the writer has been closed.'); - }, - - // ### `addTriple` adds the triple to the output stream - addTriple: function (subject, predicate, object, graph, done) { - // The triple was given as a triple object, so shift parameters - if (object === undefined) - this._writeTriple(subject.subject, subject.predicate, subject.object, - subject.graph || '', predicate); - // The optional `graph` parameter was not provided - else if (typeof graph !== 'string') - this._writeTriple(subject, predicate, object, '', graph); - // The `graph` parameter was provided - else - this._writeTriple(subject, predicate, object, graph, done); - }, - - // ### `addTriples` adds the triples to the output stream - addTriples: function (triples) { - for (var i = 0; i < triples.length; i++) - this.addTriple(triples[i]); - }, - - // ### `addPrefix` adds the prefix to the output stream - addPrefix: function (prefix, iri, done) { - var prefixes = {}; - prefixes[prefix] = iri; - this.addPrefixes(prefixes, done); - }, - - // ### `addPrefixes` adds the prefixes to the output stream - addPrefixes: function (prefixes, done) { - // Add all useful prefixes - var prefixIRIs = this._prefixIRIs, hasPrefixes = false; - for (var prefix in prefixes) { - // Verify whether the prefix can be used and does not exist yet - var iri = prefixes[prefix]; - if (/[#\/]$/.test(iri) && prefixIRIs[iri] !== (prefix += ':')) { - hasPrefixes = true; - prefixIRIs[iri] = prefix; - // Finish a possible pending triple - if (this._subject !== null) { - this._write(this._graph ? '\n}\n' : '.\n'); - this._subject = null, this._graph = ''; - } - // Write prefix - this._write('@prefix ' + prefix + ' <' + iri + '>.\n'); - } - } - // Recreate the prefix matcher - if (hasPrefixes) { - var IRIlist = '', prefixList = ''; - for (var prefixIRI in prefixIRIs) { - IRIlist += IRIlist ? '|' + prefixIRI : prefixIRI; - prefixList += (prefixList ? '|' : '') + prefixIRIs[prefixIRI]; - } - IRIlist = IRIlist.replace(/[\]\/\(\)\*\+\?\.\\\$]/g, '\\$&'); - this._prefixRegex = new RegExp('^(?:' + prefixList + ')[^\/]*$|' + - '^(' + IRIlist + ')([a-zA-Z][\\-_a-zA-Z0-9]*)$'); - } - // End a prefix block with a newline - this._write(hasPrefixes ? '\n' : '', done); - }, - - // ### `blank` creates a blank node with the given content - blank: function (predicate, object) { - var children = predicate, child, length; - // Empty blank node - if (predicate === undefined) - children = []; - // Blank node passed as blank("predicate", "object") - else if (typeof predicate === 'string') - children = [{ predicate: predicate, object: object }]; - // Blank node passed as blank({ predicate: predicate, object: object }) - else if (!('length' in predicate)) - children = [predicate]; - - switch (length = children.length) { - // Generate an empty blank node - case 0: - return '[]'; - // Generate a non-nested one-triple blank node - case 1: - child = children[0]; - if (child.object[0] !== '[') - return '[ ' + this._encodePredicate(child.predicate) + ' ' + - this._encodeObject(child.object) + ' ]'; - // Generate a multi-triple or nested blank node - default: - var contents = '['; - // Write all triples in order - for (var i = 0; i < length; i++) { - child = children[i]; - // Write only the object is the predicate is the same as the previous - if (child.predicate === predicate) - contents += ', ' + this._encodeObject(child.object); - // Otherwise, write the predicate and the object - else { - contents += (i ? ';\n ' : '\n ') + - this._encodePredicate(child.predicate) + ' ' + - this._encodeObject(child.object); - predicate = child.predicate; - } - } - return contents + '\n]'; - } - }, - - // ### `list` creates a list node with the given content - list: function (elements) { - var length = elements && elements.length || 0, contents = new Array(length); - for (var i = 0; i < length; i++) - contents[i] = this._encodeObject(elements[i]); - return '(' + contents.join(' ') + ')'; - }, - - // ### `_prefixRegex` matches a prefixed name or IRI that begins with one of the added prefixes - _prefixRegex: /$0^/, - - // ### `end` signals the end of the output stream - end: function (done) { - // Finish a possible pending triple - if (this._subject !== null) { - this._write(this._graph ? '\n}\n' : '.\n'); - this._subject = null; - } - // Disallow further writing - this._write = this._blockedWrite; - - // Try to end the underlying stream, ensuring done is called exactly one time - var singleDone = done && function (error, result) { singleDone = null, done(error, result); }; - if (this._endStream) { - try { return this._outputStream.end(singleDone); } - catch (error) { /* error closing stream */ } - } - singleDone && singleDone(); - }, -}; - -// Replaces a character by its escaped version -function characterReplacer(character) { - // Replace a single character by its escaped version - var result = escapeReplacements[character]; - if (result === undefined) { - // Replace a single character with its 4-bit unicode escape sequence - if (character.length === 1) { - result = character.charCodeAt(0).toString(16); - result = '\\u0000'.substr(0, 6 - result.length) + result; - } - // Replace a surrogate pair with its 8-bit unicode escape sequence - else { - result = ((character.charCodeAt(0) - 0xD800) * 0x400 + - character.charCodeAt(1) + 0x2400).toString(16); - result = '\\U00000000'.substr(0, 10 - result.length) + result; - } - } - return result; -} - -// ## Exports - -// Export the `N3Writer` class as a whole. -module.exports = N3Writer; - -},{}]},{},[30]); +},{"./support/isBuffer":37,"_process":21,"inherits":36}]},{},[1]);