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