blob: e5668d6fcc5afc5f77bd3fe1efe07c1617e130e3 [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
Jeff Thompson9dc10732013-06-26 21:40:32 -07007#include <memory.h>
8#include "BinaryXML.h"
9#include "BinaryXMLDecoder.h"
Jeff Thompson76317aa2013-06-25 19:11:48 -070010#include "BinaryXMLStructureDecoder.h"
11
Jeff Thompson9dc10732013-06-26 21:40:32 -070012void ndn_BinaryXMLStructureDecoder_init(struct ndn_BinaryXMLStructureDecoder *self)
13{
Jeff Thompson76317aa2013-06-25 19:11:48 -070014 self->gotElementEnd = 0;
15 self->offset = 0;
16 self->level = 0;
17 self->state = ndn_BinaryXMLStructureDecoder_READ_HEADER_OR_CLOSE;
18 self->headerLength = 0;
19 self->useHeaderBuffer = 0;
20 self->nBytesToRead = 0;
21}
Jeff Thompson9dc10732013-06-26 21:40:32 -070022
23/**
24 * Set the state to READ_HEADER_OR_CLOSE and set up to start reading the header.
25 */
26static inline void startHeader(struct ndn_BinaryXMLStructureDecoder *self) {
27 self->headerLength = 0;
28 self->useHeaderBuffer = 0;
29 self->state = ndn_BinaryXMLStructureDecoder_READ_HEADER_OR_CLOSE;
30}
31
32const char *ndn_BinaryXMLStructureDecoder_findElementEnd
33 (struct ndn_BinaryXMLStructureDecoder *self, const unsigned char *input, unsigned int inputLength)
34{
35 if (self->gotElementEnd)
36 // Someone is calling when we already got the end.
37 return (const char *)0;
38
39 struct ndn_BinaryXMLDecoder decoder;
40 ndn_BinaryXMLDecoder_init(&decoder, input, inputLength);
41
42 while (1) {
43 if (self->offset >= inputLength)
44 // All the cases assume we have some input. Return and wait for more.
45 return (const char *)0;
46
47 if (self->state == ndn_BinaryXMLStructureDecoder_READ_HEADER_OR_CLOSE) {
48 // First check for CLOSE.
49 if (self->headerLength == 0 && input[self->offset] == ndn_BinaryXML_CLOSE) {
50 ++self->offset;
51 // Close the level.
52 --self->level;
53 if (self->level == 0) {
54 // Finished.
55 self->gotElementEnd = 1;
56 return (const char *)0;
57 }
58 if (self->level < 0)
59 return "ndn_BinaryXMLStructureDecoder_findElementEnd: Unexpected close tag";
60
61 // Get ready for the next header.
62 startHeader(self);
63 continue;
64 }
65
66 unsigned int startingHeaderLength = self->headerLength;
67 while (1) {
68 if (self->offset >= inputLength) {
69 // We can't get all of the header bytes from this input. Save in headerBuffer.
70 if (self->headerLength > sizeof(self->headerBuffer))
71 return "ndn_BinaryXMLStructureDecoder_findElementEnd: Can't store more header bytes than the size of headerBuffer";
72 self->useHeaderBuffer = 1;
73 unsigned int nNewBytes = self->headerLength - startingHeaderLength;
74 memcpy(self->headerBuffer + startingHeaderLength, input + (self->offset - nNewBytes), nNewBytes);
75
76 return (const char *)0;
77 }
78 unsigned int headerByte = (unsigned int)input[self->offset++];
79 ++self->headerLength;
80 if (headerByte & ndn_BinaryXML_TT_FINAL)
81 // Break and read the header.
82 break;
83 }
84
85 unsigned int type;
86 unsigned int value;
87 if (self->useHeaderBuffer) {
88 // Copy the remaining bytes into headerBuffer.
89 if (self->headerLength > sizeof(self->headerBuffer))
90 return "ndn_BinaryXMLStructureDecoder_findElementEnd: Can't store more header bytes than the size of headerBuffer";
91 unsigned int nNewBytes = self->headerLength - startingHeaderLength;
92 memcpy(self->headerBuffer + startingHeaderLength, input + (self->offset - nNewBytes), nNewBytes);
93
94 // Use a local decoder just for the headerBuffer.
95 struct ndn_BinaryXMLDecoder bufferDecoder;
96 ndn_BinaryXMLDecoder_init(&bufferDecoder, self->headerBuffer, sizeof(self->headerBuffer));
97 if (ndn_BinaryXMLDecoder_decodeTypeAndValue(&decoder, &type, &value))
98 return "ndn_BinaryXMLStructureDecoder_findElementEnd: Can't read header type and value";
99 }
100 else {
101 // We didn't have to use the headerBuffer.
102 ndn_BinaryXMLDecoder_seek(&decoder, self->offset - self->headerLength);
103 if (ndn_BinaryXMLDecoder_decodeTypeAndValue(&decoder, &type, &value))
104 return "ndn_BinaryXMLStructureDecoder_findElementEnd: Can't read header type and value";
105 }
106
107 // Set the next state based on the type.
108 if (type == ndn_BinaryXML_DATTR)
109 // We already consumed the item. READ_HEADER_OR_CLOSE again.
110 // Binary XML has rules about what must follow an attribute, but we are just scanning.
111 startHeader(self);
112 else if (type == ndn_BinaryXML_DTAG || type == ndn_BinaryXML_EXT) {
113 // Start a new level and READ_HEADER_OR_CLOSE again.
114 ++self->level;
115 startHeader(self);
116 }
117 else if (type == ndn_BinaryXML_TAG || type == ndn_BinaryXML_ATTR) {
118 if (type == ndn_BinaryXML_TAG)
119 // Start a new level and read the tag.
120 ++self->level;
121 // Minimum tag or attribute length is 1.
122 self->nBytesToRead = value + 1;
123 self->state = ndn_BinaryXMLStructureDecoder_READ_BYTES;
124 // Binary XML has rules about what must follow an attribute, but we are just scanning.
125 }
126 else if (type == ndn_BinaryXML_BLOB || type == ndn_BinaryXML_UDATA) {
127 self->nBytesToRead = value;
128 self->state = ndn_BinaryXMLStructureDecoder_READ_BYTES;
129 }
130 else
131 return "ndn_BinaryXMLStructureDecoder_findElementEnd: Unrecognized header type";
132 }
133 else if (self->state == ndn_BinaryXMLStructureDecoder_READ_BYTES) {
134 unsigned int nRemainingBytes = inputLength - self->offset;
135 if (nRemainingBytes < self->nBytesToRead) {
136 // Need more.
137 self->offset += nRemainingBytes;
138 self->nBytesToRead -= nRemainingBytes;
139 return (const char *)0;
140 }
141 // Got the bytes. Read a new header or close.
142 self->offset += self->nBytesToRead;
143 startHeader(self);
144 }
145 else
146 // We don't expect this to happen.
147 return "ndn_BinaryXMLStructureDecoder_findElementEnd: Unrecognized state";
148 }
149}