blob: 6a8900a94c3bc1d2dfa053bf582b34951403fb45 [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;
Jeff Thompson6d17b6e2013-06-28 14:04:01 -070092
93 // First check if it is an element close (which cannot be the expected tag).
94 if (self->offset >= self->inputLength)
95 return "ndn_BinaryXMLDecoder_readElementClose: read past the end of the input";
96 if (unsafeGetOctet(self) == 0)
97 return 0;
98
Jeff Thompson74ab0812013-06-28 12:25:04 -070099 unsigned int type;
100 unsigned int value;
101 unsigned int saveOffset = self->offset;
102 char *error = ndn_BinaryXMLDecoder_decodeTypeAndValue(self, &type, &value);
Jeff Thompsonb4ee4002013-06-28 13:41:43 -0700103 // Restore offset.
Jeff Thompson74ab0812013-06-28 12:25:04 -0700104 self->offset = saveOffset;
105
106 if (error)
107 return error;
108
109 if (type == ndn_BinaryXML_DTAG && value == expectedTag)
110 *gotExpectedTag = 1;
111
Jeff Thompsonb4ee4002013-06-28 13:41:43 -0700112 return 0;
113}
114
115char *ndn_BinaryXMLDecoder_readBinaryDTagElement
116 (struct ndn_BinaryXMLDecoder *self, unsigned int expectedTag, int allowNull, unsigned char **value, unsigned int *valueLen)
117{
118 char *error;
119 if (error = ndn_BinaryXMLDecoder_readDTag(self, expectedTag))
120 return error;
121
122 if (allowNull) {
123 if (self->offset >= self->inputLength)
Jeff Thompson04c0b6a2013-06-28 13:49:13 -0700124 return "ndn_BinaryXMLDecoder_readBinaryDTagElement: read past the end of the input";
Jeff Thompsonb4ee4002013-06-28 13:41:43 -0700125
126 if (unsafeGetOctet(self) == ndn_BinaryXML_CLOSE) {
127 // The binary item is missing, and this is allowed, so read the element close and return a null value.
128 ++self->offset;
129 *value = 0;
130 *valueLen = 0;
131 return 0;
132 }
133 }
134
135 unsigned int itemType;
136 if (error = ndn_BinaryXMLDecoder_decodeTypeAndValue(self, &itemType, valueLen))
137 return error;
138 // Ignore itemType.
139 *value = self->input + self->offset;
140 self->offset += *valueLen;
141
142 if (error = ndn_BinaryXMLDecoder_readElementClose(self))
143 return error;
144
145 return 0;
146}