]> git.mjollnir.org Git - moodle.git/blob
bc5c1160d554c37792fd0b2f403ef3657471b79a
[moodle.git] /
1 /*
2 Adobe Systems Incorporated(r) Source Code License Agreement
3 Copyright(c) 2005 Adobe Systems Incorporated. All rights reserved.
4         
5 Please read this Source Code License Agreement carefully before using
6 the source code.
7         
8 Adobe Systems Incorporated grants to you a perpetual, worldwide, non-exclusive,
9 no-charge, royalty-free, irrevocable copyright license, to reproduce,
10 prepare derivative works of, publicly display, publicly perform, and
11 distribute this source code and such derivative works in source or
12 object code form without any attribution requirements.
13         
14 The name "Adobe Systems Incorporated" must not be used to endorse or promote products
15 derived from the source code without prior written permission.
16         
17 You agree to indemnify, hold harmless and defend Adobe Systems Incorporated from and
18 against any loss, damage, claims or lawsuits, including attorney's
19 fees that arise or result from your use or distribution of the source
20 code.
21         
22 THIS SOURCE CODE IS PROVIDED "AS IS" AND "WITH ALL FAULTS", WITHOUT
23 ANY TECHNICAL SUPPORT OR ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
24 BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ALSO, THERE IS NO WARRANTY OF
26 NON-INFRINGEMENT, TITLE OR QUIET ENJOYMENT. IN NO EVENT SHALL MACROMEDIA
27 OR ITS SUPPLIERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
30 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOURCE CODE, EVEN IF
33 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35
36 package com.adobe.serialization.json {
37
38       /**
39        * @private
40        */
41         public class JSONDecoder {
42                 
43                 /** The object that will get parsed from the JSON string */
44                 private var obj:Object;
45                 
46                 /** The tokenizer designated to read the JSON string */
47                 private var tokenizer:JSONTokenizer;
48                 
49                 /** The current token from the tokenizer */
50                 private var token:JSONToken;
51                 
52                 /**
53                  * Constructs a new JSONDecoder to parse a JSON string 
54                  * into a native object.
55                  *
56                  * @param s The JSON string to be converted
57                  *              into a native object
58                  * @langversion ActionScript 3.0
59                  * @playerversion Flash 8.5
60                  * @tiptext
61                  */
62                 public function JSONDecoder( s:String ) {
63                         
64                         tokenizer = new JSONTokenizer( s );
65                         
66                         nextToken();
67                         obj = parseValue();
68                         
69                 }
70                 
71                 /**
72                  * Gets the internal object that was created by parsing
73                  * the JSON string passed to the constructor.
74                  *
75                  * @return The internal object representation of the JSON
76                  *              string that was passed to the constructor
77                  * @langversion ActionScript 3.0
78                  * @playerversion Flash 8.5
79                  * @tiptext
80                  */
81                 public function getObject():Object {
82                         
83                         return obj;
84                 }
85                 
86                 /**
87                  * Returns the next token from the tokenzier reading
88                  * the JSON string
89                  */
90                 private function nextToken():JSONToken {
91                         return token = tokenizer.getNextToken();
92                 }
93                 
94                 /**
95                  * Attempt to parse an array
96                  */
97                 private function parseArray():Array {
98                         // create an array internally that we're going to attempt
99                         // to parse from the tokenizer
100                         var a:Array = new Array();
101                         
102                         // grab the next token from the tokenizer to move
103                         // past the opening [
104                         nextToken();
105                         
106                         // check to see if we have an empty array
107                         if ( token.type == JSONTokenType.RIGHT_BRACKET ) {
108                                 // we're done reading the array, so return it
109                                 return a;
110                         }
111                         
112                         // deal with elements of the array, and use an "infinite"
113                         // loop because we could have any amount of elements
114                         while ( true ) {
115                                 // read in the value and add it to the array
116                                 a.push ( parseValue() );
117                         
118                                 // after the value there should be a ] or a ,
119                                 nextToken();
120                                 
121                                 if ( token.type == JSONTokenType.RIGHT_BRACKET ) {
122                                         // we're done reading the array, so return it
123                                         return a;
124                                 } else if ( token.type == JSONTokenType.COMMA ) {
125                                         // move past the comma and read another value
126                                         nextToken();
127                                 } else {
128                                         tokenizer.parseError( "Expecting ] or , but found " + token.value );
129                                 }
130                         }
131             return null;
132                 }
133                 
134                 /**
135                  * Attempt to parse an object
136                  */
137                 private function parseObject():Object {
138                         // create the object internally that we're going to
139                         // attempt to parse from the tokenizer
140                         var o:Object = new Object();
141                                                 
142                         // store the string part of an object member so
143                         // that we can assign it a value in the object
144                         var key:String
145                         
146                         // grab the next token from the tokenizer
147                         nextToken();
148                         
149                         // check to see if we have an empty object
150                         if ( token.type == JSONTokenType.RIGHT_BRACE ) {
151                                 // we're done reading the object, so return it
152                                 return o;
153                         }
154                         
155                         // deal with members of the object, and use an "infinite"
156                         // loop because we could have any amount of members
157                         while ( true ) {
158                         
159                                 if ( token.type == JSONTokenType.STRING ) {
160                                         // the string value we read is the key for the object
161                                         key = String( token.value );
162                                         
163                                         // move past the string to see what's next
164                                         nextToken();
165                                         
166                                         // after the string there should be a :
167                                         if ( token.type == JSONTokenType.COLON ) {
168                                                 
169                                                 // move past the : and read/assign a value for the key
170                                                 nextToken();
171                                                 o[key] = parseValue();  
172                                                 
173                                                 // move past the value to see what's next
174                                                 nextToken();
175                                                 
176                                                 // after the value there's either a } or a ,
177                                                 if ( token.type == JSONTokenType.RIGHT_BRACE ) {
178                                                         // // we're done reading the object, so return it
179                                                         return o;
180                                                         
181                                                 } else if ( token.type == JSONTokenType.COMMA ) {
182                                                         // skip past the comma and read another member
183                                                         nextToken();
184                                                 } else {
185                                                         tokenizer.parseError( "Expecting } or , but found " + token.value );
186                                                 }
187                                         } else {
188                                                 tokenizer.parseError( "Expecting : but found " + token.value );
189                                         }
190                                 } else {
191                                         tokenizer.parseError( "Expecting string but found " + token.value );
192                                 }
193                         }
194             return null;
195                 }
196                 
197                 /**
198                  * Attempt to parse a value
199                  */
200                 private function parseValue():Object {
201                                         
202                         switch ( token.type ) {
203                                 case JSONTokenType.LEFT_BRACE:
204                                         return parseObject();
205                                         
206                                 case JSONTokenType.LEFT_BRACKET:
207                                         return parseArray();
208                                         
209                                 case JSONTokenType.STRING:
210                                 case JSONTokenType.NUMBER:
211                                 case JSONTokenType.TRUE:
212                                 case JSONTokenType.FALSE:
213                                 case JSONTokenType.NULL:
214                                         return token.value;
215
216                                 default:
217                                         tokenizer.parseError( "Unexpected " + token.value );
218                                         
219                         }
220             return null;
221                 }
222         }
223 }