Jeff Thompson | 47eecfc | 2013-07-07 22:56:46 -0700 | [diff] [blame] | 1 | /** |
Jeff Thompson | 7687dc0 | 2013-09-13 11:54:07 -0700 | [diff] [blame] | 2 | * Copyright (C) 2013 Regents of the University of California. |
| 3 | * @author: Jeff Thompson <jefft0@remap.ucla.edu> |
Jeff Thompson | e5b37a5 | 2013-07-08 15:39:01 -0700 | [diff] [blame] | 4 | * Derived from BinaryXMLEncoder.js by Meki Cheraoui. |
Jeff Thompson | 47eecfc | 2013-07-07 22:56:46 -0700 | [diff] [blame] | 5 | * See COPYING for copyright and distribution information. |
Jeff Thompson | c896365 | 2013-06-28 20:17:43 -0700 | [diff] [blame] | 6 | */ |
| 7 | |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 8 | #include <math.h> |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 9 | #include "../util/ndn_memory.h" |
Jeff Thompson | 5341219 | 2013-08-06 13:35:50 -0700 | [diff] [blame] | 10 | #include "binary-xml.h" |
| 11 | #include "binary-xml-encoder.h" |
Jeff Thompson | 590b869 | 2013-06-28 22:07:41 -0700 | [diff] [blame] | 12 | |
| 13 | enum { |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 14 | 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 Thompson | 590b869 | 2013-06-28 22:07:41 -0700 | [diff] [blame] | 17 | }; |
| 18 | |
| 19 | /** |
Jeff Thompson | 10ad12a | 2013-09-24 16:19:11 -0700 | [diff] [blame] | 20 | * Call ndn_DynamicUInt8Array_ensureLength to ensure that there is enough room in the output, and copy |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 21 | * array to the output. This does not write a header. |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 22 | * @param self pointer to the ndn_BinaryXmlEncoder struct |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 23 | * @param array the array to copy |
| 24 | * @param arrayLength the length of the array |
Jeff Thompson | 8b66600 | 2013-07-08 01:16:26 -0700 | [diff] [blame] | 25 | * @return 0 for success, else an error code |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 26 | */ |
Jeff Thompson | 97223af | 2013-09-24 17:01:27 -0700 | [diff] [blame] | 27 | static ndn_Error writeArray(struct ndn_BinaryXmlEncoder *self, uint8_t *array, size_t arrayLength) |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 28 | { |
Jeff Thompson | 8b66600 | 2013-07-08 01:16:26 -0700 | [diff] [blame] | 29 | ndn_Error error; |
Jeff Thompson | 10ad12a | 2013-09-24 16:19:11 -0700 | [diff] [blame] | 30 | if ((error = ndn_DynamicUInt8Array_ensureLength(self->output, self->offset + arrayLength))) |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 31 | return error; |
| 32 | |
Jeff Thompson | c978a7b | 2013-08-12 13:17:17 -0700 | [diff] [blame] | 33 | ndn_memcpy(self->output->array + self->offset, array, arrayLength); |
Jeff Thompson | 2d27e2f | 2013-08-09 12:55:00 -0700 | [diff] [blame] | 34 | self->offset += arrayLength; |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 35 | |
Jeff Thompson | adaf923 | 2013-08-08 14:30:29 -0700 | [diff] [blame] | 36 | return NDN_ERROR_success; |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 37 | } |
| 38 | |
| 39 | /** |
Jeff Thompson | 590b869 | 2013-06-28 22:07:41 -0700 | [diff] [blame] | 40 | * Return the number of bytes to encode a header of value x. |
| 41 | */ |
Jeff Thompson | 97223af | 2013-09-24 17:01:27 -0700 | [diff] [blame] | 42 | static size_t getNHeaderEncodingBytes(unsigned int x) |
Jeff Thompson | 590b869 | 2013-06-28 22:07:41 -0700 | [diff] [blame] | 43 | { |
| 44 | // Do a quick check for pre-compiled results. |
Jeff Thompson | 2d27e2f | 2013-08-09 12:55:00 -0700 | [diff] [blame] | 45 | if (x <= ENCODING_LIMIT_1_BYTE) |
Jeff Thompson | 590b869 | 2013-06-28 22:07:41 -0700 | [diff] [blame] | 46 | return 1; |
Jeff Thompson | 2d27e2f | 2013-08-09 12:55:00 -0700 | [diff] [blame] | 47 | if (x <= ENCODING_LIMIT_2_BYTES) |
Jeff Thompson | 590b869 | 2013-06-28 22:07:41 -0700 | [diff] [blame] | 48 | return 2; |
Jeff Thompson | 2d27e2f | 2013-08-09 12:55:00 -0700 | [diff] [blame] | 49 | if (x <= ENCODING_LIMIT_3_BYTES) |
Jeff Thompson | 590b869 | 2013-06-28 22:07:41 -0700 | [diff] [blame] | 50 | return 3; |
Jeff Thompson | 590b869 | 2013-06-28 22:07:41 -0700 | [diff] [blame] | 51 | |
Jeff Thompson | 97223af | 2013-09-24 17:01:27 -0700 | [diff] [blame] | 52 | size_t nBytes = 1; |
Jeff Thompson | 2d27e2f | 2013-08-09 12:55:00 -0700 | [diff] [blame] | 53 | |
| 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 Thompson | 590b869 | 2013-06-28 22:07:41 -0700 | [diff] [blame] | 63 | } |
Jeff Thompson | 433e6da | 2013-07-01 15:09:00 -0700 | [diff] [blame] | 64 | |
Jeff Thompson | 2c1d921 | 2013-07-08 02:10:03 -0700 | [diff] [blame] | 65 | /** |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 66 | * Reverse the length bytes in array. |
Jeff Thompson | 2c1d921 | 2013-07-08 02:10:03 -0700 | [diff] [blame] | 67 | * @param array |
Jeff Thompson | 2c1d921 | 2013-07-08 02:10:03 -0700 | [diff] [blame] | 68 | * @param length |
| 69 | */ |
Jeff Thompson | 97223af | 2013-09-24 17:01:27 -0700 | [diff] [blame] | 70 | static void reverse(uint8_t *array, size_t length) |
Jeff Thompson | 2c1d921 | 2013-07-08 02:10:03 -0700 | [diff] [blame] | 71 | { |
| 72 | if (length == 0) |
| 73 | return; |
| 74 | |
Jeff Thompson | 10ad12a | 2013-09-24 16:19:11 -0700 | [diff] [blame] | 75 | uint8_t *left = array; |
| 76 | uint8_t *right = array + length - 1; |
Jeff Thompson | 2c1d921 | 2013-07-08 02:10:03 -0700 | [diff] [blame] | 77 | while (left < right) { |
| 78 | // Swap. |
Jeff Thompson | 10ad12a | 2013-09-24 16:19:11 -0700 | [diff] [blame] | 79 | uint8_t temp = *left; |
Jeff Thompson | 2c1d921 | 2013-07-08 02:10:03 -0700 | [diff] [blame] | 80 | *left = *right; |
| 81 | *right = temp; |
| 82 | |
| 83 | ++left; |
| 84 | --right; |
| 85 | } |
| 86 | } |
| 87 | |
| 88 | /** |
Jeff Thompson | 10ad12a | 2013-09-24 16:19:11 -0700 | [diff] [blame] | 89 | * Write x as an unsigned decimal integer to the output with the digits in reverse order, using ndn_DynamicUInt8Array_ensureLength. |
Jeff Thompson | 2c1d921 | 2013-07-08 02:10:03 -0700 | [diff] [blame] | 90 | * This does not write a header. |
Jeff Thompson | 1cb79eb | 2013-07-08 17:59:01 -0700 | [diff] [blame] | 91 | * 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] | 92 | * @param self pointer to the ndn_BinaryXmlEncoder struct |
Jeff Thompson | 2c1d921 | 2013-07-08 02:10:03 -0700 | [diff] [blame] | 93 | * @param x the unsigned int to write |
| 94 | * @return 0 for success, else an error code |
| 95 | */ |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 96 | static ndn_Error encodeReversedUnsignedDecimalInt(struct ndn_BinaryXmlEncoder *self, unsigned int x) |
Jeff Thompson | 2c1d921 | 2013-07-08 02:10:03 -0700 | [diff] [blame] | 97 | { |
Jeff Thompson | 2c1d921 | 2013-07-08 02:10:03 -0700 | [diff] [blame] | 98 | while (1) { |
| 99 | ndn_Error error; |
Jeff Thompson | 10ad12a | 2013-09-24 16:19:11 -0700 | [diff] [blame] | 100 | if ((error = ndn_DynamicUInt8Array_ensureLength(self->output, self->offset + 1))) |
Jeff Thompson | 2c1d921 | 2013-07-08 02:10:03 -0700 | [diff] [blame] | 101 | return error; |
| 102 | |
Jeff Thompson | 10ad12a | 2013-09-24 16:19:11 -0700 | [diff] [blame] | 103 | self->output->array[self->offset++] = (uint8_t)(x % 10 + '0'); |
Jeff Thompson | 2c1d921 | 2013-07-08 02:10:03 -0700 | [diff] [blame] | 104 | x /= 10; |
| 105 | |
| 106 | if (x == 0) |
| 107 | break; |
| 108 | } |
| 109 | |
Jeff Thompson | adaf923 | 2013-08-08 14:30:29 -0700 | [diff] [blame] | 110 | return NDN_ERROR_success; |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 111 | } |
| 112 | |
| 113 | /** |
Jeff Thompson | 7c4dab3 | 2013-11-05 14:07:33 -0800 | [diff] [blame] | 114 | * 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 Thompson | 1cb79eb | 2013-07-08 17:59:01 -0700 | [diff] [blame] | 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 | c978a7b | 2013-08-12 13:17:17 -0700 | [diff] [blame] | 118 | * @param startOffset the offset in self->output->array of the start of the buffer to shift right |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 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 | 97223af | 2013-09-24 17:01:27 -0700 | [diff] [blame] | 123 | (struct ndn_BinaryXmlEncoder *self, size_t startOffset, unsigned int type) |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 124 | { |
Jeff Thompson | 97223af | 2013-09-24 17:01:27 -0700 | [diff] [blame] | 125 | size_t nBufferBytes = self->offset - startOffset; |
| 126 | size_t nHeaderBytes = getNHeaderEncodingBytes(nBufferBytes); |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 127 | ndn_Error error; |
Jeff Thompson | 10ad12a | 2013-09-24 16:19:11 -0700 | [diff] [blame] | 128 | if ((error = ndn_DynamicUInt8Array_ensureLength(self->output, self->offset + nHeaderBytes))) |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 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. |
Jeff Thompson | 10ad12a | 2013-09-24 16:19:11 -0700 | [diff] [blame] | 133 | 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 Thompson | 1cb79eb | 2013-07-08 17:59:01 -0700 | [diff] [blame] | 136 | while (from < fromEnd) |
| 137 | *(to--) = *(from++); |
| 138 | // Reverse the remaining bytes in place (if any). |
| 139 | if (nBufferBytes > nHeaderBytes) |
Jeff Thompson | c978a7b | 2013-08-12 13:17:17 -0700 | [diff] [blame] | 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 | b123be6 | 2013-08-08 21:13:19 -0700 | [diff] [blame] | 144 | if ((error = ndn_BinaryXmlEncoder_encodeTypeAndValue(self, type, 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 | adaf923 | 2013-08-08 14:30:29 -0700 | [diff] [blame] | 149 | return NDN_ERROR_success; |
Jeff Thompson | 2c1d921 | 2013-07-08 02:10:03 -0700 | [diff] [blame] | 150 | } |
| 151 | |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 152 | /** |
Jeff Thompson | 62d8d8f | 2013-08-12 17:02:24 -0700 | [diff] [blame] | 153 | * Split the absolute value of x, rounded to an integer into 32 bit unsigned integers hi32 and lo32. |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 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 | 2d27e2f | 2013-08-09 12:55:00 -0700 | [diff] [blame] | 175 | if (type > ndn_BinaryXml_UDATA) |
| 176 | return NDN_ERROR_header_type_is_out_of_range; |
Jeff Thompson | 433e6da | 2013-07-01 15:09:00 -0700 | [diff] [blame] | 177 | |
Jeff Thompson | 2d27e2f | 2013-08-09 12:55:00 -0700 | [diff] [blame] | 178 | // Encode backwards. Calculate how many bytes we need. |
Jeff Thompson | 97223af | 2013-09-24 17:01:27 -0700 | [diff] [blame] | 179 | size_t nEncodingBytes = getNHeaderEncodingBytes(value); |
Jeff Thompson | 8b66600 | 2013-07-08 01:16:26 -0700 | [diff] [blame] | 180 | ndn_Error error; |
Jeff Thompson | 10ad12a | 2013-09-24 16:19:11 -0700 | [diff] [blame] | 181 | if ((error = ndn_DynamicUInt8Array_ensureLength(self->output, self->offset + nEncodingBytes))) |
Jeff Thompson | 433e6da | 2013-07-01 15:09:00 -0700 | [diff] [blame] | 182 | return error; |
| 183 | |
Jeff Thompson | 2d27e2f | 2013-08-09 12:55:00 -0700 | [diff] [blame] | 184 | // Bottom 4 bits of value go in last byte with tag. |
Jeff Thompson | c978a7b | 2013-08-12 13:17:17 -0700 | [diff] [blame] | 185 | self->output->array[self->offset + nEncodingBytes - 1] = |
Jeff Thompson | f68a74a | 2013-11-20 15:16:11 -0800 | [diff] [blame] | 186 | ((ndn_BinaryXml_TT_MASK & type) | |
Jeff Thompson | 2d27e2f | 2013-08-09 12:55:00 -0700 | [diff] [blame] | 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; |
| 190 | |
| 191 | // Rest of value goes into preceding bytes, 7 bits per byte. (Zero top bit is "more" flag.) |
Jeff Thompson | 97223af | 2013-09-24 17:01:27 -0700 | [diff] [blame] | 192 | size_t i = self->offset + nEncodingBytes - 2; |
Jeff Thompson | 2d27e2f | 2013-08-09 12:55:00 -0700 | [diff] [blame] | 193 | while (value != 0 && i >= self->offset) { |
Jeff Thompson | c978a7b | 2013-08-12 13:17:17 -0700 | [diff] [blame] | 194 | self->output->array[i] = (value & ndn_BinaryXml_REGULAR_VALUE_MASK); |
Jeff Thompson | 2d27e2f | 2013-08-09 12:55:00 -0700 | [diff] [blame] | 195 | value >>= ndn_BinaryXml_REGULAR_VALUE_BITS; |
| 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 | 2d27e2f | 2013-08-09 12:55:00 -0700 | [diff] [blame] | 200 | return NDN_ERROR_encodeTypeAndValue_miscalculated_N_encoding_bytes; |
| 201 | |
| 202 | self->offset+= nEncodingBytes; |
Jeff Thompson | 433e6da | 2013-07-01 15:09:00 -0700 | [diff] [blame] | 203 | |
Jeff Thompson | adaf923 | 2013-08-08 14:30:29 -0700 | [diff] [blame] | 204 | return NDN_ERROR_success; |
Jeff Thompson | 433e6da | 2013-07-01 15:09:00 -0700 | [diff] [blame] | 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 | 10ad12a | 2013-09-24 16:19:11 -0700 | [diff] [blame] | 210 | if ((error = ndn_DynamicUInt8Array_ensureLength(self->output, self->offset + 1))) |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 211 | return error; |
| 212 | |
Jeff Thompson | c978a7b | 2013-08-12 13:17:17 -0700 | [diff] [blame] | 213 | self->output->array[self->offset] = ndn_BinaryXml_CLOSE; |
Jeff Thompson | 2d27e2f | 2013-08-09 12:55:00 -0700 | [diff] [blame] | 214 | self->offset += 1; |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 215 | |
Jeff Thompson | adaf923 | 2013-08-08 14:30:29 -0700 | [diff] [blame] | 216 | return NDN_ERROR_success; |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 217 | } |
| 218 | |
Jeff Thompson | 9303453 | 2013-10-08 11:52:43 -0700 | [diff] [blame] | 219 | ndn_Error ndn_BinaryXmlEncoder_writeBlob(struct ndn_BinaryXmlEncoder *self, struct ndn_Blob *value) |
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 | 9303453 | 2013-10-08 11:52:43 -0700 | [diff] [blame] | 222 | if ((error = ndn_BinaryXmlEncoder_encodeTypeAndValue(self, ndn_BinaryXml_BLOB, value->length))) |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 223 | return error; |
| 224 | |
Jeff Thompson | 9303453 | 2013-10-08 11:52:43 -0700 | [diff] [blame] | 225 | if ((error = writeArray(self, value->value, value->length))) |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 226 | return error; |
| 227 | |
Jeff Thompson | adaf923 | 2013-08-08 14:30:29 -0700 | [diff] [blame] | 228 | return NDN_ERROR_success; |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 229 | } |
| 230 | |
Jeff Thompson | 9303453 | 2013-10-08 11:52:43 -0700 | [diff] [blame] | 231 | ndn_Error ndn_BinaryXmlEncoder_writeBlobDTagElement(struct ndn_BinaryXmlEncoder *self, unsigned int tag, struct ndn_Blob *value) |
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 | 94ddc27 | 2013-08-08 14:17:38 -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 | 9303453 | 2013-10-08 11:52:43 -0700 | [diff] [blame] | 237 | if ((error = ndn_BinaryXmlEncoder_writeBlob(self, value))) |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 238 | return error; |
| 239 | |
Jeff Thompson | 94ddc27 | 2013-08-08 14:17:38 -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 | |
Jeff Thompson | adaf923 | 2013-08-08 14:30:29 -0700 | [diff] [blame] | 243 | return NDN_ERROR_success; |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 244 | } |
Jeff Thompson | e227689 | 2013-07-08 02:44:18 -0700 | [diff] [blame] | 245 | |
Jeff Thompson | 9303453 | 2013-10-08 11:52:43 -0700 | [diff] [blame] | 246 | ndn_Error ndn_BinaryXmlEncoder_writeUData(struct ndn_BinaryXmlEncoder *self, struct ndn_Blob *value) |
Jeff Thompson | 214c26f | 2013-08-27 11:45:01 -0700 | [diff] [blame] | 247 | { |
| 248 | ndn_Error error; |
Jeff Thompson | 9303453 | 2013-10-08 11:52:43 -0700 | [diff] [blame] | 249 | if ((error = ndn_BinaryXmlEncoder_encodeTypeAndValue(self, ndn_BinaryXml_UDATA, value->length))) |
Jeff Thompson | 214c26f | 2013-08-27 11:45:01 -0700 | [diff] [blame] | 250 | return error; |
| 251 | |
Jeff Thompson | 9303453 | 2013-10-08 11:52:43 -0700 | [diff] [blame] | 252 | if ((error = writeArray(self, value->value, value->length))) |
Jeff Thompson | 214c26f | 2013-08-27 11:45:01 -0700 | [diff] [blame] | 253 | return error; |
| 254 | |
| 255 | return NDN_ERROR_success; |
| 256 | } |
| 257 | |
Jeff Thompson | 9303453 | 2013-10-08 11:52:43 -0700 | [diff] [blame] | 258 | ndn_Error ndn_BinaryXmlEncoder_writeUDataDTagElement(struct ndn_BinaryXmlEncoder *self, unsigned int tag, struct ndn_Blob *value) |
Jeff Thompson | 214c26f | 2013-08-27 11:45:01 -0700 | [diff] [blame] | 259 | { |
| 260 | ndn_Error error; |
| 261 | if ((error = ndn_BinaryXmlEncoder_writeElementStartDTag(self, tag))) |
| 262 | return error; |
| 263 | |
Jeff Thompson | 9303453 | 2013-10-08 11:52:43 -0700 | [diff] [blame] | 264 | if ((error = ndn_BinaryXmlEncoder_writeUData(self, value))) |
Jeff Thompson | 214c26f | 2013-08-27 11:45:01 -0700 | [diff] [blame] | 265 | return error; |
| 266 | |
| 267 | if ((error = ndn_BinaryXmlEncoder_writeElementClose(self))) |
| 268 | return error; |
| 269 | |
| 270 | return NDN_ERROR_success; |
| 271 | } |
| 272 | |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 273 | ndn_Error ndn_BinaryXmlEncoder_writeUnsignedDecimalInt(struct ndn_BinaryXmlEncoder *self, unsigned int value) |
Jeff Thompson | e227689 | 2013-07-08 02:44:18 -0700 | [diff] [blame] | 274 | { |
| 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 Thompson | 97223af | 2013-09-24 17:01:27 -0700 | [diff] [blame] | 276 | size_t startOffset = self->offset; |
Jeff Thompson | e227689 | 2013-07-08 02:44:18 -0700 | [diff] [blame] | 277 | |
| 278 | ndn_Error error; |
Jeff Thompson | 94ddc27 | 2013-08-08 14:17:38 -0700 | [diff] [blame] | 279 | if ((error = encodeReversedUnsignedDecimalInt(self, value))) |
Jeff Thompson | e227689 | 2013-07-08 02:44:18 -0700 | [diff] [blame] | 280 | return error; |
| 281 | |
Jeff Thompson | 94ddc27 | 2013-08-08 14:17:38 -0700 | [diff] [blame] | 282 | if ((error = reverseBufferAndInsertHeader(self, startOffset, ndn_BinaryXml_UDATA))) |
Jeff Thompson | e227689 | 2013-07-08 02:44:18 -0700 | [diff] [blame] | 283 | return error; |
| 284 | |
Jeff Thompson | adaf923 | 2013-08-08 14:30:29 -0700 | [diff] [blame] | 285 | return NDN_ERROR_success; |
Jeff Thompson | e227689 | 2013-07-08 02:44:18 -0700 | [diff] [blame] | 286 | } |
Jeff Thompson | 5b696e0 | 2013-07-08 15:04:22 -0700 | [diff] [blame] | 287 | |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 288 | 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] | 289 | { |
| 290 | ndn_Error error; |
Jeff Thompson | 94ddc27 | 2013-08-08 14:17:38 -0700 | [diff] [blame] | 291 | if ((error = ndn_BinaryXmlEncoder_writeElementStartDTag(self, tag))) |
Jeff Thompson | 5b696e0 | 2013-07-08 15:04:22 -0700 | [diff] [blame] | 292 | return error; |
| 293 | |
Jeff Thompson | 94ddc27 | 2013-08-08 14:17:38 -0700 | [diff] [blame] | 294 | if ((error = ndn_BinaryXmlEncoder_writeUnsignedDecimalInt(self, value))) |
Jeff Thompson | 5b696e0 | 2013-07-08 15:04:22 -0700 | [diff] [blame] | 295 | return error; |
| 296 | |
Jeff Thompson | 94ddc27 | 2013-08-08 14:17:38 -0700 | [diff] [blame] | 297 | if ((error = ndn_BinaryXmlEncoder_writeElementClose(self))) |
Jeff Thompson | 5b696e0 | 2013-07-08 15:04:22 -0700 | [diff] [blame] | 298 | return error; |
| 299 | |
Jeff Thompson | adaf923 | 2013-08-08 14:30:29 -0700 | [diff] [blame] | 300 | return NDN_ERROR_success; |
Jeff Thompson | 5b696e0 | 2013-07-08 15:04:22 -0700 | [diff] [blame] | 301 | } |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 302 | |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 303 | ndn_Error ndn_BinaryXmlEncoder_writeAbsDoubleBigEndianBlob(struct ndn_BinaryXmlEncoder *self, double value) |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 304 | { |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 305 | unsigned long hi32, lo32; |
| 306 | splitAbsDouble(value, &hi32, &lo32); |
| 307 | |
| 308 | // First encode the big endian backwards, then reverseBufferAndInsertHeader will reverse it. |
Jeff Thompson | 97223af | 2013-09-24 17:01:27 -0700 | [diff] [blame] | 309 | size_t startOffset = self->offset; |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 310 | |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 311 | ndn_Error error; |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 312 | while (lo32 != 0) { |
Jeff Thompson | 10ad12a | 2013-09-24 16:19:11 -0700 | [diff] [blame] | 313 | if ((error = ndn_DynamicUInt8Array_ensureLength(self->output, self->offset + 1))) |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 314 | return error; |
| 315 | |
Jeff Thompson | 10ad12a | 2013-09-24 16:19:11 -0700 | [diff] [blame] | 316 | self->output->array[self->offset++] = (uint8_t)(lo32 & 0xff); |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 317 | lo32 >>= 8; |
| 318 | } |
| 319 | |
| 320 | if (hi32 != 0) { |
| 321 | // Pad the lo values out to 4 bytes. |
| 322 | while (self->offset - startOffset < 4) { |
Jeff Thompson | 10ad12a | 2013-09-24 16:19:11 -0700 | [diff] [blame] | 323 | if ((error = ndn_DynamicUInt8Array_ensureLength(self->output, self->offset + 1))) |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 324 | return error; |
| 325 | |
Jeff Thompson | c978a7b | 2013-08-12 13:17:17 -0700 | [diff] [blame] | 326 | self->output->array[self->offset++] = 0; |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 327 | } |
| 328 | |
| 329 | // Encode hi32 |
| 330 | while (hi32 != 0) { |
Jeff Thompson | 10ad12a | 2013-09-24 16:19:11 -0700 | [diff] [blame] | 331 | if ((error = ndn_DynamicUInt8Array_ensureLength(self->output, self->offset + 1))) |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 332 | return error; |
| 333 | |
Jeff Thompson | 10ad12a | 2013-09-24 16:19:11 -0700 | [diff] [blame] | 334 | self->output->array[self->offset++] = (uint8_t)(hi32 & 0xff); |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 335 | hi32 >>= 8; |
| 336 | } |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 337 | } |
| 338 | |
Jeff Thompson | 94ddc27 | 2013-08-08 14:17:38 -0700 | [diff] [blame] | 339 | if ((error = reverseBufferAndInsertHeader(self, startOffset, ndn_BinaryXml_BLOB))) |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 340 | return error; |
| 341 | |
Jeff Thompson | adaf923 | 2013-08-08 14:30:29 -0700 | [diff] [blame] | 342 | return NDN_ERROR_success; |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 343 | } |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 344 | |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 345 | 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] | 346 | { |
| 347 | ndn_Error error; |
Jeff Thompson | 94ddc27 | 2013-08-08 14:17:38 -0700 | [diff] [blame] | 348 | if ((error = ndn_BinaryXmlEncoder_writeElementStartDTag(self, tag))) |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 349 | return error; |
| 350 | |
Jeff Thompson | 94ddc27 | 2013-08-08 14:17:38 -0700 | [diff] [blame] | 351 | if ((error = ndn_BinaryXmlEncoder_writeAbsDoubleBigEndianBlob(self, (milliseconds / 1000.0) * 4096.0))) |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 352 | return error; |
| 353 | |
Jeff Thompson | 94ddc27 | 2013-08-08 14:17:38 -0700 | [diff] [blame] | 354 | if ((error = ndn_BinaryXmlEncoder_writeElementClose(self))) |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 355 | return error; |
| 356 | |
Jeff Thompson | adaf923 | 2013-08-08 14:30:29 -0700 | [diff] [blame] | 357 | return NDN_ERROR_success; |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 358 | } |