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 | c978a7b | 2013-08-12 13:17:17 -0700 | [diff] [blame] | 114 | * Reverse the buffer in self->output->array, then shift it right by the amount needed to prefix a header with type, |
Jeff Thompson | 1cb79eb | 2013-07-08 17:59:01 -0700 | [diff] [blame] | 115 | * 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 Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 118 | * @param self pointer to the ndn_BinaryXmlEncoder struct |
Jeff Thompson | c978a7b | 2013-08-12 13:17:17 -0700 | [diff] [blame] | 119 | * @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] | 120 | * @param type the header type |
| 121 | * @return 0 for success, else an error code |
| 122 | */ |
Jeff Thompson | 1cb79eb | 2013-07-08 17:59:01 -0700 | [diff] [blame] | 123 | static ndn_Error reverseBufferAndInsertHeader |
Jeff Thompson | 97223af | 2013-09-24 17:01:27 -0700 | [diff] [blame^] | 124 | (struct ndn_BinaryXmlEncoder *self, size_t startOffset, unsigned int type) |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 125 | { |
Jeff Thompson | 97223af | 2013-09-24 17:01:27 -0700 | [diff] [blame^] | 126 | size_t nBufferBytes = self->offset - startOffset; |
| 127 | size_t nHeaderBytes = getNHeaderEncodingBytes(nBufferBytes); |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 128 | ndn_Error error; |
Jeff Thompson | 10ad12a | 2013-09-24 16:19:11 -0700 | [diff] [blame] | 129 | if ((error = ndn_DynamicUInt8Array_ensureLength(self->output, self->offset + nHeaderBytes))) |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 130 | return error; |
| 131 | |
Jeff Thompson | 1cb79eb | 2013-07-08 17:59:01 -0700 | [diff] [blame] | 132 | // 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 Thompson | 10ad12a | 2013-09-24 16:19:11 -0700 | [diff] [blame] | 134 | 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 Thompson | 1cb79eb | 2013-07-08 17:59:01 -0700 | [diff] [blame] | 137 | while (from < fromEnd) |
| 138 | *(to--) = *(from++); |
| 139 | // Reverse the remaining bytes in place (if any). |
| 140 | if (nBufferBytes > nHeaderBytes) |
Jeff Thompson | c978a7b | 2013-08-12 13:17:17 -0700 | [diff] [blame] | 141 | reverse(self->output->array + startOffset + nHeaderBytes, nBufferBytes - nHeaderBytes); |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 142 | |
| 143 | // Override the offset to force encodeTypeAndValue to encode at startOffset, then fix the offset. |
| 144 | self->offset = startOffset; |
Jeff Thompson | b123be6 | 2013-08-08 21:13:19 -0700 | [diff] [blame] | 145 | if ((error = ndn_BinaryXmlEncoder_encodeTypeAndValue(self, type, nBufferBytes))) |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 146 | // 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 Thompson | adaf923 | 2013-08-08 14:30:29 -0700 | [diff] [blame] | 150 | return NDN_ERROR_success; |
Jeff Thompson | 2c1d921 | 2013-07-08 02:10:03 -0700 | [diff] [blame] | 151 | } |
| 152 | |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 153 | /** |
Jeff Thompson | 62d8d8f | 2013-08-12 17:02:24 -0700 | [diff] [blame] | 154 | * 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] | 155 | * 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 | */ |
| 162 | static 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 Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 174 | 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] | 175 | { |
Jeff Thompson | 2d27e2f | 2013-08-09 12:55:00 -0700 | [diff] [blame] | 176 | if (type > ndn_BinaryXml_UDATA) |
| 177 | return NDN_ERROR_header_type_is_out_of_range; |
Jeff Thompson | 433e6da | 2013-07-01 15:09:00 -0700 | [diff] [blame] | 178 | |
Jeff Thompson | 2d27e2f | 2013-08-09 12:55:00 -0700 | [diff] [blame] | 179 | // Encode backwards. Calculate how many bytes we need. |
Jeff Thompson | 97223af | 2013-09-24 17:01:27 -0700 | [diff] [blame^] | 180 | size_t nEncodingBytes = getNHeaderEncodingBytes(value); |
Jeff Thompson | 8b66600 | 2013-07-08 01:16:26 -0700 | [diff] [blame] | 181 | ndn_Error error; |
Jeff Thompson | 10ad12a | 2013-09-24 16:19:11 -0700 | [diff] [blame] | 182 | if ((error = ndn_DynamicUInt8Array_ensureLength(self->output, self->offset + nEncodingBytes))) |
Jeff Thompson | 433e6da | 2013-07-01 15:09:00 -0700 | [diff] [blame] | 183 | return error; |
| 184 | |
Jeff Thompson | 2d27e2f | 2013-08-09 12:55:00 -0700 | [diff] [blame] | 185 | // Bottom 4 bits of value go in last byte with tag. |
Jeff Thompson | c978a7b | 2013-08-12 13:17:17 -0700 | [diff] [blame] | 186 | self->output->array[self->offset + nEncodingBytes - 1] = |
Jeff Thompson | 2d27e2f | 2013-08-09 12:55:00 -0700 | [diff] [blame] | 187 | (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 Thompson | 97223af | 2013-09-24 17:01:27 -0700 | [diff] [blame^] | 193 | size_t i = self->offset + nEncodingBytes - 2; |
Jeff Thompson | 2d27e2f | 2013-08-09 12:55:00 -0700 | [diff] [blame] | 194 | while (value != 0 && i >= self->offset) { |
Jeff Thompson | c978a7b | 2013-08-12 13:17:17 -0700 | [diff] [blame] | 195 | self->output->array[i] = (value & ndn_BinaryXml_REGULAR_VALUE_MASK); |
Jeff Thompson | 2d27e2f | 2013-08-09 12:55:00 -0700 | [diff] [blame] | 196 | value >>= ndn_BinaryXml_REGULAR_VALUE_BITS; |
| 197 | --i; |
| 198 | } |
| 199 | if (value != 0) |
Jeff Thompson | e227689 | 2013-07-08 02:44:18 -0700 | [diff] [blame] | 200 | // This should not happen if getNHeaderEncodingBytes is correct. |
Jeff Thompson | 2d27e2f | 2013-08-09 12:55:00 -0700 | [diff] [blame] | 201 | return NDN_ERROR_encodeTypeAndValue_miscalculated_N_encoding_bytes; |
| 202 | |
| 203 | self->offset+= nEncodingBytes; |
Jeff Thompson | 433e6da | 2013-07-01 15:09:00 -0700 | [diff] [blame] | 204 | |
Jeff Thompson | adaf923 | 2013-08-08 14:30:29 -0700 | [diff] [blame] | 205 | return NDN_ERROR_success; |
Jeff Thompson | 433e6da | 2013-07-01 15:09:00 -0700 | [diff] [blame] | 206 | } |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 207 | |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 208 | ndn_Error ndn_BinaryXmlEncoder_writeElementClose(struct ndn_BinaryXmlEncoder *self) |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 209 | { |
Jeff Thompson | 8b66600 | 2013-07-08 01:16:26 -0700 | [diff] [blame] | 210 | ndn_Error error; |
Jeff Thompson | 10ad12a | 2013-09-24 16:19:11 -0700 | [diff] [blame] | 211 | if ((error = ndn_DynamicUInt8Array_ensureLength(self->output, self->offset + 1))) |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 212 | return error; |
| 213 | |
Jeff Thompson | c978a7b | 2013-08-12 13:17:17 -0700 | [diff] [blame] | 214 | self->output->array[self->offset] = ndn_BinaryXml_CLOSE; |
Jeff Thompson | 2d27e2f | 2013-08-09 12:55:00 -0700 | [diff] [blame] | 215 | self->offset += 1; |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 216 | |
Jeff Thompson | adaf923 | 2013-08-08 14:30:29 -0700 | [diff] [blame] | 217 | return NDN_ERROR_success; |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 218 | } |
| 219 | |
Jeff Thompson | 97223af | 2013-09-24 17:01:27 -0700 | [diff] [blame^] | 220 | ndn_Error ndn_BinaryXmlEncoder_writeBlob(struct ndn_BinaryXmlEncoder *self, uint8_t *value, size_t valueLength) |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 221 | { |
Jeff Thompson | 8b66600 | 2013-07-08 01:16:26 -0700 | [diff] [blame] | 222 | ndn_Error error; |
Jeff Thompson | 94ddc27 | 2013-08-08 14:17:38 -0700 | [diff] [blame] | 223 | if ((error = ndn_BinaryXmlEncoder_encodeTypeAndValue(self, ndn_BinaryXml_BLOB, valueLength))) |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 224 | return error; |
| 225 | |
Jeff Thompson | 94ddc27 | 2013-08-08 14:17:38 -0700 | [diff] [blame] | 226 | if ((error = writeArray(self, value, valueLength))) |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 227 | return error; |
| 228 | |
Jeff Thompson | adaf923 | 2013-08-08 14:30:29 -0700 | [diff] [blame] | 229 | return NDN_ERROR_success; |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 230 | } |
| 231 | |
Jeff Thompson | 97223af | 2013-09-24 17:01:27 -0700 | [diff] [blame^] | 232 | ndn_Error ndn_BinaryXmlEncoder_writeBlobDTagElement(struct ndn_BinaryXmlEncoder *self, unsigned int tag, uint8_t *value, size_t valueLength) |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 233 | { |
Jeff Thompson | 8b66600 | 2013-07-08 01:16:26 -0700 | [diff] [blame] | 234 | ndn_Error error; |
Jeff Thompson | 94ddc27 | 2013-08-08 14:17:38 -0700 | [diff] [blame] | 235 | if ((error = ndn_BinaryXmlEncoder_writeElementStartDTag(self, tag))) |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 236 | return error; |
| 237 | |
Jeff Thompson | 94ddc27 | 2013-08-08 14:17:38 -0700 | [diff] [blame] | 238 | if ((error = ndn_BinaryXmlEncoder_writeBlob(self, value, valueLength))) |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 239 | return error; |
| 240 | |
Jeff Thompson | 94ddc27 | 2013-08-08 14:17:38 -0700 | [diff] [blame] | 241 | if ((error = ndn_BinaryXmlEncoder_writeElementClose(self))) |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 242 | return error; |
| 243 | |
Jeff Thompson | adaf923 | 2013-08-08 14:30:29 -0700 | [diff] [blame] | 244 | return NDN_ERROR_success; |
Jeff Thompson | 5a98483 | 2013-07-01 19:28:27 -0700 | [diff] [blame] | 245 | } |
Jeff Thompson | e227689 | 2013-07-08 02:44:18 -0700 | [diff] [blame] | 246 | |
Jeff Thompson | 97223af | 2013-09-24 17:01:27 -0700 | [diff] [blame^] | 247 | ndn_Error ndn_BinaryXmlEncoder_writeUData(struct ndn_BinaryXmlEncoder *self, uint8_t *value, size_t valueLength) |
Jeff Thompson | 214c26f | 2013-08-27 11:45:01 -0700 | [diff] [blame] | 248 | { |
| 249 | ndn_Error error; |
| 250 | if ((error = ndn_BinaryXmlEncoder_encodeTypeAndValue(self, ndn_BinaryXml_UDATA, valueLength))) |
| 251 | return error; |
| 252 | |
| 253 | if ((error = writeArray(self, value, valueLength))) |
| 254 | return error; |
| 255 | |
| 256 | return NDN_ERROR_success; |
| 257 | } |
| 258 | |
Jeff Thompson | 97223af | 2013-09-24 17:01:27 -0700 | [diff] [blame^] | 259 | ndn_Error ndn_BinaryXmlEncoder_writeUDataDTagElement(struct ndn_BinaryXmlEncoder *self, unsigned int tag, uint8_t *value, size_t valueLength) |
Jeff Thompson | 214c26f | 2013-08-27 11:45:01 -0700 | [diff] [blame] | 260 | { |
| 261 | ndn_Error error; |
| 262 | if ((error = ndn_BinaryXmlEncoder_writeElementStartDTag(self, tag))) |
| 263 | return error; |
| 264 | |
| 265 | if ((error = ndn_BinaryXmlEncoder_writeUData(self, value, valueLength))) |
| 266 | return error; |
| 267 | |
| 268 | if ((error = ndn_BinaryXmlEncoder_writeElementClose(self))) |
| 269 | return error; |
| 270 | |
| 271 | return NDN_ERROR_success; |
| 272 | } |
| 273 | |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 274 | ndn_Error ndn_BinaryXmlEncoder_writeUnsignedDecimalInt(struct ndn_BinaryXmlEncoder *self, unsigned int value) |
Jeff Thompson | e227689 | 2013-07-08 02:44:18 -0700 | [diff] [blame] | 275 | { |
| 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 Thompson | 97223af | 2013-09-24 17:01:27 -0700 | [diff] [blame^] | 277 | size_t startOffset = self->offset; |
Jeff Thompson | e227689 | 2013-07-08 02:44:18 -0700 | [diff] [blame] | 278 | |
| 279 | ndn_Error error; |
Jeff Thompson | 94ddc27 | 2013-08-08 14:17:38 -0700 | [diff] [blame] | 280 | if ((error = encodeReversedUnsignedDecimalInt(self, value))) |
Jeff Thompson | e227689 | 2013-07-08 02:44:18 -0700 | [diff] [blame] | 281 | return error; |
| 282 | |
Jeff Thompson | 94ddc27 | 2013-08-08 14:17:38 -0700 | [diff] [blame] | 283 | if ((error = reverseBufferAndInsertHeader(self, startOffset, ndn_BinaryXml_UDATA))) |
Jeff Thompson | e227689 | 2013-07-08 02:44:18 -0700 | [diff] [blame] | 284 | return error; |
| 285 | |
Jeff Thompson | adaf923 | 2013-08-08 14:30:29 -0700 | [diff] [blame] | 286 | return NDN_ERROR_success; |
Jeff Thompson | e227689 | 2013-07-08 02:44:18 -0700 | [diff] [blame] | 287 | } |
Jeff Thompson | 5b696e0 | 2013-07-08 15:04:22 -0700 | [diff] [blame] | 288 | |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 289 | 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] | 290 | { |
| 291 | ndn_Error error; |
Jeff Thompson | 94ddc27 | 2013-08-08 14:17:38 -0700 | [diff] [blame] | 292 | if ((error = ndn_BinaryXmlEncoder_writeElementStartDTag(self, tag))) |
Jeff Thompson | 5b696e0 | 2013-07-08 15:04:22 -0700 | [diff] [blame] | 293 | return error; |
| 294 | |
Jeff Thompson | 94ddc27 | 2013-08-08 14:17:38 -0700 | [diff] [blame] | 295 | if ((error = ndn_BinaryXmlEncoder_writeUnsignedDecimalInt(self, value))) |
Jeff Thompson | 5b696e0 | 2013-07-08 15:04:22 -0700 | [diff] [blame] | 296 | return error; |
| 297 | |
Jeff Thompson | 94ddc27 | 2013-08-08 14:17:38 -0700 | [diff] [blame] | 298 | if ((error = ndn_BinaryXmlEncoder_writeElementClose(self))) |
Jeff Thompson | 5b696e0 | 2013-07-08 15:04:22 -0700 | [diff] [blame] | 299 | return error; |
| 300 | |
Jeff Thompson | adaf923 | 2013-08-08 14:30:29 -0700 | [diff] [blame] | 301 | return NDN_ERROR_success; |
Jeff Thompson | 5b696e0 | 2013-07-08 15:04:22 -0700 | [diff] [blame] | 302 | } |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 303 | |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 304 | ndn_Error ndn_BinaryXmlEncoder_writeAbsDoubleBigEndianBlob(struct ndn_BinaryXmlEncoder *self, double value) |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 305 | { |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 306 | unsigned long hi32, lo32; |
| 307 | splitAbsDouble(value, &hi32, &lo32); |
| 308 | |
| 309 | // First encode the big endian backwards, then reverseBufferAndInsertHeader will reverse it. |
Jeff Thompson | 97223af | 2013-09-24 17:01:27 -0700 | [diff] [blame^] | 310 | size_t startOffset = self->offset; |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 311 | |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 312 | ndn_Error error; |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 313 | while (lo32 != 0) { |
Jeff Thompson | 10ad12a | 2013-09-24 16:19:11 -0700 | [diff] [blame] | 314 | if ((error = ndn_DynamicUInt8Array_ensureLength(self->output, self->offset + 1))) |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 315 | return error; |
| 316 | |
Jeff Thompson | 10ad12a | 2013-09-24 16:19:11 -0700 | [diff] [blame] | 317 | self->output->array[self->offset++] = (uint8_t)(lo32 & 0xff); |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 318 | lo32 >>= 8; |
| 319 | } |
| 320 | |
| 321 | if (hi32 != 0) { |
| 322 | // Pad the lo values out to 4 bytes. |
| 323 | while (self->offset - startOffset < 4) { |
Jeff Thompson | 10ad12a | 2013-09-24 16:19:11 -0700 | [diff] [blame] | 324 | if ((error = ndn_DynamicUInt8Array_ensureLength(self->output, self->offset + 1))) |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 325 | return error; |
| 326 | |
Jeff Thompson | c978a7b | 2013-08-12 13:17:17 -0700 | [diff] [blame] | 327 | self->output->array[self->offset++] = 0; |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 328 | } |
| 329 | |
| 330 | // Encode hi32 |
| 331 | while (hi32 != 0) { |
Jeff Thompson | 10ad12a | 2013-09-24 16:19:11 -0700 | [diff] [blame] | 332 | if ((error = ndn_DynamicUInt8Array_ensureLength(self->output, self->offset + 1))) |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 333 | return error; |
| 334 | |
Jeff Thompson | 10ad12a | 2013-09-24 16:19:11 -0700 | [diff] [blame] | 335 | self->output->array[self->offset++] = (uint8_t)(hi32 & 0xff); |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 336 | hi32 >>= 8; |
| 337 | } |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 338 | } |
| 339 | |
Jeff Thompson | 94ddc27 | 2013-08-08 14:17:38 -0700 | [diff] [blame] | 340 | if ((error = reverseBufferAndInsertHeader(self, startOffset, ndn_BinaryXml_BLOB))) |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 341 | return error; |
| 342 | |
Jeff Thompson | adaf923 | 2013-08-08 14:30:29 -0700 | [diff] [blame] | 343 | return NDN_ERROR_success; |
Jeff Thompson | a259cc4 | 2013-07-08 17:14:09 -0700 | [diff] [blame] | 344 | } |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 345 | |
Jeff Thompson | f0fea00 | 2013-07-30 17:22:42 -0700 | [diff] [blame] | 346 | 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] | 347 | { |
| 348 | ndn_Error error; |
Jeff Thompson | 94ddc27 | 2013-08-08 14:17:38 -0700 | [diff] [blame] | 349 | if ((error = ndn_BinaryXmlEncoder_writeElementStartDTag(self, tag))) |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 350 | return error; |
| 351 | |
Jeff Thompson | 94ddc27 | 2013-08-08 14:17:38 -0700 | [diff] [blame] | 352 | if ((error = ndn_BinaryXmlEncoder_writeAbsDoubleBigEndianBlob(self, (milliseconds / 1000.0) * 4096.0))) |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 353 | return error; |
| 354 | |
Jeff Thompson | 94ddc27 | 2013-08-08 14:17:38 -0700 | [diff] [blame] | 355 | if ((error = ndn_BinaryXmlEncoder_writeElementClose(self))) |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 356 | return error; |
| 357 | |
Jeff Thompson | adaf923 | 2013-08-08 14:30:29 -0700 | [diff] [blame] | 358 | return NDN_ERROR_success; |
Jeff Thompson | edc2225 | 2013-07-11 18:05:44 -0700 | [diff] [blame] | 359 | } |