Example #1
0
	/*! DRAGONS: We use the current UTF16String SetString trait to ensure that we always have the correct handling,
	 *           even if the user wants these strings handled differently (i.e. we do it their way!)
	 */
	void SetStringArray(MDObjectPtr &Array, const std::list<std::string> &Strings)
	{
		// Abort if we are send a NULL pointer
		if(!Array) return;

		// Don't bother if we have nothing to do
		if(Strings.empty()) return;

		// Build a working string
		static MDTypePtr ValType = MDType::Find("UTF16String");
		MDObjectPtr Value = ValType ? new MDObject(ValType) : NULL;
		if(!Value)
		{
			error("Can't build UTF16String value required by SetStringArray() - need this type to be defined in the dictionary file\n");
			return;
		}

		// Get a buffer in which to build the final string array, make it quite granular as it will keep growing
		DataChunkPtr Buffer = new DataChunk();
		Buffer->SetGranularity(16 * 1024);

		std::list<std::string>::const_iterator it = Strings.begin();
		while(it != Strings.end())
		{
			Value->SetString(*it);
			DataChunkPtr ThisString = Value->PutData();
			Buffer->Append(ThisString);
			
			// Add terminator if required, i.e. if the sub-string we just added did not end in a zero
			UInt8 *p = &ThisString->Data[ThisString->Size];

			// Terminate if either of the last two bytes in the current buffer is non-zero - or if the string was too short to have a terminator
			if((ThisString->Size) < 2 || ((*(--p) != 0) || (*(--p) != 0)))
			{
				const UInt8 Term[2] = { 0, 0};
				Buffer->Set(2, Term, Buffer->Size);
			}

			it++;
		}

		// Set the value from this buffer
		Array->SetValue(Buffer);
	}
Example #2
0
/*! This will attempt to return an entire wrapping unit (e.g. a full frame for frame-wrapping) but will return it in
 *  smaller chunks if this would break the MaxSize limit. If a Size is specified then the chunk returned will end at
 *  the first wrapping unit end encountered before Size. On no account will portions of two or more different wrapping
 *  units be returned together. The mechanism for selecting a type of wrapping (e.g. frame, line or clip) is not 
 *  (currently) part of the common EssenceSource interface.
 *  \return Pointer to a data chunk holding the next data or a NULL pointer when no more remains
 *	\note If there is more data to come but it is not currently available the return value will be a pointer to an empty data chunk
 *	\note If Size = 0 the object will decide the size of the chunk to return
 *	\note On no account will the returned chunk be larger than MaxSize (if MaxSize > 0)
 */
DataChunkPtr ANCVBISource::GetEssenceData(size_t Size /*=0*/, size_t MaxSize /*=0*/)
{
	// Once this read is done we will be in sync with the master stream position
	CurrentPosition = MasterSource->GetCurrentPosition();

	// If we don't yet have any data prepared, prepare some (even if this will be an "empty" chunk)
	if(BufferedData.empty())
	{
		if((!MasterSource) || (MasterSource->EndOfData())) return NULL;

		BufferedData.push_back(BuildChunk());
	}

	/* Handle the simple case first:
	 * - We are allowed to decide how much data to return (one frame)
	 * - We are not already part way through a buffer
	 * - We are permitted to return the whole buffer in one go
	 */
	if(/*(Size == 0) && */(BufferOffset == 0) && ((MaxSize == 0) || (BufferedData.front()->Size <= MaxSize)))
	{
		// We will return the head item
		DataChunkPtr Ret = BufferedData.front();

		// Remove this item from the list of buffers
		BufferedData.pop_front();

		// Return it
		return Ret;
	}

	// First see how many bytes remain
	size_t Bytes = BufferedData.front()->Size - BufferOffset;
	
	// If we can return all these now, do so
	if(Bytes <= MaxSize)
	{
		// Build a new buffer to hold the reduced data
		DataChunkPtr Ret = new DataChunk(Bytes);

		// Copy in the remaining bytes
		Ret->Set(static_cast<UInt32>(Bytes), BufferedData.front()->Data);

		// Remove this item from the list of buffers
		BufferedData.pop_front();

		// Clear the buffer offset as we will start at the beginning of the next chunk
		BufferOffset = 0;

		// Return the data
		return Ret;
	}

	// Build a new buffer to hold the reduced data
	DataChunkPtr Ret = new DataChunk(MaxSize);

	// Copy in as many bytes as permitted
	Ret->Set(static_cast<UInt32>(MaxSize), BufferedData.front()->Data);

	// Update the offset
	BufferOffset -= MaxSize;

	// Return the data
	return Ret;
}