errorCode decodeDecimalValue(EXIStream* strm, Decimal* dec_val) { errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR; boolean sign; UnsignedInteger integr_part = 0; UnsignedInteger fract_part = 0; UnsignedInteger fract_part_rev = 0; unsigned int e; DEBUG_MSG(INFO, DEBUG_STREAM_IO, (">> (decimal)")); // TODO: implement checks on type overflow TRY(decodeBoolean(strm, &sign)); TRY(decodeUnsignedInteger(strm, &integr_part)); TRY(decodeUnsignedInteger(strm, &fract_part)); dec_val->exponent = 0; fract_part_rev = 0; while(fract_part > 0) { fract_part_rev = fract_part_rev*10 + fract_part%10; fract_part = fract_part/10; dec_val->exponent -= 1; } if(sign == TRUE) // negative number dec_val->mantissa = -1; else dec_val->mantissa = 1; dec_val->mantissa *= integr_part; e = dec_val->exponent; if(e != 0) { while(e) { dec_val->mantissa *= 10; e++; } dec_val->mantissa += fract_part_rev; } return EXIP_OK; }
errorCode decodeString(EXIStream* strm, String* string_val) { errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR; UnsignedInteger string_length = 0; DEBUG_MSG(INFO, DEBUG_STREAM_IO, (">> (string)")); TRY(decodeUnsignedInteger(strm, &string_length)); TRY(allocateStringMemoryManaged(&(string_val->str),(Index) string_length, &strm->memList)); return decodeStringOnly(strm,(Index) string_length, string_val); }
errorCode decodeStringOnly(EXIStream* strm, Index str_length, String* string_val) { // Assume no Restricted Character Set is defined //TODO: Handle the case when Restricted Character Set is defined // The exact size of the string is known at this point. This means that // this is the place to allocate the memory for the { CharType* str; }!!! errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR; Index i = 0; Index writerPosition = 0; UnsignedInteger tmp_code_point = 0; string_val->length = str_length; for(i = 0; i < str_length; i++) { TRY(decodeUnsignedInteger(strm, &tmp_code_point)); TRY(writeCharToString(string_val, (uint32_t) tmp_code_point, &writerPosition)); } return EXIP_OK; }
errorCode decodeBinary(EXIStream* strm, char** binary_val, Index* nbytes) { errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR; UnsignedInteger length = 0; unsigned int int_val = 0; UnsignedInteger i = 0; DEBUG_MSG(INFO, DEBUG_STREAM_IO, (">> (binary)")); TRY(decodeUnsignedInteger(strm, &length)); *nbytes = (Index) length; (*binary_val) = (char*) EXIP_MALLOC(length); // This memory should be manually freed after the content handler is invoked if((*binary_val) == NULL) return EXIP_MEMORY_ALLOCATION_ERROR; for(i = 0; i < length; i++) { TRY_CATCH(readBits(strm, 8, &int_val), EXIP_MFREE(*binary_val)); (*binary_val)[i]=(char) int_val; } return EXIP_OK; }
errorCode decodeIntegerValue(EXIStream* strm, Integer* sint_val) { // TODO: If there is associated schema datatype handle differently! // TODO: check if the result fit into int type errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR; boolean bool_val = 0; UnsignedInteger val; DEBUG_MSG(INFO, DEBUG_STREAM_IO, (">> (int)")); TRY(decodeBoolean(strm, &bool_val)); TRY(decodeUnsignedInteger(strm, &val)); if(bool_val == 0) // A sign value of zero (0) is used to represent positive integers *sint_val = (Integer) val; else if(bool_val == 1) // A sign value of one (1) is used to represent negative integers { val += 1; *sint_val = -((Integer) val); } else return EXIP_UNEXPECTED_ERROR; return EXIP_OK; }
static errorCode ops_startElement(QName qname, void* app_data) { struct ops_AppData* o_appD = (struct ops_AppData*) app_data; if(o_appD->o_strm->context.currElem.uriId == 4) // URI == http://www.w3.org/2009/exi { o_appD->prevElementUriID = 4; switch(o_appD->o_strm->context.currElem.lnId) { case 33: // strict SET_STRICT(o_appD->parsed_ops->enumOpt); o_appD->prevElementLnID = 33; break; case 31: // schemaId o_appD->prevElementLnID = 31; o_appD->parsed_ops->schemaIDMode = SCHEMA_ID_EMPTY; break; case 7: // compression SET_COMPRESSION(o_appD->parsed_ops->enumOpt); o_appD->prevElementLnID = 7; break; case 14: // fragment SET_FRAGMENT(o_appD->parsed_ops->enumOpt); o_appD->prevElementLnID = 14; break; case 13: // dtd SET_PRESERVED(o_appD->parsed_ops->preserve, PRESERVE_DTD); o_appD->prevElementLnID = 13; break; case 29: // prefixes SET_PRESERVED(o_appD->parsed_ops->preserve, PRESERVE_PREFIXES); o_appD->prevElementLnID = 29; break; case 26: // lexicalValues SET_PRESERVED(o_appD->parsed_ops->preserve, PRESERVE_LEXVALUES); o_appD->prevElementLnID = 26; break; case 5: // comments SET_PRESERVED(o_appD->parsed_ops->preserve, PRESERVE_COMMENTS); o_appD->prevElementLnID = 5; break; case 27: // pis SET_PRESERVED(o_appD->parsed_ops->preserve, PRESERVE_PIS); o_appD->prevElementLnID = 27; break; case 4: // alignment->byte SET_ALIGNMENT(o_appD->parsed_ops->enumOpt, BYTE_ALIGNMENT); o_appD->prevElementLnID = 4; break; case 28: // alignment->pre-compress SET_ALIGNMENT(o_appD->parsed_ops->enumOpt, PRE_COMPRESSION); o_appD->prevElementLnID = 28; break; case 32: // selfContained SET_SELF_CONTAINED(o_appD->parsed_ops->enumOpt); o_appD->prevElementLnID = 32; break; case 8: // datatypeRepresentationMap o_appD->prevElementLnID = 8; break; case 36: // uncommon o_appD->prevElementLnID = 36; #if EXI_PROFILE_DEFAULT { // If the EXI Profile default behaviour is followed, then we expect // SE(*) <p/> indicating default EXI Profile parameters // If this is not the case rise an error // SE(*) has event code 5 in the uncommon grammar unsigned int tmp_bits_val; UnsignedInteger lnLen = 0; errorCode tmp_err_code = UNEXPECTED_ERROR; String lnStr; QNameID qnameId = {URI_MAX, LN_MAX}; // Next event code must be SE(*) TRY(decodeNBitUnsignedInteger(o_appD->o_strm, 3, &tmp_bits_val)); if(tmp_bits_val != 5) { DEBUG_MSG(ERROR, DEBUG_CONTENT_IO, (">EXI Profile default active but <p> element missing\n")); return INVALID_EXIP_CONFIGURATION; } // The <p> element QName must be "http://www.w3.org/2009/exi:p" TRY(decodeUri(o_appD->o_strm, &qnameId.uriId)); TRY(decodeUnsignedInteger(o_appD->o_strm, &lnLen)); if(lnLen == 0) // local-name table hit -> should not be the case to have "p" in the local string table return INVALID_EXIP_CONFIGURATION; TRY(allocateStringMemoryManaged(&(lnStr.str),(Index) (lnLen - 1), &o_appD->o_strm->memList)); TRY(decodeStringOnly(o_appD->o_strm, (Index)lnLen - 1, &lnStr)); // NOTE: the "p" local name is in purpose not added to the // local name table of the http://www.w3.org/2009/exi uri, although it should be. // If there are more strings (24 or more) added there in the future // or the <p> element is encoded more than once - both are highly unlikely, // then there will be a problem with the encoding. if(qnameId.uriId != 4 || !stringEqualToAscii(lnStr, "p")) { DEBUG_MSG(ERROR, DEBUG_CONTENT_IO, (">EXI Profile default active but <p> element missing\n")); return INVALID_EXIP_CONFIGURATION; } // The next event code must be EE -> 0.0 TRY(decodeNBitUnsignedInteger(o_appD->o_strm, 2, &tmp_bits_val)); if(tmp_bits_val != 0) { DEBUG_MSG(ERROR, DEBUG_CONTENT_IO, (">EXI Profile default active but <p> element is not empty\n")); return INVALID_EXIP_CONFIGURATION; } } #endif break; } } else // URI != http://www.w3.org/2009/exi { // The previous element should be either uncommon or datatypeRepresentationMap otherwise it is an error // These are the only places where <any> element is allowed if(o_appD->prevElementUriID != 4 || o_appD->prevElementLnID != 36 || o_appD->prevElementLnID != 8) { DEBUG_MSG(ERROR, DEBUG_CONTENT_IO, (">Wrong namespace in the EXI Options\n")); return EXIP_HANDLER_STOP; } // Handle here the user defined meta-data that follows! http://www.w3.org/TR/2011/REC-exi-20110310/#key-userMetaData } return ERR_OK; }
errorCode decodeDateTimeValue(EXIStream* strm, EXIType dtType, EXIPDateTime* dt_val) { errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR; Integer year; unsigned int monDay = 0; unsigned int timeVal = 0; boolean presence = FALSE; dt_val->presenceMask = 0; DEBUG_MSG(INFO, DEBUG_STREAM_IO, (">> (dateTime)")); if(dtType == VALUE_TYPE_DATE_TIME || dtType == VALUE_TYPE_DATE || dtType == VALUE_TYPE_YEAR) { /* Year component */ TRY(decodeIntegerValue(strm, &year)); dt_val->dateTime.tm_year = (int)year - 100; } else { dt_val->dateTime.tm_year = INT_MIN; } if(dtType == VALUE_TYPE_DATE_TIME || dtType == VALUE_TYPE_DATE || dtType == VALUE_TYPE_MONTH) { /* MonthDay component */ TRY(decodeNBitUnsignedInteger(strm, 9, &monDay)); dt_val->dateTime.tm_mon = monDay / 32 - 1; dt_val->dateTime.tm_mday = monDay % 32; } else { dt_val->dateTime.tm_mon = INT_MIN; dt_val->dateTime.tm_mday = INT_MIN; } if(dtType == VALUE_TYPE_DATE_TIME || dtType == VALUE_TYPE_TIME) { /* Time component */ TRY(decodeNBitUnsignedInteger(strm, 17, &timeVal)); dt_val->dateTime.tm_hour = (timeVal / 64) / 64; dt_val->dateTime.tm_min = (timeVal / 64) % 64; dt_val->dateTime.tm_sec = timeVal % 64; /* FractionalSecs presence component */ TRY(decodeBoolean(strm, &presence)); if(presence) { UnsignedInteger fSecs = 0; unsigned int tmp = 0; dt_val->presenceMask = dt_val->presenceMask | FRACT_PRESENCE; dt_val->fSecs.offset = 0; dt_val->fSecs.value = 0; /* FractionalSecs component */ TRY(decodeUnsignedInteger(strm, &fSecs)); while(fSecs != 0) { tmp = fSecs % 10; dt_val->fSecs.offset++; if(tmp != 0) { dt_val->fSecs.value = dt_val->fSecs.value*10 + tmp; } fSecs = fSecs / 10; } dt_val->fSecs.offset -= 1; } } else { dt_val->dateTime.tm_hour = INT_MIN; dt_val->dateTime.tm_min = INT_MIN; dt_val->dateTime.tm_sec = INT_MIN; } /* TimeZone presence component */ TRY(decodeBoolean(strm, &presence)); if(presence) { unsigned int tzone = 0; dt_val->presenceMask = dt_val->presenceMask | TZONE_PRESENCE; TRY(decodeNBitUnsignedInteger(strm, 11, &tzone)); dt_val->TimeZone = tzone; } return EXIP_OK; }