Bug:Fix file validation issue
[vnfsdk/refrepo.git] / vnfmarket / src / main / webapp / vnfmarket / node_modules / redis / lib / parser / javascript.js
1 /*global Buffer require exports console setTimeout */
2
3 // TODO - incorporate these V8 pro tips:
4 //    pre-allocate Arrays if length is known in advance
5 //    do not use delete
6 //    use numbers for parser state
7
8 var events = require("events"),
9     util = require("../util");
10
11 exports.debug_mode = false;
12 exports.name = "javascript";
13
14 function RedisReplyParser(options) {
15     this.name = exports.name;
16     this.options = options || {};
17     this.reset();
18     events.EventEmitter.call(this);
19 }
20
21 util.inherits(RedisReplyParser, events.EventEmitter);
22
23 exports.Parser = RedisReplyParser;
24
25 // Buffer.toString() is quite slow for small strings
26 function small_toString(buf, len) {
27     var tmp = "", i;
28
29     for (i = 0; i < len; i += 1) {
30         tmp += String.fromCharCode(buf[i]);
31     }
32
33     return tmp;
34 }
35
36 // Reset parser to it's original state.
37 RedisReplyParser.prototype.reset = function () {
38     this.return_buffer = new Buffer(16384); // for holding replies, might grow
39     this.return_string = "";
40     this.tmp_string = ""; // for holding size fields
41
42     this.multi_bulk_length = 0;
43     this.multi_bulk_replies = null;
44     this.multi_bulk_pos = 0;
45     this.multi_bulk_nested_length = 0;
46     this.multi_bulk_nested_replies = null;
47
48     this.states = {
49         TYPE: 1,
50         SINGLE_LINE: 2,
51         MULTI_BULK_COUNT: 3,
52         INTEGER_LINE: 4,
53         BULK_LENGTH: 5,
54         ERROR_LINE: 6,
55         BULK_DATA: 7,
56         UNKNOWN_TYPE: 8,
57         FINAL_CR: 9,
58         FINAL_LF: 10,
59         MULTI_BULK_COUNT_LF: 11,
60         BULK_LF: 12
61     };
62     
63     this.state = this.states.TYPE;
64 };
65
66 RedisReplyParser.prototype.parser_error = function (message) {
67     this.emit("error", message);
68     this.reset();
69 };
70
71 RedisReplyParser.prototype.execute = function (incoming_buf) {
72     var pos = 0, bd_tmp, bd_str, i, il, states = this.states;
73     //, state_times = {}, start_execute = new Date(), start_switch, end_switch, old_state;
74     //start_switch = new Date();
75
76     while (pos < incoming_buf.length) {
77         // old_state = this.state;
78         // console.log("execute: " + this.state + ", " + pos + "/" + incoming_buf.length + ", " + String.fromCharCode(incoming_buf[pos]));
79
80         switch (this.state) {
81         case 1: // states.TYPE
82             this.type = incoming_buf[pos];
83             pos += 1;
84
85             switch (this.type) {
86             case 43: // +
87                 this.state = states.SINGLE_LINE;
88                 this.return_buffer.end = 0;
89                 this.return_string = "";
90                 break;
91             case 42: // *
92                 this.state = states.MULTI_BULK_COUNT;
93                 this.tmp_string = "";
94                 break;
95             case 58: // :
96                 this.state = states.INTEGER_LINE;
97                 this.return_buffer.end = 0;
98                 this.return_string = "";
99                 break;
100             case 36: // $
101                 this.state = states.BULK_LENGTH;
102                 this.tmp_string = "";
103                 break;
104             case 45: // -
105                 this.state = states.ERROR_LINE;
106                 this.return_buffer.end = 0;
107                 this.return_string = "";
108                 break;
109             default:
110                 this.state = states.UNKNOWN_TYPE;
111             }
112             break;
113         case 4: // states.INTEGER_LINE
114             if (incoming_buf[pos] === 13) {
115                 this.send_reply(+small_toString(this.return_buffer, this.return_buffer.end));
116                 this.state = states.FINAL_LF;
117             } else {
118                 this.return_buffer[this.return_buffer.end] = incoming_buf[pos];
119                 this.return_buffer.end += 1;
120             }
121             pos += 1;
122             break;
123         case 6: // states.ERROR_LINE
124             if (incoming_buf[pos] === 13) {
125                 this.send_error(this.return_buffer.toString("ascii", 0, this.return_buffer.end));
126                 this.state = states.FINAL_LF;
127             } else {
128                 this.return_buffer[this.return_buffer.end] = incoming_buf[pos];
129                 this.return_buffer.end += 1;
130             }
131             pos += 1;
132             break;
133         case 2: // states.SINGLE_LINE
134             if (incoming_buf[pos] === 13) {
135                 this.send_reply(this.return_string);
136                 this.state = states.FINAL_LF;
137             } else {
138                 this.return_string += String.fromCharCode(incoming_buf[pos]);
139             }
140             pos += 1;
141             break;
142         case 3: // states.MULTI_BULK_COUNT
143             if (incoming_buf[pos] === 13) { // \r
144                 this.state = states.MULTI_BULK_COUNT_LF;
145             } else {
146                 this.tmp_string += String.fromCharCode(incoming_buf[pos]);
147             }
148             pos += 1;
149             break;
150         case 11: // states.MULTI_BULK_COUNT_LF
151             if (incoming_buf[pos] === 10) { // \n
152                 if (this.multi_bulk_length) { // nested multi-bulk
153                     this.multi_bulk_nested_length = this.multi_bulk_length;
154                     this.multi_bulk_nested_replies = this.multi_bulk_replies;
155                     this.multi_bulk_nested_pos = this.multi_bulk_pos;
156                 }
157                 this.multi_bulk_length = +this.tmp_string;
158                 this.multi_bulk_pos = 0;
159                 this.state = states.TYPE;
160                 if (this.multi_bulk_length < 0) {
161                     this.send_reply(null);
162                     this.multi_bulk_length = 0;
163                 } else if (this.multi_bulk_length === 0) {
164                     this.multi_bulk_pos = 0;
165                     this.multi_bulk_replies = null;
166                     this.send_reply([]);
167                 } else {
168                     this.multi_bulk_replies = new Array(this.multi_bulk_length);
169                 }
170             } else {
171                 this.parser_error(new Error("didn't see LF after NL reading multi bulk count"));
172                 return;
173             }
174             pos += 1;
175             break;
176         case 5: // states.BULK_LENGTH
177             if (incoming_buf[pos] === 13) { // \r
178                 this.state = states.BULK_LF;
179             } else {
180                 this.tmp_string += String.fromCharCode(incoming_buf[pos]);
181             }
182             pos += 1;
183             break;
184         case 12: // states.BULK_LF
185             if (incoming_buf[pos] === 10) { // \n
186                 this.bulk_length = +this.tmp_string;
187                 if (this.bulk_length === -1) {
188                     this.send_reply(null);
189                     this.state = states.TYPE;
190                 } else if (this.bulk_length === 0) {
191                     this.send_reply(new Buffer(""));
192                     this.state = states.FINAL_CR;
193                 } else {
194                     this.state = states.BULK_DATA;
195                     if (this.bulk_length > this.return_buffer.length) {
196                         if (exports.debug_mode) {
197                             console.log("Growing return_buffer from " + this.return_buffer.length + " to " + this.bulk_length);
198                         }
199                         this.return_buffer = new Buffer(this.bulk_length);
200                     }
201                     this.return_buffer.end = 0;
202                 }
203             } else {
204                 this.parser_error(new Error("didn't see LF after NL while reading bulk length"));
205                 return;
206             }
207             pos += 1;
208             break;
209         case 7: // states.BULK_DATA
210             this.return_buffer[this.return_buffer.end] = incoming_buf[pos];
211             this.return_buffer.end += 1;
212             pos += 1;
213             if (this.return_buffer.end === this.bulk_length) {
214                 bd_tmp = new Buffer(this.bulk_length);
215                 // When the response is small, Buffer.copy() is a lot slower.
216                 if (this.bulk_length > 10) {
217                     this.return_buffer.copy(bd_tmp, 0, 0, this.bulk_length);
218                 } else {
219                     for (i = 0, il = this.bulk_length; i < il; i += 1) {
220                         bd_tmp[i] = this.return_buffer[i];
221                     }
222                 }
223                 this.send_reply(bd_tmp);
224                 this.state = states.FINAL_CR;
225             }
226             break;
227         case 9: // states.FINAL_CR
228             if (incoming_buf[pos] === 13) { // \r
229                 this.state = states.FINAL_LF;
230                 pos += 1;
231             } else {
232                 this.parser_error(new Error("saw " + incoming_buf[pos] + " when expecting final CR"));
233                 return;
234             }
235             break;
236         case 10: // states.FINAL_LF
237             if (incoming_buf[pos] === 10) { // \n
238                 this.state = states.TYPE;
239                 pos += 1;
240             } else {
241                 this.parser_error(new Error("saw " + incoming_buf[pos] + " when expecting final LF"));
242                 return;
243             }
244             break;
245         default:
246             this.parser_error(new Error("invalid state " + this.state));
247         }
248         // end_switch = new Date();
249         // if (state_times[old_state] === undefined) {
250         //     state_times[old_state] = 0;
251         // }
252         // state_times[old_state] += (end_switch - start_switch);
253         // start_switch = end_switch;
254     }
255     // console.log("execute ran for " + (Date.now() - start_execute) + " ms, on " + incoming_buf.length + " Bytes. ");
256     // Object.keys(state_times).forEach(function (state) {
257     //     console.log("    " + state + ": " + state_times[state]);
258     // });
259 };
260
261 RedisReplyParser.prototype.send_error = function (reply) {
262     if (this.multi_bulk_length > 0 || this.multi_bulk_nested_length > 0) {
263         // TODO - can this happen?  Seems like maybe not.
264         this.add_multi_bulk_reply(reply);
265     } else {
266         this.emit("reply error", reply);
267     }
268 };
269
270 RedisReplyParser.prototype.send_reply = function (reply) {
271     if (this.multi_bulk_length > 0 || this.multi_bulk_nested_length > 0) {
272         if (!this.options.return_buffers && Buffer.isBuffer(reply)) {
273             this.add_multi_bulk_reply(reply.toString("utf8"));
274         } else {
275             this.add_multi_bulk_reply(reply);
276         }
277     } else {
278         if (!this.options.return_buffers && Buffer.isBuffer(reply)) {
279             this.emit("reply", reply.toString("utf8"));
280         } else {
281             this.emit("reply", reply);
282         }
283     }
284 };
285
286 RedisReplyParser.prototype.add_multi_bulk_reply = function (reply) {
287     if (this.multi_bulk_replies) {
288         this.multi_bulk_replies[this.multi_bulk_pos] = reply;
289         this.multi_bulk_pos += 1;
290         if (this.multi_bulk_pos < this.multi_bulk_length) {
291             return;
292         }
293     } else {
294         this.multi_bulk_replies = reply;
295     }
296
297     if (this.multi_bulk_nested_length > 0) {
298         this.multi_bulk_nested_replies[this.multi_bulk_nested_pos] = this.multi_bulk_replies;
299         this.multi_bulk_nested_pos += 1;
300
301         this.multi_bulk_length = 0;
302         this.multi_bulk_replies = null;
303         this.multi_bulk_pos = 0;
304
305         if (this.multi_bulk_nested_length === this.multi_bulk_nested_pos) {
306             this.emit("reply", this.multi_bulk_nested_replies);
307             this.multi_bulk_nested_length = 0;
308             this.multi_bulk_nested_pos = 0;
309             this.multi_bulk_nested_replies = null;
310         }
311     } else {
312         this.emit("reply", this.multi_bulk_replies);
313         this.multi_bulk_length = 0;
314         this.multi_bulk_replies = null;
315         this.multi_bulk_pos = 0;
316     }
317 };