exip  Alpha 0.5.4
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
EXIParser.c
Go to the documentation of this file.
1 /*==================================================================*\
2 | EXIP - Embeddable EXI Processor in C |
3 |--------------------------------------------------------------------|
4 | This work is licensed under BSD 3-Clause License |
5 | The full license terms and conditions are located in LICENSE.txt |
6 \===================================================================*/
7 
18 #include "EXIParser.h"
19 #include "procTypes.h"
20 #include "headerDecode.h"
21 #include "memManagement.h"
22 #include "bodyDecode.h"
23 #include "sTables.h"
24 #include "grammars.h"
25 #include "initSchemaInstance.h"
26 
32  setSchema,
33  parseNext,
36 
37 errorCode initParser(Parser* parser, BinaryBuffer buffer, void* app_data)
38 {
39  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
40  TRY(initAllocList(&parser->strm.memList));
41 
42  parser->strm.buffer = buffer;
43  parser->strm.context.bitPointer = 0;
44  parser->strm.context.bufferIndx = 0;
45  parser->strm.context.currAttr.lnId = 0;
46  parser->strm.context.currAttr.uriId = 0;
47  parser->strm.context.expectATData = FALSE;
48  parser->strm.context.isNilType = FALSE;
49  parser->strm.context.attrTypeId = INDEX_MAX;
50  parser->strm.gStack = NULL;
51  parser->strm.valueTable.value = NULL;
52  parser->strm.valueTable.count = 0;
53  parser->app_data = app_data;
54  parser->strm.schema = NULL;
55  makeDefaultOpts(&parser->strm.header.opts);
56 
57  initContentHandler(&parser->handler);
58 
59 #if HASH_TABLE_USE
60  parser->strm.valueTable.hashTbl = NULL;
61 #endif
62 
63  return EXIP_OK;
64 }
65 
66 errorCode parseHeader(Parser* parser, boolean outOfBandOpts)
67 {
68  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
69 
70  TRY(decodeHeader(&parser->strm, outOfBandOpts));
71 
72  if(parser->strm.header.opts.valuePartitionCapacity > 0)
73  {
75  }
76 
77  // The parsing of the header is successful
78  // TODO: Consider removing the startDocument all together instead of invoking it always here?
79  if(parser->handler.startDocument != NULL)
80  {
81  TRY(parser->handler.startDocument(parser->app_data));
82  }
83 
84  return EXIP_OK;
85 }
86 
88 {
89  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
90 
92  {
93  // When the "schemaId" element in the EXI options document contains the xsi:nil attribute
94  // with its value set to true, no schema information is used for processing the EXI body
95  // (i.e. a schema-less EXI stream)
96  parser->strm.schema = NULL;
97 #if EXI_PROFILE_DEFAULT
98  DEBUG_MSG(ERROR, DEBUG_CONTENT_IO, ("\n> EXI Profile mode require schema mode processing"));
100 #endif
101 #if DEBUG_CONTENT_IO == ON && EXIP_DEBUG_LEVEL <= WARNING
102  if(schema != NULL)
103  DEBUG_MSG(WARNING, DEBUG_CONTENT_IO, ("\n> Ignored out-of-band schema information. Schema-less mode required"));
104 #endif
105  }
106  else if(parser->strm.header.opts.schemaIDMode == SCHEMA_ID_EMPTY)
107  {
108  // When the value of the "schemaId" element is empty, no user defined schema information
109  // is used for processing the EXI body; however, the built-in XML schema types are available for use in the EXI body
110 #if DEBUG_CONTENT_IO == ON && EXIP_DEBUG_LEVEL <= WARNING
111  if(schema != NULL)
112  DEBUG_MSG(WARNING, DEBUG_CONTENT_IO, ("\n> Ignored out-of-band schema information. Schema mode built-in types required"));
113 #endif
114  parser->strm.schema = memManagedAllocate(&parser->strm.memList, sizeof(EXIPSchema));
115  if(parser->strm.schema == NULL)
117 
119 
120  if(WITH_FRAGMENT(parser->strm.header.opts.enumOpt))
121  {
122  TRY(createFragmentGrammar(parser->strm.schema, NULL, 0));
123  }
124  else
125  {
126  TRY(createDocGrammar(parser->strm.schema, NULL, 0));
127  }
128  }
129  else if(schema != NULL)
130  {
131  /* Schema enabled mode*/
132  if(WITH_FRAGMENT(parser->strm.header.opts.enumOpt))
133  {
134  /* Fragment document grammar */
135  // TODO: create a Schema-informed Fragment Grammar from the EXIP schema object
137  }
138  else
139  {
140  parser->strm.schema = schema;
141  }
142  }
143 
144  if(parser->strm.schema == NULL)
145  {
146  // Schema-less mode
147  if(parser->strm.header.opts.schemaIDMode == SCHEMA_ID_SET)
148  {
149  DEBUG_MSG(ERROR, DEBUG_CONTENT_IO, ("\n> Schema mode required, but NULL schema set"));
151  }
152 
153 #if EXI_PROFILE_DEFAULT
154  DEBUG_MSG(ERROR, DEBUG_CONTENT_IO, ("\n> EXI Profile mode require schema mode processing"));
155  return EXIP_INVALID_EXI_INPUT;
156 #endif
157 
158  parser->strm.schema = memManagedAllocate(&parser->strm.memList, sizeof(EXIPSchema));
159  if(parser->strm.schema == NULL)
161 
163 
164  if(WITH_FRAGMENT(parser->strm.header.opts.enumOpt))
165  {
166  TRY(createFragmentGrammar(parser->strm.schema, NULL, 0));
167  }
168  else
169  {
170  TRY(createDocGrammar(parser->strm.schema, NULL, 0));
171  }
172  }
173 
174  {
175  QNameID emptyQNameID = {URI_MAX, LN_MAX};
176  TRY(pushGrammar(&parser->strm.gStack, emptyQNameID, &parser->strm.schema->docGrammar));
177  }
178 
179  return EXIP_OK;
180 }
181 
183 {
184  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
185  SmallIndex tmpNonTermID = GR_VOID_NON_TERMINAL;
186  StreamContext savedContext = parser->strm.context;
187 
188  tmp_err_code = processNextProduction(&parser->strm, &tmpNonTermID, &parser->handler, parser->app_data);
189  if(tmp_err_code == EXIP_BUFFER_END_REACHED)
190  parser->strm.context = savedContext;
191 
192  if(tmp_err_code != EXIP_OK)
193  {
194  DEBUG_MSG(ERROR, EXIP_DEBUG, ("\n>Error %s:%d at %s, line %d", GET_ERR_STRING(tmp_err_code), tmp_err_code, __FILE__, __LINE__));
195  return tmp_err_code;
196  }
197 
198  if(tmpNonTermID == GR_VOID_NON_TERMINAL)
199  {
200  popGrammar(&(parser->strm.gStack));
201  if(parser->strm.gStack == NULL) // There is no more grammars in the stack
202  {
203  return EXIP_PARSING_COMPLETE; // The stream is parsed
204  }
205  }
206  else
207  {
208  parser->strm.gStack->currNonTermID = tmpNonTermID;
209  }
210 
211  return EXIP_OK;
212 }
213 
214 errorCode pushEXIData(char* inBuf, unsigned int bufSize, unsigned int* bytesRead, Parser* parser)
215 {
216  Index bytesCopied = parser->strm.buffer.bufContent - parser->strm.context.bufferIndx;
217 
218  *bytesRead = parser->strm.buffer.bufLen - bytesCopied;
219  if(*bytesRead > bufSize)
220  *bytesRead = bufSize;
221 
222  /* Checks for possible overlaps when copying the left Over Bits,
223  * normally should not happen when the size of strm->buffer is set
224  * reasonably and not too small */
225  if(2*bytesCopied > parser->strm.buffer.bufLen)
226  {
227  DEBUG_MSG(ERROR, DEBUG_CONTENT_IO, ("\n> The size of strm->buffer is too small! Set to at least: %d", 2*bytesCopied));
229  }
230 
231  memcpy(parser->strm.buffer.buf, parser->strm.buffer.buf + parser->strm.context.bufferIndx, bytesCopied);
232  memcpy(parser->strm.buffer.buf + bytesCopied, inBuf, *bytesRead);
233 
234  parser->strm.context.bufferIndx = 0;
235  parser->strm.buffer.bufContent = bytesCopied + *bytesRead;
236 
237  return EXIP_OK;
238 }
239 
240 void destroyParser(Parser* parser)
241 {
242  while(parser->strm.gStack != NULL)
243  {
244  popGrammar(&parser->strm.gStack);
245  }
246 
247  freeAllMem(&parser->strm);
248 }