| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 | 
							- /*!
 
- Copyright (C) 2013 by WebReflection
 
- Permission is hereby granted, free of charge, to any person obtaining a copy
 
- of this software and associated documentation files (the "Software"), to deal
 
- in the Software without restriction, including without limitation the rights
 
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
- copies of the Software, and to permit persons to whom the Software is
 
- furnished to do so, subject to the following conditions:
 
- The above copyright notice and this permission notice shall be included in
 
- all copies or substantial portions of the Software.
 
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
- THE SOFTWARE.
 
- */
 
- var
 
-   // should be a not so common char
 
-   // possibly one JSON does not encode
 
-   // possibly one encodeURIComponent does not encode
 
-   // right now this char is '~' but this might change in the future
 
-   specialChar = '~',
 
-   safeSpecialChar = '\\x' + (
 
-     '0' + specialChar.charCodeAt(0).toString(16)
 
-   ).slice(-2),
 
-   escapedSafeSpecialChar = '\\' + safeSpecialChar,
 
-   specialCharRG = new RegExp(safeSpecialChar, 'g'),
 
-   safeSpecialCharRG = new RegExp(escapedSafeSpecialChar, 'g'),
 
-   safeStartWithSpecialCharRG = new RegExp('(?:^|([^\\\\]))' + escapedSafeSpecialChar),
 
-   indexOf = [].indexOf || function(v){
 
-     for(var i=this.length;i--&&this[i]!==v;);
 
-     return i;
 
-   },
 
-   $String = String  // there's no way to drop warnings in JSHint
 
-                     // about new String ... well, I need that here!
 
-                     // faked, and happy linter!
 
- ;
 
- function generateReplacer(value, replacer, resolve) {
 
-   var
 
-     path = [],
 
-     all  = [value],
 
-     seen = [value],
 
-     mapp = [resolve ? specialChar : '[Circular]'],
 
-     last = value,
 
-     lvl  = 1,
 
-     i
 
-   ;
 
-   return function(key, value) {
 
-     // the replacer has rights to decide
 
-     // if a new object should be returned
 
-     // or if there's some key to drop
 
-     // let's call it here rather than "too late"
 
-     if (replacer) value = replacer.call(this, key, value);
 
-     // did you know ? Safari passes keys as integers for arrays
 
-     // which means if (key) when key === 0 won't pass the check
 
-     if (key !== '') {
 
-       if (last !== this) {
 
-         i = lvl - indexOf.call(all, this) - 1;
 
-         lvl -= i;
 
-         all.splice(lvl, all.length);
 
-         path.splice(lvl - 1, path.length);
 
-         last = this;
 
-       }
 
-       // console.log(lvl, key, path);
 
-       if (typeof value === 'object' && value) {
 
-     	// if object isn't referring to parent object, add to the
 
-         // object path stack. Otherwise it is already there.
 
-         if (indexOf.call(all, value) < 0) {
 
-           all.push(last = value);
 
-         }
 
-         lvl = all.length;
 
-         i = indexOf.call(seen, value);
 
-         if (i < 0) {
 
-           i = seen.push(value) - 1;
 
-           if (resolve) {
 
-             // key cannot contain specialChar but could be not a string
 
-             path.push(('' + key).replace(specialCharRG, safeSpecialChar));
 
-             mapp[i] = specialChar + path.join(specialChar);
 
-           } else {
 
-             mapp[i] = mapp[0];
 
-           }
 
-         } else {
 
-           value = mapp[i];
 
-         }
 
-       } else {
 
-         if (typeof value === 'string' && resolve) {
 
-           // ensure no special char involved on deserialization
 
-           // in this case only first char is important
 
-           // no need to replace all value (better performance)
 
-           value = value .replace(safeSpecialChar, escapedSafeSpecialChar)
 
-                         .replace(specialChar, safeSpecialChar);
 
-         }
 
-       }
 
-     }
 
-     return value;
 
-   };
 
- }
 
- function retrieveFromPath(current, keys) {
 
-   for(var i = 0, length = keys.length; i < length; current = current[
 
-     // keys should be normalized back here
 
-     keys[i++].replace(safeSpecialCharRG, specialChar)
 
-   ]);
 
-   return current;
 
- }
 
- function generateReviver(reviver) {
 
-   return function(key, value) {
 
-     var isString = typeof value === 'string';
 
-     if (isString && value.charAt(0) === specialChar) {
 
-       return new $String(value.slice(1));
 
-     }
 
-     if (key === '') value = regenerate(value, value, {});
 
-     // again, only one needed, do not use the RegExp for this replacement
 
-     // only keys need the RegExp
 
-     if (isString) value = value .replace(safeStartWithSpecialCharRG, '$1' + specialChar)
 
-                                 .replace(escapedSafeSpecialChar, safeSpecialChar);
 
-     return reviver ? reviver.call(this, key, value) : value;
 
-   };
 
- }
 
- function regenerateArray(root, current, retrieve) {
 
-   for (var i = 0, length = current.length; i < length; i++) {
 
-     current[i] = regenerate(root, current[i], retrieve);
 
-   }
 
-   return current;
 
- }
 
- function regenerateObject(root, current, retrieve) {
 
-   for (var key in current) {
 
-     if (current.hasOwnProperty(key)) {
 
-       current[key] = regenerate(root, current[key], retrieve);
 
-     }
 
-   }
 
-   return current;
 
- }
 
- function regenerate(root, current, retrieve) {
 
-   return current instanceof Array ?
 
-     // fast Array reconstruction
 
-     regenerateArray(root, current, retrieve) :
 
-     (
 
-       current instanceof $String ?
 
-         (
 
-           // root is an empty string
 
-           current.length ?
 
-             (
 
-               retrieve.hasOwnProperty(current) ?
 
-                 retrieve[current] :
 
-                 retrieve[current] = retrieveFromPath(
 
-                   root, current.split(specialChar)
 
-                 )
 
-             ) :
 
-             root
 
-         ) :
 
-         (
 
-           current instanceof Object ?
 
-             // dedicated Object parser
 
-             regenerateObject(root, current, retrieve) :
 
-             // value as it is
 
-             current
 
-         )
 
-     )
 
-   ;
 
- }
 
- function stringifyRecursion(value, replacer, space, doNotResolve) {
 
-   return JSON.stringify(value, generateReplacer(value, replacer, !doNotResolve), space);
 
- }
 
- function parseRecursion(text, reviver) {
 
-   return JSON.parse(text, generateReviver(reviver));
 
- }
 
- this.stringify = stringifyRecursion;
 
- this.parse = parseRecursion;
 
 
  |