📄 smlffpln.cpp
字号:
/////////////////////////////////////////////////////////////////////////// Method:// IHXFileResponse::ReadDone// Purpose:// Notification interface provided by users of the IHXFileObject// interface. This method is called by the IHXFileObject when the// last read from the file is complete and a buffer is available.//STDMETHODIMP CSmilFileFormat::ReadDone( HX_RESULT status, IHXBuffer* pBuffer){ HX_RESULT result = HXR_OK; if ( SUCCEEDED(status) ) { HX_ASSERT(pBuffer); // /For determining what type file this is (via namespace URI), we'll // hold onto the first pBuffer for later when we handle stream header: if (!m_pStartOfFile) { pBuffer->AddRef(); m_pStartOfFile = pBuffer; } BreakUpBuffer(pBuffer); // recurse... m_pFileObject->Read(FileChunkSize); } else { // check see if we have a packet that needs added to the array. if ( m_pCurrentPacketData ) { UCHAR* pCb = m_pCurrentPacketData->pBuffer->GetBuffer(); pCb[m_ulCurrentBufferPos++] = '\"'; pCb[m_ulCurrentBufferPos++] = ')'; pCb[m_ulCurrentBufferPos++] = '\0'; m_pCurrentPacketData->pBuffer->SetSize(m_ulCurrentBufferPos); m_pArrayOfPackets->Add((void*)m_pCurrentPacketData); m_pCurrentPacketData = NULL; m_ulCurrentBufferPos = 0; } // finished reading, calculate the number of packets to send: m_ulPacketCount = m_ulCurrentPacket; m_ulCurrentPacket = 0; m_state = Ready; m_pFFResponse->InitDone(result); } return result;}/////////////////////////////////////////////////////////////////////////// Method:// GetSMILFileVersion// Purpose:// This Function will break the buffer into packets.//// This function maintains a state, such that multiple buffers should// Be able to be passed into it at any point...//HX_RESULT CSmilFileFormat::GetSMILFileVersion(){ HX_RESULT pnreslt = HXR_OK; const char* pSmilTag = NULL; const char* pCloseOfSmilTag = NULL; const char* pXmlns = NULL; const char* pXmlnsOpenQuotationMark = NULL; const char* pBuf = NULL; ULONG32 ulBufLen = 0; const char* pEqualsSign = NULL; const char* pTmp = NULL; char* pTmp2 = NULL; char* pszStartOfFile = NULL; ULONG32 ulCount = 0; LONG32 lNumCommentsOpen = 0; if (!m_pStartOfFile) { pnreslt = HXR_BUFFERTOOSMALL; goto cleanup; } // /Fixes PR 59282: m_pStartOfFile is not necessarily NULL-terminated, // so we have to limit our access of it to the size of the buffer (duh!): ulBufLen = m_pStartOfFile->GetSize(); pBuf = (const char*)m_pStartOfFile->GetBuffer(); if (!pBuf || !ulBufLen) { pnreslt = HXR_BUFFERTOOSMALL; goto cleanup; } pszStartOfFile = new char[ulBufLen+1]; if (!pszStartOfFile) { pnreslt = HXR_OUTOFMEMORY; goto cleanup; } // /Now, walk through and copy each character from non-NULL terminated buf: pTmp = pBuf; pTmp2 = pszStartOfFile; while (*pTmp && ulCount<ulBufLen) { *pTmp2 = *pTmp; pTmp++; pTmp2++; ulCount++; } pszStartOfFile[ulCount] = '\0'; // /NULL-terminate it. // /Now, let's walk through the start of pszStartOfFile looking for // namespace declaration(s) inside the <smil ...> tag, and make sure that // the smil tag is NOT inside of a comment: pTmp = pszStartOfFile; while (*pTmp) { if (0==strncmp(pTmp, "<!--", 4) ) { lNumCommentsOpen++; pTmp+=4; } else if (0==strncmp(pTmp, "-->", 3) ) { lNumCommentsOpen--; pTmp+=3; } else if (lNumCommentsOpen<=0 && 0==strncmp(pTmp, "<smil", 5) ) { pSmilTag = pTmp; // /We found the smil tag outside of a comment. break; } else { pTmp++; } } if (!pSmilTag || ulBufLen-(pSmilTag-pszStartOfFile) < 6) // /6==min size: "<smil>" { // /There had better be a <smil...> tag! pnreslt = HXR_UNEXPECTED; goto cleanup; } pCloseOfSmilTag = strchr(pSmilTag, '>'); // /Add 6 so that we don't allow "<smilxmlns ..." (which is invalid): pXmlns = strstr(pSmilTag+6, "xmlns"); if (pXmlns && isspace(*(pXmlns-1)) ) // /"xmlns" must follow a space. { pEqualsSign = strchr(pXmlns, '='); if (pEqualsSign) { pXmlnsOpenQuotationMark = strchr(pXmlns, '\"'); } } if (pXmlns && pEqualsSign && pXmlnsOpenQuotationMark && (!pCloseOfSmilTag || pXmlns<pCloseOfSmilTag)) { BOOL bIsValidNamespaceDeclaration = TRUE; // /First, make sure there is nothing but whitespace between // the "xmlns" and the '=' as well as between the '=' and the // quotation mark: char* pTmp = (char*)(pXmlns + strlen("xmlns")); while (pTmp<pEqualsSign) { if (!isspace(*pTmp)) { bIsValidNamespaceDeclaration = FALSE; break; } pTmp++; } pTmp = (char*)(pEqualsSign+1); while(pTmp<pXmlnsOpenQuotationMark) { if (!isspace(*pTmp)) { bIsValidNamespaceDeclaration = FALSE; break; } pTmp++; } if (bIsValidNamespaceDeclaration) { // /Note: SMIL 1.0 namespace is default and is: // "http://www.w3.org/TR/REC-smil". Note that if this is // tagged (first) with a SMIL 1.0 namespace followed by // another namespace, then this is a 1.0 file and we'll let // the 1.0 renderer get it and do what it can with the 2.0 // stuff (namely ignore it): const char* pSMIL10Namespace = strstr(pXmlnsOpenQuotationMark, "http://www.w3.org/TR/REC-smil\""); // /This in the final SMIL 2.0 rec: const char* pSMIL20Namespace = strstr(pXmlnsOpenQuotationMark, "http://www.w3.org/2001/SMIL20/Language\""); const char* pSMIL20NamespaceCandidateRec = strstr( pXmlnsOpenQuotationMark, "http://www.w3.org/2000/SMIL20/CR/Language\""); // /Fixes PR 55749: allow new PR namespace: const char* pSMIL20NamespaceProposedRec = strstr( pXmlnsOpenQuotationMark, "http://www.w3.org/2001/SMIL20/PR/Language\""); const char* pSMIL20NamespaceLastCall = strstr( pXmlnsOpenQuotationMark, "http://www.w3.org/TR/REC-smil/2000/SMIL20/LC/\""); // /If the SMIL 1.0 namespace is declared prior to any other // version of SMIL's namespace, then this is a SMIL 1.0 doc: if (pSMIL10Namespace && (!pSMIL20Namespace || pSMIL10Namespace < pSMIL20Namespace) && (!pSMIL20NamespaceCandidateRec || pSMIL10Namespace < pSMIL20NamespaceCandidateRec) && (!pSMIL20NamespaceProposedRec || pSMIL10Namespace < pSMIL20NamespaceProposedRec) && (!pSMIL20NamespaceLastCall || pSMIL10Namespace < pSMIL20NamespaceLastCall) ) { m_smilFileVersion = SMILFileVersionSmil10Strict; } else if (pSMIL20NamespaceCandidateRec && (!pSMIL20Namespace || pSMIL20NamespaceCandidateRec < pSMIL20Namespace)) { m_smilFileVersion = SMILFileVersionSmil20PreRec; } else if (pSMIL20NamespaceProposedRec && (!pSMIL20Namespace || pSMIL20NamespaceProposedRec < pSMIL20Namespace)) { m_smilFileVersion = SMILFileVersionSmil20PreRec; } // /Treat both LC (Last Call) and CR (Candidate Rec) as "PreRec": else if (pSMIL20NamespaceLastCall && (!pSMIL20Namespace || pSMIL20NamespaceLastCall < pSMIL20Namespace)) { m_smilFileVersion = SMILFileVersionSmil20PreRec; } else if (pSMIL20Namespace) { m_smilFileVersion = SMILFileVersionSmil20; } else { m_smilFileVersion = SMILFileVersionUnknown; } } }cleanup: if (pszStartOfFile) { HX_VECTOR_DELETE(pszStartOfFile); } return pnreslt;}/////////////////////////////////////////////////////////////////////////// Method:// BreakUpBuffer// Purpose:// This Function will break the buffer into packets.//// This function maintains a state, such that multiple buffers should// Be able to be passed into it at any point...//// XXX jhug// This doesn't allow text between tags... Future versions of SMIL might// support this... this will need a bit of a modification.HX_RESULT CSmilFileFormat::BreakUpBuffer(IHXBuffer* pBuffer){ // walk through the buffer and escape all \"s // also forget about all white space and comments... // also break the buffer up into packets for easy access. HX_RESULT result = HXR_OK; UCHAR* pCb = NULL; if ( m_pCurrentPacketData ) { pCb = m_pCurrentPacketData->pBuffer->GetBuffer(); } const UCHAR* pData = pBuffer->GetBuffer(); UINT32 ulSize = pBuffer->GetSize(); for ( UINT32 ulPos = 0; ulPos < ulSize && pData[ulPos]; ++ulPos ) { // three for the end of the packet structure, and 1 in case we have // to escape a char... if ( m_ulCurrentBufferPos >= MaxPacketSize - 4 ) { pCb[m_ulCurrentBufferPos++] = '\"'; pCb[m_ulCurrentBufferPos++] = ')'; pCb[m_ulCurrentBufferPos++] = '\0'; m_pCurrentPacketData->pBuffer->SetSize(m_ulCurrentBufferPos); m_pArrayOfPackets->Add((void*)m_pCurrentPacketData); m_pCurrentPacketData = NULL; m_ulCurrentBufferPos = 0; pCb = NULL; } if ( !m_pCurrentPacketData ) { m_pCurrentPacketData = new PacketData; if ( m_pCurrentPacketData == NULL ) { result = HXR_OUTOFMEMORY; } else { m_pCurrentPacketData->pBuffer = NULL; m_pCurrentPacketData->pNumPos = NULL; result = m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer, (void**)&m_pCurrentPacketData->pBuffer); } if ( SUCCEEDED(result) ) { result = m_pCurrentPacketData->pBuffer->SetSize(MaxPacketSize); } if ( SUCCEEDED(result) ) { pCb = m_pCurrentPacketData->pBuffer->GetBuffer(); //memset(pCb, 0xef, MaxPacketSize); sprintf((char*)pCb, "(smil-document (ver %s)(npkt %ld)" "(ttlpkt 0 )(doc \"", RMA_DRIVER_VERSION, ++m_ulCurrentPacket); m_ulCurrentBufferPos = strlen((char*)pCb); // back up to the begining of the total number position. // 13 is position back in header... m_pCurrentPacketData->pNumPos = (char*)pCb + m_ulCurrentBufferPos - 13; } } if ( FAILED(result) ) { break; } switch ( m_fileState ) { case InContent: { if ( pData[ulPos] == '\"' ) { pCb[m_ulCurrentBufferPos++] = '\\'; pCb[m_ulCurrentBufferPos++] = '\"'; } else if ( pData[ulPos] == '\\' ) { pCb[m_ulCurrentBufferPos++] = '\\'; pCb[m_ulCurrentBufferPos++] = '\"'; } else if ( pData[ulPos] == '<' ) { if ( pData[ulPos+1] == '!' ) { if ( pData[ulPos+2] == '-' && pData[ulPos+3] == '-' ) { ulPos += 3; m_fileState = InComment; } else if ( pData[ulPos+2] == '[' && pData[ulPos+3] == 'C' && pData[ulPos+4] == 'D' && pData[ulPos+5] == 'A' && pData[ulPos+6] == 'T' && pData[ulPos+7] == 'A' && pData[ulPos+8] == '[' ) { pCb[m_ulCurrentBufferPos++] = pData[ulPos++]; pCb[m_ulCurrentBufferPos++] = pData[ulPos++]; pCb[m_ulCurrentBufferPos++] = pData[ulPos++]; pCb[m_ulCurrentBufferPos++] = pData[ulPos++]; pCb[m_ulCurrentBufferPos++] = pData[ulPos++]; pCb[m_ulCurrentBufferPos++] = pData[ulPos++]; pCb[m_ulCurrentBufferPos++] = pData[ulPos]; m_fileState = InCDATA; } else if ( pData[ulPos+2] == 'D' && pData[ulPos+3] == 'O' && pData[ulPos+4] == 'C' && pData[ulPos+5] == 'T' && pData[ulPos+6] == 'Y' && pData[ulPos+7] == 'P' && pData[ulPos+8] == 'E' ) { pCb[m_ulCurrentBufferPos++] = pData[ulPos++]; pCb[m_ulCurrentBufferPos++] = pData[ulPos++]; pCb[m_ulCurrentBufferPos++] = pData[ulPos++]; pCb[m_ulCurrentBufferPos++] = pData[ulPos++]; pCb[m_ulCurrentBufferPos++] = pData[ulPos++]; pCb[m_ulCurrentBufferPos++] = pData[ulPos++]; pCb[m_ulCurrentBufferPos++] = pData[ulPos]; m_fileState = InDTD; } } else { pCb[m_ulCurrentBufferPos++] = pData[ulPos]; m_fileState = InTagName; } } // preserve all lines so line number error reporting is // accurate else if ( isspace(pData[ulPos]) && pData[ulPos] != '\n' && pData[ulPos] != '\r') { //continue... } //If we find \rx where x is not \n, then keep it else let // the next char (\n) be kept in the next iteration of // this loop. This accomodates Mac-authored '\r'-only // text. Think Different (pain is "different"). else if (isspace(pData[ulPos]) && ('\r' == pData[ulPos] && (ulPos+1 < ulSize && pData[ulPos+1]) && '\n' == pData[ulPos+1]) ) { //continue... } else { if ('\r' == pData[ulPos]) { pCb[m_ulCurrentBufferPos++] = '\n'; } else { pCb[m_ulCurrentBufferPos++] = pData[ulPos]; } } } break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -