/*! 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); }
/*! 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; }