blob: 87d36ec84087e43ab27476b385861b7fb355d726 [file] [log] [blame]
Meki Cherkaouif441d3a2012-04-22 15:17:52 -07001/*
2 * This class is used to encode and decode binary elements ( blog, type/value pairs)
3 *
4 * @author: ucla-cs
Jeff Thompson745026e2012-10-13 12:49:20 -07005 * See COPYING for copyright and distribution information.
Meki Cherkaouif441d3a2012-04-22 15:17:52 -07006 */
7var XML_EXT = 0x00;
8
9var XML_TAG = 0x01;
10
11var XML_DTAG = 0x02;
12
13var XML_ATTR = 0x03;
14
15var XML_DATTR = 0x04;
16
17var XML_BLOB = 0x05;
18
19var XML_UDATA = 0x06;
20
21var XML_CLOSE = 0x0;
22
23var XML_SUBTYPE_PROCESSING_INSTRUCTIONS = 16;
24
25
26var XML_TT_BITS = 3;
27var XML_TT_MASK = ((1 << XML_TT_BITS) - 1);
28var XML_TT_VAL_BITS = XML_TT_BITS + 1;
29var XML_TT_VAL_MASK = ((1 << (XML_TT_VAL_BITS)) - 1);
30var XML_REG_VAL_BITS = 7;
31var XML_REG_VAL_MASK = ((1 << XML_REG_VAL_BITS) - 1);
32var XML_TT_NO_MORE = (1 << XML_REG_VAL_BITS); // 0x80
33var BYTE_MASK = 0xFF;
34var LONG_BYTES = 8;
35var LONG_BITS = 64;
36
37var bits_11 = 0x0000007FF;
38var bits_18 = 0x00003FFFF;
39var bits_32 = 0x0FFFFFFFF;
40
41
42var TypeAndVal = function TypeAndVal(_type,_val) {
43 this.type = _type;
44 this.val = _val;
45
46};
47
48var BinaryXMLCodec = function BinaryXMLCodec(){
49 this.CODEC_NAME = "Binary";
50};
51
52
53
54BinaryXMLCodec.prototype.encodeTypeAndValOffset = function(
55 //int
56 type,
57 //long
58 val,
59 //byte []
60 buf,
61 //int
62 offset) {
63
64 if ((type > XML_UDATA) || (type < 0) || (val < 0)) {
Jeff Thompson34a2ec02012-09-29 21:47:05 -070065 throw new Error("Tag and value must be positive, and tag valid.");
Meki Cherkaouif441d3a2012-04-22 15:17:52 -070066 }
67
68 // Encode backwards. Calculate how many bytes we need:
69 var/*int*/ numEncodingBytes = numEncodingBytes(val);
70
71 if ((offset + numEncodingBytes) > buf.length) {
Jeff Thompson34a2ec02012-09-29 21:47:05 -070072 throw new Error("Buffer space of " + (buf.length-offset) +
Meki Cherkaouif441d3a2012-04-22 15:17:52 -070073 " bytes insufficient to hold " +
74 numEncodingBytes + " of encoded type and value.");
75 }
76
77
78 buf[offset + numEncodingBytes - 1] =
79 (BYTE_MASK &
80 (((XML_TT_MASK & type) |
81 ((XML_TT_VAL_MASK & val) << XML_TT_BITS))) |
82 XML_TT_NO_MORE);
83 val = val >>> XML_TT_VAL_BITS;;
84
85 var /*int*/ i = offset + numEncodingBytes - 2;
86 while ((0 != val) && (i >= offset)) {
87 buf[i] = (BYTE_MASK &
88 (val & XML_REG_VAL_MASK));
89 val = val >>> XML_REG_VAL_BITS;
90 --i;
91 }
92
93 return numEncodingBytes;
94};
95
96
97BinaryXMLCodec.prototype.encodeTypeAndVal = function(
98 //int
99 type,
100 //long
101 val,
102 //byte []
103 buf,
104 //int
105 offset) {
106
107 if ((type > XML_UDATA) || (type < 0) || (val < 0)) {
Jeff Thompson34a2ec02012-09-29 21:47:05 -0700108 throw new Error("Tag and value must be positive, and tag valid.");
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700109 }
110
111 // Encode backwards. Calculate how many bytes we need:
112 //int
113 var numEncodingBytes = numEncodingBytes(val);
114
115 if ((offset + numEncodingBytes) > buf.length) {
Jeff Thompson34a2ec02012-09-29 21:47:05 -0700116 throw new Error("Buffer space of " + (buf.length-offset) +
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700117 " bytes insufficient to hold " +
118 numEncodingBytes + " of encoded type and value.");
119 }
120
121 // Bottom 4 bits of val go in last byte with tag.
122 buf[offset + numEncodingBytes - 1] =
123 //(byte)
124 (BYTE_MASK &
125 (((XML_TT_MASK & type) |
126 ((XML_TT_VAL_MASK & val) << XML_TT_BITS))) |
127 XML_TT_NO_MORE); // set top bit for last byte
128 val = val >>> XML_TT_VAL_BITS;;
129
130 // Rest of val goes into preceding bytes, 7 bits per byte, top bit
131 // is "more" flag.
132 var i = offset + numEncodingBytes - 2;
133 while ((0 != val) && (i >= offset)) {
134 buf[i] = //(byte)
135 (BYTE_MASK &
136 (val & XML_REG_VAL_MASK)); // leave top bit unset
137 val = val >>> XML_REG_VAL_BITS;
138 --i;
139 }
140 if (val != 0) {
Jeff Thompson34a2ec02012-09-29 21:47:05 -0700141 throw new Error( "This should not happen: miscalculated encoding");
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700142 //Log.warning(Log.FAC_ENCODING, "This should not happen: miscalculated encoding length, have " + val + " left.");
143 }
144
145 return numEncodingBytes;
146}
147
148
149
150BinaryXMLCodec.prototype.decodeTypeAndVal = function(
151 /*InputStream*/
152 istream) {
153
154 /*int*/next;
155 /*int*/type = -1;
156 /*long*/val = 0;
157 /*boolean*/more = true;
158
159 do {
160 next = istream.read();
161
162 if (next < 0) {
163 return null;
164 }
165
166 if ((0 == next) && (0 == val)) {
167 return null;
168 }
169
170 more = (0 == (next & XML_TT_NO_MORE));
171
172 if (more) {
173 val = val << XML_REG_VAL_BITS;
174 val |= (next & XML_REG_VAL_MASK);
175 } else {
176
177 type = next & XML_TT_MASK;
178 val = val << XML_TT_VAL_BITS;
179 val |= ((next >>> XML_TT_BITS) & XML_TT_VAL_MASK);
180 }
181
182 } while (more);
183
184 return new TypeAndVal(type, val);
185};
186
187BinaryXMLCodec.prototype.encodeUString = function(
188 //OutputStream
189 ostream,
190 //String
191 ustring,
192 //byte
193 type,
194 offset) {
195
196 // We elide the encoding of a 0-length UString
197 if ((null == ustring) || (ustring.length == 0)) {
198 //if (Log.isLoggable(Log.FAC_ENCODING, Level.FINER))
199 //Log.finer(Log.FAC_ENCODING, "Eliding 0-length UString.");
200 return;
201 }
202
203 //byte [] data utils
204 /*custom*/
205 //byte[]
206 strBytes = new Array(ustring.Length);
207 var i = 0;
208 for( ;i<ustring.lengh;i++) //in InStr.ToCharArray())
209 {
210 strBytes[i] = ustring[i];
211 }
212 //strBytes = DataUtils.getBytesFromUTF8String(ustring);
213
214 this.encodeTypeAndVal(type,
215 (((type == XML_TAG) || (type == XML_ATTR)) ?
216 (strBytes.length-1) :
217 strBytes.length), ostream);
218 //
219 //console.log(strBytes.toString());
220
221 ostream.write(strBytes.toString(),offset);
222
223 //
224};
225
226BinaryXMLCodec.prototype.encodeBlob = function(
227 //OutputStream
228 ostream,
229 //byte []
230 blob,
231 //int
232 offset,
233 //int
234 length) {
235 // We elide the encoding of a 0-length blob
236 if ((null == blob) || (length == 0)) {
237
238 return;
239 }
240
241 encodeTypeAndVal(XML_BLOB, length, ostream,offset);
242 if (null != blob) {
243 ostream.write(blob, this.offset, length);
244 this.offset += length;
245 }
246};
247
248
249var ENCODING_LIMIT_1_BYTE = ((1 << (XML_TT_VAL_BITS)) - 1);
250var ENCODING_LIMIT_2_BYTES = ((1 << (XML_TT_VAL_BITS + XML_REG_VAL_BITS)) - 1);
251var ENCODING_LIMIT_3_BYTES = ((1 << (XML_TT_VAL_BITS + 2 * XML_REG_VAL_BITS)) - 1);
252
253var numEncodingBytes = function(
254 //long
255 x) {
256 if (x <= ENCODING_LIMIT_1_BYTE) return (1);
257 if (x <= ENCODING_LIMIT_2_BYTES) return (2);
258 if (x <= ENCODING_LIMIT_3_BYTES) return (3);
259
260 var numbytes = 1;
261
262 // Last byte gives you XML_TT_VAL_BITS
263 // Remainder each give you XML_REG_VAL_BITS
264 x = x >>> XML_TT_VAL_BITS;
265 while (x != 0) {
266 numbytes++;
267 x = x >>> XML_REG_VAL_BITS;
268 }
269 return (numbytes);
270}
271
272//TODO