|
1 # This Source Code Form is subject to the terms of the Mozilla Public |
|
2 # License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 # file, You can obtain one at http://mozilla.org/MPL/2.0/. |
|
4 |
|
5 |
|
6 // A helper class that knows how to parse from and serialize to |
|
7 // protocol4. This is a simple, historical format used by some Google |
|
8 // interfaces, for example the Toolbar (i.e., ancient services). |
|
9 // |
|
10 // Protocol4 consists of a newline-separated sequence of name/value |
|
11 // pairs (strings). Each line consists of the name, the value length, |
|
12 // and the value itself, all separated by colons. Example: |
|
13 // |
|
14 // foo:6:barbaz\n |
|
15 // fritz:33:issickofdynamicallytypedlanguages\n |
|
16 |
|
17 |
|
18 /** |
|
19 * This class knows how to serialize/deserialize maps to/from their |
|
20 * protocol4 representation. |
|
21 * |
|
22 * @constructor |
|
23 */ |
|
24 function G_Protocol4Parser() { |
|
25 this.debugZone = "protocol4"; |
|
26 |
|
27 this.protocol4RegExp_ = new RegExp("([^:]+):\\d+:(.*)$"); |
|
28 this.newlineRegExp_ = new RegExp("(\\r)?\\n"); |
|
29 } |
|
30 |
|
31 /** |
|
32 * Create a map from a protocol4 string. Silently skips invalid lines. |
|
33 * |
|
34 * @param text String holding the protocol4 representation |
|
35 * |
|
36 * @returns Object as an associative array with keys and values |
|
37 * given in text. The empty object is returned if none |
|
38 * are parsed. |
|
39 */ |
|
40 G_Protocol4Parser.prototype.parse = function(text) { |
|
41 |
|
42 var response = {}; |
|
43 if (!text) |
|
44 return response; |
|
45 |
|
46 // Responses are protocol4: (repeated) name:numcontentbytes:content\n |
|
47 var lines = text.split(this.newlineRegExp_); |
|
48 for (var i = 0; i < lines.length; i++) |
|
49 if (this.protocol4RegExp_.exec(lines[i])) |
|
50 response[RegExp.$1] = RegExp.$2; |
|
51 |
|
52 return response; |
|
53 } |
|
54 |
|
55 /** |
|
56 * Create a protocol4 string from a map (object). Throws an error on |
|
57 * an invalid input. |
|
58 * |
|
59 * @param map Object as an associative array with keys and values |
|
60 * given as strings. |
|
61 * |
|
62 * @returns text String holding the protocol4 representation |
|
63 */ |
|
64 G_Protocol4Parser.prototype.serialize = function(map) { |
|
65 if (typeof map != "object") |
|
66 throw new Error("map must be an object"); |
|
67 |
|
68 var text = ""; |
|
69 for (var key in map) { |
|
70 if (typeof map[key] != "string") |
|
71 throw new Error("Keys and values must be strings"); |
|
72 |
|
73 text += key + ":" + map[key].length + ":" + map[key] + "\n"; |
|
74 } |
|
75 |
|
76 return text; |
|
77 } |
|
78 |
|
79 #ifdef DEBUG |
|
80 /** |
|
81 * Cheesey unittests |
|
82 */ |
|
83 function TEST_G_Protocol4Parser() { |
|
84 if (G_GDEBUG) { |
|
85 var z = "protocol4 UNITTEST"; |
|
86 G_debugService.enableZone(z); |
|
87 |
|
88 G_Debug(z, "Starting"); |
|
89 |
|
90 var p = new G_Protocol4Parser(); |
|
91 |
|
92 function isEmpty(map) { |
|
93 for (var key in map) |
|
94 return false; |
|
95 return true; |
|
96 }; |
|
97 |
|
98 G_Assert(z, isEmpty(p.parse(null)), "Parsing null broken"); |
|
99 G_Assert(z, isEmpty(p.parse("")), "Parsing nothing broken"); |
|
100 |
|
101 var t = "foo:3:bar"; |
|
102 G_Assert(z, p.parse(t)["foo"] === "bar", "Parsing one line broken"); |
|
103 |
|
104 t = "foo:3:bar\n"; |
|
105 G_Assert(z, p.parse(t)["foo"] === "bar", "Parsing line with lf broken"); |
|
106 |
|
107 t = "foo:3:bar\r\n"; |
|
108 G_Assert(z, p.parse(t)["foo"] === "bar", "Parsing with crlf broken"); |
|
109 |
|
110 |
|
111 t = "foo:3:bar\nbar:3:baz\r\nbom:3:yaz\n"; |
|
112 G_Assert(z, p.parse(t)["foo"] === "bar", "First in multiline"); |
|
113 G_Assert(z, p.parse(t)["bar"] === "baz", "Second in multiline"); |
|
114 G_Assert(z, p.parse(t)["bom"] === "yaz", "Third in multiline"); |
|
115 G_Assert(z, p.parse(t)[""] === undefined, "Nonexistent in multiline"); |
|
116 |
|
117 // Test serialization |
|
118 |
|
119 var original = { |
|
120 "1": "1", |
|
121 "2": "2", |
|
122 "foobar": "baz", |
|
123 "hello there": "how are you?" , |
|
124 }; |
|
125 var deserialized = p.parse(p.serialize(original)); |
|
126 for (var key in original) |
|
127 G_Assert(z, original[key] === deserialized[key], |
|
128 "Trouble (de)serializing " + key); |
|
129 |
|
130 G_Debug(z, "PASSED"); |
|
131 } |
|
132 } |
|
133 #endif |