blob: a8e2f0987568e61aa0061336ba13737e1b7275e8 [file] [log] [blame]
Jeff Thompson47eecfc2013-07-07 22:56:46 -07001/**
Jeff Thompson7687dc02013-09-13 11:54:07 -07002 * Copyright (C) 2013 Regents of the University of California.
3 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
Jeff Thompson47eecfc2013-07-07 22:56:46 -07004 * See COPYING for copyright and distribution information.
Jeff Thompson76317aa2013-06-25 19:11:48 -07005 */
6
Jeff Thompsonf418fe02013-06-27 17:28:55 -07007#include "../util/ndn_memory.h"
Jeff Thompson53412192013-08-06 13:35:50 -07008#include "binary-xml.h"
9#include "binary-xml-decoder.h"
10#include "binary-xml-structure-decoder.h"
Jeff Thompson76317aa2013-06-25 19:11:48 -070011
Jeff Thompsond1427fb2013-08-29 17:20:32 -070012void ndn_BinaryXmlStructureDecoder_initialize(struct ndn_BinaryXmlStructureDecoder *self)
Jeff Thompson9dc10732013-06-26 21:40:32 -070013{
Jeff Thompson76317aa2013-06-25 19:11:48 -070014 self->gotElementEnd = 0;
15 self->offset = 0;
16 self->level = 0;
Jeff Thompsonf0fea002013-07-30 17:22:42 -070017 self->state = ndn_BinaryXmlStructureDecoder_READ_HEADER_OR_CLOSE;
Jeff Thompson76317aa2013-06-25 19:11:48 -070018 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 Thompsonf0fea002013-07-30 17:22:42 -070026static inline void startHeader(struct ndn_BinaryXmlStructureDecoder *self)
Jeff Thompson7afc98e2013-06-27 14:33:53 -070027{
Jeff Thompson9dc10732013-06-26 21:40:32 -070028 self->headerLength = 0;
29 self->useHeaderBuffer = 0;
Jeff Thompsonf0fea002013-07-30 17:22:42 -070030 self->state = ndn_BinaryXmlStructureDecoder_READ_HEADER_OR_CLOSE;
Jeff Thompson9dc10732013-06-26 21:40:32 -070031}
32
Jeff Thompsonf0fea002013-07-30 17:22:42 -070033ndn_Error ndn_BinaryXmlStructureDecoder_findElementEnd
Jeff Thompson97223af2013-09-24 17:01:27 -070034 (struct ndn_BinaryXmlStructureDecoder *self, uint8_t *input, size_t inputLength)
Jeff Thompson9dc10732013-06-26 21:40:32 -070035{
36 if (self->gotElementEnd)
37 // Someone is calling when we already got the end.
Jeff Thompsonadaf9232013-08-08 14:30:29 -070038 return NDN_ERROR_success;
Jeff Thompson9dc10732013-06-26 21:40:32 -070039
Jeff Thompsonf0fea002013-07-30 17:22:42 -070040 struct ndn_BinaryXmlDecoder decoder;
Jeff Thompsond1427fb2013-08-29 17:20:32 -070041 ndn_BinaryXmlDecoder_initialize(&decoder, input, inputLength);
Jeff Thompson9dc10732013-06-26 21:40:32 -070042
43 while (1) {
44 if (self->offset >= inputLength)
45 // All the cases assume we have some input. Return and wait for more.
Jeff Thompsonadaf9232013-08-08 14:30:29 -070046 return NDN_ERROR_success;
Jeff Thompson9dc10732013-06-26 21:40:32 -070047
Jeff Thompsonf0fea002013-07-30 17:22:42 -070048 if (self->state == ndn_BinaryXmlStructureDecoder_READ_HEADER_OR_CLOSE) {
Jeff Thompson9dc10732013-06-26 21:40:32 -070049 // First check for CLOSE.
Jeff Thompsonf0fea002013-07-30 17:22:42 -070050 if (self->headerLength == 0 && input[self->offset] == ndn_BinaryXml_CLOSE) {
Jeff Thompson9dc10732013-06-26 21:40:32 -070051 ++self->offset;
52 // Close the level.
53 --self->level;
54 if (self->level == 0) {
55 // Finished.
56 self->gotElementEnd = 1;
Jeff Thompsonadaf9232013-08-08 14:30:29 -070057 return NDN_ERROR_success;
Jeff Thompson9dc10732013-06-26 21:40:32 -070058 }
59 if (self->level < 0)
Jeff Thompson8b666002013-07-08 01:16:26 -070060 return NDN_ERROR_findElementEnd_unexpected_close_tag;
Jeff Thompson9dc10732013-06-26 21:40:32 -070061
62 // Get ready for the next header.
63 startHeader(self);
64 continue;
65 }
66
Jeff Thompson97223af2013-09-24 17:01:27 -070067 size_t startingHeaderLength = self->headerLength;
Jeff Thompson9dc10732013-06-26 21:40:32 -070068 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))
Jeff Thompson8b666002013-07-08 01:16:26 -070072 return NDN_ERROR_cannot_store_more_header_bytes_than_the_size_of_headerBuffer;
Jeff Thompson9dc10732013-06-26 21:40:32 -070073 self->useHeaderBuffer = 1;
Jeff Thompson97223af2013-09-24 17:01:27 -070074 size_t nNewBytes = self->headerLength - startingHeaderLength;
Jeff Thompsonf418fe02013-06-27 17:28:55 -070075 ndn_memcpy(self->headerBuffer + startingHeaderLength, input + (self->offset - nNewBytes), nNewBytes);
Jeff Thompson9dc10732013-06-26 21:40:32 -070076
Jeff Thompsonadaf9232013-08-08 14:30:29 -070077 return NDN_ERROR_success;
Jeff Thompson9dc10732013-06-26 21:40:32 -070078 }
79 unsigned int headerByte = (unsigned int)input[self->offset++];
80 ++self->headerLength;
Jeff Thompsonf0fea002013-07-30 17:22:42 -070081 if (headerByte & ndn_BinaryXml_TT_FINAL)
Jeff Thompson9dc10732013-06-26 21:40:32 -070082 // 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))
Jeff Thompson8b666002013-07-08 01:16:26 -070091 return NDN_ERROR_cannot_store_more_header_bytes_than_the_size_of_headerBuffer;
Jeff Thompson97223af2013-09-24 17:01:27 -070092 size_t nNewBytes = self->headerLength - startingHeaderLength;
Jeff Thompsonf418fe02013-06-27 17:28:55 -070093 ndn_memcpy(self->headerBuffer + startingHeaderLength, input + (self->offset - nNewBytes), nNewBytes);
Jeff Thompson9dc10732013-06-26 21:40:32 -070094
95 // Use a local decoder just for the headerBuffer.
Jeff Thompsonf0fea002013-07-30 17:22:42 -070096 struct ndn_BinaryXmlDecoder bufferDecoder;
Jeff Thompsond1427fb2013-08-29 17:20:32 -070097 ndn_BinaryXmlDecoder_initialize(&bufferDecoder, self->headerBuffer, sizeof(self->headerBuffer));
Jeff Thompsonf0fea002013-07-30 17:22:42 -070098 if (ndn_BinaryXmlDecoder_decodeTypeAndValue(&bufferDecoder, &type, &value))
Jeff Thompson8b666002013-07-08 01:16:26 -070099 return NDN_ERROR_findElementEnd_cannot_read_header_type_and_value;
Jeff Thompson9dc10732013-06-26 21:40:32 -0700100 }
101 else {
102 // We didn't have to use the headerBuffer.
Jeff Thompsonf0fea002013-07-30 17:22:42 -0700103 ndn_BinaryXmlDecoder_seek(&decoder, self->offset - self->headerLength);
104 if (ndn_BinaryXmlDecoder_decodeTypeAndValue(&decoder, &type, &value))
Jeff Thompson8b666002013-07-08 01:16:26 -0700105 return NDN_ERROR_findElementEnd_cannot_read_header_type_and_value;
Jeff Thompson9dc10732013-06-26 21:40:32 -0700106 }
107
108 // Set the next state based on the type.
Jeff Thompsonf0fea002013-07-30 17:22:42 -0700109 if (type == ndn_BinaryXml_DATTR)
Jeff Thompson9dc10732013-06-26 21:40:32 -0700110 // 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);
Jeff Thompsonf0fea002013-07-30 17:22:42 -0700113 else if (type == ndn_BinaryXml_DTAG || type == ndn_BinaryXml_EXT) {
Jeff Thompson9dc10732013-06-26 21:40:32 -0700114 // Start a new level and READ_HEADER_OR_CLOSE again.
115 ++self->level;
116 startHeader(self);
117 }
Jeff Thompsonf0fea002013-07-30 17:22:42 -0700118 else if (type == ndn_BinaryXml_TAG || type == ndn_BinaryXml_ATTR) {
119 if (type == ndn_BinaryXml_TAG)
Jeff Thompson9dc10732013-06-26 21:40:32 -0700120 // Start a new level and read the tag.
121 ++self->level;
122 // Minimum tag or attribute length is 1.
123 self->nBytesToRead = value + 1;
Jeff Thompsonf0fea002013-07-30 17:22:42 -0700124 self->state = ndn_BinaryXmlStructureDecoder_READ_BYTES;
Jeff Thompson9dc10732013-06-26 21:40:32 -0700125 // Binary XML has rules about what must follow an attribute, but we are just scanning.
126 }
Jeff Thompsonf0fea002013-07-30 17:22:42 -0700127 else if (type == ndn_BinaryXml_BLOB || type == ndn_BinaryXml_UDATA) {
Jeff Thompson9dc10732013-06-26 21:40:32 -0700128 self->nBytesToRead = value;
Jeff Thompsonf0fea002013-07-30 17:22:42 -0700129 self->state = ndn_BinaryXmlStructureDecoder_READ_BYTES;
Jeff Thompson9dc10732013-06-26 21:40:32 -0700130 }
131 else
Jeff Thompson8b666002013-07-08 01:16:26 -0700132 return NDN_ERROR_findElementEnd_unrecognized_header_type;
Jeff Thompson9dc10732013-06-26 21:40:32 -0700133 }
Jeff Thompsonf0fea002013-07-30 17:22:42 -0700134 else if (self->state == ndn_BinaryXmlStructureDecoder_READ_BYTES) {
Jeff Thompson97223af2013-09-24 17:01:27 -0700135 size_t nRemainingBytes = inputLength - self->offset;
Jeff Thompson9dc10732013-06-26 21:40:32 -0700136 if (nRemainingBytes < self->nBytesToRead) {
137 // Need more.
138 self->offset += nRemainingBytes;
139 self->nBytesToRead -= nRemainingBytes;
Jeff Thompsonadaf9232013-08-08 14:30:29 -0700140 return NDN_ERROR_success;
Jeff Thompson9dc10732013-06-26 21:40:32 -0700141 }
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.
Jeff Thompson8b666002013-07-08 01:16:26 -0700148 return NDN_ERROR_findElementEnd_unrecognized_state;
Jeff Thompson9dc10732013-06-26 21:40:32 -0700149 }
150}