Path: blob/master/node_modules/ajv/lib/compile/util.js
1126 views
'use strict';123module.exports = {4copy: copy,5checkDataType: checkDataType,6checkDataTypes: checkDataTypes,7coerceToTypes: coerceToTypes,8toHash: toHash,9getProperty: getProperty,10escapeQuotes: escapeQuotes,11equal: require('fast-deep-equal'),12ucs2length: require('./ucs2length'),13varOccurences: varOccurences,14varReplace: varReplace,15schemaHasRules: schemaHasRules,16schemaHasRulesExcept: schemaHasRulesExcept,17schemaUnknownRules: schemaUnknownRules,18toQuotedString: toQuotedString,19getPathExpr: getPathExpr,20getPath: getPath,21getData: getData,22unescapeFragment: unescapeFragment,23unescapeJsonPointer: unescapeJsonPointer,24escapeFragment: escapeFragment,25escapeJsonPointer: escapeJsonPointer26};272829function copy(o, to) {30to = to || {};31for (var key in o) to[key] = o[key];32return to;33}343536function checkDataType(dataType, data, strictNumbers, negate) {37var EQUAL = negate ? ' !== ' : ' === '38, AND = negate ? ' || ' : ' && '39, OK = negate ? '!' : ''40, NOT = negate ? '' : '!';41switch (dataType) {42case 'null': return data + EQUAL + 'null';43case 'array': return OK + 'Array.isArray(' + data + ')';44case 'object': return '(' + OK + data + AND +45'typeof ' + data + EQUAL + '"object"' + AND +46NOT + 'Array.isArray(' + data + '))';47case 'integer': return '(typeof ' + data + EQUAL + '"number"' + AND +48NOT + '(' + data + ' % 1)' +49AND + data + EQUAL + data +50(strictNumbers ? (AND + OK + 'isFinite(' + data + ')') : '') + ')';51case 'number': return '(typeof ' + data + EQUAL + '"' + dataType + '"' +52(strictNumbers ? (AND + OK + 'isFinite(' + data + ')') : '') + ')';53default: return 'typeof ' + data + EQUAL + '"' + dataType + '"';54}55}565758function checkDataTypes(dataTypes, data, strictNumbers) {59switch (dataTypes.length) {60case 1: return checkDataType(dataTypes[0], data, strictNumbers, true);61default:62var code = '';63var types = toHash(dataTypes);64if (types.array && types.object) {65code = types.null ? '(': '(!' + data + ' || ';66code += 'typeof ' + data + ' !== "object")';67delete types.null;68delete types.array;69delete types.object;70}71if (types.number) delete types.integer;72for (var t in types)73code += (code ? ' && ' : '' ) + checkDataType(t, data, strictNumbers, true);7475return code;76}77}787980var COERCE_TO_TYPES = toHash([ 'string', 'number', 'integer', 'boolean', 'null' ]);81function coerceToTypes(optionCoerceTypes, dataTypes) {82if (Array.isArray(dataTypes)) {83var types = [];84for (var i=0; i<dataTypes.length; i++) {85var t = dataTypes[i];86if (COERCE_TO_TYPES[t]) types[types.length] = t;87else if (optionCoerceTypes === 'array' && t === 'array') types[types.length] = t;88}89if (types.length) return types;90} else if (COERCE_TO_TYPES[dataTypes]) {91return [dataTypes];92} else if (optionCoerceTypes === 'array' && dataTypes === 'array') {93return ['array'];94}95}969798function toHash(arr) {99var hash = {};100for (var i=0; i<arr.length; i++) hash[arr[i]] = true;101return hash;102}103104105var IDENTIFIER = /^[a-z$_][a-z$_0-9]*$/i;106var SINGLE_QUOTE = /'|\\/g;107function getProperty(key) {108return typeof key == 'number'109? '[' + key + ']'110: IDENTIFIER.test(key)111? '.' + key112: "['" + escapeQuotes(key) + "']";113}114115116function escapeQuotes(str) {117return str.replace(SINGLE_QUOTE, '\\$&')118.replace(/\n/g, '\\n')119.replace(/\r/g, '\\r')120.replace(/\f/g, '\\f')121.replace(/\t/g, '\\t');122}123124125function varOccurences(str, dataVar) {126dataVar += '[^0-9]';127var matches = str.match(new RegExp(dataVar, 'g'));128return matches ? matches.length : 0;129}130131132function varReplace(str, dataVar, expr) {133dataVar += '([^0-9])';134expr = expr.replace(/\$/g, '$$$$');135return str.replace(new RegExp(dataVar, 'g'), expr + '$1');136}137138139function schemaHasRules(schema, rules) {140if (typeof schema == 'boolean') return !schema;141for (var key in schema) if (rules[key]) return true;142}143144145function schemaHasRulesExcept(schema, rules, exceptKeyword) {146if (typeof schema == 'boolean') return !schema && exceptKeyword != 'not';147for (var key in schema) if (key != exceptKeyword && rules[key]) return true;148}149150151function schemaUnknownRules(schema, rules) {152if (typeof schema == 'boolean') return;153for (var key in schema) if (!rules[key]) return key;154}155156157function toQuotedString(str) {158return '\'' + escapeQuotes(str) + '\'';159}160161162function getPathExpr(currentPath, expr, jsonPointers, isNumber) {163var path = jsonPointers // false by default164? '\'/\' + ' + expr + (isNumber ? '' : '.replace(/~/g, \'~0\').replace(/\\//g, \'~1\')')165: (isNumber ? '\'[\' + ' + expr + ' + \']\'' : '\'[\\\'\' + ' + expr + ' + \'\\\']\'');166return joinPaths(currentPath, path);167}168169170function getPath(currentPath, prop, jsonPointers) {171var path = jsonPointers // false by default172? toQuotedString('/' + escapeJsonPointer(prop))173: toQuotedString(getProperty(prop));174return joinPaths(currentPath, path);175}176177178var JSON_POINTER = /^\/(?:[^~]|~0|~1)*$/;179var RELATIVE_JSON_POINTER = /^([0-9]+)(#|\/(?:[^~]|~0|~1)*)?$/;180function getData($data, lvl, paths) {181var up, jsonPointer, data, matches;182if ($data === '') return 'rootData';183if ($data[0] == '/') {184if (!JSON_POINTER.test($data)) throw new Error('Invalid JSON-pointer: ' + $data);185jsonPointer = $data;186data = 'rootData';187} else {188matches = $data.match(RELATIVE_JSON_POINTER);189if (!matches) throw new Error('Invalid JSON-pointer: ' + $data);190up = +matches[1];191jsonPointer = matches[2];192if (jsonPointer == '#') {193if (up >= lvl) throw new Error('Cannot access property/index ' + up + ' levels up, current level is ' + lvl);194return paths[lvl - up];195}196197if (up > lvl) throw new Error('Cannot access data ' + up + ' levels up, current level is ' + lvl);198data = 'data' + ((lvl - up) || '');199if (!jsonPointer) return data;200}201202var expr = data;203var segments = jsonPointer.split('/');204for (var i=0; i<segments.length; i++) {205var segment = segments[i];206if (segment) {207data += getProperty(unescapeJsonPointer(segment));208expr += ' && ' + data;209}210}211return expr;212}213214215function joinPaths (a, b) {216if (a == '""') return b;217return (a + ' + ' + b).replace(/([^\\])' \+ '/g, '$1');218}219220221function unescapeFragment(str) {222return unescapeJsonPointer(decodeURIComponent(str));223}224225226function escapeFragment(str) {227return encodeURIComponent(escapeJsonPointer(str));228}229230231function escapeJsonPointer(str) {232return str.replace(/~/g, '~0').replace(/\//g, '~1');233}234235236function unescapeJsonPointer(str) {237return str.replace(/~1/g, '/').replace(/~0/g, '~');238}239240241