blob: c70a44ac41e4a93d2ad61653f8a8f9ca199447c0 [file] [log] [blame]
Jeff Thompsonc8963652013-06-28 20:17:43 -07001/*
2 * Author: Jeff Thompson
3 *
4 * BSD license, See the LICENSE file for more information.
5 */
6
Jeff Thompson590b8692013-06-28 22:07:41 -07007#include "BinaryXML.h"
Jeff Thompsonc8963652013-06-28 20:17:43 -07008#include "BinaryXMLEncoder.h"
Jeff Thompson590b8692013-06-28 22:07:41 -07009
10enum {
11 ENCODING_LIMIT_1_BYTE = ((1 << ndn_BinaryXML_TT_VALUE_BITS) - 1),
12 ENCODING_LIMIT_2_BYTES = ((1 << (ndn_BinaryXML_TT_VALUE_BITS + ndn_BinaryXML_REGULAR_VALUE_BITS)) - 1),
13 ENCODING_LIMIT_3_BYTES = ((1 << (ndn_BinaryXML_TT_VALUE_BITS + 2 * ndn_BinaryXML_REGULAR_VALUE_BITS)) - 1)
14};
15
16/**
17 * Return the number of bytes to encode a header of value x.
18 */
19static unsigned int getNEncodingBytes(unsigned int x)
20{
21 // Do a quick check for pre-compiled results.
22 if (x <= ENCODING_LIMIT_1_BYTE)
23 return 1;
24 if (x <= ENCODING_LIMIT_2_BYTES)
25 return 2;
26 if (x <= ENCODING_LIMIT_3_BYTES)
27 return 3;
28
29 unsigned int nBytes = 1;
30
31 // Last byte gives you TT_VALUE_BITS.
32 // Remainder each gives you REGULAR_VALUE_BITS.
33 x >>= ndn_BinaryXML_TT_VALUE_BITS;
34 while (x != 0) {
35 ++nBytes;
36 x >>= ndn_BinaryXML_REGULAR_VALUE_BITS;
37 }
38
39 return nBytes;
40}
Jeff Thompson433e6da2013-07-01 15:09:00 -070041
42char *ndn_BinaryXMLEncoder_encodeTypeAndValue(struct ndn_BinaryXMLEncoder *self, unsigned int type, unsigned int value)
43{
44 if (type > ndn_BinaryXML_UDATA)
45 return "ndn_BinaryXMLEncoder_encodeTypeAndValue: type is out of range";
46
47 // Encode backwards. Calculate how many bytes we need.
48 unsigned int nEncodingBytes = getNEncodingBytes(value);
49 char *error;
50 if (error = ndn_DynamicUCharArray_ensureLength(&self->output, self->offset + nEncodingBytes))
51 return error;
52
53 // Bottom 4 bits of value go in last byte with tag.
54 self->output.array[self->offset + nEncodingBytes - 1] =
55 (ndn_BinaryXML_TT_MASK & type |
56 ((ndn_BinaryXML_TT_VALUE_MASK & value) << ndn_BinaryXML_TT_BITS)) |
57 ndn_BinaryXML_TT_FINAL; // set top bit for last byte
58 value >>= ndn_BinaryXML_TT_VALUE_BITS;
59
60 // Rest of value goes into preceding bytes, 7 bits per byte. (Zero top bit is "more" flag.)
61 unsigned int i = self->offset + nEncodingBytes - 2;
62 while (value != 0 && i >= self->offset) {
63 self->output.array[i] = (value & ndn_BinaryXML_REGULAR_VALUE_MASK);
64 value >>= ndn_BinaryXML_REGULAR_VALUE_BITS;
65 --i;
66 }
67 if (value != 0)
68 // This should not happen if getNEncodingBytes is correct.
69 return "ndn_BinaryXMLEncoder_encodeTypeAndValue: : miscalculated N encoding bytes";
70
71 self->offset+= nEncodingBytes;
72
73 return 0;
74}