blob: 10f6cd63006ccdada07f46abfdf2df44c90e69eb [file] [log] [blame]
Jeff Thompson47eecfc2013-07-07 22:56:46 -07001/**
Jeff Thompson7687dc02013-09-13 11:54:07 -07002 * Copyright (C) 2013 Regents of the University of California.
3 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
Jeff Thompsone5b37a52013-07-08 15:39:01 -07004 * Derived from BinaryXMLEncoder.js by Meki Cheraoui.
Jeff Thompson47eecfc2013-07-07 22:56:46 -07005 * See COPYING for copyright and distribution information.
Jeff Thompsonc8963652013-06-28 20:17:43 -07006 */
7
Jeff Thompsonedc22252013-07-11 18:05:44 -07008#include <math.h>
Jeff Thompson5a984832013-07-01 19:28:27 -07009#include "../util/ndn_memory.h"
Jeff Thompson53412192013-08-06 13:35:50 -070010#include "binary-xml.h"
11#include "binary-xml-encoder.h"
Jeff Thompson590b8692013-06-28 22:07:41 -070012
13enum {
Jeff Thompsonf0fea002013-07-30 17:22:42 -070014 ENCODING_LIMIT_1_BYTE = ((1 << ndn_BinaryXml_TT_VALUE_BITS) - 1),
15 ENCODING_LIMIT_2_BYTES = ((1 << (ndn_BinaryXml_TT_VALUE_BITS + ndn_BinaryXml_REGULAR_VALUE_BITS)) - 1),
16 ENCODING_LIMIT_3_BYTES = ((1 << (ndn_BinaryXml_TT_VALUE_BITS + 2 * ndn_BinaryXml_REGULAR_VALUE_BITS)) - 1)
Jeff Thompson590b8692013-06-28 22:07:41 -070017};
18
19/**
Jeff Thompson10ad12a2013-09-24 16:19:11 -070020 * Call ndn_DynamicUInt8Array_ensureLength to ensure that there is enough room in the output, and copy
Jeff Thompson5a984832013-07-01 19:28:27 -070021 * array to the output. This does not write a header.
Jeff Thompsonf0fea002013-07-30 17:22:42 -070022 * @param self pointer to the ndn_BinaryXmlEncoder struct
Jeff Thompson5a984832013-07-01 19:28:27 -070023 * @param array the array to copy
24 * @param arrayLength the length of the array
Jeff Thompson8b666002013-07-08 01:16:26 -070025 * @return 0 for success, else an error code
Jeff Thompson5a984832013-07-01 19:28:27 -070026 */
Jeff Thompson97223af2013-09-24 17:01:27 -070027static ndn_Error writeArray(struct ndn_BinaryXmlEncoder *self, uint8_t *array, size_t arrayLength)
Jeff Thompson5a984832013-07-01 19:28:27 -070028{
Jeff Thompson8b666002013-07-08 01:16:26 -070029 ndn_Error error;
Jeff Thompson10ad12a2013-09-24 16:19:11 -070030 if ((error = ndn_DynamicUInt8Array_ensureLength(self->output, self->offset + arrayLength)))
Jeff Thompson5a984832013-07-01 19:28:27 -070031 return error;
32
Jeff Thompsonc978a7b2013-08-12 13:17:17 -070033 ndn_memcpy(self->output->array + self->offset, array, arrayLength);
Jeff Thompson2d27e2f2013-08-09 12:55:00 -070034 self->offset += arrayLength;
Jeff Thompson5a984832013-07-01 19:28:27 -070035
Jeff Thompsonadaf9232013-08-08 14:30:29 -070036 return NDN_ERROR_success;
Jeff Thompson5a984832013-07-01 19:28:27 -070037}
38
39/**
Jeff Thompson590b8692013-06-28 22:07:41 -070040 * Return the number of bytes to encode a header of value x.
41 */
Jeff Thompson97223af2013-09-24 17:01:27 -070042static size_t getNHeaderEncodingBytes(unsigned int x)
Jeff Thompson590b8692013-06-28 22:07:41 -070043{
44 // Do a quick check for pre-compiled results.
Jeff Thompson2d27e2f2013-08-09 12:55:00 -070045 if (x <= ENCODING_LIMIT_1_BYTE)
Jeff Thompson590b8692013-06-28 22:07:41 -070046 return 1;
Jeff Thompson2d27e2f2013-08-09 12:55:00 -070047 if (x <= ENCODING_LIMIT_2_BYTES)
Jeff Thompson590b8692013-06-28 22:07:41 -070048 return 2;
Jeff Thompson2d27e2f2013-08-09 12:55:00 -070049 if (x <= ENCODING_LIMIT_3_BYTES)
Jeff Thompson590b8692013-06-28 22:07:41 -070050 return 3;
Jeff Thompson590b8692013-06-28 22:07:41 -070051
Jeff Thompson97223af2013-09-24 17:01:27 -070052 size_t nBytes = 1;
Jeff Thompson2d27e2f2013-08-09 12:55:00 -070053
54 // Last byte gives you TT_VALUE_BITS.
55 // Remainder each gives you REGULAR_VALUE_BITS.
56 x >>= ndn_BinaryXml_TT_VALUE_BITS;
57 while (x != 0) {
58 ++nBytes;
59 x >>= ndn_BinaryXml_REGULAR_VALUE_BITS;
60 }
61
62 return nBytes;
Jeff Thompson590b8692013-06-28 22:07:41 -070063}
Jeff Thompson433e6da2013-07-01 15:09:00 -070064
Jeff Thompson2c1d9212013-07-08 02:10:03 -070065/**
Jeff Thompsona259cc42013-07-08 17:14:09 -070066 * Reverse the length bytes in array.
Jeff Thompson2c1d9212013-07-08 02:10:03 -070067 * @param array
Jeff Thompson2c1d9212013-07-08 02:10:03 -070068 * @param length
69 */
Jeff Thompson97223af2013-09-24 17:01:27 -070070static void reverse(uint8_t *array, size_t length)
Jeff Thompson2c1d9212013-07-08 02:10:03 -070071{
72 if (length == 0)
73 return;
74
Jeff Thompson10ad12a2013-09-24 16:19:11 -070075 uint8_t *left = array;
76 uint8_t *right = array + length - 1;
Jeff Thompson2c1d9212013-07-08 02:10:03 -070077 while (left < right) {
78 // Swap.
Jeff Thompson10ad12a2013-09-24 16:19:11 -070079 uint8_t temp = *left;
Jeff Thompson2c1d9212013-07-08 02:10:03 -070080 *left = *right;
81 *right = temp;
82
83 ++left;
84 --right;
85 }
86}
87
88/**
Jeff Thompson10ad12a2013-09-24 16:19:11 -070089 * Write x as an unsigned decimal integer to the output with the digits in reverse order, using ndn_DynamicUInt8Array_ensureLength.
Jeff Thompson2c1d9212013-07-08 02:10:03 -070090 * This does not write a header.
Jeff Thompson1cb79eb2013-07-08 17:59:01 -070091 * We encode in reverse order, because this is the natural way to encode the digits, and the caller can reverse as needed.
Jeff Thompsonf0fea002013-07-30 17:22:42 -070092 * @param self pointer to the ndn_BinaryXmlEncoder struct
Jeff Thompson2c1d9212013-07-08 02:10:03 -070093 * @param x the unsigned int to write
94 * @return 0 for success, else an error code
95 */
Jeff Thompsonf0fea002013-07-30 17:22:42 -070096static ndn_Error encodeReversedUnsignedDecimalInt(struct ndn_BinaryXmlEncoder *self, unsigned int x)
Jeff Thompson2c1d9212013-07-08 02:10:03 -070097{
Jeff Thompson2c1d9212013-07-08 02:10:03 -070098 while (1) {
99 ndn_Error error;
Jeff Thompson10ad12a2013-09-24 16:19:11 -0700100 if ((error = ndn_DynamicUInt8Array_ensureLength(self->output, self->offset + 1)))
Jeff Thompson2c1d9212013-07-08 02:10:03 -0700101 return error;
102
Jeff Thompson10ad12a2013-09-24 16:19:11 -0700103 self->output->array[self->offset++] = (uint8_t)(x % 10 + '0');
Jeff Thompson2c1d9212013-07-08 02:10:03 -0700104 x /= 10;
105
106 if (x == 0)
107 break;
108 }
109
Jeff Thompsonadaf9232013-08-08 14:30:29 -0700110 return NDN_ERROR_success;
Jeff Thompsona259cc42013-07-08 17:14:09 -0700111}
112
113/**
Jeff Thompsonc978a7b2013-08-12 13:17:17 -0700114 * Reverse the buffer in self->output->array, then shift it right by the amount needed to prefix a header with type,
Jeff Thompson1cb79eb2013-07-08 17:59:01 -0700115 * then encode the header at startOffset.
116 * startOffser it the position in self-output.array of the first byte of the buffer and self->offset is the first byte past the end.
117 * We reverse and shift in the same function to avoid unnecessary copying if we first reverse then shift.
Jeff Thompsonf0fea002013-07-30 17:22:42 -0700118 * @param self pointer to the ndn_BinaryXmlEncoder struct
Jeff Thompsonc978a7b2013-08-12 13:17:17 -0700119 * @param startOffset the offset in self->output->array of the start of the buffer to shift right
Jeff Thompsona259cc42013-07-08 17:14:09 -0700120 * @param type the header type
121 * @return 0 for success, else an error code
122 */
Jeff Thompson1cb79eb2013-07-08 17:59:01 -0700123static ndn_Error reverseBufferAndInsertHeader
Jeff Thompson97223af2013-09-24 17:01:27 -0700124 (struct ndn_BinaryXmlEncoder *self, size_t startOffset, unsigned int type)
Jeff Thompsona259cc42013-07-08 17:14:09 -0700125{
Jeff Thompson97223af2013-09-24 17:01:27 -0700126 size_t nBufferBytes = self->offset - startOffset;
127 size_t nHeaderBytes = getNHeaderEncodingBytes(nBufferBytes);
Jeff Thompsona259cc42013-07-08 17:14:09 -0700128 ndn_Error error;
Jeff Thompson10ad12a2013-09-24 16:19:11 -0700129 if ((error = ndn_DynamicUInt8Array_ensureLength(self->output, self->offset + nHeaderBytes)))
Jeff Thompsona259cc42013-07-08 17:14:09 -0700130 return error;
131
Jeff Thompson1cb79eb2013-07-08 17:59:01 -0700132 // To reverse and shift at the same time, we first shift nHeaderBytes to the destination while reversing,
133 // then reverse the remaining bytes in place.
Jeff Thompson10ad12a2013-09-24 16:19:11 -0700134 uint8_t *from = self->output->array + startOffset;
135 uint8_t *fromEnd = from + nHeaderBytes;
136 uint8_t *to = self->output->array + startOffset + nBufferBytes + nHeaderBytes - 1;
Jeff Thompson1cb79eb2013-07-08 17:59:01 -0700137 while (from < fromEnd)
138 *(to--) = *(from++);
139 // Reverse the remaining bytes in place (if any).
140 if (nBufferBytes > nHeaderBytes)
Jeff Thompsonc978a7b2013-08-12 13:17:17 -0700141 reverse(self->output->array + startOffset + nHeaderBytes, nBufferBytes - nHeaderBytes);
Jeff Thompsona259cc42013-07-08 17:14:09 -0700142
143 // Override the offset to force encodeTypeAndValue to encode at startOffset, then fix the offset.
144 self->offset = startOffset;
Jeff Thompsonb123be62013-08-08 21:13:19 -0700145 if ((error = ndn_BinaryXmlEncoder_encodeTypeAndValue(self, type, nBufferBytes)))
Jeff Thompsona259cc42013-07-08 17:14:09 -0700146 // We don't really expect to get an error, since we have already ensured the length.
147 return error;
148 self->offset = startOffset + nHeaderBytes + nBufferBytes;
149
Jeff Thompsonadaf9232013-08-08 14:30:29 -0700150 return NDN_ERROR_success;
Jeff Thompson2c1d9212013-07-08 02:10:03 -0700151}
152
Jeff Thompsonedc22252013-07-11 18:05:44 -0700153/**
Jeff Thompson62d8d8f2013-08-12 17:02:24 -0700154 * Split the absolute value of x, rounded to an integer into 32 bit unsigned integers hi32 and lo32.
Jeff Thompsonedc22252013-07-11 18:05:44 -0700155 * We need this because not all C compilers support 64 bit long long integers, so we carry around
156 * a high precision value as a double, which we assume has more than 32 bits.
157 * But we want to do bit-wise operations on integers.
158 * @param x the double value
159 * @param hi32 output the high 32 bits
160 * @param lo32 output the low 32 bits
161 */
162static inline void splitAbsDouble(double x, unsigned long *hi32, unsigned long *lo32)
163{
164 if (x < 0)
165 x = -x;
166 x = round(x);
167
168 double twoPower32 = 4294967296.0;
169 double lo32Double = fmod(x, twoPower32);
170 *lo32 = (unsigned long)lo32Double;
171 *hi32 = (unsigned long)((x - lo32Double) / twoPower32);
172}
173
Jeff Thompsonf0fea002013-07-30 17:22:42 -0700174ndn_Error ndn_BinaryXmlEncoder_encodeTypeAndValue(struct ndn_BinaryXmlEncoder *self, unsigned int type, unsigned int value)
Jeff Thompson433e6da2013-07-01 15:09:00 -0700175{
Jeff Thompson2d27e2f2013-08-09 12:55:00 -0700176 if (type > ndn_BinaryXml_UDATA)
177 return NDN_ERROR_header_type_is_out_of_range;
Jeff Thompson433e6da2013-07-01 15:09:00 -0700178
Jeff Thompson2d27e2f2013-08-09 12:55:00 -0700179 // Encode backwards. Calculate how many bytes we need.
Jeff Thompson97223af2013-09-24 17:01:27 -0700180 size_t nEncodingBytes = getNHeaderEncodingBytes(value);
Jeff Thompson8b666002013-07-08 01:16:26 -0700181 ndn_Error error;
Jeff Thompson10ad12a2013-09-24 16:19:11 -0700182 if ((error = ndn_DynamicUInt8Array_ensureLength(self->output, self->offset + nEncodingBytes)))
Jeff Thompson433e6da2013-07-01 15:09:00 -0700183 return error;
184
Jeff Thompson2d27e2f2013-08-09 12:55:00 -0700185 // Bottom 4 bits of value go in last byte with tag.
Jeff Thompsonc978a7b2013-08-12 13:17:17 -0700186 self->output->array[self->offset + nEncodingBytes - 1] =
Jeff Thompson2d27e2f2013-08-09 12:55:00 -0700187 (ndn_BinaryXml_TT_MASK & type |
188 ((ndn_BinaryXml_TT_VALUE_MASK & value) << ndn_BinaryXml_TT_BITS)) |
189 ndn_BinaryXml_TT_FINAL; // set top bit for last byte
190 value >>= ndn_BinaryXml_TT_VALUE_BITS;
191
192 // Rest of value goes into preceding bytes, 7 bits per byte. (Zero top bit is "more" flag.)
Jeff Thompson97223af2013-09-24 17:01:27 -0700193 size_t i = self->offset + nEncodingBytes - 2;
Jeff Thompson2d27e2f2013-08-09 12:55:00 -0700194 while (value != 0 && i >= self->offset) {
Jeff Thompsonc978a7b2013-08-12 13:17:17 -0700195 self->output->array[i] = (value & ndn_BinaryXml_REGULAR_VALUE_MASK);
Jeff Thompson2d27e2f2013-08-09 12:55:00 -0700196 value >>= ndn_BinaryXml_REGULAR_VALUE_BITS;
197 --i;
198 }
199 if (value != 0)
Jeff Thompsone2276892013-07-08 02:44:18 -0700200 // This should not happen if getNHeaderEncodingBytes is correct.
Jeff Thompson2d27e2f2013-08-09 12:55:00 -0700201 return NDN_ERROR_encodeTypeAndValue_miscalculated_N_encoding_bytes;
202
203 self->offset+= nEncodingBytes;
Jeff Thompson433e6da2013-07-01 15:09:00 -0700204
Jeff Thompsonadaf9232013-08-08 14:30:29 -0700205 return NDN_ERROR_success;
Jeff Thompson433e6da2013-07-01 15:09:00 -0700206}
Jeff Thompson5a984832013-07-01 19:28:27 -0700207
Jeff Thompsonf0fea002013-07-30 17:22:42 -0700208ndn_Error ndn_BinaryXmlEncoder_writeElementClose(struct ndn_BinaryXmlEncoder *self)
Jeff Thompson5a984832013-07-01 19:28:27 -0700209{
Jeff Thompson8b666002013-07-08 01:16:26 -0700210 ndn_Error error;
Jeff Thompson10ad12a2013-09-24 16:19:11 -0700211 if ((error = ndn_DynamicUInt8Array_ensureLength(self->output, self->offset + 1)))
Jeff Thompson5a984832013-07-01 19:28:27 -0700212 return error;
213
Jeff Thompsonc978a7b2013-08-12 13:17:17 -0700214 self->output->array[self->offset] = ndn_BinaryXml_CLOSE;
Jeff Thompson2d27e2f2013-08-09 12:55:00 -0700215 self->offset += 1;
Jeff Thompson5a984832013-07-01 19:28:27 -0700216
Jeff Thompsonadaf9232013-08-08 14:30:29 -0700217 return NDN_ERROR_success;
Jeff Thompson5a984832013-07-01 19:28:27 -0700218}
219
Jeff Thompson93034532013-10-08 11:52:43 -0700220ndn_Error ndn_BinaryXmlEncoder_writeBlob(struct ndn_BinaryXmlEncoder *self, struct ndn_Blob *value)
Jeff Thompson5a984832013-07-01 19:28:27 -0700221{
Jeff Thompson8b666002013-07-08 01:16:26 -0700222 ndn_Error error;
Jeff Thompson93034532013-10-08 11:52:43 -0700223 if ((error = ndn_BinaryXmlEncoder_encodeTypeAndValue(self, ndn_BinaryXml_BLOB, value->length)))
Jeff Thompson5a984832013-07-01 19:28:27 -0700224 return error;
225
Jeff Thompson93034532013-10-08 11:52:43 -0700226 if ((error = writeArray(self, value->value, value->length)))
Jeff Thompson5a984832013-07-01 19:28:27 -0700227 return error;
228
Jeff Thompsonadaf9232013-08-08 14:30:29 -0700229 return NDN_ERROR_success;
Jeff Thompson5a984832013-07-01 19:28:27 -0700230}
231
Jeff Thompson93034532013-10-08 11:52:43 -0700232ndn_Error ndn_BinaryXmlEncoder_writeBlobDTagElement(struct ndn_BinaryXmlEncoder *self, unsigned int tag, struct ndn_Blob *value)
Jeff Thompson5a984832013-07-01 19:28:27 -0700233{
Jeff Thompson8b666002013-07-08 01:16:26 -0700234 ndn_Error error;
Jeff Thompson94ddc272013-08-08 14:17:38 -0700235 if ((error = ndn_BinaryXmlEncoder_writeElementStartDTag(self, tag)))
Jeff Thompson5a984832013-07-01 19:28:27 -0700236 return error;
237
Jeff Thompson93034532013-10-08 11:52:43 -0700238 if ((error = ndn_BinaryXmlEncoder_writeBlob(self, value)))
Jeff Thompson5a984832013-07-01 19:28:27 -0700239 return error;
240
Jeff Thompson94ddc272013-08-08 14:17:38 -0700241 if ((error = ndn_BinaryXmlEncoder_writeElementClose(self)))
Jeff Thompson5a984832013-07-01 19:28:27 -0700242 return error;
243
Jeff Thompsonadaf9232013-08-08 14:30:29 -0700244 return NDN_ERROR_success;
Jeff Thompson5a984832013-07-01 19:28:27 -0700245}
Jeff Thompsone2276892013-07-08 02:44:18 -0700246
Jeff Thompson93034532013-10-08 11:52:43 -0700247ndn_Error ndn_BinaryXmlEncoder_writeUData(struct ndn_BinaryXmlEncoder *self, struct ndn_Blob *value)
Jeff Thompson214c26f2013-08-27 11:45:01 -0700248{
249 ndn_Error error;
Jeff Thompson93034532013-10-08 11:52:43 -0700250 if ((error = ndn_BinaryXmlEncoder_encodeTypeAndValue(self, ndn_BinaryXml_UDATA, value->length)))
Jeff Thompson214c26f2013-08-27 11:45:01 -0700251 return error;
252
Jeff Thompson93034532013-10-08 11:52:43 -0700253 if ((error = writeArray(self, value->value, value->length)))
Jeff Thompson214c26f2013-08-27 11:45:01 -0700254 return error;
255
256 return NDN_ERROR_success;
257}
258
Jeff Thompson93034532013-10-08 11:52:43 -0700259ndn_Error ndn_BinaryXmlEncoder_writeUDataDTagElement(struct ndn_BinaryXmlEncoder *self, unsigned int tag, struct ndn_Blob *value)
Jeff Thompson214c26f2013-08-27 11:45:01 -0700260{
261 ndn_Error error;
262 if ((error = ndn_BinaryXmlEncoder_writeElementStartDTag(self, tag)))
263 return error;
264
Jeff Thompson93034532013-10-08 11:52:43 -0700265 if ((error = ndn_BinaryXmlEncoder_writeUData(self, value)))
Jeff Thompson214c26f2013-08-27 11:45:01 -0700266 return error;
267
268 if ((error = ndn_BinaryXmlEncoder_writeElementClose(self)))
269 return error;
270
271 return NDN_ERROR_success;
272}
273
Jeff Thompsonf0fea002013-07-30 17:22:42 -0700274ndn_Error ndn_BinaryXmlEncoder_writeUnsignedDecimalInt(struct ndn_BinaryXmlEncoder *self, unsigned int value)
Jeff Thompsone2276892013-07-08 02:44:18 -0700275{
276 // First write the decimal int (to find out how many bytes it is), then shift it forward to make room for the header.
Jeff Thompson97223af2013-09-24 17:01:27 -0700277 size_t startOffset = self->offset;
Jeff Thompsone2276892013-07-08 02:44:18 -0700278
279 ndn_Error error;
Jeff Thompson94ddc272013-08-08 14:17:38 -0700280 if ((error = encodeReversedUnsignedDecimalInt(self, value)))
Jeff Thompsone2276892013-07-08 02:44:18 -0700281 return error;
282
Jeff Thompson94ddc272013-08-08 14:17:38 -0700283 if ((error = reverseBufferAndInsertHeader(self, startOffset, ndn_BinaryXml_UDATA)))
Jeff Thompsone2276892013-07-08 02:44:18 -0700284 return error;
285
Jeff Thompsonadaf9232013-08-08 14:30:29 -0700286 return NDN_ERROR_success;
Jeff Thompsone2276892013-07-08 02:44:18 -0700287}
Jeff Thompson5b696e02013-07-08 15:04:22 -0700288
Jeff Thompsonf0fea002013-07-30 17:22:42 -0700289ndn_Error ndn_BinaryXmlEncoder_writeUnsignedDecimalIntDTagElement(struct ndn_BinaryXmlEncoder *self, unsigned int tag, unsigned int value)
Jeff Thompson5b696e02013-07-08 15:04:22 -0700290{
291 ndn_Error error;
Jeff Thompson94ddc272013-08-08 14:17:38 -0700292 if ((error = ndn_BinaryXmlEncoder_writeElementStartDTag(self, tag)))
Jeff Thompson5b696e02013-07-08 15:04:22 -0700293 return error;
294
Jeff Thompson94ddc272013-08-08 14:17:38 -0700295 if ((error = ndn_BinaryXmlEncoder_writeUnsignedDecimalInt(self, value)))
Jeff Thompson5b696e02013-07-08 15:04:22 -0700296 return error;
297
Jeff Thompson94ddc272013-08-08 14:17:38 -0700298 if ((error = ndn_BinaryXmlEncoder_writeElementClose(self)))
Jeff Thompson5b696e02013-07-08 15:04:22 -0700299 return error;
300
Jeff Thompsonadaf9232013-08-08 14:30:29 -0700301 return NDN_ERROR_success;
Jeff Thompson5b696e02013-07-08 15:04:22 -0700302}
Jeff Thompsona259cc42013-07-08 17:14:09 -0700303
Jeff Thompsonf0fea002013-07-30 17:22:42 -0700304ndn_Error ndn_BinaryXmlEncoder_writeAbsDoubleBigEndianBlob(struct ndn_BinaryXmlEncoder *self, double value)
Jeff Thompsona259cc42013-07-08 17:14:09 -0700305{
Jeff Thompsonedc22252013-07-11 18:05:44 -0700306 unsigned long hi32, lo32;
307 splitAbsDouble(value, &hi32, &lo32);
308
309 // First encode the big endian backwards, then reverseBufferAndInsertHeader will reverse it.
Jeff Thompson97223af2013-09-24 17:01:27 -0700310 size_t startOffset = self->offset;
Jeff Thompsonedc22252013-07-11 18:05:44 -0700311
Jeff Thompsona259cc42013-07-08 17:14:09 -0700312 ndn_Error error;
Jeff Thompsonedc22252013-07-11 18:05:44 -0700313 while (lo32 != 0) {
Jeff Thompson10ad12a2013-09-24 16:19:11 -0700314 if ((error = ndn_DynamicUInt8Array_ensureLength(self->output, self->offset + 1)))
Jeff Thompsona259cc42013-07-08 17:14:09 -0700315 return error;
316
Jeff Thompson10ad12a2013-09-24 16:19:11 -0700317 self->output->array[self->offset++] = (uint8_t)(lo32 & 0xff);
Jeff Thompsonedc22252013-07-11 18:05:44 -0700318 lo32 >>= 8;
319 }
320
321 if (hi32 != 0) {
322 // Pad the lo values out to 4 bytes.
323 while (self->offset - startOffset < 4) {
Jeff Thompson10ad12a2013-09-24 16:19:11 -0700324 if ((error = ndn_DynamicUInt8Array_ensureLength(self->output, self->offset + 1)))
Jeff Thompsonedc22252013-07-11 18:05:44 -0700325 return error;
326
Jeff Thompsonc978a7b2013-08-12 13:17:17 -0700327 self->output->array[self->offset++] = 0;
Jeff Thompsonedc22252013-07-11 18:05:44 -0700328 }
329
330 // Encode hi32
331 while (hi32 != 0) {
Jeff Thompson10ad12a2013-09-24 16:19:11 -0700332 if ((error = ndn_DynamicUInt8Array_ensureLength(self->output, self->offset + 1)))
Jeff Thompsonedc22252013-07-11 18:05:44 -0700333 return error;
334
Jeff Thompson10ad12a2013-09-24 16:19:11 -0700335 self->output->array[self->offset++] = (uint8_t)(hi32 & 0xff);
Jeff Thompsonedc22252013-07-11 18:05:44 -0700336 hi32 >>= 8;
337 }
Jeff Thompsona259cc42013-07-08 17:14:09 -0700338 }
339
Jeff Thompson94ddc272013-08-08 14:17:38 -0700340 if ((error = reverseBufferAndInsertHeader(self, startOffset, ndn_BinaryXml_BLOB)))
Jeff Thompsona259cc42013-07-08 17:14:09 -0700341 return error;
342
Jeff Thompsonadaf9232013-08-08 14:30:29 -0700343 return NDN_ERROR_success;
Jeff Thompsona259cc42013-07-08 17:14:09 -0700344}
Jeff Thompsonedc22252013-07-11 18:05:44 -0700345
Jeff Thompsonf0fea002013-07-30 17:22:42 -0700346ndn_Error ndn_BinaryXmlEncoder_writeTimeMillisecondsDTagElement(struct ndn_BinaryXmlEncoder *self, unsigned int tag, double milliseconds)
Jeff Thompsonedc22252013-07-11 18:05:44 -0700347{
348 ndn_Error error;
Jeff Thompson94ddc272013-08-08 14:17:38 -0700349 if ((error = ndn_BinaryXmlEncoder_writeElementStartDTag(self, tag)))
Jeff Thompsonedc22252013-07-11 18:05:44 -0700350 return error;
351
Jeff Thompson94ddc272013-08-08 14:17:38 -0700352 if ((error = ndn_BinaryXmlEncoder_writeAbsDoubleBigEndianBlob(self, (milliseconds / 1000.0) * 4096.0)))
Jeff Thompsonedc22252013-07-11 18:05:44 -0700353 return error;
354
Jeff Thompson94ddc272013-08-08 14:17:38 -0700355 if ((error = ndn_BinaryXmlEncoder_writeElementClose(self)))
Jeff Thompsonedc22252013-07-11 18:05:44 -0700356 return error;
357
Jeff Thompsonadaf9232013-08-08 14:30:29 -0700358 return NDN_ERROR_success;
Jeff Thompsonedc22252013-07-11 18:05:44 -0700359}