blob: e27cbbc879cf9c00d39fd3acb7f2d92ff5e3f365 [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 Thompson7c4dab32013-11-05 14:07:33 -0800114 * Reverse the buffer in self->output->array from startOffset to the current offset, then shift it right by the amount
115 * needed to prefix a header with type, then encode the header at startOffset.
Jeff Thompson1cb79eb2013-07-08 17:59:01 -0700116 * 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 -0700117 * @param self pointer to the ndn_BinaryXmlEncoder struct
Jeff Thompsonc978a7b2013-08-12 13:17:17 -0700118 * @param startOffset the offset in self->output->array of the start of the buffer to shift right
Jeff Thompsona259cc42013-07-08 17:14:09 -0700119 * @param type the header type
120 * @return 0 for success, else an error code
121 */
Jeff Thompson1cb79eb2013-07-08 17:59:01 -0700122static ndn_Error reverseBufferAndInsertHeader
Jeff Thompson97223af2013-09-24 17:01:27 -0700123 (struct ndn_BinaryXmlEncoder *self, size_t startOffset, unsigned int type)
Jeff Thompsona259cc42013-07-08 17:14:09 -0700124{
Jeff Thompson97223af2013-09-24 17:01:27 -0700125 size_t nBufferBytes = self->offset - startOffset;
126 size_t nHeaderBytes = getNHeaderEncodingBytes(nBufferBytes);
Jeff Thompsona259cc42013-07-08 17:14:09 -0700127 ndn_Error error;
Jeff Thompson10ad12a2013-09-24 16:19:11 -0700128 if ((error = ndn_DynamicUInt8Array_ensureLength(self->output, self->offset + nHeaderBytes)))
Jeff Thompsona259cc42013-07-08 17:14:09 -0700129 return error;
130
Jeff Thompson1cb79eb2013-07-08 17:59:01 -0700131 // To reverse and shift at the same time, we first shift nHeaderBytes to the destination while reversing,
132 // then reverse the remaining bytes in place.
Jeff Thompson10ad12a2013-09-24 16:19:11 -0700133 uint8_t *from = self->output->array + startOffset;
134 uint8_t *fromEnd = from + nHeaderBytes;
135 uint8_t *to = self->output->array + startOffset + nBufferBytes + nHeaderBytes - 1;
Jeff Thompson1cb79eb2013-07-08 17:59:01 -0700136 while (from < fromEnd)
137 *(to--) = *(from++);
138 // Reverse the remaining bytes in place (if any).
139 if (nBufferBytes > nHeaderBytes)
Jeff Thompsonc978a7b2013-08-12 13:17:17 -0700140 reverse(self->output->array + startOffset + nHeaderBytes, nBufferBytes - nHeaderBytes);
Jeff Thompsona259cc42013-07-08 17:14:09 -0700141
142 // Override the offset to force encodeTypeAndValue to encode at startOffset, then fix the offset.
143 self->offset = startOffset;
Jeff Thompsonb123be62013-08-08 21:13:19 -0700144 if ((error = ndn_BinaryXmlEncoder_encodeTypeAndValue(self, type, nBufferBytes)))
Jeff Thompsona259cc42013-07-08 17:14:09 -0700145 // We don't really expect to get an error, since we have already ensured the length.
146 return error;
147 self->offset = startOffset + nHeaderBytes + nBufferBytes;
148
Jeff Thompsonadaf9232013-08-08 14:30:29 -0700149 return NDN_ERROR_success;
Jeff Thompson2c1d9212013-07-08 02:10:03 -0700150}
151
Jeff Thompsonedc22252013-07-11 18:05:44 -0700152/**
Jeff Thompson62d8d8f2013-08-12 17:02:24 -0700153 * 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 -0700154 * We need this because not all C compilers support 64 bit long long integers, so we carry around
155 * a high precision value as a double, which we assume has more than 32 bits.
156 * But we want to do bit-wise operations on integers.
157 * @param x the double value
158 * @param hi32 output the high 32 bits
159 * @param lo32 output the low 32 bits
160 */
161static inline void splitAbsDouble(double x, unsigned long *hi32, unsigned long *lo32)
162{
163 if (x < 0)
164 x = -x;
165 x = round(x);
166
167 double twoPower32 = 4294967296.0;
168 double lo32Double = fmod(x, twoPower32);
169 *lo32 = (unsigned long)lo32Double;
170 *hi32 = (unsigned long)((x - lo32Double) / twoPower32);
171}
172
Jeff Thompsonf0fea002013-07-30 17:22:42 -0700173ndn_Error ndn_BinaryXmlEncoder_encodeTypeAndValue(struct ndn_BinaryXmlEncoder *self, unsigned int type, unsigned int value)
Jeff Thompson433e6da2013-07-01 15:09:00 -0700174{
Jeff Thompson2d27e2f2013-08-09 12:55:00 -0700175 if (type > ndn_BinaryXml_UDATA)
176 return NDN_ERROR_header_type_is_out_of_range;
Jeff Thompson433e6da2013-07-01 15:09:00 -0700177
Jeff Thompson2d27e2f2013-08-09 12:55:00 -0700178 // Encode backwards. Calculate how many bytes we need.
Jeff Thompson97223af2013-09-24 17:01:27 -0700179 size_t nEncodingBytes = getNHeaderEncodingBytes(value);
Jeff Thompson8b666002013-07-08 01:16:26 -0700180 ndn_Error error;
Jeff Thompson10ad12a2013-09-24 16:19:11 -0700181 if ((error = ndn_DynamicUInt8Array_ensureLength(self->output, self->offset + nEncodingBytes)))
Jeff Thompson433e6da2013-07-01 15:09:00 -0700182 return error;
183
Jeff Thompson2d27e2f2013-08-09 12:55:00 -0700184 // Bottom 4 bits of value go in last byte with tag.
Jeff Thompsonc978a7b2013-08-12 13:17:17 -0700185 self->output->array[self->offset + nEncodingBytes - 1] =
Jeff Thompsonf68a74a2013-11-20 15:16:11 -0800186 ((ndn_BinaryXml_TT_MASK & type) |
Jeff Thompson2d27e2f2013-08-09 12:55:00 -0700187 ((ndn_BinaryXml_TT_VALUE_MASK & value) << ndn_BinaryXml_TT_BITS)) |
188 ndn_BinaryXml_TT_FINAL; // set top bit for last byte
189 value >>= ndn_BinaryXml_TT_VALUE_BITS;
190
191 // Rest of value goes into preceding bytes, 7 bits per byte. (Zero top bit is "more" flag.)
Jeff Thompson97223af2013-09-24 17:01:27 -0700192 size_t i = self->offset + nEncodingBytes - 2;
Jeff Thompson2d27e2f2013-08-09 12:55:00 -0700193 while (value != 0 && i >= self->offset) {
Jeff Thompsonc978a7b2013-08-12 13:17:17 -0700194 self->output->array[i] = (value & ndn_BinaryXml_REGULAR_VALUE_MASK);
Jeff Thompson2d27e2f2013-08-09 12:55:00 -0700195 value >>= ndn_BinaryXml_REGULAR_VALUE_BITS;
196 --i;
197 }
198 if (value != 0)
Jeff Thompsone2276892013-07-08 02:44:18 -0700199 // This should not happen if getNHeaderEncodingBytes is correct.
Jeff Thompson2d27e2f2013-08-09 12:55:00 -0700200 return NDN_ERROR_encodeTypeAndValue_miscalculated_N_encoding_bytes;
201
202 self->offset+= nEncodingBytes;
Jeff Thompson433e6da2013-07-01 15:09:00 -0700203
Jeff Thompsonadaf9232013-08-08 14:30:29 -0700204 return NDN_ERROR_success;
Jeff Thompson433e6da2013-07-01 15:09:00 -0700205}
Jeff Thompson5a984832013-07-01 19:28:27 -0700206
Jeff Thompsonf0fea002013-07-30 17:22:42 -0700207ndn_Error ndn_BinaryXmlEncoder_writeElementClose(struct ndn_BinaryXmlEncoder *self)
Jeff Thompson5a984832013-07-01 19:28:27 -0700208{
Jeff Thompson8b666002013-07-08 01:16:26 -0700209 ndn_Error error;
Jeff Thompson10ad12a2013-09-24 16:19:11 -0700210 if ((error = ndn_DynamicUInt8Array_ensureLength(self->output, self->offset + 1)))
Jeff Thompson5a984832013-07-01 19:28:27 -0700211 return error;
212
Jeff Thompsonc978a7b2013-08-12 13:17:17 -0700213 self->output->array[self->offset] = ndn_BinaryXml_CLOSE;
Jeff Thompson2d27e2f2013-08-09 12:55:00 -0700214 self->offset += 1;
Jeff Thompson5a984832013-07-01 19:28:27 -0700215
Jeff Thompsonadaf9232013-08-08 14:30:29 -0700216 return NDN_ERROR_success;
Jeff Thompson5a984832013-07-01 19:28:27 -0700217}
218
Jeff Thompson93034532013-10-08 11:52:43 -0700219ndn_Error ndn_BinaryXmlEncoder_writeBlob(struct ndn_BinaryXmlEncoder *self, struct ndn_Blob *value)
Jeff Thompson5a984832013-07-01 19:28:27 -0700220{
Jeff Thompson8b666002013-07-08 01:16:26 -0700221 ndn_Error error;
Jeff Thompson93034532013-10-08 11:52:43 -0700222 if ((error = ndn_BinaryXmlEncoder_encodeTypeAndValue(self, ndn_BinaryXml_BLOB, value->length)))
Jeff Thompson5a984832013-07-01 19:28:27 -0700223 return error;
224
Jeff Thompson93034532013-10-08 11:52:43 -0700225 if ((error = writeArray(self, value->value, value->length)))
Jeff Thompson5a984832013-07-01 19:28:27 -0700226 return error;
227
Jeff Thompsonadaf9232013-08-08 14:30:29 -0700228 return NDN_ERROR_success;
Jeff Thompson5a984832013-07-01 19:28:27 -0700229}
230
Jeff Thompson93034532013-10-08 11:52:43 -0700231ndn_Error ndn_BinaryXmlEncoder_writeBlobDTagElement(struct ndn_BinaryXmlEncoder *self, unsigned int tag, struct ndn_Blob *value)
Jeff Thompson5a984832013-07-01 19:28:27 -0700232{
Jeff Thompson8b666002013-07-08 01:16:26 -0700233 ndn_Error error;
Jeff Thompson94ddc272013-08-08 14:17:38 -0700234 if ((error = ndn_BinaryXmlEncoder_writeElementStartDTag(self, tag)))
Jeff Thompson5a984832013-07-01 19:28:27 -0700235 return error;
236
Jeff Thompson93034532013-10-08 11:52:43 -0700237 if ((error = ndn_BinaryXmlEncoder_writeBlob(self, value)))
Jeff Thompson5a984832013-07-01 19:28:27 -0700238 return error;
239
Jeff Thompson94ddc272013-08-08 14:17:38 -0700240 if ((error = ndn_BinaryXmlEncoder_writeElementClose(self)))
Jeff Thompson5a984832013-07-01 19:28:27 -0700241 return error;
242
Jeff Thompsonadaf9232013-08-08 14:30:29 -0700243 return NDN_ERROR_success;
Jeff Thompson5a984832013-07-01 19:28:27 -0700244}
Jeff Thompsone2276892013-07-08 02:44:18 -0700245
Jeff Thompson93034532013-10-08 11:52:43 -0700246ndn_Error ndn_BinaryXmlEncoder_writeUData(struct ndn_BinaryXmlEncoder *self, struct ndn_Blob *value)
Jeff Thompson214c26f2013-08-27 11:45:01 -0700247{
248 ndn_Error error;
Jeff Thompson93034532013-10-08 11:52:43 -0700249 if ((error = ndn_BinaryXmlEncoder_encodeTypeAndValue(self, ndn_BinaryXml_UDATA, value->length)))
Jeff Thompson214c26f2013-08-27 11:45:01 -0700250 return error;
251
Jeff Thompson93034532013-10-08 11:52:43 -0700252 if ((error = writeArray(self, value->value, value->length)))
Jeff Thompson214c26f2013-08-27 11:45:01 -0700253 return error;
254
255 return NDN_ERROR_success;
256}
257
Jeff Thompson93034532013-10-08 11:52:43 -0700258ndn_Error ndn_BinaryXmlEncoder_writeUDataDTagElement(struct ndn_BinaryXmlEncoder *self, unsigned int tag, struct ndn_Blob *value)
Jeff Thompson214c26f2013-08-27 11:45:01 -0700259{
260 ndn_Error error;
261 if ((error = ndn_BinaryXmlEncoder_writeElementStartDTag(self, tag)))
262 return error;
263
Jeff Thompson93034532013-10-08 11:52:43 -0700264 if ((error = ndn_BinaryXmlEncoder_writeUData(self, value)))
Jeff Thompson214c26f2013-08-27 11:45:01 -0700265 return error;
266
267 if ((error = ndn_BinaryXmlEncoder_writeElementClose(self)))
268 return error;
269
270 return NDN_ERROR_success;
271}
272
Jeff Thompsonf0fea002013-07-30 17:22:42 -0700273ndn_Error ndn_BinaryXmlEncoder_writeUnsignedDecimalInt(struct ndn_BinaryXmlEncoder *self, unsigned int value)
Jeff Thompsone2276892013-07-08 02:44:18 -0700274{
275 // 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 -0700276 size_t startOffset = self->offset;
Jeff Thompsone2276892013-07-08 02:44:18 -0700277
278 ndn_Error error;
Jeff Thompson94ddc272013-08-08 14:17:38 -0700279 if ((error = encodeReversedUnsignedDecimalInt(self, value)))
Jeff Thompsone2276892013-07-08 02:44:18 -0700280 return error;
281
Jeff Thompson94ddc272013-08-08 14:17:38 -0700282 if ((error = reverseBufferAndInsertHeader(self, startOffset, ndn_BinaryXml_UDATA)))
Jeff Thompsone2276892013-07-08 02:44:18 -0700283 return error;
284
Jeff Thompsonadaf9232013-08-08 14:30:29 -0700285 return NDN_ERROR_success;
Jeff Thompsone2276892013-07-08 02:44:18 -0700286}
Jeff Thompson5b696e02013-07-08 15:04:22 -0700287
Jeff Thompsonf0fea002013-07-30 17:22:42 -0700288ndn_Error ndn_BinaryXmlEncoder_writeUnsignedDecimalIntDTagElement(struct ndn_BinaryXmlEncoder *self, unsigned int tag, unsigned int value)
Jeff Thompson5b696e02013-07-08 15:04:22 -0700289{
290 ndn_Error error;
Jeff Thompson94ddc272013-08-08 14:17:38 -0700291 if ((error = ndn_BinaryXmlEncoder_writeElementStartDTag(self, tag)))
Jeff Thompson5b696e02013-07-08 15:04:22 -0700292 return error;
293
Jeff Thompson94ddc272013-08-08 14:17:38 -0700294 if ((error = ndn_BinaryXmlEncoder_writeUnsignedDecimalInt(self, value)))
Jeff Thompson5b696e02013-07-08 15:04:22 -0700295 return error;
296
Jeff Thompson94ddc272013-08-08 14:17:38 -0700297 if ((error = ndn_BinaryXmlEncoder_writeElementClose(self)))
Jeff Thompson5b696e02013-07-08 15:04:22 -0700298 return error;
299
Jeff Thompsonadaf9232013-08-08 14:30:29 -0700300 return NDN_ERROR_success;
Jeff Thompson5b696e02013-07-08 15:04:22 -0700301}
Jeff Thompsona259cc42013-07-08 17:14:09 -0700302
Jeff Thompsonf0fea002013-07-30 17:22:42 -0700303ndn_Error ndn_BinaryXmlEncoder_writeAbsDoubleBigEndianBlob(struct ndn_BinaryXmlEncoder *self, double value)
Jeff Thompsona259cc42013-07-08 17:14:09 -0700304{
Jeff Thompsonedc22252013-07-11 18:05:44 -0700305 unsigned long hi32, lo32;
306 splitAbsDouble(value, &hi32, &lo32);
307
308 // First encode the big endian backwards, then reverseBufferAndInsertHeader will reverse it.
Jeff Thompson97223af2013-09-24 17:01:27 -0700309 size_t startOffset = self->offset;
Jeff Thompsonedc22252013-07-11 18:05:44 -0700310
Jeff Thompsona259cc42013-07-08 17:14:09 -0700311 ndn_Error error;
Jeff Thompsonedc22252013-07-11 18:05:44 -0700312 while (lo32 != 0) {
Jeff Thompson10ad12a2013-09-24 16:19:11 -0700313 if ((error = ndn_DynamicUInt8Array_ensureLength(self->output, self->offset + 1)))
Jeff Thompsona259cc42013-07-08 17:14:09 -0700314 return error;
315
Jeff Thompson10ad12a2013-09-24 16:19:11 -0700316 self->output->array[self->offset++] = (uint8_t)(lo32 & 0xff);
Jeff Thompsonedc22252013-07-11 18:05:44 -0700317 lo32 >>= 8;
318 }
319
320 if (hi32 != 0) {
321 // Pad the lo values out to 4 bytes.
322 while (self->offset - startOffset < 4) {
Jeff Thompson10ad12a2013-09-24 16:19:11 -0700323 if ((error = ndn_DynamicUInt8Array_ensureLength(self->output, self->offset + 1)))
Jeff Thompsonedc22252013-07-11 18:05:44 -0700324 return error;
325
Jeff Thompsonc978a7b2013-08-12 13:17:17 -0700326 self->output->array[self->offset++] = 0;
Jeff Thompsonedc22252013-07-11 18:05:44 -0700327 }
328
329 // Encode hi32
330 while (hi32 != 0) {
Jeff Thompson10ad12a2013-09-24 16:19:11 -0700331 if ((error = ndn_DynamicUInt8Array_ensureLength(self->output, self->offset + 1)))
Jeff Thompsonedc22252013-07-11 18:05:44 -0700332 return error;
333
Jeff Thompson10ad12a2013-09-24 16:19:11 -0700334 self->output->array[self->offset++] = (uint8_t)(hi32 & 0xff);
Jeff Thompsonedc22252013-07-11 18:05:44 -0700335 hi32 >>= 8;
336 }
Jeff Thompsona259cc42013-07-08 17:14:09 -0700337 }
338
Jeff Thompson94ddc272013-08-08 14:17:38 -0700339 if ((error = reverseBufferAndInsertHeader(self, startOffset, ndn_BinaryXml_BLOB)))
Jeff Thompsona259cc42013-07-08 17:14:09 -0700340 return error;
341
Jeff Thompsonadaf9232013-08-08 14:30:29 -0700342 return NDN_ERROR_success;
Jeff Thompsona259cc42013-07-08 17:14:09 -0700343}
Jeff Thompsonedc22252013-07-11 18:05:44 -0700344
Jeff Thompsonf0fea002013-07-30 17:22:42 -0700345ndn_Error ndn_BinaryXmlEncoder_writeTimeMillisecondsDTagElement(struct ndn_BinaryXmlEncoder *self, unsigned int tag, double milliseconds)
Jeff Thompsonedc22252013-07-11 18:05:44 -0700346{
347 ndn_Error error;
Jeff Thompson94ddc272013-08-08 14:17:38 -0700348 if ((error = ndn_BinaryXmlEncoder_writeElementStartDTag(self, tag)))
Jeff Thompsonedc22252013-07-11 18:05:44 -0700349 return error;
350
Jeff Thompson94ddc272013-08-08 14:17:38 -0700351 if ((error = ndn_BinaryXmlEncoder_writeAbsDoubleBigEndianBlob(self, (milliseconds / 1000.0) * 4096.0)))
Jeff Thompsonedc22252013-07-11 18:05:44 -0700352 return error;
353
Jeff Thompson94ddc272013-08-08 14:17:38 -0700354 if ((error = ndn_BinaryXmlEncoder_writeElementClose(self)))
Jeff Thompsonedc22252013-07-11 18:05:44 -0700355 return error;
356
Jeff Thompsonadaf9232013-08-08 14:30:29 -0700357 return NDN_ERROR_success;
Jeff Thompsonedc22252013-07-11 18:05:44 -0700358}