⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xmpscanner.cpp

📁 flash xmp sdk,flash官方SDK
💻 CPP
📖 第 1 页 / 共 4 页
字号:
// =================================================================================================// GetSnipCount// ============longXMPScanner::GetSnipCount (){	return fInternalSnips.size();}	// GetSnipCount// =================================================================================================// StreamAllScanned// ================boolXMPScanner::StreamAllScanned (){	InternalSnipIterator currPos = fInternalSnips.begin();	InternalSnipIterator endPos  = fInternalSnips.end();	for ( ; currPos != endPos; ++currPos ) {		if ( currPos->fInfo.fState == eNotSeenSnip ) return false;	}	return true;}	// StreamAllScanned// =================================================================================================// SplitInternalSnip// =================//// Split the given snip into up to 3 pieces.  The new pieces are inserted before and after this one// in the snip list.  The relOffset is the first byte to be kept, it is relative to this snip.  If// the preceeding or following snips have the same state as this one, just shift the boundaries.// I.e. move the contents from one snip to the other, don't create a new snip.// *** To be thread safe we ought to lock the entire list during manipulation.  Let data scanning// *** happen in parallel, serialize all mucking with the list.voidXMPScanner::SplitInternalSnip ( InternalSnipIterator snipPos, XMP_Int64 relOffset, XMP_Int64 newLength ){	assert ( (relOffset + newLength) > relOffset );	// Check for overflow.	assert ( (relOffset + newLength) <= snipPos->fInfo.fLength );		// -----------------------------------	// First deal with the low offset end.		if ( relOffset > 0 ) {		InternalSnipIterator prevPos;		if ( snipPos != fInternalSnips.begin() ) prevPos = PrevSnip ( snipPos );		if ( (snipPos != fInternalSnips.begin()) && (snipPos->fInfo.fState == prevPos->fInfo.fState) ) {			prevPos->fInfo.fLength += relOffset;	// Adjust the preceeding snip.		} else {			InternalSnip headExcess ( snipPos->fInfo.fOffset, relOffset );			headExcess.fInfo.fState = snipPos->fInfo.fState;			headExcess.fInfo.fOutOfOrder = snipPos->fInfo.fOutOfOrder;			fInternalSnips.insert ( snipPos, headExcess );	// Insert the head piece before the middle piece.		}		snipPos->fInfo.fOffset += relOffset;	// Adjust the remainder of this snip.		snipPos->fInfo.fLength -= relOffset;	}		// ----------------------------------	// Now deal with the high offset end.		if ( newLength < snipPos->fInfo.fLength ) {		InternalSnipIterator nextPos    = NextSnip ( snipPos );		const XMP_Int64      tailLength = snipPos->fInfo.fLength - newLength;		if ( (nextPos != fInternalSnips.end()) && (snipPos->fInfo.fState == nextPos->fInfo.fState) ) {			nextPos->fInfo.fOffset -= tailLength;		// Adjust the following snip.			nextPos->fInfo.fLength += tailLength;		} else {			InternalSnip tailExcess ( (snipPos->fInfo.fOffset + newLength), tailLength );			tailExcess.fInfo.fState = snipPos->fInfo.fState;			tailExcess.fInfo.fOutOfOrder = snipPos->fInfo.fOutOfOrder;			fInternalSnips.insert ( nextPos, tailExcess );		// Insert the tail piece after the middle piece.		}		snipPos->fInfo.fLength = newLength;	}}	// SplitInternalSnip// =================================================================================================// MergeInternalSnips// ==================XMPScanner::InternalSnipIteratorXMPScanner::MergeInternalSnips ( InternalSnipIterator firstPos, InternalSnipIterator secondPos ){	firstPos->fInfo.fLength += secondPos->fInfo.fLength;	fInternalSnips.erase ( secondPos );	return firstPos;}	// MergeInternalSnips// =================================================================================================// Scan// ====voidXMPScanner::Scan ( const void * bufferOrigin, XMP_Int64 bufferOffset, XMP_Int64 bufferLength ){	XMP_Int64	relOffset;		#if 0		cout << "Scan: @ " << bufferOrigin << ", " << bufferOffset << ", " << bufferLength << endl;	#endif		if ( bufferLength == 0 ) return;		// ----------------------------------------------------------------	// These comparisons are carefully done to avoid overflow problems.		if ( (bufferOffset >= fStreamLength) ||		 (bufferLength > (fStreamLength - bufferOffset)) ||		 (bufferOrigin == 0) ) {		throw ScanError ( "Bad origin, offset, or length" );	}		// ----------------------------------------------------------------------------------------------	// This buffer must be within a not-seen snip.  Find it and split it.  The first snip whose whose	// end is beyond the buffer must be the enclosing one.		// *** It would be friendly for rescans for out of order problems to accept any buffer postion.		const XMP_Int64			endOffset	= bufferOffset + bufferLength - 1;	InternalSnipIterator	snipPos	= fInternalSnips.begin();		while ( endOffset > (snipPos->fInfo.fOffset + snipPos->fInfo.fLength - 1) ) ++ snipPos;	if ( snipPos->fInfo.fState != eNotSeenSnip ) throw ScanError ( "Already seen" );		relOffset = bufferOffset - snipPos->fInfo.fOffset;	if ( (relOffset + bufferLength) > snipPos->fInfo.fLength ) throw ScanError ( "Not within existing snip" );		SplitInternalSnip ( snipPos, relOffset, bufferLength );		// *** If sequential & prev is partial, just tack on,		// --------------------------------------------------------	// Merge this snip with the preceeding snip if appropriate.		// *** When out of order I/O is supported we have to do something about buffers who's predecessor is not seen.		if ( snipPos->fInfo.fOffset > 0 ) {		InternalSnipIterator prevPos = PrevSnip ( snipPos );		if ( prevPos->fInfo.fState == ePartialPacketSnip ) snipPos = MergeInternalSnips ( prevPos, snipPos );	}		// ----------------------------------	// Look for packets within this snip.	snipPos->fInfo.fState = ePendingSnip;	PacketMachine* thisMachine = snipPos->fMachine.get();	// DumpSnipList ( "Before scan" );	if ( thisMachine != 0 ) {		thisMachine->AssociateBuffer ( bufferOffset, bufferOrigin, bufferLength );	} else {		// *** snipPos->fMachine.reset ( new PacketMachine ( bufferOffset, bufferOrigin, bufferLength ) );		VC++ lacks reset		#if 0			snipPos->fMachine = auto_ptr<PacketMachine> ( new PacketMachine ( bufferOffset, bufferOrigin, bufferLength ) );		#else			{				// Some versions of gcc complain about the assignment operator above.  This avoids the gcc bug.				PacketMachine *	pm	= new PacketMachine ( bufferOffset, bufferOrigin, bufferLength );				auto_ptr<PacketMachine>	ap ( pm );				snipPos->fMachine = ap;			}		#endif		thisMachine = snipPos->fMachine.get();	}		bool	bufferDone	= false;	while ( ! bufferDone ) {		PacketMachine::TriState	foundPacket = thisMachine->FindNextPacket();				if ( foundPacket == PacketMachine::eTriNo ) {					// -----------------------------------------------------------------------			// No packet, mark the snip as raw data and get rid of the packet machine.			// We're done with this buffer.						snipPos->fInfo.fState = eRawInputSnip;			#if 0				snipPos->fMachine = auto_ptr<PacketMachine>();	// *** snipPos->fMachine.reset();	VC++ lacks reset			#else				{					// Some versions of gcc complain about the assignment operator above.  This avoids the gcc bug.					auto_ptr<PacketMachine>	ap ( 0 );					snipPos->fMachine = ap;				}			#endif			bufferDone = true;				} else {					// ---------------------------------------------------------------------------------------------			// Either a full or partial packet.  First trim any excess off of the front as a raw input snip.			// If this is a partial packet mark the snip and keep the packet machine to be resumed later.			// We're done with this buffer, the partial packet by definition extends to the end.  If this is			// a complete packet first extract the additional information from the packet machine.  If there			// is leftover data split the snip and transfer the packet machine to the new trailing snip.						if ( thisMachine->fPacketStart > snipPos->fInfo.fOffset ) {				// There is data at the front of the current snip that must be trimmed.				SnipState	savedState	= snipPos->fInfo.fState;				snipPos->fInfo.fState = eRawInputSnip;	// ! So it gets propagated to the trimmed front part.				relOffset = thisMachine->fPacketStart - snipPos->fInfo.fOffset;				SplitInternalSnip ( snipPos, relOffset, (snipPos->fInfo.fLength - relOffset) );				snipPos->fInfo.fState = savedState;			}					if ( foundPacket == PacketMachine::eTriMaybe ) {								// We have only found a partial packet.				snipPos->fInfo.fState = ePartialPacketSnip;				bufferDone = true;						} else {							// We have found a complete packet. Extract all the info for it and split any trailing data.								InternalSnipIterator	packetSnip	= snipPos;				SnipState				packetState	= eValidPacketSnip;								if ( thisMachine->fBogusPacket ) packetState = eBadPacketSnip;								packetSnip->fInfo.fAccess = thisMachine->fAccess;				packetSnip->fInfo.fCharForm = thisMachine->fCharForm;				packetSnip->fInfo.fBytesAttr = thisMachine->fBytesAttr;				packetSnip->fInfo.fEncodingAttr = thisMachine->fEncodingAttr.c_str();				thisMachine->fEncodingAttr.erase ( thisMachine->fEncodingAttr.begin(), thisMachine->fEncodingAttr.end() );								if ( (thisMachine->fCharForm != eChar8Bit) && CharFormIsBigEndian ( thisMachine->fCharForm ) ) {									// ------------------------------------------------------------------------------					// Handle a special case for big endian characters.  The packet machine works as					// though things were little endian.  The packet starting offset points to the					// byte containing the opening '<', and the length includes presumed nulls that					// follow the last "real" byte.  If the characters are big endian we now have to					// decrement the starting offset of the packet, and also decrement the length of					// the previous snip.					//					// Note that we can't do this before the head trimming above in general.  The					// nulls might have been exactly at the end of a buffer and already in the					// previous snip.  We are doing this before trimming the tail from the raw snip					// containing the packet.  We adjust the raw snip's size because it ends with					// the input buffer.  We don't adjust the packet's size, it is already correct.					//					// The raw snip (the one before the packet) might entirely disappear.  A simple					// example of this is when the packet is at the start of the file.										assert ( packetSnip != fInternalSnips.begin() );	// Leading nulls were trimmed!										if ( packetSnip != fInternalSnips.begin() ) {	// ... but let's program defensibly.						InternalSnipIterator prevSnip  = PrevSnip ( packetSnip );						const unsigned int nullsToAdd = ( CharFormIs16Bit ( thisMachine->fCharForm ) ? 1 : 3 );						assert ( nullsToAdd <= prevSnip->fInfo.fLength );						prevSnip->fInfo.fLength -= nullsToAdd;						if ( prevSnip->fInfo.fLength == 0 ) (void) fInternalSnips.erase ( prevSnip );												packetSnip->fInfo.fOffset	-= nullsToAdd;						packetSnip->fInfo.fLength	+= nullsToAdd;						thisMachine->fPacketStart	-= nullsToAdd;					}									}								if ( thisMachine->fPacketLength == snipPos->fInfo.fLength ) {									// This packet ends exactly at the end of the current snip.					#if 0						snipPos->fMachine = auto_ptr<PacketMachine>();	// *** snipPos->fMachine.reset();	VC++ lacks reset					#else						{							// Some versions of gcc complain about the assignment operator above.  This avoids the gcc bug.							auto_ptr<PacketMachine>	ap ( 0 );							snipPos->fMachine = ap;						}					#endif					bufferDone = true;				} else {										// There is trailing data to split from the just found packet.					SplitInternalSnip ( snipPos, 0, thisMachine->fPacketLength );								InternalSnipIterator	tailPos	= NextSnip ( snipPos );										tailPos->fMachine = snipPos->fMachine;	// auto_ptr assignment - taking ownership					thisMachine->ResetMachine ();										snipPos = tailPos;								}								packetSnip->fInfo.fState = packetState;	// Do this last to avoid messing up the tail split.				// DumpSnipList ( "Found a packet" );							}				}		}		// --------------------------------------------------------	// Merge this snip with the preceeding snip if appropriate.		// *** When out of order I/O is supported we have to check the following snip too.		if ( (snipPos->fInfo.fOffset > 0) && (snipPos->fInfo.fState == eRawInputSnip) ) {		InternalSnipIterator prevPos = PrevSnip ( snipPos );		if ( prevPos->fInfo.fState == eRawInputSnip ) snipPos = MergeInternalSnips ( prevPos, snipPos );	}		// DumpSnipList ( "After scan" );	}	// Scan// =================================================================================================// Report// ======voidXMPScanner::Report ( SnipInfoVector& snips ){	const int				count	= fInternalSnips.size();	InternalSnipIterator	snipPos	= fInternalSnips.begin();		int	s;	// DumpSnipList ( "Report" );	snips.erase ( snips.begin(), snips.end() );		// ! Should use snips.clear, but VC++ doesn't have it.	snips.reserve ( count );		for ( s = 0; s < count; s += 1 ) {		snips.push_back ( SnipInfo ( snipPos->fInfo.fState, snipPos->fInfo.fOffset, snipPos->fInfo.fLength ) );		snips[s] = snipPos->fInfo;	// Pick up all of the fields.		++ snipPos;	}}	// Report

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -