Guest User

Untitled

a guest
Jul 20th, 2018
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.78 KB | None | 0 0
  1. //
  2. // extended Javascript Serialized Object Notation
  3. //
  4. // -API (js.* namespaced)
  5. // -stringify(* obj) -> String
  6. // -parse(String str) -> *
  7. //
  8. // -Conformance
  9. // -Errors in expected locations except for Circular references
  10. //
  11. // -Performance (competitive)
  12. // -Non-recursive, single pass, fast fail
  13. // -Could be sped up to match v8's JSON speed most likely
  14. //
  15. // -Circular References
  16. // -uses mozilla's #Identifier format, #1 will appear before the first instance of the object
  17. // -example : [#1{x:#1},#1] would be an array with indexes of the same reference with a circular reference
  18. // -parser is more lax and allows any identifier in [0-9a-zA-Z_$]+ to follow the '#'
  19. //
  20. ;(function(js) {
  21. function stringify(o) {
  22. var stack = [o]
  23. var indices = []
  24. var parts = []
  25. var pointer
  26. var first
  27. var visited = [{}]//fix for fact 0 === -0
  28. var counts = [0]
  29. while (pointer = stack[stack.length-1]) {
  30. if(pointer !== null && pointer instanceof Object) {
  31. var key = undefined
  32. var index = visited.indexOf(pointer)
  33. if(index === -1) {
  34. visited.push(pointer)
  35. counts.push(1)
  36. index = visited.length - 1
  37. }
  38. else if(indices[stack.length-1] === undefined) {
  39. counts[index]++
  40. parts.push(index)
  41. stack.pop()
  42. continue
  43. }
  44. if(pointer instanceof Array) {
  45. if(indices[stack.length-1] === undefined) {
  46. parts.push(index)
  47. parts.push("[")
  48. first = true
  49. key = indices[stack.length-1] = 0
  50. }
  51. else {
  52. key = indices[stack.length-1]
  53. first = false
  54. }
  55.  
  56. if(key === pointer.length) {
  57. parts.push("]")
  58. parts.push(-index)
  59. indices[stack.length-1] = undefined
  60. stack.pop()
  61. }
  62. else {
  63. if(!first) {
  64. parts.push(",")
  65. }
  66. indices[stack.length-1]+=1
  67. stack.push(pointer[key])
  68. }
  69. }
  70. else {
  71. first = false
  72. if(indices[stack.length-1] === undefined) {
  73. parts.push(index)
  74. parts.push("{")
  75. first = true
  76. var keys = []
  77. for(var k in pointer) {
  78. keys.push(String(k))
  79. }
  80. indices[stack.length-1] = keys
  81. }
  82. key = indices[stack.length-1].shift()
  83.  
  84. if(key === undefined) {
  85. parts.push("}")
  86. parts.push(-index)
  87. indices[stack.length-1] = undefined
  88. stack.pop()
  89. }
  90. else {
  91. if(!first) {
  92. parts.push(",")
  93. }
  94. parts.push('"')
  95. parts.push(String(key))
  96. parts.push('":')
  97. stack.push(pointer[key])
  98. }
  99. }
  100. }
  101. else {
  102. if(isNaN(pointer)||!isFinite(pointer)) pointer = null
  103. parts.push(String(pointer))
  104. stack.pop()
  105. }
  106. }
  107. visited = {}
  108. stack = []
  109. for(var i = 0; i < parts.length; i++) {
  110. var item = parts[i]
  111. if(typeof item === "number") {
  112. if(item > 0) {
  113. if(visited[item] === undefined) {
  114. visited[item] = []
  115. stack.push(item)
  116. }
  117. if(counts[item] > 1) parts[i] = "#"+item
  118. else parts.splice(i,1)
  119. }
  120. else {
  121. parts.splice(i,1)
  122. stack.pop()
  123. }
  124. }
  125. else {
  126. if(stack.length) {
  127. visited[stack[stack.length-1]].push(item)
  128. }
  129. }
  130. }
  131. return parts.join("")
  132. }
  133.  
  134. var tokenizer = new RegExp( "("+[
  135. '"(?:\\[^\\n]|[^"])*"',//1
  136. "'(?:\\[^\\n]|[^\"])'",//2
  137. "[-]?(?:[0-9]+[.]?[0-9]*|[.][0-9]+)(?:[eE][-+][0-9]+)?",//3
  138. "true|false",//4
  139. "null",//5
  140. "[#][0-9a-zA-Z_$]+",//6
  141. "\\[",//7
  142. "\\]",//8
  143. "\\,",//9
  144. "\\:",//10
  145. "\\{",//11
  146. "\\}",//12
  147. "\\s+"//13
  148. ].join(")|(")+")" , "g" )
  149. function parse(str) {
  150. str = String(str)
  151. var reference
  152. var references = {}
  153. var stack = [[]]
  154. var keys = [0]
  155. var matcher = tokenizer
  156. matcher.lastIndex = 0
  157. var index = 0
  158. var match
  159. var lookingForContinuable = false
  160. var lookingForKey = false
  161. var lookingForValue = false
  162. function addProperty(value) {
  163. var key = keys[stack.length-1]
  164. var item = stack[stack.length-1]
  165. if(key === undefined) {
  166. throw new Error("Value encountered without a Key")
  167. }
  168. item[key] = value
  169. if(item instanceof Array) {
  170. keys[stack.length-1]++
  171. }
  172. else {
  173. keys[stack.length-1] = undefined
  174. }
  175. if(reference !== undefined) {
  176. references[reference] = value
  177. }
  178. reference = undefined
  179. lookingForKey = false
  180. lookingForValue = false
  181. lookingForContinuable = true
  182. }
  183. while(match = matcher.exec(str)) {
  184. if(index != match.index) {throw new Error("Unexpected '"+str.slice(index,match.index)+"'")}
  185. if(match[1] !== undefined) {
  186. var value = match[1].slice(1,-1)
  187. if(lookingForKey) {
  188. keys[stack.length-1] = value
  189. lookingForKey = false
  190. lookingForValue = true
  191. lookingForContinuable = false
  192. }
  193. else {
  194. addProperty(value)
  195. }
  196. }
  197. else if(match[2] !== undefined) {
  198. var value = match[2].slice(1,-1)
  199. if(lookingForKey) {
  200. keys[stack.length-1] = value
  201. lookingForKey = false
  202. lookingForValue = true
  203. lookingForContinuable = false
  204. }
  205. else {
  206. addProperty(value)
  207. }
  208. }
  209. else if(match[3] !== undefined) {
  210. addProperty(Number(match[3]))
  211. }
  212. else if(match[4] !== undefined) {
  213. addProperty(match[4] === "true")
  214. }
  215. else if(match[5] !== undefined) {
  216. addProperty(null)
  217. }
  218. else if(match[6] !== undefined) {
  219. if(references[match[6]] !== undefined) {
  220. addProperty(references[match[6]])
  221. }
  222. else {
  223. reference = match[6]
  224. }
  225. }
  226. else if(match[7] !== undefined) {
  227. var child = []
  228. addProperty(child)
  229. lookingForContinuable = true
  230. lookingForValue = true
  231. stack[stack.length] = child
  232. keys[keys.length] = 0
  233. }
  234. else if(match[8] !== undefined) {
  235. if(!lookingForContinuable) throw new Error("Unexpected end of Array at "+index)
  236. stack.length--
  237. keys.length--
  238. }
  239. else if(match[9] !== undefined) {
  240. if(!lookingForContinuable || lookingForKey || lookingForValue) throw new Error("Unexpected ',' at "+index)
  241. var item = stack[stack.length-1]
  242. lookingForContinuable = false
  243. if(!(item instanceof Array)) {
  244. lookingForKey = true
  245. }
  246. }
  247. else if(match[10] !== undefined) {
  248. if(lookingForContinuable || lookingForKey) throw new Error("Unexpected ':' at "+index)
  249. lookingForValue = true
  250. }
  251. else if(match[11] !== undefined) {
  252. var child = {}
  253. addProperty(child)
  254. lookingForKey = true
  255. stack[stack.length] = child
  256. keys[keys.length] = null
  257. }
  258. else if(match[12] !== undefined) {
  259. if(!lookingForContinuable) throw new Error("Unexpected end of Object at "+index)
  260. stack.length--
  261. keys.length--
  262. }
  263. index = matcher.lastIndex
  264. if(stack.length == 1 && stack[0].length) break
  265. }
  266. if(index !== str.length){throw new Error("Unexpected '"+str.substr(index)+"'")}
  267. return stack[0][0]
  268. }
  269. js.parse = parse
  270. js.stringify = stringify
  271. }) (typeof exports !== "undefined" ? exports : js = {}));
Add Comment
Please, Sign In to add comment