]> git.cworth.org Git - obsolete/notmuch-web/blob - node_modules/express/node_modules/qs/lib/querystring.js
Install the "express" node module via npm
[obsolete/notmuch-web] / node_modules / express / node_modules / qs / lib / querystring.js
1
2 /*!
3  * querystring
4  * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
5  * MIT Licensed
6  */
7
8 /**
9  * Library version.
10  */
11
12 exports.version = '0.1.0';
13
14 /**
15  * Parse the given query `str`, returning an object.
16  *
17  * @param {String} str
18  * @return {Object}
19  * @api public
20  */
21
22 exports.parse = function(str) {
23   if (str == undefined || str == '') return {};
24
25   return String(str)
26     .split('&')
27     .reduce(function(ret, pair){
28       var pair = decodeURIComponent(pair.replace(/\+/g, ' '))
29         , eql = pair.indexOf('=')
30         , brace = lastBraceInKey(pair)
31         , key = pair.substr(0, brace || eql)
32         , val = pair.substr(brace || eql, pair.length)
33         , val = val.substr(val.indexOf('=') + 1, val.length)
34         , obj = ret;
35
36       // ?foo
37       if ('' == key) key = pair, val = '';
38
39       // nested
40       if (~key.indexOf(']')) {
41         var parts = key.split('[')
42           , len = parts.length
43           , last = len - 1;
44
45         function parse(obj, parts, parent, key) {
46           var part = parts.shift();
47
48           // end
49           if (!part) {
50             if (Array.isArray(parent[key])) {
51               parent[key].push(val);
52             } else if ('object' == typeof parent[key]) {
53               parent[key] = val;
54             } else {
55               parent[key] = [parent[key], val];
56             }
57           // array
58           } else if (']' == part) {
59             obj = parent[key] = Array.isArray(parent[key])
60               ? parent[key]
61               : [];
62             if ('' != val) obj.push(val);
63           // prop
64           } else if (~part.indexOf(']')) {
65             part = part.substr(0, part.length - 1);
66             parse(obj[part] = obj[part] || {}, parts, obj, part);
67           // key
68           } else {
69             parse(obj[part] = obj[part] || {}, parts, obj, part);
70           }
71         }
72
73         parse(obj, parts);
74       // optimize
75       } else {
76         set(obj, key, val);
77       }
78
79       return ret;
80     }, {});
81 };
82
83 /**
84  * Set `obj`'s `key` to `val` respecting
85  * the weird and wonderful syntax of a qs,
86  * where "foo=bar&foo=baz" becomes an array.
87  *
88  * @param {Object} obj
89  * @param {String} key
90  * @param {String} val
91  * @api private
92  */
93
94 function set(obj, key, val) {
95   var v = obj[key];
96   if (undefined === v) {
97     obj[key] = val;
98   } else if (Array.isArray(v)) {
99     v.push(val);
100   } else {
101     obj[key] = [v, val];
102   }
103 }
104
105 /**
106  * Locate last brace in `str` within the key.
107  *
108  * @param {String} str
109  * @return {Number}
110  * @api private
111  */
112
113 function lastBraceInKey(str) {
114   var len = str.length
115     , brace
116     , c;
117   for (var i = 0; i < len; ++i) {
118     c = str[i];
119     if (']' == c) brace = false;
120     if ('[' == c) brace = true;
121     if ('=' == c && !brace) return i;
122   }
123 }