blob: f5e49288fd3efa5abf6e17182190d217f6c1d47c [file] [log] [blame]
Jeff Thompson76317aa2013-06-25 19:11:48 -07001/*
2 * Author: Jeff Thompson
3 *
4 * BSD license, See the LICENSE file for more information.
5 */
6
7#include "BinaryXML.h"
8#include "BinaryXMLDecoder.h"
9
Jeff Thompsonb4ee4002013-06-28 13:41:43 -070010/**
11 * Return the octet at self->offset, converting to unsigned int. Increment self->offset.
12 * This does not check for reading past the end of the input, so this is called "unsafe".
13 */
14static inline unsigned int unsafeReadOctet(struct ndn_BinaryXMLDecoder *self)
15{
16 return (unsigned int)(self->input[self->offset++] & 0xff);
17}
18
19/**
20 * Return the octet at self->offset, converting to unsigned int. Do not increment self->offset.
21 * This does not check for reading past the end of the input, so this is called "unsafe".
22 */
23static inline unsigned int unsafeGetOctet(struct ndn_BinaryXMLDecoder *self)
24{
25 return (unsigned int)(self->input[self->offset] & 0xff);
26}
27
Jeff Thompsond6f13282013-06-27 17:31:50 -070028char *ndn_BinaryXMLDecoder_decodeTypeAndValue(struct ndn_BinaryXMLDecoder *self, unsigned int *type, unsigned int *valueOut)
Jeff Thompson82222e82013-06-26 19:32:59 -070029{
Jeff Thompson76317aa2013-06-25 19:11:48 -070030 unsigned int value = 0;
Jeff Thompson38cbd572013-06-28 14:01:10 -070031 int gotFirstOctet = 0;
Jeff Thompson76317aa2013-06-25 19:11:48 -070032
33 while (1) {
Jeff Thompsonf7316692013-06-26 21:31:42 -070034 if (self->offset >= self->inputLength)
Jeff Thompson04c0b6a2013-06-28 13:49:13 -070035 return "ndn_BinaryXMLDecoder_decodeTypeAndVal: read past the end of the input";
Jeff Thompson76317aa2013-06-25 19:11:48 -070036
Jeff Thompsonb4ee4002013-06-28 13:41:43 -070037 unsigned int octet = unsafeReadOctet(self);
Jeff Thompson76317aa2013-06-25 19:11:48 -070038
Jeff Thompson38cbd572013-06-28 14:01:10 -070039 if (!gotFirstOctet) {
40 if (octet == 0)
41 return "ndn_BinaryXMLDecoder_decodeTypeAndVal: the first header octet may not be zero";
42
43 gotFirstOctet = 1;
44 }
45
Jeff Thompson76317aa2013-06-25 19:11:48 -070046 if (octet & ndn_BinaryXML_TT_FINAL) {
47 // Finished.
48 *type = octet & ndn_BinaryXML_TT_MASK;
49 value = (value << ndn_BinaryXML_TT_VALUE_BITS) | ((octet >> ndn_BinaryXML_TT_BITS) & ndn_BinaryXML_TT_VALUE_MASK);
50 break;
51 }
52
53 value = (value << ndn_BinaryXML_REGULAR_VALUE_BITS) | (octet & ndn_BinaryXML_REGULAR_VALUE_MASK);
54 }
55
56 *valueOut = value;
Jeff Thompsonb4ee4002013-06-28 13:41:43 -070057 return 0;
Jeff Thompson76317aa2013-06-25 19:11:48 -070058}
Jeff Thompson179d0502013-06-28 11:36:00 -070059
Jeff Thompson74ab0812013-06-28 12:25:04 -070060char *ndn_BinaryXMLDecoder_readDTag(struct ndn_BinaryXMLDecoder *self, unsigned int expectedTag)
Jeff Thompson179d0502013-06-28 11:36:00 -070061{
62 char *error;
63 unsigned int type;
64 unsigned int value;
65 if (error = ndn_BinaryXMLDecoder_decodeTypeAndValue(self, &type, &value))
66 return error;
67
68 if (type != ndn_BinaryXML_DTAG)
69 return "ndn_BinaryXMLDecoder_readDTag: header type is not a DTAG";
70
Jeff Thompson74ab0812013-06-28 12:25:04 -070071 if (value != expectedTag)
Jeff Thompson179d0502013-06-28 11:36:00 -070072 return "ndn_BinaryXMLDecoder_readDTag: did not get the expected DTAG";
73
Jeff Thompsonb4ee4002013-06-28 13:41:43 -070074 return 0;
Jeff Thompson74ab0812013-06-28 12:25:04 -070075}
76
77char *ndn_BinaryXMLDecoder_readElementClose(struct ndn_BinaryXMLDecoder *self)
78{
79 if (self->offset >= self->inputLength)
Jeff Thompson04c0b6a2013-06-28 13:49:13 -070080 return "ndn_BinaryXMLDecoder_readElementClose: read past the end of the input";
Jeff Thompson74ab0812013-06-28 12:25:04 -070081
Jeff Thompsonb4ee4002013-06-28 13:41:43 -070082 if (unsafeReadOctet(self) != ndn_BinaryXML_CLOSE)
Jeff Thompson74ab0812013-06-28 12:25:04 -070083 return "ndn_BinaryXMLDecoder_readDTag: did not get the expected element close";
84
Jeff Thompsonb4ee4002013-06-28 13:41:43 -070085 return 0;
Jeff Thompson74ab0812013-06-28 12:25:04 -070086}
87
88char *ndn_BinaryXMLDecoder_peekDTag(struct ndn_BinaryXMLDecoder *self, unsigned int expectedTag, int *gotExpectedTag)
89{
90 // Default to 0.
91 *gotExpectedTag = 0;
92
93 unsigned int type;
94 unsigned int value;
95 unsigned int saveOffset = self->offset;
96 char *error = ndn_BinaryXMLDecoder_decodeTypeAndValue(self, &type, &value);
Jeff Thompsonb4ee4002013-06-28 13:41:43 -070097 // Restore offset.
Jeff Thompson74ab0812013-06-28 12:25:04 -070098 self->offset = saveOffset;
99
100 if (error)
101 return error;
102
103 if (type == ndn_BinaryXML_DTAG && value == expectedTag)
104 *gotExpectedTag = 1;
105
Jeff Thompsonb4ee4002013-06-28 13:41:43 -0700106 return 0;
107}
108
109char *ndn_BinaryXMLDecoder_readBinaryDTagElement
110 (struct ndn_BinaryXMLDecoder *self, unsigned int expectedTag, int allowNull, unsigned char **value, unsigned int *valueLen)
111{
112 char *error;
113 if (error = ndn_BinaryXMLDecoder_readDTag(self, expectedTag))
114 return error;
115
116 if (allowNull) {
117 if (self->offset >= self->inputLength)
Jeff Thompson04c0b6a2013-06-28 13:49:13 -0700118 return "ndn_BinaryXMLDecoder_readBinaryDTagElement: read past the end of the input";
Jeff Thompsonb4ee4002013-06-28 13:41:43 -0700119
120 if (unsafeGetOctet(self) == ndn_BinaryXML_CLOSE) {
121 // The binary item is missing, and this is allowed, so read the element close and return a null value.
122 ++self->offset;
123 *value = 0;
124 *valueLen = 0;
125 return 0;
126 }
127 }
128
129 unsigned int itemType;
130 if (error = ndn_BinaryXMLDecoder_decodeTypeAndValue(self, &itemType, valueLen))
131 return error;
132 // Ignore itemType.
133 *value = self->input + self->offset;
134 self->offset += *valueLen;
135
136 if (error = ndn_BinaryXMLDecoder_readElementClose(self))
137 return error;
138
139 return 0;
140}