second
[josuexyz/.git] / node_modules / qs / lib / utils.js
1 'use strict';
2
3 var has = Object.prototype.hasOwnProperty;
4
5 var hexTable = (function () {
6     var array = [];
7     for (var i = 0; i < 256; ++i) {
8         array.push('%' + ((i < 16 ? '0' : '') + i.toString(16)).toUpperCase());
9     }
10
11     return array;
12 }());
13
14 var compactQueue = function compactQueue(queue) {
15     var obj;
16
17     while (queue.length) {
18         var item = queue.pop();
19         obj = item.obj[item.prop];
20
21         if (Array.isArray(obj)) {
22             var compacted = [];
23
24             for (var j = 0; j < obj.length; ++j) {
25                 if (typeof obj[j] !== 'undefined') {
26                     compacted.push(obj[j]);
27                 }
28             }
29
30             item.obj[item.prop] = compacted;
31         }
32     }
33
34     return obj;
35 };
36
37 var arrayToObject = function arrayToObject(source, options) {
38     var obj = options && options.plainObjects ? Object.create(null) : {};
39     for (var i = 0; i < source.length; ++i) {
40         if (typeof source[i] !== 'undefined') {
41             obj[i] = source[i];
42         }
43     }
44
45     return obj;
46 };
47
48 var merge = function merge(target, source, options) {
49     if (!source) {
50         return target;
51     }
52
53     if (typeof source !== 'object') {
54         if (Array.isArray(target)) {
55             target.push(source);
56         } else if (typeof target === 'object') {
57             if (options.plainObjects || options.allowPrototypes || !has.call(Object.prototype, source)) {
58                 target[source] = true;
59             }
60         } else {
61             return [target, source];
62         }
63
64         return target;
65     }
66
67     if (typeof target !== 'object') {
68         return [target].concat(source);
69     }
70
71     var mergeTarget = target;
72     if (Array.isArray(target) && !Array.isArray(source)) {
73         mergeTarget = arrayToObject(target, options);
74     }
75
76     if (Array.isArray(target) && Array.isArray(source)) {
77         source.forEach(function (item, i) {
78             if (has.call(target, i)) {
79                 if (target[i] && typeof target[i] === 'object') {
80                     target[i] = merge(target[i], item, options);
81                 } else {
82                     target.push(item);
83                 }
84             } else {
85                 target[i] = item;
86             }
87         });
88         return target;
89     }
90
91     return Object.keys(source).reduce(function (acc, key) {
92         var value = source[key];
93
94         if (has.call(acc, key)) {
95             acc[key] = merge(acc[key], value, options);
96         } else {
97             acc[key] = value;
98         }
99         return acc;
100     }, mergeTarget);
101 };
102
103 var assign = function assignSingleSource(target, source) {
104     return Object.keys(source).reduce(function (acc, key) {
105         acc[key] = source[key];
106         return acc;
107     }, target);
108 };
109
110 var decode = function (str) {
111     try {
112         return decodeURIComponent(str.replace(/\+/g, ' '));
113     } catch (e) {
114         return str;
115     }
116 };
117
118 var encode = function encode(str) {
119     // This code was originally written by Brian White (mscdex) for the io.js core querystring library.
120     // It has been adapted here for stricter adherence to RFC 3986
121     if (str.length === 0) {
122         return str;
123     }
124
125     var string = typeof str === 'string' ? str : String(str);
126
127     var out = '';
128     for (var i = 0; i < string.length; ++i) {
129         var c = string.charCodeAt(i);
130
131         if (
132             c === 0x2D // -
133             || c === 0x2E // .
134             || c === 0x5F // _
135             || c === 0x7E // ~
136             || (c >= 0x30 && c <= 0x39) // 0-9
137             || (c >= 0x41 && c <= 0x5A) // a-z
138             || (c >= 0x61 && c <= 0x7A) // A-Z
139         ) {
140             out += string.charAt(i);
141             continue;
142         }
143
144         if (c < 0x80) {
145             out = out + hexTable[c];
146             continue;
147         }
148
149         if (c < 0x800) {
150             out = out + (hexTable[0xC0 | (c >> 6)] + hexTable[0x80 | (c & 0x3F)]);
151             continue;
152         }
153
154         if (c < 0xD800 || c >= 0xE000) {
155             out = out + (hexTable[0xE0 | (c >> 12)] + hexTable[0x80 | ((c >> 6) & 0x3F)] + hexTable[0x80 | (c & 0x3F)]);
156             continue;
157         }
158
159         i += 1;
160         c = 0x10000 + (((c & 0x3FF) << 10) | (string.charCodeAt(i) & 0x3FF));
161         out += hexTable[0xF0 | (c >> 18)]
162             + hexTable[0x80 | ((c >> 12) & 0x3F)]
163             + hexTable[0x80 | ((c >> 6) & 0x3F)]
164             + hexTable[0x80 | (c & 0x3F)];
165     }
166
167     return out;
168 };
169
170 var compact = function compact(value) {
171     var queue = [{ obj: { o: value }, prop: 'o' }];
172     var refs = [];
173
174     for (var i = 0; i < queue.length; ++i) {
175         var item = queue[i];
176         var obj = item.obj[item.prop];
177
178         var keys = Object.keys(obj);
179         for (var j = 0; j < keys.length; ++j) {
180             var key = keys[j];
181             var val = obj[key];
182             if (typeof val === 'object' && val !== null && refs.indexOf(val) === -1) {
183                 queue.push({ obj: obj, prop: key });
184                 refs.push(val);
185             }
186         }
187     }
188
189     return compactQueue(queue);
190 };
191
192 var isRegExp = function isRegExp(obj) {
193     return Object.prototype.toString.call(obj) === '[object RegExp]';
194 };
195
196 var isBuffer = function isBuffer(obj) {
197     if (obj === null || typeof obj === 'undefined') {
198         return false;
199     }
200
201     return !!(obj.constructor && obj.constructor.isBuffer && obj.constructor.isBuffer(obj));
202 };
203
204 module.exports = {
205     arrayToObject: arrayToObject,
206     assign: assign,
207     compact: compact,
208     decode: decode,
209     encode: encode,
210     isBuffer: isBuffer,
211     isRegExp: isRegExp,
212     merge: merge
213 };