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