Tizen 2.1 base
[platform/framework/web/web-ui-fw.git] / libs / js / jquery-mobile-1.2.0 / node_modules / grunt / node_modules / connect / node_modules / qs / lib / querystring.js
1
2 /**
3  * Object#toString() ref for stringify().
4  */
5
6 var toString = Object.prototype.toString;
7
8 /**
9  * Cache non-integer test regexp.
10  */
11
12 var isint = /^[0-9]+$/;
13
14 function promote(parent, key) {
15   if (parent[key].length == 0) return parent[key] = {};
16   var t = {};
17   for (var i in parent[key]) t[i] = parent[key][i];
18   parent[key] = t;
19   return t;
20 }
21
22 function parse(parts, parent, key, val) {
23   var part = parts.shift();
24   // end
25   if (!part) {
26     if (Array.isArray(parent[key])) {
27       parent[key].push(val);
28     } else if ('object' == typeof parent[key]) {
29       parent[key] = val;
30     } else if ('undefined' == typeof parent[key]) {
31       parent[key] = val;
32     } else {
33       parent[key] = [parent[key], val];
34     }
35     // array
36   } else {
37     var obj = parent[key] = parent[key] || [];
38     if (']' == part) {
39       if (Array.isArray(obj)) {
40         if ('' != val) obj.push(val);
41       } else if ('object' == typeof obj) {
42         obj[Object.keys(obj).length] = val;
43       } else {
44         obj = parent[key] = [parent[key], val];
45       }
46       // prop
47     } else if (~part.indexOf(']')) {
48       part = part.substr(0, part.length - 1);
49       if (!isint.test(part) && Array.isArray(obj)) obj = promote(parent, key);
50       parse(parts, obj, part, val);
51       // key
52     } else {
53       if (!isint.test(part) && Array.isArray(obj)) obj = promote(parent, key);
54       parse(parts, obj, part, val);
55     }
56   }
57 }
58
59 /**
60  * Merge parent key/val pair.
61  */
62
63 function merge(parent, key, val){
64   if (~key.indexOf(']')) {
65     var parts = key.split('[')
66       , len = parts.length
67       , last = len - 1;
68     parse(parts, parent, 'base', val);
69     // optimize
70   } else {
71     if (!isint.test(key) && Array.isArray(parent.base)) {
72       var t = {};
73       for (var k in parent.base) t[k] = parent.base[k];
74       parent.base = t;
75     }
76     set(parent.base, key, val);
77   }
78
79   return parent;
80 }
81
82 /**
83  * Parse the given obj.
84  */
85
86 function parseObject(obj){
87   var ret = { base: {} };
88   Object.keys(obj).forEach(function(name){
89     merge(ret, name, obj[name]);
90   });
91   return ret.base;
92 }
93
94 /**
95  * Parse the given str.
96  */
97
98 function parseString(str){
99   return String(str)
100     .split('&')
101     .reduce(function(ret, pair){
102       var eql = pair.indexOf('=')
103         , brace = lastBraceInKey(pair)
104         , key = pair.substr(0, brace || eql)
105         , val = pair.substr(brace || eql, pair.length)
106         , val = val.substr(val.indexOf('=') + 1, val.length);
107
108       // ?foo
109       if ('' == key) key = pair, val = '';
110
111       return merge(ret, decode(key), decode(val));
112     }, { base: {} }).base;
113 }
114
115 /**
116  * Parse the given query `str` or `obj`, returning an object.
117  *
118  * @param {String} str | {Object} obj
119  * @return {Object}
120  * @api public
121  */
122
123 exports.parse = function(str){
124   if (null == str || '' == str) return {};
125   return 'object' == typeof str
126     ? parseObject(str)
127     : parseString(str);
128 };
129
130 /**
131  * Turn the given `obj` into a query string
132  *
133  * @param {Object} obj
134  * @return {String}
135  * @api public
136  */
137
138 var stringify = exports.stringify = function(obj, prefix) {
139   if (Array.isArray(obj)) {
140     return stringifyArray(obj, prefix);
141   } else if ('[object Object]' == toString.call(obj)) {
142     return stringifyObject(obj, prefix);
143   } else if ('string' == typeof obj) {
144     return stringifyString(obj, prefix);
145   } else {
146     return prefix + '=' + obj;
147   }
148 };
149
150 /**
151  * Stringify the given `str`.
152  *
153  * @param {String} str
154  * @param {String} prefix
155  * @return {String}
156  * @api private
157  */
158
159 function stringifyString(str, prefix) {
160   if (!prefix) throw new TypeError('stringify expects an object');
161   return prefix + '=' + encodeURIComponent(str);
162 }
163
164 /**
165  * Stringify the given `arr`.
166  *
167  * @param {Array} arr
168  * @param {String} prefix
169  * @return {String}
170  * @api private
171  */
172
173 function stringifyArray(arr, prefix) {
174   var ret = [];
175   if (!prefix) throw new TypeError('stringify expects an object');
176   for (var i = 0; i < arr.length; i++) {
177     ret.push(stringify(arr[i], prefix + '['+i+']'));
178   }
179   return ret.join('&');
180 }
181
182 /**
183  * Stringify the given `obj`.
184  *
185  * @param {Object} obj
186  * @param {String} prefix
187  * @return {String}
188  * @api private
189  */
190
191 function stringifyObject(obj, prefix) {
192   var ret = []
193     , keys = Object.keys(obj)
194     , key;
195
196   for (var i = 0, len = keys.length; i < len; ++i) {
197     key = keys[i];
198     ret.push(stringify(obj[key], prefix
199       ? prefix + '[' + encodeURIComponent(key) + ']'
200       : encodeURIComponent(key)));
201   }
202
203   return ret.join('&');
204 }
205
206 /**
207  * Set `obj`'s `key` to `val` respecting
208  * the weird and wonderful syntax of a qs,
209  * where "foo=bar&foo=baz" becomes an array.
210  *
211  * @param {Object} obj
212  * @param {String} key
213  * @param {String} val
214  * @api private
215  */
216
217 function set(obj, key, val) {
218   var v = obj[key];
219   if (undefined === v) {
220     obj[key] = val;
221   } else if (Array.isArray(v)) {
222     v.push(val);
223   } else {
224     obj[key] = [v, val];
225   }
226 }
227
228 /**
229  * Locate last brace in `str` within the key.
230  *
231  * @param {String} str
232  * @return {Number}
233  * @api private
234  */
235
236 function lastBraceInKey(str) {
237   var len = str.length
238     , brace
239     , c;
240   for (var i = 0; i < len; ++i) {
241     c = str[i];
242     if (']' == c) brace = false;
243     if ('[' == c) brace = true;
244     if ('=' == c && !brace) return i;
245   }
246 }
247
248 /**
249  * Decode `str`.
250  *
251  * @param {String} str
252  * @return {String}
253  * @api private
254  */
255
256 function decode(str) {
257   try {
258     return decodeURIComponent(str.replace(/\+/g, ' '));
259   } catch (err) {
260     return str;
261   }
262 }