exip  Alpha 0.5.4
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
EXISerializer.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 "EXISerializer.h"
19 #include "grammars.h"
20 #include "memManagement.h"
21 #include "sTables.h"
22 #include "headerEncode.h"
23 #include "bodyEncode.h"
24 #include "hashtable.h"
25 #include "stringManipulate.h"
26 #include "streamEncode.h"
27 #include "initSchemaInstance.h"
28 #include "ioUtil.h"
29 #include "streamEncode.h"
30 
37  endElement,
38  attribute,
39  intData,
41  stringData,
42  floatData,
43  binaryData,
46  listData,
47  qnameData,
52  initHeader,
53  initStream,
55  flushEXIData};
56 
57 #if EXI_PROFILE_DEFAULT
58 
59 extern const String XML_SCHEMA_INSTANCE;
60 extern const String URI_2_LN[];
61 
62 static errorCode encodeATXsiType(EXIStream* strm);
63 static errorCode encodeAnyType(EXIStream* strm);
64 #endif
65 
66 void initHeader(EXIStream* strm)
67 {
68  strm->header.has_cookie = FALSE;
69  strm->header.has_options = FALSE;
71  strm->header.version_number = 1;
72  makeDefaultOpts(&strm->header.opts);
73 }
74 
76 {
77  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
78 
79  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, (">EXI stream initialization \n"));
80 
82 
83  TRY(initAllocList(&(strm->memList)));
84  strm->buffer = buffer;
85  strm->context.bitPointer = 0;
86  strm->context.bufferIndx = 0;
87  strm->context.currAttr.uriId = URI_MAX;
88  strm->context.currAttr.lnId = LN_MAX;
89  strm->context.expectATData = FALSE;
90  strm->context.isNilType = FALSE;
92  strm->gStack = NULL;
93  strm->valueTable.value = NULL;
94  strm->valueTable.count = 0;
95  strm->schema = NULL;
96 
97  if(strm->header.opts.valuePartitionCapacity > 0)
98  {
100  }
101 
103  {
104  // When the "schemaId" element in the EXI options document contains the xsi:nil attribute
105  // with its value set to true, no schema information is used for processing the EXI body
106  // (i.e. a schema-less EXI stream)
107  strm->schema = NULL;
108 #if EXI_PROFILE_DEFAULT
109  DEBUG_MSG(ERROR, DEBUG_CONTENT_IO, ("\n> EXI Profile mode require schema mode processing"));
110  return EXIP_INVALID_EXI_INPUT;
111 #endif
112 
113 #if DEBUG_CONTENT_IO == ON && EXIP_DEBUG_LEVEL <= WARNING
114  if(schema != NULL)
115  DEBUG_MSG(WARNING, DEBUG_CONTENT_IO, ("\n> Ignored schema information - SCHEMA_ID_NIL mode required"));
116 #endif
117  }
118  else if(strm->header.opts.schemaIDMode == SCHEMA_ID_EMPTY)
119  {
120  // When the value of the "schemaId" element is empty, no user defined schema information
121  // is used for processing the EXI body; however, the built-in XML schema types are available for use in the EXI body
122 #if DEBUG_CONTENT_IO == ON && EXIP_DEBUG_LEVEL <= WARNING
123  if(schema != NULL)
124  DEBUG_MSG(WARNING, DEBUG_CONTENT_IO, ("\n> Ignored out-of-band schema information. Schema mode built-in types required"));
125 #endif
126  strm->schema = memManagedAllocate(&strm->memList, sizeof(EXIPSchema));
127  if(strm->schema == NULL)
129 
131 
132  if(WITH_FRAGMENT(strm->header.opts.enumOpt))
133  {
134  TRY(createFragmentGrammar(strm->schema, NULL, 0));
135  }
136  else
137  {
138  TRY(createDocGrammar(strm->schema, NULL, 0));
139  }
140  }
141  else if(schema != NULL)
142  {
143  /* Schema enabled mode*/
145  {
146  if(isStringEmpty(&strm->header.opts.schemaID))
148  }
149 
150  if(WITH_FRAGMENT(strm->header.opts.enumOpt))
151  {
152  /* Fragment document grammar */
153  // TODO: create a Schema-informed Fragment Grammar from the EXIP schema object
155  }
156  else
157  {
158  strm->schema = schema;
159  }
160  }
161 
162  if(strm->schema == NULL)
163  {
164  // Schema-less mode
166  {
167  DEBUG_MSG(ERROR, DEBUG_CONTENT_IO, ("\n> SCHEMA_ID_SET mode required, but NULL schema set"));
169  }
170 
171 #if EXI_PROFILE_DEFAULT
172  DEBUG_MSG(ERROR, DEBUG_CONTENT_IO, ("\n> EXI Profile mode require schema mode processing"));
173  return EXIP_INVALID_EXI_INPUT;
174 #endif
175 
176  strm->schema = memManagedAllocate(&strm->memList, sizeof(EXIPSchema));
177  if(strm->schema == NULL)
179 
181 
182  if(WITH_FRAGMENT(strm->header.opts.enumOpt))
183  {
184  TRY(createFragmentGrammar(strm->schema, NULL, 0));
185  }
186  else
187  {
188  TRY(createDocGrammar(strm->schema, NULL, 0));
189  }
190  }
191 
192  {
193  QNameID emptyQNameID = {URI_MAX, LN_MAX};
194  TRY(pushGrammar(&strm->gStack, emptyQNameID, &strm->schema->docGrammar));
195  }
196  // #DOCUMENT#
197  // Hashtable for fast look-up of global values in the table.
198  // Only used when:
199  // serializing &&
200  // valuePartitionCapacity > 50 && //for small table full-scan will work better
201  // valueMaxLength > 0 && // this is essentially equal to valuePartitionCapacity == 0
202  // HASH_TABLE_USE == ON // build configuration parameter
203 #if HASH_TABLE_USE
205  strm->header.opts.valueMaxLength > 0)
206  {
208  if(strm->valueTable.hashTbl == NULL)
209  return EXIP_HASH_TABLE_ERROR;
210  }
211  else
212  strm->valueTable.hashTbl = NULL;
213 #endif
214  return EXIP_OK;
215 }
216 
218 {
219  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, (">Start doc serialization\n"));
220 
221  if(strm->gStack->grammar == NULL && strm->gStack->currNonTermID != GR_DOC_CONTENT)
223 
224  return EXIP_OK;
225 }
226 
228 {
229  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
230  Production prodHit = {0, INDEX_MAX, {URI_MAX, LN_MAX}};
231  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, (">End doc serialization\n"));
232 
233  if(strm->gStack->grammar == NULL)
235 
236  tmp_err_code = encodeProduction(strm, EVENT_ED_CLASS, TRUE, NULL, VALUE_TYPE_NONE_CLASS, &prodHit);
237 
238  // Store the size of the encoded stream contained in the BinaryBuffer in the BinaryBuffer.bufContent
239  strm->buffer.bufContent = strm->context.bufferIndx + (strm->context.bitPointer > 0);
240 
241  return tmp_err_code;
242 }
243 
245 {
246  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
247  Production prodHit = {0, INDEX_MAX, {URI_MAX, LN_MAX}};
248 
249  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, ("\n>Start element serialization\n"));
250 
251  if(strm->gStack->grammar == NULL)
252 #if EXI_PROFILE_DEFAULT
253  {
254  TRY(encodeATXsiType(strm));
255  TRY(encodeAnyType(strm));
256  }
257 #else
258  {
260  }
261 #endif
262 
263  *valueType = VALUE_TYPE_NONE_CLASS;
264 
265  TRY(encodeProduction(strm, EVENT_SE_CLASS, TRUE, &qname, VALUE_TYPE_NONE_CLASS, &prodHit));
266 
267  if(GET_PROD_EXI_EVENT(prodHit.content) == EVENT_SE_ALL)
268  {
269  EXIGrammar* elemGrammar = NULL;
270  QNameID tmpQid;
271 
272  TRY(encodeQName(strm, qname, EVENT_SE_ALL, &tmpQid));
273 
274  // New element grammar is pushed on the stack
275 #if EXI_PROFILE_DEFAULT
276  if(GET_LN_URI_QNAME(strm->schema->uriTable, tmpQid).elemGrammar == EXI_PROFILE_STUB_GRAMMAR_INDX)
277  elemGrammar = NULL;
278  else
279 #endif
280  elemGrammar = GET_ELEM_GRAMMAR_QNAMEID(strm->schema, tmpQid);
281 
282  if(elemGrammar != NULL) // The grammar is found
283  {
284  TRY(pushGrammar(&(strm->gStack), tmpQid, elemGrammar));
285  }
286  else
287  {
288 #if BUILD_IN_GRAMMARS_USE
289  EXIGrammar newElementGrammar;
290  Index dynArrIndx;
291  TRY(createBuiltInElementGrammar(&newElementGrammar, strm));
292 
293  TRY(addDynEntry(&strm->schema->grammarTable.dynArray, &newElementGrammar, &dynArrIndx));
294 
295  GET_LN_URI_QNAME(strm->schema->uriTable, tmpQid).elemGrammar = dynArrIndx;
296  TRY(pushGrammar(&(strm->gStack), tmpQid, &strm->schema->grammarTable.grammar[dynArrIndx]));
297 #elif EXI_PROFILE_DEFAULT
298  // Leave the grammar NULL - if the next event is valid AT(xsi:type)
299  // then its value will be the next grammar.
300  // If the next event is not valid AT(xsi:type) - then the event
301  // AT(xsi:type="anyType") will be inserted beforehand
302  TRY(pushGrammar(&(strm->gStack), tmpQid, elemGrammar));
303 
304  return EXIP_OK;
305 #else
306  DEBUG_MSG(ERROR, DEBUG_CONTENT_IO, (">Build-in element grammars are not supported by this configuration \n"));
307  assert(FALSE);
309 #endif
310  }
311  }
312  else if(GET_PROD_EXI_EVENT(prodHit.content) == EVENT_SE_QNAME)
313  {
314  EXIGrammar* elemGrammar = NULL;
315 
316  TRY(encodePfxQName(strm, &qname, EVENT_SE_QNAME, prodHit.qnameId.uriId));
317 
318  // New element grammar is pushed on the stack
319  if(IS_BUILT_IN_ELEM(strm->gStack->grammar->props)) // If the current grammar is build-in Element grammar ...
320  {
321  elemGrammar = GET_ELEM_GRAMMAR_QNAMEID(strm->schema, prodHit.qnameId);
322  }
323  else
324  {
325  elemGrammar = &strm->schema->grammarTable.grammar[prodHit.typeId];
326  }
327 
328  if(elemGrammar != NULL) // The grammar is found
329  TRY(pushGrammar(&(strm->gStack), prodHit.qnameId, elemGrammar));
330  else
331  return EXIP_INCONSISTENT_PROC_STATE; // The event require the presence of Element Grammar previously created
332  }
333  else
335 
336  if(!IS_BUILT_IN_ELEM(strm->gStack->grammar->props)) // If the current grammar is not build-in Element grammar ...
337  {
338  GrammarRule* currentRule;
339  currentRule = &strm->gStack->grammar->rule[strm->gStack->currNonTermID];
340  assert(currentRule->production);
341  if(GET_PROD_EXI_EVENT(currentRule->production[currentRule->pCount-1].content) == EVENT_CH)
342  {
343  // This must be simple type grammar
344  if(currentRule->production[currentRule->pCount-1].typeId == INDEX_MAX)
345  *valueType = VALUE_TYPE_UNTYPED_CLASS;
346  else
347  *valueType = GET_VALUE_TYPE_CLASS(GET_EXI_TYPE(strm->schema->simpleTypeTable.sType[currentRule->production[currentRule->pCount-1].typeId].content));
348  }
349  }
350 
351  return EXIP_OK;
352 }
353 
355 {
356  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
357  Production prodHit = {0, INDEX_MAX, {URI_MAX, LN_MAX}};
358 
359  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, (">End element serialization\n"));
360 
361  if(strm->gStack->grammar == NULL)
362 #if EXI_PROFILE_DEFAULT
363  {
364  TRY(encodeATXsiType(strm));
365  TRY(encodeAnyType(strm));
366  }
367 #else
368  {
370  }
371 #endif
372 
374 
376  popGrammar(&(strm->gStack));
377  else
379 
380  return EXIP_OK;
381 }
382 
383 errorCode attribute(EXIStream* strm, QName qname, boolean isSchemaType, EXITypeClass* valueType)
384 {
385  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
386  Production prodHit = {0, INDEX_MAX, {URI_MAX, LN_MAX}};
387 
388  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, ("\n>Start attribute serialization\n"));
389 
390  assert(qname.uri != NULL);
391  assert(qname.localName != NULL);
392 
393  if(strm->gStack->grammar == NULL)
394 #if EXI_PROFILE_DEFAULT
395  {
396  // if qname == xsi:type
397  if(stringEqual(*qname.uri, XML_SCHEMA_INSTANCE) &&
399  {
400  // Encode the xsi:type and wait for a QName type serialization;
401  // Leave the current grammar NULL
402  TRY(encodeATXsiType(strm));
403  strm->context.expectATData = TRUE;
407  *valueType = VALUE_TYPE_QNAME_CLASS;
408  return EXIP_OK;
409  }
410  else
411  {
412  // Insert first an AT(xsi:type="anyType) event
413  TRY(encodeATXsiType(strm));
414  TRY(encodeAnyType(strm));
415  }
416  }
417 #else
418  {
420  }
421 #endif
422 
423  // Check for trying to represent namespace declarations with AT event
424  // Only in debug mode!
425  // See EXI errata about namespace declarations - http://www.w3.org/XML/EXI/exi-10-errata
426 #if EXIP_DEBUG == ON && EXIP_DEBUG_LEVEL == WARNING
427  {
428  String ln = *qname.localName;
429 
430  if(!stringEqualToAscii(*qname.uri, "http://www.w3.org/2000/xmlns/"))
431  {
432  DEBUG_MSG(WARNING, DEBUG_CONTENT_IO, ("\n>Trying to represent namespace declarations with AT event\n"));
433  return EXIP_INVALID_EXI_INPUT;
434  }
435 
436  if(ln.length != 0)
437  {
438  ln.length = 5;
439  if(!stringEqualToAscii(ln, "xmlns"))
440  {
441  DEBUG_MSG(WARNING, DEBUG_CONTENT_IO, ("\n>Trying to represent namespace declarations with AT event\n"));
442  return EXIP_INVALID_EXI_INPUT;
443  }
444  }
445  }
446 #endif
447 
448  TRY(encodeProduction(strm, EVENT_AT_CLASS, isSchemaType, &qname, VALUE_TYPE_NONE_CLASS, &prodHit));
449 
450  if(prodHit.typeId == INDEX_MAX)
451  *valueType = VALUE_TYPE_NONE_CLASS;
452  else
454 
455  if(GET_PROD_EXI_EVENT(prodHit.content) == EVENT_AT_ALL)
456  {
457  TRY(encodeQName(strm, qname, EVENT_AT_ALL, &strm->context.currAttr));
458 
461  {
462  DEBUG_MSG(ERROR, DEBUG_CONTENT_IO, (">In schema-informed grammars, xsi:type and xsi:nil attributes MUST NOT be represented using AT(*) terminal\n"));
464  }
465  }
466  else if(GET_PROD_EXI_EVENT(prodHit.content) == EVENT_AT_QNAME)
467  {
468  strm->context.currAttr.uriId = prodHit.qnameId.uriId;
469  strm->context.currAttr.lnId = prodHit.qnameId.lnId;
470 
471  TRY(encodePfxQName(strm, &qname, EVENT_AT_QNAME, prodHit.qnameId.uriId));
472  }
473  else
475 
476  strm->context.expectATData = TRUE;
477  strm->context.attrTypeId = prodHit.typeId;
478 
479  return EXIP_OK;
480 }
481 
483 {
484  Index intTypeId;
485  QNameID qnameID;
486  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, ("\n>Start integer data serialization\n"));
487 
488  if(strm->gStack->grammar == NULL)
490 
491  if(strm->context.expectATData > 0) // Value for an attribute or list item
492  {
493  intTypeId = strm->context.attrTypeId;
494  qnameID = strm->context.currAttr;
495  strm->context.expectATData -= 1;
496  }
497  else
498  {
499  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
500  Production prodHit = {0, INDEX_MAX, {URI_MAX, LN_MAX}};
501 
502  // TODO: passing the type class is not enough:
503  // we need to check if the int value (int_val) fits in the
504  // production value content description.
505  // If it does not fit we need to again use untyped second level production
507  qnameID = strm->gStack->currQNameID;
508  intTypeId = prodHit.typeId;
509  }
510 
511  return encodeIntData(strm, int_val, qnameID, intTypeId);
512 }
513 
514 errorCode booleanData(EXIStream* strm, boolean bool_val)
515 {
516  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
517  boolean isXsiNilAttr = FALSE;
518  Index booleanTypeId;
519  EXIType exiType;
520  QNameID qnameID;
521 
522  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, ("\n>Start boolean data serialization\n"));
523 
524  if(strm->gStack->grammar == NULL)
526 
527  if(strm->context.expectATData > 0) // Value for an attribute
528  {
529  strm->context.expectATData -= 1;
531  {
532  // xsi:nill
533  isXsiNilAttr = TRUE;
534  }
535  booleanTypeId = strm->context.attrTypeId;
536  qnameID = strm->context.currAttr;
537  }
538  else
539  {
540  Production prodHit = {0, INDEX_MAX, {URI_MAX, LN_MAX}};
541 
543  booleanTypeId = prodHit.typeId;
544  qnameID = strm->gStack->currQNameID;
545  }
546 
547  if(booleanTypeId != INDEX_MAX)
548  exiType = GET_EXI_TYPE(strm->schema->simpleTypeTable.sType[booleanTypeId].content);
549  else
550  exiType = VALUE_TYPE_NONE;
551 
552  if(exiType == VALUE_TYPE_BOOLEAN)
553  {
554  TRY(encodeBoolean(strm, bool_val));
555  }
556  else if(exiType == VALUE_TYPE_STRING || exiType == VALUE_TYPE_UNTYPED || exiType == VALUE_TYPE_NONE)
557  {
558  // 1) Print Warning
559  // 2) convert the boolean to sting
560  // 3) encode string
561  String tmpStr;
562 
563  DEBUG_MSG(WARNING, DEBUG_CONTENT_IO, ("\n>Boolean to String conversion required \n"));
564 #if EXIP_IMPLICIT_DATA_TYPE_CONVERSION
565  TRY(booleanToString(bool_val, &tmpStr));
566  TRY(encodeStringData(strm, tmpStr, qnameID, booleanTypeId));
567  EXIP_MFREE(tmpStr.str);
568 #else
569  return EXIP_INVALID_EXI_INPUT;
570 #endif
571  }
572  else
573  {
574  DEBUG_MSG(ERROR, DEBUG_CONTENT_IO, ("\n>Production type is not a boolean\n"));
576  }
577 
578  if(IS_SCHEMA(strm->gStack->grammar->props) && isXsiNilAttr && bool_val)
579  {
580  // In a schema-informed grammar && xsi:nil == TRUE
581  strm->context.isNilType = TRUE;
583  }
584 
585  return EXIP_OK;
586 }
587 
588 errorCode stringData(EXIStream* strm, const String str_val)
589 {
590  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
591  QNameID qnameID;
592  Index typeId;
593  EXIType exiType;
594 
595  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, ("\n>Start string data serialization\n"));
596 
597  if(strm->gStack->grammar == NULL)
598 #if EXI_PROFILE_DEFAULT
599  {
600  TRY(encodeATXsiType(strm));
601  TRY(encodeAnyType(strm));
602  }
603 #else
604  {
606  }
607 #endif
608 
609  if(strm->context.expectATData > 0) // Value for an attribute
610  {
611  strm->context.expectATData -= 1;
612  qnameID = strm->context.currAttr;
613  typeId = strm->context.attrTypeId;
614  }
615  else
616  {
617  Production prodHit = {0, INDEX_MAX, {URI_MAX, LN_MAX}};
618 
620 
621  qnameID = strm->gStack->currQNameID;
622  typeId = prodHit.typeId;
623  }
624 
625  if(typeId != INDEX_MAX)
626  exiType = GET_EXI_TYPE(strm->schema->simpleTypeTable.sType[typeId].content);
627  else
628  exiType = VALUE_TYPE_NONE;
629 
630  if(exiType == VALUE_TYPE_STRING || exiType == VALUE_TYPE_UNTYPED || exiType == VALUE_TYPE_NONE)
631  {
632  return encodeStringData(strm, str_val, qnameID, typeId);
633  }
634  else
635  {
636  DEBUG_MSG(ERROR, DEBUG_CONTENT_IO, ("\n>Expected typed data, but string provided\n"));
637  return EXIP_INVALID_EXI_INPUT;
638  }
639 }
640 
642 {
643  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
644  Index typeId;
645  QNameID qnameID;
646  EXIType exiType;
647  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, ("\n>Start float data serialization\n"));
648 
649  if(strm->gStack->grammar == NULL)
651 
652  if(strm->context.expectATData > 0) // Value for an attribute
653  {
654  strm->context.expectATData -= 1;
655  typeId = strm->context.attrTypeId;
656  qnameID = strm->context.currAttr;
657  }
658  else
659  {
660  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
661  Production prodHit = {0, INDEX_MAX, {URI_MAX, LN_MAX}};
662 
664  qnameID = strm->gStack->currQNameID;
665  typeId = prodHit.typeId;
666  }
667 
668  if(typeId != INDEX_MAX)
669  exiType = GET_EXI_TYPE(strm->schema->simpleTypeTable.sType[typeId].content);
670  else
671  exiType = VALUE_TYPE_NONE;
672 
673  if(exiType == VALUE_TYPE_FLOAT)
674  {
675  return encodeFloatValue(strm, float_val);
676  }
677  else if(exiType == VALUE_TYPE_STRING || exiType == VALUE_TYPE_UNTYPED || exiType == VALUE_TYPE_NONE)
678  {
679  // 1) Print Warning
680  // 2) convert the float to sting
681  // 3) encode string
682  String tmpStr;
683 
684  DEBUG_MSG(WARNING, DEBUG_CONTENT_IO, ("\n>Float to String conversion required \n"));
685 #if EXIP_IMPLICIT_DATA_TYPE_CONVERSION
686  TRY(floatToString(float_val, &tmpStr));
687  TRY(encodeStringData(strm, tmpStr, qnameID, typeId));
688  EXIP_MFREE(tmpStr.str);
689 #else
690  return EXIP_INVALID_EXI_INPUT;
691 #endif
692  }
693  else
694  {
695  DEBUG_MSG(ERROR, DEBUG_CONTENT_IO, ("\n>Production type is not a float\n"));
697  }
698 
699  return EXIP_OK;
700 }
701 
702 errorCode binaryData(EXIStream* strm, const char* binary_val, Index nbytes)
703 {
704  Index typeId;
705  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, ("\n>Start binary data serialization\n"));
706 
707  if(strm->gStack->grammar == NULL)
709 
710  if(strm->context.expectATData > 0) // Value for an attribute
711  {
712  strm->context.expectATData -= 1;
713  typeId = strm->context.attrTypeId;
714  }
715  else
716  {
717  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
718  Production prodHit = {0, INDEX_MAX, {URI_MAX, LN_MAX}};
719 
721  typeId = prodHit.typeId;
722  }
723 
724  if(typeId == INDEX_MAX || GET_EXI_TYPE(strm->schema->simpleTypeTable.sType[typeId].content) != VALUE_TYPE_BINARY)
725  {
726  // Binary to string conversion is not supported
727  DEBUG_MSG(ERROR, DEBUG_CONTENT_IO, ("\n>Production type is not a binary\n"));
729  }
730 
731  return encodeBinary(strm, (char *)binary_val, nbytes);
732 }
733 
735 {
736  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
737  Index typeId;
738  QNameID qnameID;
739  EXIType exiType;
740  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, ("\n>Start dateTime data serialization\n"));
741 
742  if(strm->gStack->grammar == NULL)
744 
745  if(strm->context.expectATData > 0) // Value for an attribute
746  {
747  strm->context.expectATData -= 1;
748  typeId = strm->context.attrTypeId;
749  qnameID = strm->context.currAttr;
750  }
751  else
752  {
753  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
754  Production prodHit = {0, INDEX_MAX, {URI_MAX, LN_MAX}};
755 
756  // TODO: passing the type class is not enough:
757  // we need to check if the dt_val value fits in the
758  // production value content description.
759  // If it does not fit we need to again use untyped second level production
761  typeId = prodHit.typeId;
762  qnameID = strm->gStack->currQNameID;
763  }
764 
765  if(typeId != INDEX_MAX)
766  exiType = GET_EXI_TYPE(strm->schema->simpleTypeTable.sType[typeId].content);
767  else
768  exiType = VALUE_TYPE_NONE;
769 
771  {
772  return encodeDateTimeValue(strm, exiType, dt_val);
773  }
774  else if(exiType == VALUE_TYPE_STRING || exiType == VALUE_TYPE_UNTYPED || exiType == VALUE_TYPE_NONE)
775  {
776  // 1) Print Warning
777  // 2) convert the dateTime to sting
778  // 3) encode string
779  String tmpStr;
780 
781  DEBUG_MSG(WARNING, DEBUG_CONTENT_IO, ("\n>DateTime to String conversion required \n"));
782 #if EXIP_IMPLICIT_DATA_TYPE_CONVERSION
783  TRY(dateTimeToString(dt_val, &tmpStr));
784  TRY(encodeStringData(strm, tmpStr, qnameID, typeId));
785  EXIP_MFREE(tmpStr.str);
786 #else
787  return EXIP_INVALID_EXI_INPUT;
788 #endif
789  }
790  else
791  {
792  DEBUG_MSG(ERROR, DEBUG_CONTENT_IO, ("\n>Production type is not a dateTime\n"));
794  }
795 
796  return EXIP_OK;
797 }
798 
800 {
801  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
802  Index typeId;
803  QNameID qnameID;
804  EXIType exiType;
805  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, ("\n>Start decimal data serialization\n"));
806 
807  if(strm->gStack->grammar == NULL)
809 
810  if(strm->context.expectATData > 0) // Value for an attribute
811  {
812  strm->context.expectATData -= 1;
813  typeId = strm->context.attrTypeId;
814  qnameID = strm->context.currAttr;
815  }
816  else
817  {
818  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
819  Production prodHit = {0, INDEX_MAX, {URI_MAX, LN_MAX}};
820 
822  qnameID = strm->gStack->currQNameID;
823  typeId = prodHit.typeId;
824  }
825 
826  if(typeId != INDEX_MAX)
827  exiType = GET_EXI_TYPE(strm->schema->simpleTypeTable.sType[typeId].content);
828  else
829  exiType = VALUE_TYPE_NONE;
830 
831  if(exiType == VALUE_TYPE_DECIMAL)
832  {
833  // TODO: make conditional, not all use cases need Schema type validation
836  {
837  unsigned int totalDigits = 0;
838 
839  if(dec_val.exponent != 0 && dec_val.mantissa != 0)
840  {
841  int64_t mantissa = dec_val.mantissa;
842  while(mantissa)
843  {
844  mantissa /= 10;
845  totalDigits++;
846  }
847 
848  if(dec_val.exponent > 0)
849  totalDigits += dec_val.exponent;
850  }
851  else
852  totalDigits = 1;
853 
854  if(totalDigits > (strm->schema->simpleTypeTable.sType[typeId].length >> 16))
855  return EXIP_INVALID_EXI_INPUT;
856  }
857 
859  {
860  unsigned int fractionDigits = 0;
861 
862  if(dec_val.exponent < 0 && dec_val.mantissa != 0)
863  fractionDigits = -dec_val.exponent;
864 
865  if(fractionDigits > (strm->schema->simpleTypeTable.sType[typeId].length & 0xFFFF))
866  return EXIP_INVALID_EXI_INPUT;
867  }
869 
870  return encodeDecimalValue(strm, dec_val);
871  }
872  else if(exiType == VALUE_TYPE_STRING || exiType == VALUE_TYPE_UNTYPED || exiType == VALUE_TYPE_NONE)
873  {
874  // 1) Print Warning
875  // 2) convert the float to sting
876  // 3) encode string
877  String tmpStr;
878 
879  DEBUG_MSG(WARNING, DEBUG_CONTENT_IO, ("\n>Decimal to String conversion required \n"));
880 #if EXIP_IMPLICIT_DATA_TYPE_CONVERSION
881  TRY(decimalToString(dec_val, &tmpStr));
882  TRY(encodeStringData(strm, tmpStr, qnameID, typeId));
883  EXIP_MFREE(tmpStr.str);
884 #else
885  return EXIP_INVALID_EXI_INPUT;
886 #endif
887  }
888  else
889  {
890  DEBUG_MSG(ERROR, DEBUG_CONTENT_IO, ("\n>Production type is not a decimal\n"));
892  }
893 
894  return EXIP_OK;
895 }
896 
897 errorCode listData(EXIStream* strm, unsigned int itemCount)
898 {
899  Index typeId;
900  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, ("\n>Start list data serialization\n"));
901 
902  if(strm->gStack->grammar == NULL)
904 
905  if(strm->context.expectATData > 0) // Value for an attribute
906  {
907  strm->context.expectATData -= 1;
908  typeId = strm->context.attrTypeId;
909 
910  // TODO: is it allowed to have list with elements lists??? To be checked...
911  }
912  else
913  {
914  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
915  Production prodHit = {0, INDEX_MAX, {URI_MAX, LN_MAX}};
916 
918  }
919 
920  strm->context.expectATData = itemCount;
921  strm->context.attrTypeId = strm->schema->simpleTypeTable.sType[typeId].length; // The actual type of the list items
922 
923  return encodeUnsignedInteger(strm, (UnsignedInteger) itemCount);
924 }
925 
927 {
928  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, ("\n>Start qname data serialization\n"));
929  // Only allowed for AT(xsi:type) productions
930  // TODO: Add the case when Preserve.lexicalValues option value is true - instead of Qname encode it as String
931 
933  {
934  // Value for the attribute xsi:type
935  QNameID qnameId;
936  EXIGrammar* newGrammar = NULL;
937  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
938 
939  strm->context.expectATData -= 1;
940 
941  TRY(encodeQName(strm, qname, EVENT_AT_ALL, &qnameId));
942 
943  // New type grammar is pushed on the stack if it exists
944  newGrammar = GET_TYPE_GRAMMAR_QNAMEID(strm->schema, qnameId);
945 
946  if(newGrammar != NULL)
947  {
948  // The grammar is found
949  // preserve the currQNameID
950  QNameID currQNameID = strm->gStack->currQNameID;
951  popGrammar(&(strm->gStack));
952  TRY(pushGrammar(&(strm->gStack), currQNameID, newGrammar));
953  }
954  else if(strm->gStack->grammar == NULL)
956 
957  return EXIP_OK;
958  }
959  else
961 }
962 
964 {
966 }
967 
968 errorCode namespaceDeclaration(EXIStream* strm, const String ns, const String prefix, boolean isLocalElementNS)
969 {
970  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
971  SmallIndex uriId;
972  Production prodHit = {0, INDEX_MAX, {URI_MAX, LN_MAX}};
973 
974  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, (">Start namespace declaration\n"));
975 
977  return EXIP_INVALID_EXI_INPUT;
978 
979  if(strm->gStack->grammar == NULL)
980 #if EXI_PROFILE_DEFAULT
981  {
982  EventCode tmpEvCode;
983 
984  tmpEvCode.length = 2;
985  if(GET_LN_URI_QNAME(strm->schema->uriTable, strm->gStack->currQNameID).elemGrammar == EXI_PROFILE_STUB_GRAMMAR_INDX)
986  {
987  // This is the case when there is a top level AT(xsi:type) production inserted and hence
988  // the first part of the event code with value 1 must be encoded before the second level part of the event code
989  tmpEvCode.part[0] = 1;
990  tmpEvCode.bits[0] = 1;
991  }
992  else
993  {
994  tmpEvCode.part[0] = 0;
995  tmpEvCode.bits[0] = 0;
996  }
997 
998  tmpEvCode.part[1] = 2;
999  tmpEvCode.bits[1] = 2 + (IS_PRESERVED(strm->header.opts.preserve, PRESERVE_PREFIXES) ||
1002  // serialize NS event code
1003  TRY(writeEventCode(strm, tmpEvCode));
1004  // serialize NS event content
1005  TRY(encodeUri(strm, (String*) &ns, &uriId));
1006  TRY(encodePfx(strm, uriId, (String*) &prefix));
1007  // Leave the current grammar NULL
1008  return encodeBoolean(strm, isLocalElementNS);
1009  }
1010 #else
1011  {
1013  }
1014 #endif
1015 
1017  TRY(encodeUri(strm, (String*) &ns, &uriId));
1018 
1019  TRY(encodePfx(strm, uriId, (String*) &prefix));
1020 
1021  return encodeBoolean(strm, isLocalElementNS);
1022 }
1023 
1025 {
1026  return EXIP_NOT_IMPLEMENTED_YET;
1027 }
1028 
1030 {
1031  errorCode tmp_err_code = EXIP_OK;
1032 
1033  while(strm->gStack != NULL)
1034  {
1035  popGrammar(&strm->gStack);
1036  }
1037 
1038  // Flush the buffer first if there is an output Stream
1039  if(strm->buffer.ioStrm.readWriteToStream != NULL)
1040  {
1041  if((Index)strm->buffer.ioStrm.readWriteToStream(strm->buffer.buf, strm->context.bufferIndx + 1, strm->buffer.ioStrm.stream) < strm->context.bufferIndx + 1)
1042  tmp_err_code = EXIP_BUFFER_END_REACHED;
1043  }
1044 
1045  freeAllMem(strm);
1046  return tmp_err_code;
1047 }
1048 
1049 errorCode flushEXIData(EXIStream* strm, char* outBuf, unsigned int bufSize, unsigned int* bytesFlush)
1050 {
1051  char leftOverBits;
1052 
1053  if(bufSize < strm->context.bufferIndx)
1054  return EXIP_OUT_OF_BOUND_BUFFER;
1055 
1056  leftOverBits = strm->buffer.buf[strm->context.bufferIndx];
1057 
1058  memcpy(outBuf, strm->buffer.buf, strm->context.bufferIndx);
1059 
1060  strm->buffer.buf[0] = leftOverBits;
1061 
1062  *bytesFlush = strm->context.bufferIndx;
1063 
1064  strm->context.bufferIndx = 0;
1065 
1066  return EXIP_OK;
1067 }
1068 
1070 {
1071  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
1072  GrammarRule* currentRule;
1073  Production* tmpProd = NULL;
1074 
1075  if(strm->gStack->currNonTermID >= strm->gStack->grammar->count)
1077 
1078 #if BUILD_IN_GRAMMARS_USE
1079  if(IS_BUILT_IN_ELEM(strm->gStack->grammar->props)) // If the current grammar is build-in Element grammar ...
1080  currentRule = (GrammarRule*) &((DynGrammarRule*) strm->gStack->grammar->rule)[strm->gStack->currNonTermID];
1081  else
1082 #endif
1083  currentRule = &strm->gStack->grammar->rule[strm->gStack->currNonTermID];
1084 
1085  TRY(writeEventCode(strm, ec));
1086 
1087  if(ec.length == 1)
1088  {
1089  tmpProd = &currentRule->production[currentRule->pCount - 1 - ec.part[0]];
1090  }
1091  else if(ec.length == 2)
1092  return EXIP_NOT_IMPLEMENTED_YET;
1093  else // length == 3
1094  return EXIP_NOT_IMPLEMENTED_YET;
1095 
1096  strm->gStack->currNonTermID = GET_PROD_NON_TERM(tmpProd->content);
1097 
1098  switch(GET_PROD_EXI_EVENT(tmpProd->content))
1099  {
1100  case EVENT_SD:
1101  return EXIP_OK;
1102  break;
1103  case EVENT_ED:
1104  return EXIP_OK;
1105  break;
1106  case EVENT_AT_QNAME:
1107 
1108  strm->context.currAttr.uriId = tmpProd->qnameId.uriId;
1109  strm->context.currAttr.lnId = tmpProd->qnameId.lnId;
1110 
1111  TRY(encodePfxQName(strm, qname, EVENT_AT_QNAME, tmpProd->qnameId.uriId));
1112 
1113  strm->context.expectATData = TRUE;
1114  strm->context.attrTypeId = tmpProd->typeId;
1115 
1116  break;
1117  case EVENT_AT_URI:
1118  return EXIP_NOT_IMPLEMENTED_YET;
1119  break;
1120  case EVENT_AT_ALL:
1121  if(qname == NULL)
1122  return EXIP_NULL_POINTER_REF;
1123 
1124  TRY(encodeQName(strm, *qname, EVENT_AT_ALL, &strm->context.currAttr));
1125 
1126  strm->context.expectATData = TRUE;
1127  strm->context.attrTypeId = tmpProd->typeId;
1128  break;
1129  case EVENT_SE_QNAME:
1130  {
1131  EXIGrammar* elemGrammar = NULL;
1132 
1133  TRY(encodePfxQName(strm, qname, EVENT_SE_QNAME, tmpProd->qnameId.uriId));
1134 
1135  // New element grammar is pushed on the stack
1136  if(IS_BUILT_IN_ELEM(strm->gStack->grammar->props)) // If the current grammar is build-in Element grammar ...
1137  {
1138  elemGrammar = GET_ELEM_GRAMMAR_QNAMEID(strm->schema, strm->gStack->currQNameID);
1139  }
1140  else
1141  {
1142  elemGrammar = &strm->schema->grammarTable.grammar[tmpProd->typeId];
1143  }
1144 
1145  if(elemGrammar != NULL) // The grammar is found
1146  TRY(pushGrammar(&(strm->gStack), tmpProd->qnameId, elemGrammar));
1147  else
1148  return EXIP_INCONSISTENT_PROC_STATE; // The event require the presence of Element Grammar previously created
1149  }
1150  break;
1151  case EVENT_SE_URI:
1152  return EXIP_NOT_IMPLEMENTED_YET;
1153  break;
1154  case EVENT_SE_ALL:
1155  {
1156  EXIGrammar* elemGrammar = NULL;
1157  QNameID tmpQid;
1158 
1159  if(qname == NULL)
1160  return EXIP_NULL_POINTER_REF;
1161 
1162  TRY(encodeQName(strm, *qname, EVENT_SE_ALL, &tmpQid));
1163 
1164  // New element grammar is pushed on the stack
1165 #if EXI_PROFILE_DEFAULT
1166  if(GET_LN_URI_QNAME(strm->schema->uriTable, tmpQid).elemGrammar == EXI_PROFILE_STUB_GRAMMAR_INDX)
1167  elemGrammar = NULL;
1168  else
1169 #endif
1170  elemGrammar = GET_ELEM_GRAMMAR_QNAMEID(strm->schema, tmpQid);
1171 
1172  if(elemGrammar != NULL) // The grammar is found
1173  {
1174  TRY(pushGrammar(&(strm->gStack), tmpQid, elemGrammar));
1175  }
1176  else
1177  {
1178 #if BUILD_IN_GRAMMARS_USE
1179  EXIGrammar newElementGrammar;
1180  Index dynArrIndx;
1181  TRY(createBuiltInElementGrammar(&newElementGrammar, strm));
1182 
1183  TRY(addDynEntry(&strm->schema->grammarTable.dynArray, &newElementGrammar, &dynArrIndx));
1184 
1185  GET_LN_URI_QNAME(strm->schema->uriTable, tmpQid).elemGrammar = dynArrIndx;
1186 
1187  TRY(pushGrammar(&(strm->gStack), tmpQid, &strm->schema->grammarTable.grammar[dynArrIndx]));
1188 #elif EXI_PROFILE_DEFAULT
1189  // Leave the grammar NULL - if the next event is valid AT(xsi:type)
1190  // then its value will be the next grammar.
1191  // If the next event is not valid AT(xsi:type) - then the event
1192  // AT(xsi:type="anyType") will be inserted beforehand
1193  TRY(pushGrammar(&(strm->gStack), tmpQid, elemGrammar));
1194 
1195  return EXIP_OK;
1196 #else
1197  DEBUG_MSG(ERROR, DEBUG_CONTENT_IO, (">Build-in element grammars are not supported by this configuration \n"));
1198  assert(FALSE);
1200 #endif
1201  }
1202  }
1203  break;
1204  case EVENT_EE:
1206 
1207  popGrammar(&(strm->gStack));
1208  break;
1209  case EVENT_CH:
1210  return EXIP_NOT_IMPLEMENTED_YET;
1211  break;
1212  case EVENT_NS:
1213  return EXIP_NOT_IMPLEMENTED_YET;
1214  break;
1215  case EVENT_CM:
1216  return EXIP_NOT_IMPLEMENTED_YET;
1217  break;
1218  case EVENT_PI:
1219  return EXIP_NOT_IMPLEMENTED_YET;
1220  break;
1221  case EVENT_DT:
1222  return EXIP_NOT_IMPLEMENTED_YET;
1223  break;
1224  case EVENT_ER:
1225  return EXIP_NOT_IMPLEMENTED_YET;
1226  break;
1227  case EVENT_SC:
1228  return EXIP_NOT_IMPLEMENTED_YET;
1229  break;
1230  default:
1232  }
1233 
1234  return EXIP_OK;
1235 }
1236 
1237 #if EXI_PROFILE_DEFAULT
1238 static errorCode encodeATXsiType(EXIStream* strm)
1239 {
1240  // This indicates that there was a SE(*) which let the
1241  // grammar be NULL. Insert an AT(xsi:type="anyType") event
1242  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
1243  EventCode tmpEvCode;
1244 
1245  tmpEvCode.length = 2;
1246  if(GET_LN_URI_QNAME(strm->schema->uriTable, strm->gStack->currQNameID).elemGrammar == EXI_PROFILE_STUB_GRAMMAR_INDX)
1247  {
1248  // This is the case when there is a top level AT(xsi:type) production inserted and hence
1249  // the first part of the event code with value 1 must be encoded before the second level part of the event code
1250  tmpEvCode.part[0] = 1;
1251  tmpEvCode.bits[0] = 1;
1252  }
1253  else
1254  {
1255  tmpEvCode.part[0] = 0;
1256  tmpEvCode.bits[0] = 0;
1257  GET_LN_URI_QNAME(strm->schema->uriTable, strm->gStack->currQNameID).elemGrammar = EXI_PROFILE_STUB_GRAMMAR_INDX;
1258  }
1259 
1260  tmpEvCode.part[1] = 1;
1261  tmpEvCode.bits[1] = 2 + (IS_PRESERVED(strm->header.opts.preserve, PRESERVE_PREFIXES) ||
1264  // serialize AT(xsi:type)
1265  TRY(writeEventCode(strm, tmpEvCode));
1267  TRY(encodeUnsignedInteger(strm, 0));
1269 
1270  return EXIP_OK;
1271 }
1272 
1273 static errorCode encodeAnyType(EXIStream* strm)
1274 {
1275  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
1276  EXIGrammar* anyGrammar = NULL;
1277  QNameID anyTypeId;
1278  // preserve the currQNameID
1279  QNameID currQNameID = strm->gStack->currQNameID;
1280 
1281  // serialize "xs:anyType"
1283  TRY(encodeUnsignedInteger(strm, 0));
1285 
1286  // "xs:anyType" grammar is pushed on the stack instead of the NULL one
1287  popGrammar(&(strm->gStack));
1288  anyTypeId.uriId = XML_SCHEMA_NAMESPACE_ID;
1289  anyTypeId.lnId = SIMPLE_TYPE_ANY_TYPE;
1290  anyGrammar = GET_TYPE_GRAMMAR_QNAMEID(strm->schema, anyTypeId);
1291  assert(anyGrammar != NULL);
1292 
1293  TRY(pushGrammar(&(strm->gStack), currQNameID, anyGrammar));
1294 
1295  return EXIP_OK;
1296 }
1297 #endif