blob: 6a3d417b68c018037b6baf0420be220c22070328 [file] [log] [blame]
Jeff Thompson47eecfc2013-07-07 22:56:46 -07001/**
2 * @author: Jeff Thompson
3 * See COPYING for copyright and distribution information.
Jeff Thompson76317aa2013-06-25 19:11:48 -07004 */
5
Jeff Thompsonf418fe02013-06-27 17:28:55 -07006#include "../util/ndn_memory.h"
Jeff Thompson53412192013-08-06 13:35:50 -07007#include "binary-xml.h"
8#include "binary-xml-decoder.h"
9#include "binary-xml-structure-decoder.h"
Jeff Thompson76317aa2013-06-25 19:11:48 -070010
Jeff Thompsonf0fea002013-07-30 17:22:42 -070011void ndn_BinaryXmlStructureDecoder_init(struct ndn_BinaryXmlStructureDecoder *self)
Jeff Thompson9dc10732013-06-26 21:40:32 -070012{
Jeff Thompson76317aa2013-06-25 19:11:48 -070013 self->gotElementEnd = 0;
14 self->offset = 0;
15 self->level = 0;
Jeff Thompsonf0fea002013-07-30 17:22:42 -070016 self->state = ndn_BinaryXmlStructureDecoder_READ_HEADER_OR_CLOSE;
Jeff Thompson76317aa2013-06-25 19:11:48 -070017 self->headerLength = 0;
18 self->useHeaderBuffer = 0;
19 self->nBytesToRead = 0;
20}
Jeff Thompson9dc10732013-06-26 21:40:32 -070021
22/**
23 * Set the state to READ_HEADER_OR_CLOSE and set up to start reading the header.
24 */
Jeff Thompsonf0fea002013-07-30 17:22:42 -070025static inline void startHeader(struct ndn_BinaryXmlStructureDecoder *self)
Jeff Thompson7afc98e2013-06-27 14:33:53 -070026{
Jeff Thompson9dc10732013-06-26 21:40:32 -070027 self->headerLength = 0;
28 self->useHeaderBuffer = 0;
Jeff Thompsonf0fea002013-07-30 17:22:42 -070029 self->state = ndn_BinaryXmlStructureDecoder_READ_HEADER_OR_CLOSE;
Jeff Thompson9dc10732013-06-26 21:40:32 -070030}
31
Jeff Thompsonf0fea002013-07-30 17:22:42 -070032ndn_Error ndn_BinaryXmlStructureDecoder_findElementEnd
33 (struct ndn_BinaryXmlStructureDecoder *self, unsigned char *input, unsigned int inputLength)
Jeff Thompson9dc10732013-06-26 21:40:32 -070034{
35 if (self->gotElementEnd)
36 // Someone is calling when we already got the end.
Jeff Thompsonadaf9232013-08-08 14:30:29 -070037 return NDN_ERROR_success;
Jeff Thompson9dc10732013-06-26 21:40:32 -070038
Jeff Thompsonf0fea002013-07-30 17:22:42 -070039 struct ndn_BinaryXmlDecoder decoder;
40 ndn_BinaryXmlDecoder_init(&decoder, input, inputLength);
Jeff Thompson9dc10732013-06-26 21:40:32 -070041
42 while (1) {
43 if (self->offset >= inputLength)
44 // All the cases assume we have some input. Return and wait for more.
Jeff Thompsonadaf9232013-08-08 14:30:29 -070045 return NDN_ERROR_success;
Jeff Thompson9dc10732013-06-26 21:40:32 -070046
Jeff Thompsonf0fea002013-07-30 17:22:42 -070047 if (self->state == ndn_BinaryXmlStructureDecoder_READ_HEADER_OR_CLOSE) {
Jeff Thompson9dc10732013-06-26 21:40:32 -070048 // First check for CLOSE.
Jeff Thompsonf0fea002013-07-30 17:22:42 -070049 if (self->headerLength == 0 && input[self->offset] == ndn_BinaryXml_CLOSE) {
Jeff Thompson9dc10732013-06-26 21:40:32 -070050 ++self->offset;
51 // Close the level.
52 --self->level;
53 if (self->level == 0) {
54 // Finished.
55 self->gotElementEnd = 1;
Jeff Thompsonadaf9232013-08-08 14:30:29 -070056 return NDN_ERROR_success;
Jeff Thompson9dc10732013-06-26 21:40:32 -070057 }
58 if (self->level < 0)
Jeff Thompson8b666002013-07-08 01:16:26 -070059 return NDN_ERROR_findElementEnd_unexpected_close_tag;
Jeff Thompson9dc10732013-06-26 21:40:32 -070060
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))
Jeff Thompson8b666002013-07-08 01:16:26 -070071 return NDN_ERROR_cannot_store_more_header_bytes_than_the_size_of_headerBuffer;
Jeff Thompson9dc10732013-06-26 21:40:32 -070072 self->useHeaderBuffer = 1;
73 unsigned int nNewBytes = self->headerLength - startingHeaderLength;
Jeff Thompsonf418fe02013-06-27 17:28:55 -070074 ndn_memcpy(self->headerBuffer + startingHeaderLength, input + (self->offset - nNewBytes), nNewBytes);
Jeff Thompson9dc10732013-06-26 21:40:32 -070075
Jeff Thompsonadaf9232013-08-08 14:30:29 -070076 return NDN_ERROR_success;
Jeff Thompson9dc10732013-06-26 21:40:32 -070077 }
78 unsigned int headerByte = (unsigned int)input[self->offset++];
79 ++self->headerLength;
Jeff Thompsonf0fea002013-07-30 17:22:42 -070080 if (headerByte & ndn_BinaryXml_TT_FINAL)
Jeff Thompson9dc10732013-06-26 21:40:32 -070081 // 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))
Jeff Thompson8b666002013-07-08 01:16:26 -070090 return NDN_ERROR_cannot_store_more_header_bytes_than_the_size_of_headerBuffer;
Jeff Thompson9dc10732013-06-26 21:40:32 -070091 unsigned int nNewBytes = self->headerLength - startingHeaderLength;
Jeff Thompsonf418fe02013-06-27 17:28:55 -070092 ndn_memcpy(self->headerBuffer + startingHeaderLength, input + (self->offset - nNewBytes), nNewBytes);
Jeff Thompson9dc10732013-06-26 21:40:32 -070093
94 // Use a local decoder just for the headerBuffer.
Jeff Thompsonf0fea002013-07-30 17:22:42 -070095 struct ndn_BinaryXmlDecoder bufferDecoder;
96 ndn_BinaryXmlDecoder_init(&bufferDecoder, self->headerBuffer, sizeof(self->headerBuffer));
97 if (ndn_BinaryXmlDecoder_decodeTypeAndValue(&bufferDecoder, &type, &value))
Jeff Thompson8b666002013-07-08 01:16:26 -070098 return NDN_ERROR_findElementEnd_cannot_read_header_type_and_value;
Jeff Thompson9dc10732013-06-26 21:40:32 -070099 }
100 else {
101 // We didn't have to use the headerBuffer.
Jeff Thompsonf0fea002013-07-30 17:22:42 -0700102 ndn_BinaryXmlDecoder_seek(&decoder, self->offset - self->headerLength);
103 if (ndn_BinaryXmlDecoder_decodeTypeAndValue(&decoder, &type, &value))
Jeff Thompson8b666002013-07-08 01:16:26 -0700104 return NDN_ERROR_findElementEnd_cannot_read_header_type_and_value;
Jeff Thompson9dc10732013-06-26 21:40:32 -0700105 }
106
107 // Set the next state based on the type.
Jeff Thompsonf0fea002013-07-30 17:22:42 -0700108 if (type == ndn_BinaryXml_DATTR)
Jeff Thompson9dc10732013-06-26 21:40:32 -0700109 // 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);
Jeff Thompsonf0fea002013-07-30 17:22:42 -0700112 else if (type == ndn_BinaryXml_DTAG || type == ndn_BinaryXml_EXT) {
Jeff Thompson9dc10732013-06-26 21:40:32 -0700113 // Start a new level and READ_HEADER_OR_CLOSE again.
114 ++self->level;
115 startHeader(self);
116 }
Jeff Thompsonf0fea002013-07-30 17:22:42 -0700117 else if (type == ndn_BinaryXml_TAG || type == ndn_BinaryXml_ATTR) {
118 if (type == ndn_BinaryXml_TAG)
Jeff Thompson9dc10732013-06-26 21:40:32 -0700119 // Start a new level and read the tag.
120 ++self->level;
121 // Minimum tag or attribute length is 1.
122 self->nBytesToRead = value + 1;
Jeff Thompsonf0fea002013-07-30 17:22:42 -0700123 self->state = ndn_BinaryXmlStructureDecoder_READ_BYTES;
Jeff Thompson9dc10732013-06-26 21:40:32 -0700124 // Binary XML has rules about what must follow an attribute, but we are just scanning.
125 }
Jeff Thompsonf0fea002013-07-30 17:22:42 -0700126 else if (type == ndn_BinaryXml_BLOB || type == ndn_BinaryXml_UDATA) {
Jeff Thompson9dc10732013-06-26 21:40:32 -0700127 self->nBytesToRead = value;
Jeff Thompsonf0fea002013-07-30 17:22:42 -0700128 self->state = ndn_BinaryXmlStructureDecoder_READ_BYTES;
Jeff Thompson9dc10732013-06-26 21:40:32 -0700129 }
130 else
Jeff Thompson8b666002013-07-08 01:16:26 -0700131 return NDN_ERROR_findElementEnd_unrecognized_header_type;
Jeff Thompson9dc10732013-06-26 21:40:32 -0700132 }
Jeff Thompsonf0fea002013-07-30 17:22:42 -0700133 else if (self->state == ndn_BinaryXmlStructureDecoder_READ_BYTES) {
Jeff Thompson9dc10732013-06-26 21:40:32 -0700134 unsigned int nRemainingBytes = inputLength - self->offset;
135 if (nRemainingBytes < self->nBytesToRead) {
136 // Need more.
137 self->offset += nRemainingBytes;
138 self->nBytesToRead -= nRemainingBytes;
Jeff Thompsonadaf9232013-08-08 14:30:29 -0700139 return NDN_ERROR_success;
Jeff Thompson9dc10732013-06-26 21:40:32 -0700140 }
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.
Jeff Thompson8b666002013-07-08 01:16:26 -0700147 return NDN_ERROR_findElementEnd_unrecognized_state;
Jeff Thompson9dc10732013-06-26 21:40:32 -0700148 }
149}