blob: ad329099ed35cbbf0d052196d029bd6264cd5a80 [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;
31
32 while (1) {
Jeff Thompsonf7316692013-06-26 21:31:42 -070033 if (self->offset >= self->inputLength)
Jeff Thompson04c0b6a2013-06-28 13:49:13 -070034 return "ndn_BinaryXMLDecoder_decodeTypeAndVal: read past the end of the input";
Jeff Thompson76317aa2013-06-25 19:11:48 -070035
Jeff Thompsonb4ee4002013-06-28 13:41:43 -070036 unsigned int octet = unsafeReadOctet(self);
Jeff Thompson76317aa2013-06-25 19:11:48 -070037
38 if (octet & ndn_BinaryXML_TT_FINAL) {
39 // Finished.
40 *type = octet & ndn_BinaryXML_TT_MASK;
41 value = (value << ndn_BinaryXML_TT_VALUE_BITS) | ((octet >> ndn_BinaryXML_TT_BITS) & ndn_BinaryXML_TT_VALUE_MASK);
42 break;
43 }
44
45 value = (value << ndn_BinaryXML_REGULAR_VALUE_BITS) | (octet & ndn_BinaryXML_REGULAR_VALUE_MASK);
46 }
47
48 *valueOut = value;
Jeff Thompsonb4ee4002013-06-28 13:41:43 -070049 return 0;
Jeff Thompson76317aa2013-06-25 19:11:48 -070050}
Jeff Thompson179d0502013-06-28 11:36:00 -070051
Jeff Thompson74ab0812013-06-28 12:25:04 -070052char *ndn_BinaryXMLDecoder_readDTag(struct ndn_BinaryXMLDecoder *self, unsigned int expectedTag)
Jeff Thompson179d0502013-06-28 11:36:00 -070053{
54 char *error;
55 unsigned int type;
56 unsigned int value;
57 if (error = ndn_BinaryXMLDecoder_decodeTypeAndValue(self, &type, &value))
58 return error;
59
60 if (type != ndn_BinaryXML_DTAG)
61 return "ndn_BinaryXMLDecoder_readDTag: header type is not a DTAG";
62
Jeff Thompson74ab0812013-06-28 12:25:04 -070063 if (value != expectedTag)
Jeff Thompson179d0502013-06-28 11:36:00 -070064 return "ndn_BinaryXMLDecoder_readDTag: did not get the expected DTAG";
65
Jeff Thompsonb4ee4002013-06-28 13:41:43 -070066 return 0;
Jeff Thompson74ab0812013-06-28 12:25:04 -070067}
68
69char *ndn_BinaryXMLDecoder_readElementClose(struct ndn_BinaryXMLDecoder *self)
70{
71 if (self->offset >= self->inputLength)
Jeff Thompson04c0b6a2013-06-28 13:49:13 -070072 return "ndn_BinaryXMLDecoder_readElementClose: read past the end of the input";
Jeff Thompson74ab0812013-06-28 12:25:04 -070073
Jeff Thompsonb4ee4002013-06-28 13:41:43 -070074 if (unsafeReadOctet(self) != ndn_BinaryXML_CLOSE)
Jeff Thompson74ab0812013-06-28 12:25:04 -070075 return "ndn_BinaryXMLDecoder_readDTag: did not get the expected element close";
76
Jeff Thompsonb4ee4002013-06-28 13:41:43 -070077 return 0;
Jeff Thompson74ab0812013-06-28 12:25:04 -070078}
79
80char *ndn_BinaryXMLDecoder_peekDTag(struct ndn_BinaryXMLDecoder *self, unsigned int expectedTag, int *gotExpectedTag)
81{
82 // Default to 0.
83 *gotExpectedTag = 0;
84
85 unsigned int type;
86 unsigned int value;
87 unsigned int saveOffset = self->offset;
88 char *error = ndn_BinaryXMLDecoder_decodeTypeAndValue(self, &type, &value);
Jeff Thompsonb4ee4002013-06-28 13:41:43 -070089 // Restore offset.
Jeff Thompson74ab0812013-06-28 12:25:04 -070090 self->offset = saveOffset;
91
92 if (error)
93 return error;
94
95 if (type == ndn_BinaryXML_DTAG && value == expectedTag)
96 *gotExpectedTag = 1;
97
Jeff Thompsonb4ee4002013-06-28 13:41:43 -070098 return 0;
99}
100
101char *ndn_BinaryXMLDecoder_readBinaryDTagElement
102 (struct ndn_BinaryXMLDecoder *self, unsigned int expectedTag, int allowNull, unsigned char **value, unsigned int *valueLen)
103{
104 char *error;
105 if (error = ndn_BinaryXMLDecoder_readDTag(self, expectedTag))
106 return error;
107
108 if (allowNull) {
109 if (self->offset >= self->inputLength)
Jeff Thompson04c0b6a2013-06-28 13:49:13 -0700110 return "ndn_BinaryXMLDecoder_readBinaryDTagElement: read past the end of the input";
Jeff Thompsonb4ee4002013-06-28 13:41:43 -0700111
112 if (unsafeGetOctet(self) == ndn_BinaryXML_CLOSE) {
113 // The binary item is missing, and this is allowed, so read the element close and return a null value.
114 ++self->offset;
115 *value = 0;
116 *valueLen = 0;
117 return 0;
118 }
119 }
120
121 unsigned int itemType;
122 if (error = ndn_BinaryXMLDecoder_decodeTypeAndValue(self, &itemType, valueLen))
123 return error;
124 // Ignore itemType.
125 *value = self->input + self->offset;
126 self->offset += *valueLen;
127
128 if (error = ndn_BinaryXMLDecoder_readElementClose(self))
129 return error;
130
131 return 0;
132}