exip  Alpha 0.5.4
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
bodyDecode.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 
17 #include "bodyDecode.h"
18 #include "sTables.h"
19 #include "memManagement.h"
20 #include "ioUtil.h"
21 #include "streamDecode.h"
22 #include "grammars.h"
23 #include "dynamicArray.h"
24 #include "stringManipulate.h"
25 
26 
27 static errorCode stateMachineProdDecode(EXIStream* strm, GrammarRule* currentRule, SmallIndex* nonTermID_out, ContentHandler* handler, void* app_data);
28 static errorCode handleProduction(EXIStream* strm, Production* prodHit, SmallIndex* nonTermID_out, ContentHandler* handler, void* app_data);
29 static errorCode decodeQNameValue(EXIStream* strm, ContentHandler* handler, SmallIndex* nonTermID_out, void* app_data);
30 
31 errorCode processNextProduction(EXIStream* strm, SmallIndex* nonTermID_out, ContentHandler* handler, void* app_data)
32 {
33  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
34  unsigned int bitCount;
35  unsigned int tmp_bits_val = 0;
36  GrammarRule* currentRule;
37  Index prodCount;
38  SmallIndex currNonTermID = strm->gStack->currNonTermID;
39 
40  // TODO: GR_CONTENT_2 is only needed when schema deviations are allowed.
41  // Here and in many other places when schema deviations are fully disabled
42  // many parts of the code can be pruned during compile time using macro parameters in the build.
43  // This includes the EXI Profile features itself (excluding localValueCapping)
44  if(currNonTermID == GR_CONTENT_2)
45  currNonTermID = GET_CONTENT_INDEX(strm->gStack->grammar->props);
46 
47  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, ("\n>Next production non-term-id: %u\n", (unsigned int) currNonTermID));
48 
49  if(currNonTermID >= strm->gStack->grammar->count)
51 
52 #if BUILD_IN_GRAMMARS_USE
53  if(IS_BUILT_IN_ELEM(strm->gStack->grammar->props)) // If the current grammar is build-in Element grammar ...
54  currentRule = (GrammarRule*) &((DynGrammarRule*) strm->gStack->grammar->rule)[currNonTermID];
55  else
56 #endif
57  currentRule = &strm->gStack->grammar->rule[currNonTermID];
58 
59 #if DEBUG_CONTENT_IO == ON
60  TRY(printGrammarRule(currNonTermID, currentRule, strm->schema));
61 #endif
62 
63  if(strm->context.isNilType == FALSE)
64  prodCount = currentRule->pCount;
65  else
66  { /* xsi:nil=true case */
67  prodCount = RULE_GET_AT_COUNT(currentRule->meta) + RULE_CONTAIN_EE(currentRule->meta);
68  if(currNonTermID >= GET_CONTENT_INDEX(strm->gStack->grammar->props))
69  {
70  // Instead of content we have a single EE production in the emptyType grammars
71  prodCount = 1;
72  bitCount = getBitsFirstPartCode(strm, prodCount, currNonTermID);
73  if(bitCount > 0)
74  TRY(decodeNBitUnsignedInteger(strm, bitCount, &tmp_bits_val));
75  strm->context.isNilType = FALSE;
76  if(handler->endElement != NULL)
77  {
78  TRY(handler->endElement(app_data));
79  }
80 
81  return EXIP_OK;
82  }
83  }
84 
85  bitCount = getBitsFirstPartCode(strm, prodCount, currNonTermID);
86 
87  if(prodCount > 0)
88  {
89  if(bitCount == 0)
90  {
91  // encoded with zero bits
92  return handleProduction(strm, &currentRule->production[0], nonTermID_out, handler, app_data);
93  }
94  else
95  {
96  TRY(decodeNBitUnsignedInteger(strm, bitCount, &tmp_bits_val));
97 
98  if(tmp_bits_val < prodCount)
99  {
100  if(strm->context.isNilType == TRUE && tmp_bits_val == (prodCount - 1))
101  {
102  // Because SE productions are ordered before the EE in case of emptyTypeGrammar this might be either AT or EE
103  if(RULE_CONTAIN_EE(currentRule->meta))
104  {
105  // Always last so this is an EE event
106  strm->context.isNilType = FALSE;
107  if(handler->endElement != NULL)
108  {
109  TRY(handler->endElement(app_data));
110  }
111 
112  return EXIP_OK;
113  }
114  }
115 
116  return handleProduction(strm, &currentRule->production[prodCount - 1 - tmp_bits_val], nonTermID_out, handler, app_data);
117  }
118  }
119  }
120 
121  // Production with length code 1 not found: search second or third level productions
122  // Invoke state machine
123 
124  return stateMachineProdDecode(strm, currentRule, nonTermID_out, handler, app_data);
125 }
126 
127 static errorCode handleProduction(EXIStream* strm, Production* prodHit, SmallIndex* nonTermID_out, ContentHandler* handler, void* app_data)
128 {
129  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
130  *nonTermID_out = GET_PROD_NON_TERM(prodHit->content);
131 
132  switch(GET_PROD_EXI_EVENT(prodHit->content))
133  {
134  case EVENT_ED:
135  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, ("> ED event:\n"));
136  if(handler->endDocument != NULL)
137  {
138  TRY(handler->endDocument(app_data));
139  }
140  break;
141  case EVENT_EE:
142  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, ("> EE event:\n"));
143  strm->context.isNilType = FALSE;
144  if(handler->endElement != NULL)
145  {
146  TRY(handler->endElement(app_data));
147  }
148  break;
149  case EVENT_SC:
150  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, ("> SC event:\n"));
151  if(handler->selfContained != NULL)
152  {
153  TRY(handler->selfContained(app_data));
154  }
155  break;
156  default: // The event has content!
157  return decodeEventContent(strm, prodHit, handler, nonTermID_out, app_data);
158  break;
159  }
160 
161  return EXIP_OK;
162 }
163 
164 static errorCode stateMachineProdDecode(EXIStream* strm, GrammarRule* currentRule, SmallIndex* nonTermID_out, ContentHandler* handler, void* app_data)
165 {
166  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
167  unsigned int prodCnt = 0;
168  unsigned int tmp_bits_val = 0;
169 
170  if(IS_BUILT_IN_ELEM(strm->gStack->grammar->props))
171  {
172  // Built-in element grammar
173 #if BUILD_IN_GRAMMARS_USE
174  QNameID voidQnameID = {URI_MAX, LN_MAX};
175 
176  /* There are 8 possible states to exit the state machine: EE, AT (*), NS etc.
177  * The state depends on the input event code from the stream and the
178  * available productions at level 2.
179  * (Note this is the state for level 2 productions) */
180  unsigned int state = 0;
181 
182  /* The state mask stores the availability of the productions on level 2.
183  * They are encoded ordered:
184  * Availability for EE is encoded in position 0,
185  * availability for AT(xsi:type) is encoded in position 1,
186  * and so on. */
187  boolean state_mask[8] = {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE};
188  unsigned int i;
189 
190  prodCnt = 2; // Always SE, CH, position 4, 5
191  state_mask[4] = TRUE;
192  state_mask[5] = TRUE;
193 
195  {
196  prodCnt += 2; // EE, AT, position 0, 1
197  state_mask[0] = TRUE;
198  state_mask[1] = TRUE;
199 
201  {
202  prodCnt += 1; // NS, position 2
203  state_mask[2] = TRUE;
204  }
205 
207  {
208  prodCnt += 1; // SC, position 3
209  state_mask[3] = TRUE;
210  }
211  }
212 
214  {
215  prodCnt += 1; // ER position 6
216  state_mask[6] = TRUE;
217  }
218 
220  {
221  prodCnt += 1; // CM or PI, position 7
222  state_mask[7] = TRUE;
223  }
224 
225  TRY(decodeNBitUnsignedInteger(strm, getBitsNumber(prodCnt - 1), &tmp_bits_val));
226  state = tmp_bits_val;
227 
228  for(i = 0; i <= state && state < 8; i++)
229  {
230  state = state + (state_mask[i] == 0);
231  }
232 
233  switch(state)
234  {
235  case 0:
236  // StartTagContent : EE event
237  strm->context.isNilType = FALSE;
238  if(handler->endElement != NULL)
239  {
240  TRY(handler->endElement(app_data));
241  }
242 
243  *nonTermID_out = GR_VOID_NON_TERMINAL;
244 
245  // TODO: First you need to check if EE does not already exists, just then insert it
246  TRY(insertZeroProduction((DynGrammarRule*) currentRule, EVENT_EE, GR_VOID_NON_TERMINAL, &voidQnameID, 1));
247  break;
248  case 1:
249  // StartTagContent : AT(*) event
250  *nonTermID_out = GR_START_TAG_CONTENT;
251 
252  TRY(decodeATWildcardEvent(strm, handler, nonTermID_out, app_data));
253 
254  // If eventType == AT(qname) and qname == xsi:type check first if there is no
255  // such production already at top level (see http://www.w3.org/XML/EXI/exi-10-errata#Substantive20120508)
256  // If there is no -> insert one, otherwise don't insert it
258  {
259  if(!RULE_CONTAIN_XSI_TYPE(((DynGrammarRule*) currentRule)->meta))
260  {
261  RULE_SET_CONTAIN_XSI_TYPE(((DynGrammarRule*) currentRule)->meta);
262  TRY(insertZeroProduction((DynGrammarRule*) currentRule, EVENT_AT_QNAME, GR_START_TAG_CONTENT, &strm->context.currAttr, 1));
263  }
264  }
265  else
266  TRY(insertZeroProduction((DynGrammarRule*) currentRule, EVENT_AT_QNAME, GR_START_TAG_CONTENT, &strm->context.currAttr, 1));
267  break;
268  case 2:
269  // StartTagContent : NS event
270  TRY(decodeNSEvent(strm, handler, nonTermID_out, app_data));
271  break;
272  case 3:
273  // StartTagContent : SC event
275  break;
276  case 4:
277  // SE(*) event
279 
280  TRY(decodeSEWildcardEvent(strm, handler, nonTermID_out, app_data));
281  TRY(insertZeroProduction((DynGrammarRule*) currentRule, EVENT_SE_QNAME, GR_ELEMENT_CONTENT, &strm->gStack->currQNameID, 1));
282  break;
283  case 5:
284  // CH event
285  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, (">CH event\n"));
286 
287  *nonTermID_out = GR_ELEMENT_CONTENT;
288 
289  TRY(decodeValueItem(strm, INDEX_MAX, handler, nonTermID_out, strm->gStack->currQNameID, app_data));
290  // TODO: First you need to check if CH does not already exists, just then insert it
291  TRY(insertZeroProduction((DynGrammarRule*) currentRule, EVENT_CH, *nonTermID_out, &voidQnameID, 1));
292  break;
293  case 6:
294  // ER event
296  break;
297  case 7:
298  // CM or PI event
300  break;
301  default:
303  }
304 #else
305  DEBUG_MSG(ERROR, DEBUG_CONTENT_IO, (">Build-in element grammars are not supported by this configuration \n"));
306  assert(FALSE);
308 #endif
309  }
310  else if(IS_DOCUMENT(strm->gStack->grammar->props))
311  {
312  // Document grammar
313  /* There are 3 possible states to exit the state machine: DT, CM or PI
314  * The state depends on the input event code from the stream and the
315  * available productions at level 2 and 3.*/
316  unsigned int state = 0;
317  unsigned int level3ProdCnt = 0;
318 
319  if(strm->gStack->currNonTermID == GR_DOC_CONTENT)
320  {
322  prodCnt += 1; // DT event
323 
325  level3ProdCnt += 1;
326 
328  level3ProdCnt += 1;
329 
330  if(level3ProdCnt > 0)
331  prodCnt += 1; // CM or PI third level
332 
333  if(prodCnt == 2)
334  {
335  TRY(decodeNBitUnsignedInteger(strm, 1, &tmp_bits_val));
336  if(tmp_bits_val == 0)
337  state = 0;
338  else if(tmp_bits_val == 1)
339  {
340  // CM or PI third level
341  if(level3ProdCnt == 2)
342  {
343  TRY(decodeNBitUnsignedInteger(strm, 1, &tmp_bits_val));
344  state = tmp_bits_val + 1;
345  }
346  else if(level3ProdCnt == 1)
347  {
348  state = !IS_PRESERVED(strm->header.opts.preserve, PRESERVE_COMMENTS) + 1;
349  }
350  else
352  }
353  else
355  }
356  else if(prodCnt == 1)
357  {
359  state = 0;
360  else
361  {
362  // CM or PI third level
363  if(level3ProdCnt == 2)
364  {
365  TRY(decodeNBitUnsignedInteger(strm, 1, &tmp_bits_val));
366  state = tmp_bits_val + 1;
367  }
368  else if(level3ProdCnt == 1)
369  {
370  state = !IS_PRESERVED(strm->header.opts.preserve, PRESERVE_COMMENTS) + 1;
371  }
372  else
374  }
375  }
376  else
378  }
379  else
380  {
382  prodCnt += 1; // CM second level
383 
385  prodCnt += 1; // PI second level
386 
387  if(prodCnt == 2)
388  {
389  TRY(decodeNBitUnsignedInteger(strm, 1, &tmp_bits_val));
390  state = tmp_bits_val + 1;
391  }
392  else if(prodCnt == 1)
393  {
394  state = !IS_PRESERVED(strm->header.opts.preserve, PRESERVE_COMMENTS) + 1;
395  }
396  else
398  }
399 
400  switch(state)
401  {
402  case 0:
403  // DT event
405  break;
406  case 1:
407  // CM event
409  break;
410  case 2:
411  // PI event
413  break;
414  default:
416  }
417  }
418  else if(IS_FRAGMENT(strm->gStack->grammar->props))
419  {
420  // Fragment grammar
421  // CM or PI event
423  }
424  else
425  {
426  // Schema-informed element/type grammar
427  QName qname;
428 
429  if(WITH_STRICT(strm->header.opts.enumOpt))
430  {
431  // Strict mode
432 
433  // Only available second level event if it is an entry grammar rule and is not Nil type grammar
435  {
436  /* There are 2 possible states to exit the state machine: AT(xsi:type) and AT(xsi:nil)
437  * (Note this is the state for level 2 productions) */
438  unsigned int state = 1;
439  boolean nil;
440 
441  *nonTermID_out = GR_START_TAG_CONTENT;
442 
444  {
445  prodCnt += 1;
446  state = 0;
447  }
448 
449  if(IS_NILLABLE(strm->gStack->grammar->props))
450  prodCnt += 1;
451 
452  if(prodCnt == 0)
454  else if(prodCnt == 2)
455  {
456  TRY(decodeNBitUnsignedInteger(strm, 1, &state));
457  if(state > 1)
459  }
460  // if prodCnt == 1 -> zero bit encoded event
461 
462  switch(state)
463  {
464  case 0:
465  // AT(xsi:type) event
466  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, (">AT(xsi:type) event\n"));
469  qname.uri = &strm->schema->uriTable.uri[strm->context.currAttr.uriId].uriStr;
470  qname.localName = &GET_LN_URI_QNAME(strm->schema->uriTable, strm->context.currAttr).lnStr;
471 
472  if(handler->attribute != NULL) // Invoke handler method
473  {
474  TRY(handler->attribute(qname, app_data));
475  }
476  TRY(decodeQNameValue(strm, handler, nonTermID_out, app_data));
477  break;
478  case 1:
479  // AT(xsi:nil) event
480  TRY(decodeBoolean(strm, &nil));
481  if(nil == TRUE)
482  strm->context.isNilType = TRUE;
483 
484  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, (">AT(xsi:nil) event\n"));
487  qname.uri = &strm->schema->uriTable.uri[strm->context.currAttr.uriId].uriStr;
488  qname.localName = &GET_LN_URI_QNAME(strm->schema->uriTable, strm->context.currAttr).lnStr;
489 
490  if(handler->attribute != NULL) // Invoke handler method
491  {
492  TRY(handler->attribute(qname, app_data));
493  }
494 
495  if(handler->booleanData != NULL) // Invoke handler method
496  {
497  TRY(handler->booleanData(nil, app_data));
498  }
499  *nonTermID_out = GR_START_TAG_CONTENT;
500  break;
501  default:
503  }
504  }
505  else
507  }
508  else // Non-strict mode
509  {
510  /* There are 11 possible states to exit the state machine: EE, AT(xsi:type), AT(xsi:nil) etc.
511  * The state depends on the input event code from the stream and the
512  * available productions at level 2.
513  * (Note this is the state for level 2 productions) */
514  unsigned int state = 0;
515 
516  /* The state mask stores the availability of the productions on level 2.
517  * They are encoded ordered:
518  * Availability for EE is encoded in position 0,
519  * availability for AT(xsi:type) is encoded in position 1,
520  * and so on. */
521  boolean state_mask[11] = {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE};
522  unsigned int i;
523  // Create a copy of the content grammar if and only if there are AT
524  // productions that point to the content grammar rule OR the content index is 0.
525  // The content2 grammar rule is only needed in case the current rule is
526  // equal the content grammar rule. Note that when content index is 0, the entry grammar
527  // is the content2 grammar rule and by default the GR_START_TAG_CONTENT is pointing
528  // to the content2 while GR_CONTENT_2 is pointing to content i.e. the roles are
529  // reversed in this situation. It is implemented in this way in order to keep
530  // all the rule processing in tact in the other parts of the implementation.
531  boolean isContent2Grammar = FALSE;
532 
533  if(strm->gStack->currNonTermID == GR_CONTENT_2)
534  {
536  isContent2Grammar = TRUE;
537  }
540  {
541  isContent2Grammar = TRUE;
542  }
543 
544  prodCnt = 2; // SE(*), CH(untyped) always available, position 7 and 8
545  state_mask[7] = TRUE;
546  state_mask[8] = TRUE;
547  if(isContent2Grammar ||
549  {
550  prodCnt += 2; // AT(*), AT(untyped) third level, position 3 and 4
551  state_mask[3] = TRUE;
552  state_mask[4] = TRUE;
553  }
554 
555  if(!RULE_CONTAIN_EE(currentRule->meta))
556  {
557  prodCnt += 1; // EE, position 0
558  state_mask[0] = TRUE;
559  }
560 
562  {
563  prodCnt += 2; // AT(xsi:type), AT(xsi:nil), position 1 and 2
564  state_mask[1] = TRUE;
565  state_mask[2] = TRUE;
566 
568  {
569  prodCnt += 1; // NS, position 5
570  state_mask[5] = TRUE;
571  }
573  {
574  prodCnt += 1; // SC, position 6
575  state_mask[6] = TRUE;
576  }
577  }
578 
580  {
581  prodCnt += 1; // ER, position 9
582  state_mask[9] = TRUE;
583  }
584 
586  {
587  prodCnt += 1; // CM or PI, position 10
588  state_mask[10] = TRUE;
589  }
590 
591  TRY(decodeNBitUnsignedInteger(strm, getBitsNumber(prodCnt - 1), &tmp_bits_val));
592 
593  state = tmp_bits_val;
594 
595  for(i = 0; i <= state && state < 11; i++)
596  {
597  state = state + (state_mask[i] == 0);
598  }
599 
600  switch(state)
601  {
602  case 0:
603  // EE event
604  strm->context.isNilType = FALSE;
605  if(handler->endElement != NULL)
606  {
607  TRY(handler->endElement(app_data));
608  }
609  *nonTermID_out = GR_VOID_NON_TERMINAL;
610  break;
611  case 1:
612  // AT(xsi:type) event
613  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, (">AT(xsi:type) event\n"));
616  qname.uri = &strm->schema->uriTable.uri[strm->context.currAttr.uriId].uriStr;
617  qname.localName = &GET_LN_URI_QNAME(strm->schema->uriTable, strm->context.currAttr).lnStr;
618 
619  if(handler->attribute != NULL) // Invoke handler method
620  {
621  TRY(handler->attribute(qname, app_data));
622  }
623  TRY(decodeQNameValue(strm, handler, nonTermID_out, app_data));
624  break;
625  case 2:
626  // AT(xsi:nil) Element i, 0
627  {
628  boolean nil = FALSE;
629  TRY(decodeBoolean(strm, &nil));
630  if(nil == TRUE)
631  strm->context.isNilType = TRUE;
632 
633  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, (">AT(xsi:nil) event\n"));
636  qname.uri = &strm->schema->uriTable.uri[strm->context.currAttr.uriId].uriStr;
637  qname.localName = &GET_LN_URI_QNAME(strm->schema->uriTable, strm->context.currAttr).lnStr;
638 
639  if(handler->attribute != NULL) // Invoke handler method
640  {
641  TRY(handler->attribute(qname, app_data));
642  }
643 
644  if(handler->booleanData != NULL) // Invoke handler method
645  {
646  TRY(handler->booleanData(nil, app_data));
647  }
648  *nonTermID_out = GR_START_TAG_CONTENT;
649  }
650  break;
651  case 3:
652  // AT(*)
653  *nonTermID_out = strm->gStack->currNonTermID;
654  TRY(decodeATWildcardEvent(strm, handler, nonTermID_out, app_data));
655  break;
656  case 4:
657  // third level AT: eighter AT (qname) [untyped value] or AT (*) [untyped value]
659  break;
660  case 5:
661  // NS Element i, 0
662  TRY(decodeNSEvent(strm, handler, nonTermID_out, app_data));
663  break;
664  case 6:
665  // SC event
667  break;
668  case 7:
669  // SE(*) content|same_rule
670  if(isContent2Grammar || strm->gStack->currNonTermID < GET_CONTENT_INDEX(strm->gStack->grammar->props))
671  {
672  // currNonTermID should point to the content grammar rule
675  else
677  }
678  TRY(decodeSEWildcardEvent(strm, handler, nonTermID_out, app_data));
679  break;
680  case 8:
681  // CH [untyped value] content|same_rule
682  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, (">CH event\n"));
683  if(isContent2Grammar || strm->gStack->currNonTermID < GET_CONTENT_INDEX(strm->gStack->grammar->props))
684  {
685  // nonTermID_out should point to the content grammar rule
687  *nonTermID_out = GR_CONTENT_2;
688  else
689  *nonTermID_out = GET_CONTENT_INDEX(strm->gStack->grammar->props);
690  }
691  else
692  *nonTermID_out = strm->gStack->currNonTermID;
693  TRY(decodeValueItem(strm, INDEX_MAX, handler, nonTermID_out, strm->gStack->currQNameID, app_data));
694  break;
695  case 9:
696  // ER event
698  break;
699  case 10:
700  // third level: CM or PI event
702  break;
703  default:
705  }
706  }
707  }
708 
709  return EXIP_OK;
710 }
711 
712 /*
713  * #1#:
714  * All productions in the built-in element grammar of the form LeftHandSide : EE are evaluated as follows:
715  * - If a production of the form, LeftHandSide : EE with an event code of length 1 does not exist in
716  * the current element grammar, create one with event code 0 and increment the first part of the
717  * event code of each production in the current grammar with the non-terminal LeftHandSide on the left-hand side.
718  * - Add the production created in step 1 to the grammar
719  *
720  * #2#
721  * All productions in the built-in element grammar of the form LeftHandSide : CH RightHandSide are evaluated as follows:
722  * - If a production of the form, LeftHandSide : CH RightHandSide with an event code of length 1 does not exist in
723  * the current element grammar, create one with event code 0 and increment the first part of the event code of
724  * each production in the current grammar with the non-terminal LeftHandSide on the left-hand side.
725  * - Add the production created in step 1 to the grammar
726  * - Evaluate the remainder of event sequence using RightHandSide.
727  * */
728 
729 errorCode decodeQName(EXIStream* strm, QName* qname, QNameID* qnameID)
730 {
731  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
732 
733  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, (">Decoding QName\n"));
734 
735  TRY(decodeUri(strm, &qnameID->uriId));
736  qname->uri = &(strm->schema->uriTable.uri[qnameID->uriId].uriStr);
737  TRY(decodeLn(strm, qnameID->uriId, &qnameID->lnId));
738  qname->localName = &GET_LN_P_URI_P_QNAME(&strm->schema->uriTable, qnameID).lnStr;
739 
740  return decodePfxQname(strm, qname, qnameID->uriId);
741 }
742 
744 {
745  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
746  unsigned int tmp_val_buf = 0;
747  unsigned char uriBits = getBitsNumber(strm->schema->uriTable.count);
748 
749  TRY(decodeNBitUnsignedInteger(strm, uriBits, &tmp_val_buf));
750  if(tmp_val_buf == 0) // uri miss
751  {
752  String str;
753  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, (">URI miss\n"));
754  TRY(decodeString(strm, &str));
755  TRY(addUriEntry(&strm->schema->uriTable, str, uriId));
756  }
757  else // uri hit
758  {
759  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, (">URI hit\n"));
760  *uriId = tmp_val_buf - 1;
761  if(*uriId >= strm->schema->uriTable.count)
762  return EXIP_INVALID_EXI_INPUT;
763  }
764 
765  return EXIP_OK;
766 }
767 
768 errorCode decodeLn(EXIStream* strm, Index uriId, Index* lnId)
769 {
770  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
771  UnsignedInteger tmpVar = 0;
772 
773  TRY(decodeUnsignedInteger(strm, &tmpVar));
774 
775  if(tmpVar == 0) // local-name table hit
776  {
777  unsigned int l_lnId;
778  unsigned char lnBits = getBitsNumber((unsigned int)(strm->schema->uriTable.uri[uriId].lnTable.count - 1));
779  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, (">local-name table hit\n"));
780  TRY(decodeNBitUnsignedInteger(strm, lnBits, &l_lnId));
781 
782  if(l_lnId >= strm->schema->uriTable.uri[uriId].lnTable.count)
783  return EXIP_INVALID_EXI_INPUT;
784  *lnId = l_lnId;
785  }
786  else // local-name table miss
787  {
788  String lnStr;
789  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, (">local-name table miss\n"));
790 
791  TRY(allocateStringMemoryManaged(&(lnStr.str),(Index) (tmpVar - 1), &strm->memList));
792  TRY(decodeStringOnly(strm, (Index)tmpVar - 1, &lnStr));
793 
794  if(strm->schema->uriTable.uri[uriId].lnTable.ln == NULL)
795  {
796  // Create local name table for this URI entry
798  }
799  TRY(addLnEntry(&strm->schema->uriTable.uri[uriId].lnTable, lnStr, lnId));
800  }
801 
802  return EXIP_OK;
803 }
804 
806 {
807  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
808  unsigned char prefixBits = 0;
809  unsigned int prefixID = 0;
810 
811  qname->prefix = NULL;
812 
814  return EXIP_OK;
815 
816  if(strm->schema->uriTable.uri[uriId].pfxTable.count == 0)
817  return EXIP_OK;
818 
819  prefixBits = getBitsNumber(strm->schema->uriTable.uri[uriId].pfxTable.count - 1);
820 
821  if(prefixBits > 0)
822  {
823  TRY(decodeNBitUnsignedInteger(strm, prefixBits, &prefixID));
824 
825  if(prefixID >= strm->schema->uriTable.uri[uriId].pfxTable.count)
826  return EXIP_INVALID_EXI_INPUT;
827  }
828 
829  qname->prefix = &strm->schema->uriTable.uri[uriId].pfxTable.pfx[prefixID];
830 
831  return EXIP_OK;
832 }
833 
835 {
836  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
837  unsigned int tmp_val_buf = 0;
838  unsigned char prfxBits = getBitsNumber(strm->schema->uriTable.uri[uriId].pfxTable.count);
839 
840  TRY(decodeNBitUnsignedInteger(strm, prfxBits, &tmp_val_buf));
841 
842  if(tmp_val_buf == 0) // prefix miss
843  {
844  String str;
845  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, (">Prefix miss\n"));
846  TRY(decodeString(strm, &str));
847  TRY(addPfxEntry(&strm->schema->uriTable.uri[uriId].pfxTable, str, pfxId));
848  }
849  else // prefix hit
850  {
851  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, (">Prefix hit\n"));
852  *pfxId = tmp_val_buf-1;
853  if(*pfxId >= strm->schema->uriTable.uri[uriId].pfxTable.count)
854  return EXIP_INVALID_EXI_INPUT;
855  }
856 
857  return EXIP_OK;
858 }
859 
861 {
862  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
863  UnsignedInteger tmpVar = 0;
864  TRY(decodeUnsignedInteger(strm, &tmpVar));
865 
866  if(tmpVar == 0) // "local" value partition table hit
867  {
868 #if VALUE_CROSSTABLE_USE
869  unsigned int vxEntryId = 0;
870  unsigned char vxBits;
871  VxTable* vxTable;
872 
873  vxTable = GET_LN_URI_QNAME(strm->schema->uriTable, qnameID).vxTable;
874  assert(vxTable);
875  vxBits = getBitsNumber(vxTable->count - 1);
876  TRY(decodeNBitUnsignedInteger(strm, vxBits, &vxEntryId));
877 
878  *value = strm->valueTable.value[vxTable->vx[vxEntryId].globalId].valueStr;
879 #else
880  DEBUG_MSG(ERROR, DEBUG_CONTENT_IO, ("> Local-value partition table hit but VALUE_CROSSTABLE_USE disabled \n"));
882 #endif
883  }
884  else if(tmpVar == 1)// global value partition table hit
885  {
886  unsigned int valueEntryID = 0;
887  unsigned char valueBits;
888 
889  valueBits = getBitsNumber(strm->valueTable.count - 1);
890  TRY(decodeNBitUnsignedInteger(strm, valueBits, &valueEntryID));
891 
892  *value = strm->valueTable.value[valueEntryID].valueStr;
893  }
894  else // "local" value partition and global value partition table miss
895  {
896  Index vStrLen = (Index) tmpVar - 2;
897 
898  TRY(allocateStringMemory(&value->str, vStrLen));
899  TRY(decodeStringOnly(strm, vStrLen, value));
900 
901  if(vStrLen > 0 && vStrLen <= strm->header.opts.valueMaxLength && strm->header.opts.valuePartitionCapacity > 0)
902  {
903  // The value should be entered in the value partitions of the string tables
904  TRY(addValueEntry(strm, *value, qnameID));
905  }
906  }
907  return EXIP_OK;
908 }
909 
911  SmallIndex* nonTermID_out, void* app_data)
912 {
913  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
914  QName qname;
915 
916  // TODO: implement all cases of events such as PI, CM etc.
917 
918  switch(GET_PROD_EXI_EVENT(prodHit->content))
919  {
920  case EVENT_SE_ALL:
921  strm->gStack->currNonTermID = GET_PROD_NON_TERM(prodHit->content);
922  assert(strm->context.isNilType == FALSE);
923 
924  TRY(decodeSEWildcardEvent(strm, handler, nonTermID_out, app_data));
925  break;
926  case EVENT_AT_ALL:
927  TRY(decodeATWildcardEvent(strm, handler, nonTermID_out, app_data));
928  break;
929  case EVENT_SE_QNAME:
930  {
931  EXIGrammar* elemGrammar = NULL;
932 
933  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, (">SE(qname) event: \n"));
934  assert(strm->context.isNilType == FALSE);
935 
936  qname.uri = &(strm->schema->uriTable.uri[prodHit->qnameId.uriId].uriStr);
937  qname.localName = &(GET_LN_URI_QNAME(strm->schema->uriTable, prodHit->qnameId).lnStr);
938 #if DEBUG_CONTENT_IO == ON && EXIP_DEBUG_LEVEL == INFO
939  printString(qname.uri);
940  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, (" : "));
941  printString(qname.localName);
942  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, ("\n"));
943 #endif
944  TRY(decodePfxQname(strm, &qname, prodHit->qnameId.uriId));
945 
946  strm->gStack->currNonTermID = *nonTermID_out;
947 
948  // New element grammar is pushed on the stack
949  if(IS_BUILT_IN_ELEM(strm->gStack->grammar->props)) // If the current grammar is build-in Element grammar ...
950  {
951  elemGrammar = GET_ELEM_GRAMMAR_QNAMEID(strm->schema, prodHit->qnameId);
952  }
953  else
954  {
955  elemGrammar = &strm->schema->grammarTable.grammar[prodHit->typeId];
956  }
957 
958  if(elemGrammar != NULL) // The grammar is found
959  {
960  *nonTermID_out = GR_START_TAG_CONTENT;
961  TRY(pushGrammar(&(strm->gStack), prodHit->qnameId, elemGrammar));
962  }
963  else
964  {
965  return EXIP_INCONSISTENT_PROC_STATE; // The event require the presence of Element Grammar previously created
966  }
967 
968  if(handler->startElement != NULL) // Invoke handler method passing the element qname
969  {
970  TRY(handler->startElement(qname, app_data));
971  }
972  }
973  break;
974  case EVENT_AT_QNAME:
975  {
976  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, (">AT(qname) event\n"));
977  strm->context.currAttr = prodHit->qnameId;
978  qname.uri = &strm->schema->uriTable.uri[strm->context.currAttr.uriId].uriStr;
979  qname.localName = &GET_LN_URI_QNAME(strm->schema->uriTable, prodHit->qnameId).lnStr;
980 #if DEBUG_CONTENT_IO == ON && EXIP_DEBUG_LEVEL == INFO
981  printString(qname.uri);
982  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, (" : "));
983  printString(qname.localName);
984  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, ("\n"));
985 #endif
986  TRY(decodePfxQname(strm, &qname, prodHit->qnameId.uriId));
987  if(handler->attribute != NULL) // Invoke handler method
988  {
989  TRY(handler->attribute(qname, app_data));
990  }
991  TRY(decodeValueItem(strm, prodHit->typeId, handler, nonTermID_out, prodHit->qnameId, app_data));
992  }
993  break;
994  case EVENT_CH:
995  {
996  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, (">CH event\n"));
997  assert(strm->context.isNilType == FALSE);
998  TRY(decodeValueItem(strm, prodHit->typeId, handler, nonTermID_out, strm->gStack->currQNameID, app_data));
999  }
1000  break;
1001  case EVENT_NS:
1002  TRY(decodeNSEvent(strm, handler, nonTermID_out, app_data));
1003  break;
1004  default:
1005  return EXIP_NOT_IMPLEMENTED_YET;
1006  }
1007 
1008  return EXIP_OK;
1009 }
1010 
1011 errorCode decodeValueItem(EXIStream* strm, Index typeId, ContentHandler* handler, SmallIndex* nonTermID_out, QNameID localQNameID, void* app_data)
1012 {
1013  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
1014  EXIType exiType = VALUE_TYPE_NONE;
1015 
1016  if(typeId != INDEX_MAX)
1017  exiType = GET_EXI_TYPE(strm->schema->simpleTypeTable.sType[typeId].content);
1018  else if(localQNameID.uriId == XML_SCHEMA_INSTANCE_ID &&
1019  (localQNameID.lnId == XML_SCHEMA_INSTANCE_TYPE_ID || localQNameID.lnId == XML_SCHEMA_INSTANCE_NIL_ID))
1020  {
1021  exiType = VALUE_TYPE_QNAME;
1022  }
1023 
1024  switch(exiType)
1025  {
1027  {
1028  UnsignedInteger uintVal;
1029  TRY(decodeUnsignedInteger(strm, &uintVal));
1030 
1031  if(handler->intData != NULL) // Invoke handler method
1032  {
1033  // TODO: the cast to signed int can introduce errors. Check first!
1034  TRY(handler->intData((Integer) uintVal, app_data));
1035  }
1036  }
1037  break;
1038  case VALUE_TYPE_INTEGER:
1039  {
1040  Integer sintVal;
1041  TRY(decodeIntegerValue(strm, &sintVal));
1042  if(handler->intData != NULL) // Invoke handler method
1043  {
1044  TRY(handler->intData(sintVal, app_data));
1045  }
1046  }
1047  break;
1049  {
1050  unsigned int uintVal;
1051  int base;
1052  int64_t upLimit;
1053 
1054  if(typeId >= strm->schema->simpleTypeTable.count)
1055  return EXIP_INVALID_EXI_INPUT;
1056 
1059  return EXIP_INVALID_EXI_INPUT;
1062  return EXIP_INVALID_EXI_INPUT;
1063 
1065  base = strm->schema->simpleTypeTable.sType[typeId].min;
1066  else
1067  return EXIP_NOT_IMPLEMENTED_YET;
1068 
1070  upLimit = strm->schema->simpleTypeTable.sType[typeId].max;
1071  else
1072  return EXIP_NOT_IMPLEMENTED_YET;
1073 
1074  TRY(decodeNBitUnsignedInteger(strm, getBitsNumber(upLimit - base), &uintVal));
1075  if(handler->intData != NULL) // Invoke handler method
1076  {
1077  TRY(handler->intData((Integer) (base + uintVal), app_data));
1078  }
1079  }
1080  break;
1081  case VALUE_TYPE_FLOAT:
1082  {
1083  Float flVal;
1084  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, (">Float value\n"));
1085  TRY(decodeFloatValue(strm, &flVal));
1086  if(handler->floatData != NULL) // Invoke handler method
1087  {
1088  TRY(handler->floatData(flVal, app_data));
1089  }
1090  }
1091  break;
1092  case VALUE_TYPE_BOOLEAN:
1093  {
1094  boolean bool_val;
1095  TRY(decodeBoolean(strm, &bool_val));
1096  if(handler->booleanData != NULL) // Invoke handler method
1097  {
1098  TRY(handler->booleanData(bool_val, app_data));
1099  }
1100 
1101  // handle xsi:nil attribute
1102  if(IS_SCHEMA(strm->gStack->grammar->props) && localQNameID.uriId == XML_SCHEMA_INSTANCE_ID && localQNameID.lnId == XML_SCHEMA_INSTANCE_NIL_ID) // Schema-enabled grammar and http://www.w3.org/2001/XMLSchema-instance:nil
1103  {
1104  if(bool_val == TRUE)
1105  {
1106  // xsi:nil attribute equals to true & schema mode
1107  strm->context.isNilType = TRUE;
1108  *nonTermID_out = GR_START_TAG_CONTENT;
1109  }
1110  }
1111  }
1112  break;
1113  case VALUE_TYPE_BINARY:
1114  {
1115  Index nbytes;
1116  char *binary_val;
1117  //DEBUG_MSG(INFO, DEBUG_CONTENT_IO, (">Binary value\n"));
1118  TRY(decodeBinary(strm, &binary_val, &nbytes));
1119 
1120  if(handler->binaryData != NULL) // Invoke handler method
1121  {
1122  TRY_CATCH(handler->binaryData(binary_val, nbytes, app_data), EXIP_MFREE(binary_val));
1123  }
1124 
1125  /* Free the memory allocated by decodeBinary() */
1126  EXIP_MFREE(binary_val);
1127  }
1128  break;
1129  case VALUE_TYPE_DECIMAL:
1130  {
1131  Decimal decVal;
1132 
1133  TRY(decodeDecimalValue(strm, &decVal));
1134 
1135  // TODO: make conditional, not all use cases need Schema type validation
1138  {
1139  unsigned int totalDigits = 0;
1140 
1141  if(decVal.exponent != 0 && decVal.mantissa != 0)
1142  {
1143  int64_t mantissa = decVal.mantissa;
1144  while(mantissa)
1145  {
1146  mantissa /= 10;
1147  totalDigits++;
1148  }
1149 
1150  if(decVal.exponent > 0)
1151  totalDigits += decVal.exponent;
1152  }
1153  else
1154  totalDigits = 1;
1155 
1156  if(totalDigits > (strm->schema->simpleTypeTable.sType[typeId].length >> 16))
1157  return EXIP_INVALID_EXI_INPUT;
1158  }
1159 
1161  {
1162  unsigned int fractionDigits = 0;
1163 
1164  if(decVal.exponent < 0 && decVal.mantissa != 0)
1165  fractionDigits = -decVal.exponent;
1166 
1167  if(fractionDigits > (strm->schema->simpleTypeTable.sType[typeId].length & 0xFFFF))
1168  return EXIP_INVALID_EXI_INPUT;
1169  }
1171 
1172  if(handler->decimalData != NULL) // Invoke handler method
1173  {
1174  TRY(handler->decimalData(decVal, app_data));
1175  }
1176  }
1177  break;
1178  case VALUE_TYPE_DATE_TIME:
1179  case VALUE_TYPE_YEAR:
1180  case VALUE_TYPE_DATE:
1181  case VALUE_TYPE_MONTH:
1182  case VALUE_TYPE_TIME:
1183  {
1184  EXIPDateTime dtVal;
1185 
1186  TRY(decodeDateTimeValue(strm, exiType, &dtVal));
1187  if(handler->dateTimeData != NULL) // Invoke handler method
1188  {
1189  TRY(handler->dateTimeData(dtVal, app_data));
1190  }
1191  }
1192  break;
1193  case VALUE_TYPE_LIST:
1194  {
1195  UnsignedInteger itemCount;
1196  Index itemTypeId;
1197  unsigned int i;
1198 
1199  TRY(decodeUnsignedInteger(strm, &itemCount));
1200 
1201  itemTypeId = strm->schema->simpleTypeTable.sType[typeId].length; // The item typeID must be encoded in the length field
1202  if(itemTypeId >= strm->schema->simpleTypeTable.count)
1203  return EXIP_UNEXPECTED_ERROR;
1204 
1205  if(handler->listData != NULL) // Invoke handler method
1206  {
1207  TRY(handler->listData(GET_EXI_TYPE(strm->schema->simpleTypeTable.sType[itemTypeId].content), (unsigned int) itemCount, app_data));
1208  }
1209 
1210  for(i = 0; i < itemCount; i++)
1211  {
1212  TRY(decodeValueItem(strm, itemTypeId, handler, nonTermID_out, localQNameID, app_data));
1213  }
1214  }
1215  break;
1216  case VALUE_TYPE_QNAME:
1217  {
1218  // Only allowed if the current production is AT(xsi:type)
1219  assert(localQNameID.uriId == XML_SCHEMA_INSTANCE_ID && localQNameID.lnId == XML_SCHEMA_INSTANCE_TYPE_ID);
1220  TRY(decodeQNameValue(strm, handler, nonTermID_out, app_data));
1221  }
1222  break;
1223  default: // VALUE_TYPE_STRING || VALUE_TYPE_NONE || VALUE_TYPE_UNTYPED
1224  {
1225  String value;
1226  boolean freeable = FALSE;
1227 
1228  /* ENUMERATION CHECK */
1230  {
1231  // There is enumeration defined
1232  EnumDefinition eDefSearch;
1233  EnumDefinition* eDefFound;
1234  unsigned int indx;
1235 
1236  eDefSearch.typeId = typeId;
1237  eDefFound = bsearch(&eDefSearch, strm->schema->enumTable.enumDef, strm->schema->enumTable.count, sizeof(EnumDefinition), compareEnumDefs);
1238  if(eDefFound == NULL)
1239  return EXIP_UNEXPECTED_ERROR;
1240 
1241  TRY(decodeNBitUnsignedInteger(strm, getBitsNumber(eDefFound->count - 1), &indx));
1242  value = ((String*) eDefFound->values)[indx];
1243  freeable = FALSE;
1244  }
1245  else
1246  {
1247  TRY(decodeStringValue(strm, localQNameID, &value));
1248 
1249  if(value.length == 0 || value.length > strm->header.opts.valueMaxLength || strm->header.opts.valuePartitionCapacity == 0)
1250  freeable = TRUE;
1251  }
1252 
1253  if(handler->stringData != NULL) // Invoke handler method
1254  {
1255  TRY(handler->stringData(value, app_data));
1256  }
1257 
1258  if(freeable)
1259  EXIP_MFREE(value.str);
1260  } break;
1261  }
1262 
1263  return EXIP_OK;
1264 }
1265 
1266 errorCode decodeNSEvent(EXIStream* strm, ContentHandler* handler, SmallIndex* nonTermID_out, void* app_data)
1267 {
1268  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
1269  SmallIndex ns_uriId;
1270  SmallIndex pfxId;
1271  boolean bool = FALSE;
1272 
1273  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, (">NS event:\n"));
1274  *nonTermID_out = GR_START_TAG_CONTENT;
1275 
1276  TRY(decodeUri(strm, &ns_uriId));
1277 
1278  TRY(decodePfx(strm, ns_uriId, &pfxId));
1279  TRY(decodeBoolean(strm, &bool));
1280 
1281  if(handler->namespaceDeclaration != NULL) // Invoke handler method
1282  {
1283  TRY(handler->namespaceDeclaration(strm->schema->uriTable.uri[ns_uriId].uriStr, strm->schema->uriTable.uri[ns_uriId].pfxTable.pfx[pfxId], bool, app_data));
1284  }
1285  return EXIP_OK;
1286 }
1287 
1288 errorCode decodeSEWildcardEvent(EXIStream* strm, ContentHandler* handler, SmallIndex* nonTermID_out, void* app_data)
1289 {
1290  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
1291  EXIGrammar* elemGrammar = NULL;
1292  QName qname;
1293  QNameID qnameId = {URI_MAX, LN_MAX};
1294 
1295  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, (">SE(*) event\n"));
1296 
1297  // The content of SE event is the element qname
1298  TRY(decodeQName(strm, &qname, &qnameId));
1299 
1300  if(handler->startElement != NULL) // Invoke handler method passing the element qname
1301  {
1302  TRY(handler->startElement(qname, app_data));
1303  }
1304 
1305  // New element grammar is pushed on the stack
1306 #if EXI_PROFILE_DEFAULT
1307  if(GET_LN_URI_QNAME(strm->schema->uriTable, qnameId).elemGrammar == EXI_PROFILE_STUB_GRAMMAR_INDX)
1308  elemGrammar = NULL;
1309  else
1310 #endif
1311  elemGrammar = GET_ELEM_GRAMMAR_QNAMEID(strm->schema, qnameId);
1312  *nonTermID_out = GR_START_TAG_CONTENT;
1313 
1314  if(elemGrammar != NULL)
1315  {
1316  // The grammar is found
1317  TRY(pushGrammar(&(strm->gStack), qnameId, elemGrammar));
1318  }
1319  else
1320  {
1321 #if BUILD_IN_GRAMMARS_USE
1322  Index dynArrIndx;
1323  EXIGrammar newElementGrammar;
1324  TRY(createBuiltInElementGrammar(&newElementGrammar, strm));
1325  TRY(addDynEntry(&strm->schema->grammarTable.dynArray, &newElementGrammar, &dynArrIndx));
1326 
1327  GET_LN_URI_QNAME(strm->schema->uriTable, qnameId).elemGrammar = dynArrIndx;
1328  TRY(pushGrammar(&(strm->gStack), qnameId, &strm->schema->grammarTable.grammar[dynArrIndx]));
1329 #elif EXI_PROFILE_DEFAULT
1330  {
1331  unsigned int prodCnt = 4;
1332  unsigned int tmp_bits_val = 0;
1333  QName attrQname;
1334  QNameID attrQnameId = {URI_MAX, LN_MAX};
1335  boolean nsProdHit = FALSE;
1336 
1337  prodCnt += IS_PRESERVED(strm->header.opts.preserve, PRESERVE_PREFIXES);
1338  prodCnt += WITH_SELF_CONTAINED(strm->header.opts.enumOpt);
1339  prodCnt += IS_PRESERVED(strm->header.opts.preserve, PRESERVE_DTD);
1341 
1342  do
1343  {
1344  if(GET_LN_URI_QNAME(strm->schema->uriTable, qnameId).elemGrammar == EXI_PROFILE_STUB_GRAMMAR_INDX)
1345  {
1346  // This grammar must be the EXI Profile stub grammar.
1347  // It indicates that there is a AT(xsi:type) as a top level production
1348  // There should be a AT(xsi:type) with event code 0
1349  TRY(decodeNBitUnsignedInteger(strm, 1, &tmp_bits_val));
1350  if(tmp_bits_val != 1)
1351  {
1352  DEBUG_MSG(ERROR, DEBUG_CONTENT_IO, (">AT(xsi:type) should always be represented as AT(*) according to EXI Profile spec\n"));
1354  }
1355  }
1356 
1357  // There should be a valid xsi:type switch, otherwise rise an error
1358  // Note also that there might be NS productions before the xsi:type switch
1359  TRY(decodeNBitUnsignedInteger(strm, getBitsNumber(prodCnt - 1), &tmp_bits_val));
1360  if(tmp_bits_val != 1)
1361  {
1362  if(IS_PRESERVED(strm->header.opts.preserve, PRESERVE_PREFIXES) && tmp_bits_val == 2)
1363  {
1364  // NS event(s)
1365  TRY(decodeNSEvent(strm, handler, nonTermID_out, app_data));
1366  nsProdHit = TRUE;
1367  }
1368 
1369  DEBUG_MSG(ERROR, DEBUG_CONTENT_IO, (">Build-in element grammars are not supported by this configuration \n"));
1371  }
1372  else
1373  nsProdHit = FALSE;
1374  }
1375  while(nsProdHit);
1376 
1377  TRY(decodeQName(strm, &attrQname, &attrQnameId));
1378  if(attrQnameId.uriId != XML_SCHEMA_INSTANCE_ID || attrQnameId.lnId != XML_SCHEMA_INSTANCE_TYPE_ID)
1379  {
1380  DEBUG_MSG(ERROR, DEBUG_CONTENT_IO, (">Build-in element grammars are not supported by this configuration \n"));
1382  }
1383 
1384  if(handler->attribute != NULL) // Invoke handler method for xsi:type
1385  {
1386  TRY(handler->attribute(attrQname, app_data));
1387  }
1388 
1389  TRY(decodeQName(strm, &attrQname, &attrQnameId));
1390 
1391  if(handler->qnameData != NULL) // Invoke handler method for the QName value of xsi:type
1392  {
1393  TRY(handler->qnameData(attrQname, app_data));
1394  }
1395 
1396  GET_LN_URI_QNAME(strm->schema->uriTable, qnameId).elemGrammar = EXI_PROFILE_STUB_GRAMMAR_INDX;
1397 
1398  // Successful xsi:type switch
1399  // New element grammar is pushed on the stack
1400  elemGrammar = GET_TYPE_GRAMMAR_QNAMEID(strm->schema, attrQnameId);
1401 
1402  if(elemGrammar != NULL)
1403  {
1404  // The grammar is found
1405  TRY(pushGrammar(&(strm->gStack), qnameId, elemGrammar));
1406  }
1407  else
1408  {
1409  DEBUG_MSG(ERROR, DEBUG_CONTENT_IO, (">Build-in element grammars are not supported by this configuration \n"));
1411  }
1412  }
1413 #else
1414  DEBUG_MSG(ERROR, DEBUG_CONTENT_IO, (">Build-in element grammars are not supported by this configuration \n"));
1415  assert(FALSE);
1417 #endif
1418  }
1419 
1420  return EXIP_OK;
1421 }
1422 
1423 errorCode decodeATWildcardEvent(EXIStream* strm, ContentHandler* handler, SmallIndex* nonTermID_out, void* app_data)
1424 {
1425  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
1426  QName qname;
1427  QNameID qnameId = {URI_MAX, LN_MAX};
1428 
1429  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, (">AT(*) event\n"));
1430 
1431  TRY(decodeQName(strm, &qname, &qnameId));
1432 
1433  if(qnameId.uriId == XML_SCHEMA_INSTANCE_ID &&
1435  {
1436  if(IS_SCHEMA(strm->gStack->grammar->props))
1437  {
1438  DEBUG_MSG(ERROR, DEBUG_CONTENT_IO, (">In schema-informed grammars, xsi:type and xsi:nil attributes MUST NOT be represented using AT(*) terminal\n"));
1440  }
1441  }
1442 
1443  if(handler->attribute != NULL) // Invoke handler method
1444  {
1445  TRY(handler->attribute(qname, app_data));
1446  }
1447 
1448  TRY(decodeValueItem(strm, INDEX_MAX, handler, nonTermID_out, qnameId, app_data));
1449  strm->context.currAttr = qnameId;
1450 
1451  return EXIP_OK;
1452 }
1453 
1454 static errorCode decodeQNameValue(EXIStream* strm, ContentHandler* handler, SmallIndex* nonTermID_out, void* app_data)
1455 {
1456  // TODO: Add the case when Preserve.lexicalValues option value is true - instead of Qname decode it as String
1457  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
1458  QName qname;
1459  QNameID qnameId;
1460  EXIGrammar* newGrammar = NULL;
1461 
1462  TRY(decodeQName(strm, &qname, &qnameId));
1463 
1464  if(handler->qnameData != NULL) // Invoke handler method
1465  {
1466  TRY(handler->qnameData(qname, app_data));
1467  }
1468 
1469  // New type grammar is pushed on the stack if it exists
1470  newGrammar = GET_TYPE_GRAMMAR_QNAMEID(strm->schema, qnameId);
1471 
1472  if(newGrammar != NULL)
1473  {
1474  // The grammar is found
1475  // preserve the currQNameID
1476  QNameID currQNameID = strm->gStack->currQNameID;
1477  popGrammar(&(strm->gStack));
1478 
1479  *nonTermID_out = GR_START_TAG_CONTENT;
1480  TRY(pushGrammar(&(strm->gStack), currQNameID, newGrammar));
1481  }
1482 
1483  return EXIP_OK;
1484 }