| 'use strict'; | |
| 
 | |
| var formats = require('./formats'); | |
| 
 | |
| var has = Object.prototype.hasOwnProperty; | |
| var isArray = Array.isArray; | |
| 
 | |
| var hexTable = (function () { | |
|     var array = []; | |
|     for (var i = 0; i < 256; ++i) { | |
|         array.push('%' + ((i < 16 ? '0' : '') + i.toString(16)).toUpperCase()); | |
|     } | |
| 
 | |
|     return array; | |
| }()); | |
| 
 | |
| var compactQueue = function compactQueue(queue) { | |
|     while (queue.length > 1) { | |
|         var item = queue.pop(); | |
|         var obj = item.obj[item.prop]; | |
| 
 | |
|         if (isArray(obj)) { | |
|             var compacted = []; | |
| 
 | |
|             for (var j = 0; j < obj.length; ++j) { | |
|                 if (typeof obj[j] !== 'undefined') { | |
|                     compacted.push(obj[j]); | |
|                 } | |
|             } | |
| 
 | |
|             item.obj[item.prop] = compacted; | |
|         } | |
|     } | |
| }; | |
| 
 | |
| var arrayToObject = function arrayToObject(source, options) { | |
|     var obj = options && options.plainObjects ? { __proto__: null } : {}; | |
|     for (var i = 0; i < source.length; ++i) { | |
|         if (typeof source[i] !== 'undefined') { | |
|             obj[i] = source[i]; | |
|         } | |
|     } | |
| 
 | |
|     return obj; | |
| }; | |
| 
 | |
| var merge = function merge(target, source, options) { | |
|     /* eslint no-param-reassign: 0 */ | |
|     if (!source) { | |
|         return target; | |
|     } | |
| 
 | |
|     if (typeof source !== 'object' && typeof source !== 'function') { | |
|         if (isArray(target)) { | |
|             target.push(source); | |
|         } else if (target && typeof target === 'object') { | |
|             if ( | |
|                 (options && (options.plainObjects || options.allowPrototypes)) | |
|                 || !has.call(Object.prototype, source) | |
|             ) { | |
|                 target[source] = true; | |
|             } | |
|         } else { | |
|             return [target, source]; | |
|         } | |
| 
 | |
|         return target; | |
|     } | |
| 
 | |
|     if (!target || typeof target !== 'object') { | |
|         return [target].concat(source); | |
|     } | |
| 
 | |
|     var mergeTarget = target; | |
|     if (isArray(target) && !isArray(source)) { | |
|         mergeTarget = arrayToObject(target, options); | |
|     } | |
| 
 | |
|     if (isArray(target) && isArray(source)) { | |
|         source.forEach(function (item, i) { | |
|             if (has.call(target, i)) { | |
|                 var targetItem = target[i]; | |
|                 if (targetItem && typeof targetItem === 'object' && item && typeof item === 'object') { | |
|                     target[i] = merge(targetItem, item, options); | |
|                 } else { | |
|                     target.push(item); | |
|                 } | |
|             } else { | |
|                 target[i] = item; | |
|             } | |
|         }); | |
|         return target; | |
|     } | |
| 
 | |
|     return Object.keys(source).reduce(function (acc, key) { | |
|         var value = source[key]; | |
| 
 | |
|         if (has.call(acc, key)) { | |
|             acc[key] = merge(acc[key], value, options); | |
|         } else { | |
|             acc[key] = value; | |
|         } | |
|         return acc; | |
|     }, mergeTarget); | |
| }; | |
| 
 | |
| var assign = function assignSingleSource(target, source) { | |
|     return Object.keys(source).reduce(function (acc, key) { | |
|         acc[key] = source[key]; | |
|         return acc; | |
|     }, target); | |
| }; | |
| 
 | |
| var decode = function (str, defaultDecoder, charset) { | |
|     var strWithoutPlus = str.replace(/\+/g, ' '); | |
|     if (charset === 'iso-8859-1') { | |
|         // unescape never throws, no try...catch needed: | |
|         return strWithoutPlus.replace(/%[0-9a-f]{2}/gi, unescape); | |
|     } | |
|     // utf-8 | |
|     try { | |
|         return decodeURIComponent(strWithoutPlus); | |
|     } catch (e) { | |
|         return strWithoutPlus; | |
|     } | |
| }; | |
| 
 | |
| var limit = 1024; | |
| 
 | |
| /* eslint operator-linebreak: [2, "before"] */ | |
| 
 | |
| var encode = function encode(str, defaultEncoder, charset, kind, format) { | |
|     // This code was originally written by Brian White (mscdex) for the io.js core querystring library. | |
|     // It has been adapted here for stricter adherence to RFC 3986 | |
|     if (str.length === 0) { | |
|         return str; | |
|     } | |
| 
 | |
|     var string = str; | |
|     if (typeof str === 'symbol') { | |
|         string = Symbol.prototype.toString.call(str); | |
|     } else if (typeof str !== 'string') { | |
|         string = String(str); | |
|     } | |
| 
 | |
|     if (charset === 'iso-8859-1') { | |
|         return escape(string).replace(/%u[0-9a-f]{4}/gi, function ($0) { | |
|             return '%26%23' + parseInt($0.slice(2), 16) + '%3B'; | |
|         }); | |
|     } | |
| 
 | |
|     var out = ''; | |
|     for (var j = 0; j < string.length; j += limit) { | |
|         var segment = string.length >= limit ? string.slice(j, j + limit) : string; | |
|         var arr = []; | |
| 
 | |
|         for (var i = 0; i < segment.length; ++i) { | |
|             var c = segment.charCodeAt(i); | |
|             if ( | |
|                 c === 0x2D // - | |
|                 || c === 0x2E // . | |
|                 || c === 0x5F // _ | |
|                 || c === 0x7E // ~ | |
|                 || (c >= 0x30 && c <= 0x39) // 0-9 | |
|                 || (c >= 0x41 && c <= 0x5A) // a-z | |
|                 || (c >= 0x61 && c <= 0x7A) // A-Z | |
|                 || (format === formats.RFC1738 && (c === 0x28 || c === 0x29)) // ( ) | |
|             ) { | |
|                 arr[arr.length] = segment.charAt(i); | |
|                 continue; | |
|             } | |
| 
 | |
|             if (c < 0x80) { | |
|                 arr[arr.length] = hexTable[c]; | |
|                 continue; | |
|             } | |
| 
 | |
|             if (c < 0x800) { | |
|                 arr[arr.length] = hexTable[0xC0 | (c >> 6)] | |
|                     + hexTable[0x80 | (c & 0x3F)]; | |
|                 continue; | |
|             } | |
| 
 | |
|             if (c < 0xD800 || c >= 0xE000) { | |
|                 arr[arr.length] = hexTable[0xE0 | (c >> 12)] | |
|                     + hexTable[0x80 | ((c >> 6) & 0x3F)] | |
|                     + hexTable[0x80 | (c & 0x3F)]; | |
|                 continue; | |
|             } | |
| 
 | |
|             i += 1; | |
|             c = 0x10000 + (((c & 0x3FF) << 10) | (segment.charCodeAt(i) & 0x3FF)); | |
| 
 | |
|             arr[arr.length] = hexTable[0xF0 | (c >> 18)] | |
|                 + hexTable[0x80 | ((c >> 12) & 0x3F)] | |
|                 + hexTable[0x80 | ((c >> 6) & 0x3F)] | |
|                 + hexTable[0x80 | (c & 0x3F)]; | |
|         } | |
| 
 | |
|         out += arr.join(''); | |
|     } | |
| 
 | |
|     return out; | |
| }; | |
| 
 | |
| var compact = function compact(value) { | |
|     var queue = [{ obj: { o: value }, prop: 'o' }]; | |
|     var refs = []; | |
| 
 | |
|     for (var i = 0; i < queue.length; ++i) { | |
|         var item = queue[i]; | |
|         var obj = item.obj[item.prop]; | |
| 
 | |
|         var keys = Object.keys(obj); | |
|         for (var j = 0; j < keys.length; ++j) { | |
|             var key = keys[j]; | |
|             var val = obj[key]; | |
|             if (typeof val === 'object' && val !== null && refs.indexOf(val) === -1) { | |
|                 queue.push({ obj: obj, prop: key }); | |
|                 refs.push(val); | |
|             } | |
|         } | |
|     } | |
| 
 | |
|     compactQueue(queue); | |
| 
 | |
|     return value; | |
| }; | |
| 
 | |
| var isRegExp = function isRegExp(obj) { | |
|     return Object.prototype.toString.call(obj) === '[object RegExp]'; | |
| }; | |
| 
 | |
| var isBuffer = function isBuffer(obj) { | |
|     if (!obj || typeof obj !== 'object') { | |
|         return false; | |
|     } | |
| 
 | |
|     return !!(obj.constructor && obj.constructor.isBuffer && obj.constructor.isBuffer(obj)); | |
| }; | |
| 
 | |
| var combine = function combine(a, b) { | |
|     return [].concat(a, b); | |
| }; | |
| 
 | |
| var maybeMap = function maybeMap(val, fn) { | |
|     if (isArray(val)) { | |
|         var mapped = []; | |
|         for (var i = 0; i < val.length; i += 1) { | |
|             mapped.push(fn(val[i])); | |
|         } | |
|         return mapped; | |
|     } | |
|     return fn(val); | |
| }; | |
| 
 | |
| module.exports = { | |
|     arrayToObject: arrayToObject, | |
|     assign: assign, | |
|     combine: combine, | |
|     compact: compact, | |
|     decode: decode, | |
|     encode: encode, | |
|     isBuffer: isBuffer, | |
|     isRegExp: isRegExp, | |
|     maybeMap: maybeMap, | |
|     merge: merge | |
| };
 |