/*! * querystring * Copyright(c) 2010 TJ Holowaychuk * MIT Licensed */ /** * Library version. */ exports.version = '0.1.0'; /** * Parse the given query `str`, returning an object. * * @param {String} str * @return {Object} * @api public */ exports.parse = function(str) { if (str == undefined || str == '') return {}; return String(str) .split('&') .reduce(function(ret, pair){ var pair = decodeURIComponent(pair.replace(/\+/g, ' ')) , eql = pair.indexOf('=') , brace = lastBraceInKey(pair) , key = pair.substr(0, brace || eql) , val = pair.substr(brace || eql, pair.length) , val = val.substr(val.indexOf('=') + 1, val.length) , obj = ret; // ?foo if ('' == key) key = pair, val = ''; // nested if (~key.indexOf(']')) { var parts = key.split('[') , len = parts.length , last = len - 1; function parse(obj, parts, parent, key) { var part = parts.shift(); // end if (!part) { if (Array.isArray(parent[key])) { parent[key].push(val); } else if ('object' == typeof parent[key]) { parent[key] = val; } else { parent[key] = [parent[key], val]; } // array } else if (']' == part) { obj = parent[key] = Array.isArray(parent[key]) ? parent[key] : []; if ('' != val) obj.push(val); // prop } else if (~part.indexOf(']')) { part = part.substr(0, part.length - 1); parse(obj[part] = obj[part] || {}, parts, obj, part); // key } else { parse(obj[part] = obj[part] || {}, parts, obj, part); } } parse(obj, parts); // optimize } else { set(obj, key, val); } return ret; }, {}); }; /** * Set `obj`'s `key` to `val` respecting * the weird and wonderful syntax of a qs, * where "foo=bar&foo=baz" becomes an array. * * @param {Object} obj * @param {String} key * @param {String} val * @api private */ function set(obj, key, val) { var v = obj[key]; if (undefined === v) { obj[key] = val; } else if (Array.isArray(v)) { v.push(val); } else { obj[key] = [v, val]; } } /** * Locate last brace in `str` within the key. * * @param {String} str * @return {Number} * @api private */ function lastBraceInKey(str) { var len = str.length , brace , c; for (var i = 0; i < len; ++i) { c = str[i]; if (']' == c) brace = false; if ('[' == c) brace = true; if ('=' == c && !brace) return i; } }