Jeff Thompson | 47eecfc | 2013-07-07 22:56:46 -0700 | [diff] [blame] | 1 | /** |
| 2 | * @author: Jeff Thompson |
Jeff Thompson | e5b37a5 | 2013-07-08 15:39:01 -0700 | [diff] [blame] | 3 | * Derived from BinaryXMLEncoder.js by Meki Cheraoui. |
Jeff Thompson | 47eecfc | 2013-07-07 22:56:46 -0700 | [diff] [blame] | 4 | * See COPYING for copyright and distribution information. |
Jeff Thompson | c896365 | 2013-06-28 20:17:43 -0700 | [diff] [blame] | 5 | */ |
| 6 | |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 7 | #include <math.h> |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 8 | #include "../util/ndn_memory.h" |
Jeff Thompson | 590b869 | 2013-06-28 22:07:41 -0700 | [diff] [blame] | 9 | #include "BinaryXML.h" |
Jeff Thompson | c896365 | 2013-06-28 20:17:43 -0700 | [diff] [blame] | 10 | #include "BinaryXMLEncoder.h" |
Jeff Thompson | 590b869 | 2013-06-28 22:07:41 -0700 | [diff] [blame] | 11 | |
| 12 | enum { |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 13 | ENCODING_LIMIT_1_BYTE = ((1 << ndn_BinaryXml_TT_VALUE_BITS) - 1), |
| 14 | ENCODING_LIMIT_2_BYTES = ((1 << (ndn_BinaryXml_TT_VALUE_BITS + ndn_BinaryXml_REGULAR_VALUE_BITS)) - 1), |
| 15 | ENCODING_LIMIT_3_BYTES = ((1 << (ndn_BinaryXml_TT_VALUE_BITS + 2 * ndn_BinaryXml_REGULAR_VALUE_BITS)) - 1) |
Jeff Thompson | 590b869 | 2013-06-28 22:07:41 -0700 | [diff] [blame] | 16 | }; |
| 17 | |
| 18 | /** |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 19 | * Call ndn_DynamicUCharArray_ensureLength to ensure that there is enough room in the output, and copy |
| 20 | * array to the output. This does not write a header. |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 21 | * @param self pointer to the ndn_BinaryXmlEncoder struct |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 22 | * @param array the array to copy |
| 23 | * @param arrayLength the length of the array |
Jeff Thompson | 8b66600 | 2013-07-08 01:16:26 -0700 | [diff] [blame] | 24 | * @return 0 for success, else an error code |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 25 | */ |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 26 | static ndn_Error writeArray(struct ndn_BinaryXmlEncoder *self, unsigned char *array, unsigned int arrayLength) |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 27 | { |
Jeff Thompson | 8b66600 | 2013-07-08 01:16:26 -0700 | [diff] [blame] | 28 | ndn_Error error; |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 29 | if (error = ndn_DynamicUCharArray_ensureLength(&self->output, self->offset + arrayLength)) |
| 30 | return error; |
| 31 | |
| 32 | ndn_memcpy(self->output.array + self->offset, array, arrayLength); |
| 33 | self->offset += arrayLength; |
| 34 | |
| 35 | return 0; |
| 36 | } |
| 37 | |
| 38 | /** |
Jeff Thompson | 590b869 | 2013-06-28 22:07:41 -0700 | [diff] [blame] | 39 | * Return the number of bytes to encode a header of value x. |
| 40 | */ |
Jeff Thompson | e227689 | 2013-07-08 02:44:18 -0700 | [diff] [blame] | 41 | static unsigned int getNHeaderEncodingBytes(unsigned int x) |
Jeff Thompson | 590b869 | 2013-06-28 22:07:41 -0700 | [diff] [blame] | 42 | { |
| 43 | // Do a quick check for pre-compiled results. |
| 44 | if (x <= ENCODING_LIMIT_1_BYTE) |
| 45 | return 1; |
| 46 | if (x <= ENCODING_LIMIT_2_BYTES) |
| 47 | return 2; |
| 48 | if (x <= ENCODING_LIMIT_3_BYTES) |
| 49 | return 3; |
| 50 | |
| 51 | unsigned int nBytes = 1; |
| 52 | |
| 53 | // Last byte gives you TT_VALUE_BITS. |
| 54 | // Remainder each gives you REGULAR_VALUE_BITS. |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 55 | x >>= ndn_BinaryXml_TT_VALUE_BITS; |
Jeff Thompson | 590b869 | 2013-06-28 22:07:41 -0700 | [diff] [blame] | 56 | while (x != 0) { |
| 57 | ++nBytes; |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 58 | x >>= ndn_BinaryXml_REGULAR_VALUE_BITS; |
Jeff Thompson | 590b869 | 2013-06-28 22:07:41 -0700 | [diff] [blame] | 59 | } |
| 60 | |
| 61 | return nBytes; |
| 62 | } |
Jeff Thompson | 433e6da | 2013-07-01 15:09:00 -0700 | [diff] [blame] | 63 | |
Jeff Thompson | 2c1d921 | 2013-07-08 02:10:03 -0700 | [diff] [blame] | 64 | /** |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 65 | * Reverse the length bytes in array. |
Jeff Thompson | 2c1d921 | 2013-07-08 02:10:03 -0700 | [diff] [blame] | 66 | * @param array |
Jeff Thompson | 2c1d921 | 2013-07-08 02:10:03 -0700 | [diff] [blame] | 67 | * @param length |
| 68 | */ |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 69 | static void reverse(unsigned char *array, unsigned int length) |
Jeff Thompson | 2c1d921 | 2013-07-08 02:10:03 -0700 | [diff] [blame] | 70 | { |
| 71 | if (length == 0) |
| 72 | return; |
| 73 | |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 74 | unsigned char *left = array; |
| 75 | unsigned char *right = array + length - 1; |
Jeff Thompson | 2c1d921 | 2013-07-08 02:10:03 -0700 | [diff] [blame] | 76 | while (left < right) { |
| 77 | // Swap. |
| 78 | unsigned char temp = *left; |
| 79 | *left = *right; |
| 80 | *right = temp; |
| 81 | |
| 82 | ++left; |
| 83 | --right; |
| 84 | } |
| 85 | } |
| 86 | |
| 87 | /** |
Jeff Thompson | 1cb79eb | 2013-07-08 17:59:01 -0700 | [diff] [blame] | 88 | * Write x as an unsigned decimal integer to the output with the digits in reverse order, using ndn_DynamicUCharArray_ensureLength. |
Jeff Thompson | 2c1d921 | 2013-07-08 02:10:03 -0700 | [diff] [blame] | 89 | * This does not write a header. |
Jeff Thompson | 1cb79eb | 2013-07-08 17:59:01 -0700 | [diff] [blame] | 90 | * We encode in reverse order, because this is the natural way to encode the digits, and the caller can reverse as needed. |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 91 | * @param self pointer to the ndn_BinaryXmlEncoder struct |
Jeff Thompson | 2c1d921 | 2013-07-08 02:10:03 -0700 | [diff] [blame] | 92 | * @param x the unsigned int to write |
| 93 | * @return 0 for success, else an error code |
| 94 | */ |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 95 | static ndn_Error encodeReversedUnsignedDecimalInt(struct ndn_BinaryXmlEncoder *self, unsigned int x) |
Jeff Thompson | 2c1d921 | 2013-07-08 02:10:03 -0700 | [diff] [blame] | 96 | { |
Jeff Thompson | 2c1d921 | 2013-07-08 02:10:03 -0700 | [diff] [blame] | 97 | while (1) { |
| 98 | ndn_Error error; |
| 99 | if (error = ndn_DynamicUCharArray_ensureLength(&self->output, self->offset + 1)) |
| 100 | return error; |
| 101 | |
| 102 | self->output.array[self->offset++] = (unsigned char)(x % 10 + '0'); |
| 103 | x /= 10; |
| 104 | |
| 105 | if (x == 0) |
| 106 | break; |
| 107 | } |
| 108 | |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 109 | return 0; |
| 110 | } |
| 111 | |
| 112 | /** |
Jeff Thompson | 1cb79eb | 2013-07-08 17:59:01 -0700 | [diff] [blame] | 113 | * Reverse the buffer in self->output.array, then shift it right by the amount needed to prefix a header with type, |
| 114 | * then encode the header at startOffset. |
| 115 | * 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. |
| 116 | * We reverse and shift in the same function to avoid unnecessary copying if we first reverse then shift. |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 117 | * @param self pointer to the ndn_BinaryXmlEncoder struct |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 118 | * @param startOffset the offset in self->output.array of the start of the buffer to shift right |
| 119 | * @param type the header type |
| 120 | * @return 0 for success, else an error code |
| 121 | */ |
Jeff Thompson | 1cb79eb | 2013-07-08 17:59:01 -0700 | [diff] [blame] | 122 | static ndn_Error reverseBufferAndInsertHeader |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 123 | (struct ndn_BinaryXmlEncoder *self, unsigned int startOffset, unsigned int type) |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 124 | { |
| 125 | unsigned int nBufferBytes = self->offset - startOffset; |
| 126 | unsigned int nHeaderBytes = getNHeaderEncodingBytes(nBufferBytes); |
| 127 | ndn_Error error; |
| 128 | if (error = ndn_DynamicUCharArray_ensureLength(&self->output, self->offset + nHeaderBytes)) |
| 129 | return error; |
| 130 | |
Jeff Thompson | 1cb79eb | 2013-07-08 17:59:01 -0700 | [diff] [blame] | 131 | // 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. |
| 133 | unsigned char *from = self->output.array + startOffset; |
| 134 | unsigned char *fromEnd = from + nHeaderBytes; |
| 135 | unsigned char *to = self->output.array + startOffset + nBufferBytes + nHeaderBytes - 1; |
| 136 | while (from < fromEnd) |
| 137 | *(to--) = *(from++); |
| 138 | // Reverse the remaining bytes in place (if any). |
| 139 | if (nBufferBytes > nHeaderBytes) |
| 140 | reverse(self->output.array + startOffset + nHeaderBytes, nBufferBytes - nHeaderBytes); |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 141 | |
| 142 | // Override the offset to force encodeTypeAndValue to encode at startOffset, then fix the offset. |
| 143 | self->offset = startOffset; |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 144 | if (error = ndn_BinaryXmlEncoder_encodeTypeAndValue(self, ndn_BinaryXml_UDATA, nBufferBytes)) |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 145 | // 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 Thompson | 2c1d921 | 2013-07-08 02:10:03 -0700 | [diff] [blame] | 149 | return 0; |
| 150 | } |
| 151 | |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 152 | /** |
| 153 | * Split the absolute value of x into 32 bit unsigned integers hi32 and lo32. |
| 154 | * 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 | */ |
| 161 | static 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 Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 173 | ndn_Error ndn_BinaryXmlEncoder_encodeTypeAndValue(struct ndn_BinaryXmlEncoder *self, unsigned int type, unsigned int value) |
Jeff Thompson | 433e6da | 2013-07-01 15:09:00 -0700 | [diff] [blame] | 174 | { |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 175 | if (type > ndn_BinaryXml_UDATA) |
Jeff Thompson | 8b66600 | 2013-07-08 01:16:26 -0700 | [diff] [blame] | 176 | return NDN_ERROR_header_type_is_out_of_range; |
Jeff Thompson | 433e6da | 2013-07-01 15:09:00 -0700 | [diff] [blame] | 177 | |
| 178 | // Encode backwards. Calculate how many bytes we need. |
Jeff Thompson | e227689 | 2013-07-08 02:44:18 -0700 | [diff] [blame] | 179 | unsigned int nEncodingBytes = getNHeaderEncodingBytes(value); |
Jeff Thompson | 8b66600 | 2013-07-08 01:16:26 -0700 | [diff] [blame] | 180 | ndn_Error error; |
Jeff Thompson | 433e6da | 2013-07-01 15:09:00 -0700 | [diff] [blame] | 181 | if (error = ndn_DynamicUCharArray_ensureLength(&self->output, self->offset + nEncodingBytes)) |
| 182 | return error; |
| 183 | |
| 184 | // Bottom 4 bits of value go in last byte with tag. |
| 185 | self->output.array[self->offset + nEncodingBytes - 1] = |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 186 | (ndn_BinaryXml_TT_MASK & type | |
| 187 | ((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; |
Jeff Thompson | 433e6da | 2013-07-01 15:09:00 -0700 | [diff] [blame] | 190 | |
| 191 | // Rest of value goes into preceding bytes, 7 bits per byte. (Zero top bit is "more" flag.) |
| 192 | unsigned int i = self->offset + nEncodingBytes - 2; |
| 193 | while (value != 0 && i >= self->offset) { |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 194 | self->output.array[i] = (value & ndn_BinaryXml_REGULAR_VALUE_MASK); |
| 195 | value >>= ndn_BinaryXml_REGULAR_VALUE_BITS; |
Jeff Thompson | 433e6da | 2013-07-01 15:09:00 -0700 | [diff] [blame] | 196 | --i; |
| 197 | } |
| 198 | if (value != 0) |
Jeff Thompson | e227689 | 2013-07-08 02:44:18 -0700 | [diff] [blame] | 199 | // This should not happen if getNHeaderEncodingBytes is correct. |
Jeff Thompson | 8b66600 | 2013-07-08 01:16:26 -0700 | [diff] [blame] | 200 | return NDN_ERROR_encodeTypeAndValue_miscalculated_N_encoding_bytes; |
Jeff Thompson | 433e6da | 2013-07-01 15:09:00 -0700 | [diff] [blame] | 201 | |
| 202 | self->offset+= nEncodingBytes; |
| 203 | |
| 204 | return 0; |
| 205 | } |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 206 | |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 207 | ndn_Error ndn_BinaryXmlEncoder_writeElementClose(struct ndn_BinaryXmlEncoder *self) |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 208 | { |
Jeff Thompson | 8b66600 | 2013-07-08 01:16:26 -0700 | [diff] [blame] | 209 | ndn_Error error; |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 210 | if (error = ndn_DynamicUCharArray_ensureLength(&self->output, self->offset + 1)) |
| 211 | return error; |
| 212 | |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 213 | self->output.array[self->offset] = ndn_BinaryXml_CLOSE; |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 214 | self->offset += 1; |
| 215 | |
| 216 | return 0; |
| 217 | } |
| 218 | |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 219 | ndn_Error ndn_BinaryXmlEncoder_writeBlob(struct ndn_BinaryXmlEncoder *self, unsigned char *value, unsigned int valueLength) |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 220 | { |
Jeff Thompson | 8b66600 | 2013-07-08 01:16:26 -0700 | [diff] [blame] | 221 | ndn_Error error; |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 222 | if (error = ndn_BinaryXmlEncoder_encodeTypeAndValue(self, ndn_BinaryXml_BLOB, valueLength)) |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 223 | return error; |
| 224 | |
| 225 | if (error = writeArray(self, value, valueLength)) |
| 226 | return error; |
| 227 | |
| 228 | return 0; |
| 229 | } |
| 230 | |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 231 | ndn_Error ndn_BinaryXmlEncoder_writeBlobDTagElement(struct ndn_BinaryXmlEncoder *self, unsigned int tag, unsigned char *value, unsigned int valueLength) |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 232 | { |
Jeff Thompson | 8b66600 | 2013-07-08 01:16:26 -0700 | [diff] [blame] | 233 | ndn_Error error; |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 234 | if (error = ndn_BinaryXmlEncoder_writeElementStartDTag(self, tag)) |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 235 | return error; |
| 236 | |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 237 | if (error = ndn_BinaryXmlEncoder_writeBlob(self, value, valueLength)) |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 238 | return error; |
| 239 | |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 240 | if (error = ndn_BinaryXmlEncoder_writeElementClose(self)) |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 241 | return error; |
| 242 | |
| 243 | return 0; |
| 244 | } |
Jeff Thompson | e227689 | 2013-07-08 02:44:18 -0700 | [diff] [blame] | 245 | |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 246 | ndn_Error ndn_BinaryXmlEncoder_writeUnsignedDecimalInt(struct ndn_BinaryXmlEncoder *self, unsigned int value) |
Jeff Thompson | e227689 | 2013-07-08 02:44:18 -0700 | [diff] [blame] | 247 | { |
| 248 | // First write the decimal int (to find out how many bytes it is), then shift it forward to make room for the header. |
| 249 | unsigned int startOffset = self->offset; |
| 250 | |
| 251 | ndn_Error error; |
Jeff Thompson | 1cb79eb | 2013-07-08 17:59:01 -0700 | [diff] [blame] | 252 | if (error = encodeReversedUnsignedDecimalInt(self, value)) |
Jeff Thompson | e227689 | 2013-07-08 02:44:18 -0700 | [diff] [blame] | 253 | return error; |
| 254 | |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 255 | if (error = reverseBufferAndInsertHeader(self, startOffset, ndn_BinaryXml_UDATA)) |
Jeff Thompson | e227689 | 2013-07-08 02:44:18 -0700 | [diff] [blame] | 256 | return error; |
| 257 | |
Jeff Thompson | e227689 | 2013-07-08 02:44:18 -0700 | [diff] [blame] | 258 | return 0; |
| 259 | } |
Jeff Thompson | 5b696e0 | 2013-07-08 15:04:22 -0700 | [diff] [blame] | 260 | |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 261 | ndn_Error ndn_BinaryXmlEncoder_writeUnsignedDecimalIntDTagElement(struct ndn_BinaryXmlEncoder *self, unsigned int tag, unsigned int value) |
Jeff Thompson | 5b696e0 | 2013-07-08 15:04:22 -0700 | [diff] [blame] | 262 | { |
| 263 | ndn_Error error; |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 264 | if (error = ndn_BinaryXmlEncoder_writeElementStartDTag(self, tag)) |
Jeff Thompson | 5b696e0 | 2013-07-08 15:04:22 -0700 | [diff] [blame] | 265 | return error; |
| 266 | |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 267 | if (error = ndn_BinaryXmlEncoder_writeUnsignedDecimalInt(self, value)) |
Jeff Thompson | 5b696e0 | 2013-07-08 15:04:22 -0700 | [diff] [blame] | 268 | return error; |
| 269 | |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 270 | if (error = ndn_BinaryXmlEncoder_writeElementClose(self)) |
Jeff Thompson | 5b696e0 | 2013-07-08 15:04:22 -0700 | [diff] [blame] | 271 | return error; |
| 272 | |
| 273 | return 0; |
| 274 | } |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 275 | |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 276 | ndn_Error ndn_BinaryXmlEncoder_writeAbsDoubleBigEndianBlob(struct ndn_BinaryXmlEncoder *self, double value) |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 277 | { |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 278 | unsigned long hi32, lo32; |
| 279 | splitAbsDouble(value, &hi32, &lo32); |
| 280 | |
| 281 | // First encode the big endian backwards, then reverseBufferAndInsertHeader will reverse it. |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 282 | unsigned int startOffset = self->offset; |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 283 | |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 284 | ndn_Error error; |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 285 | while (lo32 != 0) { |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 286 | if (error = ndn_DynamicUCharArray_ensureLength(&self->output, self->offset + 1)) |
| 287 | return error; |
| 288 | |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 289 | self->output.array[self->offset++] = (unsigned char)(lo32 & 0xff); |
| 290 | lo32 >>= 8; |
| 291 | } |
| 292 | |
| 293 | if (hi32 != 0) { |
| 294 | // Pad the lo values out to 4 bytes. |
| 295 | while (self->offset - startOffset < 4) { |
| 296 | if (error = ndn_DynamicUCharArray_ensureLength(&self->output, self->offset + 1)) |
| 297 | return error; |
| 298 | |
| 299 | self->output.array[self->offset++] = 0; |
| 300 | } |
| 301 | |
| 302 | // Encode hi32 |
| 303 | while (hi32 != 0) { |
| 304 | if (error = ndn_DynamicUCharArray_ensureLength(&self->output, self->offset + 1)) |
| 305 | return error; |
| 306 | |
| 307 | self->output.array[self->offset++] = (unsigned char)(hi32 & 0xff); |
| 308 | hi32 >>= 8; |
| 309 | } |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 310 | } |
| 311 | |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 312 | if (error = reverseBufferAndInsertHeader(self, startOffset, ndn_BinaryXml_BLOB)) |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 313 | return error; |
| 314 | |
| 315 | return 0; |
| 316 | } |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 317 | |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 318 | ndn_Error ndn_BinaryXmlEncoder_writeTimeMillisecondsDTagElement(struct ndn_BinaryXmlEncoder *self, unsigned int tag, double milliseconds) |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 319 | { |
| 320 | ndn_Error error; |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 321 | if (error = ndn_BinaryXmlEncoder_writeElementStartDTag(self, tag)) |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 322 | return error; |
| 323 | |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 324 | if (error = ndn_BinaryXmlEncoder_writeAbsDoubleBigEndianBlob(self, (milliseconds / 1000.0) * 4096.0)) |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 325 | return error; |
| 326 | |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 327 | if (error = ndn_BinaryXmlEncoder_writeElementClose(self)) |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 328 | return error; |
| 329 | |
| 330 | return 0; |
| 331 | } |