XMPIterator::XMPIterator ( XMP_StringPtr /*schemaNS*/, XMP_StringPtr /*propName*/, XMP_OptionBits options ) : clientRefs(0), info(IterInfo(options,0)) { XMP_Throw ( "Unimplemented XMPIterator constructor for global tables", kXMPErr_Unimplemented ); } // XMPIterator for global tables
void ExpatAdapter::ParseBuffer ( const void * buffer, size_t length, bool last /* = true */ ) { enum XML_Status status; if ( length == 0 ) { // Expat does not like empty buffers. if ( ! last ) return; buffer = kOneSpace; length = 1; } status = XML_Parse ( this->parser, (const char *)buffer, length, last ); #if BanAllEntityUsage if ( this->isAborted ) XMP_Throw ( "DOCTYPE is not allowed", kXMPErr_BadXML ); #endif if ( status != XML_STATUS_OK ) { XMP_StringPtr errMsg = "XML parsing failure"; #if 0 // XMP_DebugBuild // Disable for now to make test output uniform. Restore later with thread safety. // *** This is a good candidate for a callback error notification mechanism. // *** This code is not thread safe, the sExpatMessage isn't locked. But that's OK for debug usage. enum XML_Error expatErr = XML_GetErrorCode ( this->parser ); const char * expatMsg = XML_ErrorString ( expatErr ); int errLine = XML_GetCurrentLineNumber ( this->parser ); char msgBuffer[1000]; // AUDIT: Use of sizeof(msgBuffer) for snprintf length is safe. snprintf ( msgBuffer, sizeof(msgBuffer), "# Expat error %d at line %d, \"%s\"", expatErr, errLine, expatMsg ); sExpatMessage = msgBuffer; errMsg = sExpatMessage.c_str(); #if DumpXMLParseEvents if ( this->parseLog != 0 ) fprintf ( this->parseLog, "%s\n", errMsg, expatErr, errLine, expatMsg ); #endif #endif XMP_Throw ( errMsg, kXMPErr_BadXML ); } } // ExpatAdapter::ParseBuffer
XMPIterator::XMPIterator ( XMP_StringPtr schemaNS, XMP_StringPtr propName, XMP_OptionBits options ) : clientRefs(0), info(IterInfo(options,0)) { XMP_Throw ( "Unimplemented XMPIterator constructor for global tables", kXMPErr_Unimplemented ); void * p; p = &schemaNS; p = &propName; p = &options; // Avoid unused param warnings. } // XMPIterator for global tables
void XMP_WinXP_HGQueue::Wait ( XMP_BasicMutex & queueMutex ) { ++this->waitCount; // ! Does not need atomic increment, protected by queue mutex. ReleaseBasicMutex ( queueMutex ); DWORD status = WaitForSingleObject ( this->queueEvent, INFINITE ); if ( status != WAIT_OBJECT_0 ) XMP_Throw ( "Failure from WaitForSingleObject", kXMPErr_ExternalFailure ); AcquireBasicMutex ( queueMutex ); --this->waitCount; // ! Does not need atomic decrement, protected by queue mutex. if ( this->releaseAll ) { if ( this->waitCount == 0 ) { this->releaseAll = false; } else { BOOL ok = SetEvent ( this->queueEvent ); if ( ! ok ) XMP_Throw ( "Failure from SetEvent", kXMPErr_ExternalFailure ); } } }
void PluginBase::FillAssociatedResources( std::vector<std::string> * resourceList ) { XMP_OptionBits flags = this->mHandlerFlags; if ( (flags & kXMPFiles_HandlerOwnsFile) || (flags & kXMPFiles_UsesSidecarXMP) || (flags & kXMPFiles_FolderBasedFormat) ) { XMP_Throw ( "GetAssociatedResources is not implemented for this file format", kXMPErr_PluginFillAssociatedResources ); } resourceList->push_back ( this->getPath() ); }
void GIF_MetaHandler::SeekFile( XMP_IO * fileRef, XMP_Int64 offset, SeekMode mode ) { if ( offset > fileRef->Length() || ( mode == kXMP_SeekFromCurrent && fileRef->Offset() + offset > fileRef->Length() ) ) { XMP_Throw( "Out of range seek operation", kXMPErr_InternalFailure ); } else fileRef->Seek( offset, mode ); } // GIF_MetaHandler::SeekFile
void PluginBase::FillMetadataFiles( std::vector<std::string> * metadataFiles ) { XMP_OptionBits flags = this->mHandlerFlags; if ( (flags & kXMPFiles_UsesSidecarXMP) || (flags & kXMPFiles_FolderBasedFormat) ) { XMP_Throw ( "Base implementation of FillMetadataFiles only for embedding handlers", kXMPErr_PluginFillMetadataFiles ); } metadataFiles->push_back ( this->getPath() ); }
static XMP_Node * AddQualifierNode ( XMP_Node * xmpParent, const XML_Node & attr ) { if ( attr.ns.empty() ) { XMP_Throw ( "XML namespace required for all elements and attributes", kXMPErr_BadRDF ); } return AddQualifierNode ( xmpParent, attr.name, attr.value ); } // AddQualifierNode
void XMP_NamespaceTable::Dump ( XMP_TextOutputProc outProc, void * refCon ) const { XMP_AutoLock tableLock ( &this->lock, kXMP_ReadLock ); XMP_cStringMapPos p2uEnd = this->prefixToURIMap.end(); // ! Move up to avoid gcc complaints. XMP_cStringMapPos u2pEnd = this->uriToPrefixMap.end(); DumpStringMap ( this->prefixToURIMap, "Dumping namespace prefix to URI map", outProc, refCon ); if ( this->prefixToURIMap.size() != this->uriToPrefixMap.size() ) { OutProcLiteral ( "** bad namespace map sizes **" ); XMP_Throw ( "Fatal namespace map problem", kXMPErr_InternalFailure ); } for ( XMP_cStringMapPos nsLeft = this->prefixToURIMap.begin(); nsLeft != p2uEnd; ++nsLeft ) { XMP_cStringMapPos nsOther = this->uriToPrefixMap.find ( nsLeft->second ); if ( (nsOther == u2pEnd) || (nsLeft != this->prefixToURIMap.find ( nsOther->second )) ) { OutProcLiteral ( " ** bad namespace URI ** " ); DumpClearString ( nsLeft->second, outProc, refCon ); break; } for ( XMP_cStringMapPos nsRight = nsLeft; nsRight != p2uEnd; ++nsRight ) { if ( nsRight == nsLeft ) continue; // ! Can't start at nsLeft+1, no operator+! if ( nsLeft->second == nsRight->second ) { OutProcLiteral ( " ** duplicate namespace URI ** " ); DumpClearString ( nsLeft->second, outProc, refCon ); break; } } } for ( XMP_cStringMapPos nsLeft = this->uriToPrefixMap.begin(); nsLeft != u2pEnd; ++nsLeft ) { XMP_cStringMapPos nsOther = this->prefixToURIMap.find ( nsLeft->second ); if ( (nsOther == p2uEnd) || (nsLeft != this->uriToPrefixMap.find ( nsOther->second )) ) { OutProcLiteral ( " ** bad namespace prefix ** " ); DumpClearString ( nsLeft->second, outProc, refCon ); break; } for ( XMP_cStringMapPos nsRight = nsLeft; nsRight != u2pEnd; ++nsRight ) { if ( nsRight == nsLeft ) continue; // ! Can't start at nsLeft+1, no operator+! if ( nsLeft->second == nsRight->second ) { OutProcLiteral ( " ** duplicate namespace prefix ** " ); DumpClearString ( nsLeft->second, outProc, refCon ); break; } } } } // XMP_NamespaceTable::Dump
void MetadataSet::removeAt( XMP_Uns32 pos ) { if( mMeta != NULL && pos < mMeta->size() ) { mMeta->erase( mMeta->begin() + pos ); } else { XMP_Throw( "Index out of range.", kXMPErr_BadIndex ); } }
bool ASF_MetaHandler::SafeWriteFile() { XMP_IO* originalFile = this->parent->ioRef; XMP_IO* tempFile = originalFile->DeriveTemp(); if ( tempFile == 0 ) XMP_Throw ( "Failure creating ASF temp file", kXMPErr_InternalFailure ); this->WriteTempFile ( tempFile ); originalFile->AbsorbTemp(); return true; } // ASF_MetaHandler::SafeWriteFile
static void StartElementHandler ( void * userData, XMP_StringPtr name, XMP_StringPtr* attrs ) { XMP_Assert ( attrs != 0 ); ExpatAdapter * thiz = (ExpatAdapter*)userData; size_t attrCount = 0; for ( XMP_StringPtr* a = attrs; *a != 0; ++a ) ++attrCount; if ( (attrCount & 1) != 0 ) XMP_Throw ( "Expat attribute info has odd length", kXMPErr_ExternalFailure ); attrCount = attrCount/2; // They are name/value pairs. #if XMP_DebugBuild & DumpXMLParseEvents if ( thiz->parseLog != 0 ) { PrintIndent ( thiz->parseLog, thiz->elemNesting ); fprintf ( thiz->parseLog, "StartElement: %s, %d attrs", name, attrCount ); for ( XMP_StringPtr* attr = attrs; *attr != 0; attr += 2 ) { XMP_StringPtr attrName = *attr; XMP_StringPtr attrValue = *(attr+1); fprintf ( thiz->parseLog, ", %s = \"%s\"", attrName, attrValue ); } fprintf ( thiz->parseLog, "\n" ); } #endif XML_Node * parentNode = thiz->parseStack.back(); XML_Node * elemNode = new XML_Node ( parentNode, "", kElemNode ); SetQualName ( name, elemNode ); for ( XMP_StringPtr* attr = attrs; *attr != 0; attr += 2 ) { XMP_StringPtr attrName = *attr; XMP_StringPtr attrValue = *(attr+1); XML_Node * attrNode = new XML_Node ( elemNode, "", kAttrNode ); SetQualName ( attrName, attrNode ); attrNode->value = attrValue; if ( attrNode->name == "xml:lang" ) NormalizeLangValue ( &attrNode->value ); elemNode->attrs.push_back ( attrNode ); } parentNode->content.push_back ( elemNode ); thiz->parseStack.push_back ( elemNode ); if ( elemNode->name == "rdf:RDF" ) { thiz->rootNode = elemNode; ++thiz->rootCount; } #if XMP_DebugBuild ++thiz->elemNesting; #endif } // StartElementHandler
static void SetQualName ( XMP_StringPtr fullName, XML_Node * node ) { // Expat delivers the full name as a catenation of namespace URI, separator, and local name. // As a compatibility hack, an "about" or "ID" attribute of an rdf:Description element is // changed to "rdf:about" or rdf:ID. Easier done here than in the RDF recognizer. // As a bug fix hack, change a URI of "http://purl.org/dc/1.1/" to ""http://purl.org/dc/elements/1.1/. // Early versions of Flash that put XMP in SWF used a bad URI for the dc: namespace. // ! This code presumes the RDF namespace prefix is "rdf". size_t sepPos = strlen(fullName); for ( --sepPos; sepPos > 0; --sepPos ) { if ( fullName[sepPos] == FullNameSeparator ) break; } if ( fullName[sepPos] == FullNameSeparator ) { XMP_StringPtr prefix; XMP_StringLen prefixLen; XMP_StringPtr localPart = fullName + sepPos + 1; node->ns.assign ( fullName, sepPos ); if ( node->ns == "http://purl.org/dc/1.1/" ) node->ns = "http://purl.org/dc/elements/1.1/"; bool found = XMPMeta::GetNamespacePrefix ( node->ns.c_str(), &prefix, &prefixLen ); if ( ! found ) XMP_Throw ( "Unknown URI in Expat full name", kXMPErr_ExternalFailure ); node->nsPrefixLen = prefixLen; // ! Includes the ':'. node->name = prefix; node->name += localPart; } else { node->name = fullName; // The name is not in a namespace. if ( node->parent->name == "rdf:Description" ) { if ( node->name == "about" ) { node->ns = kXMP_NS_RDF; node->name = "rdf:about"; node->nsPrefixLen = 4; // ! Include the ':'. } else if ( node->name == "ID" ) { node->ns = kXMP_NS_RDF; node->name = "rdf:ID"; node->nsPrefixLen = 4; // ! Include the ':'. } } } } // SetQualName
static void RDF_LiteralPropertyElement ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel ) { XMP_Node * newChild = AddChildNode ( xmpParent, xmlNode, "", isTopLevel ); XML_cNodePos currAttr = xmlNode.attrs.begin(); XML_cNodePos endAttr = xmlNode.attrs.end(); for ( ; currAttr != endAttr; ++currAttr ) { XMP_VarString & attrName = (*currAttr)->name; if ( attrName == "xml:lang" ) { AddQualifierNode ( newChild, **currAttr ); } else if ( (attrName == "rdf:ID") || (attrName == "rdf:datatype") ) { continue; // Ignore all rdf:ID and rdf:datatype attributes. } else { XMP_Throw ( "Invalid attribute for literal property element", kXMPErr_BadRDF ); } } XML_cNodePos currChild = xmlNode.content.begin(); XML_cNodePos endChild = xmlNode.content.end(); size_t textSize = 0; for ( ; currChild != endChild; ++currChild ) { if ( (*currChild)->kind != kCDataNode ) XMP_Throw ( "Invalid child of literal property element", kXMPErr_BadRDF ); textSize += (*currChild)->value.size(); } newChild->value.reserve ( textSize ); for ( currChild = xmlNode.content.begin(); currChild != endChild; ++currChild ) { newChild->value += (*currChild)->value; } #if 0 // *** XMP_DebugBuild newChild->_valuePtr = newChild->value.c_str(); #endif } // RDF_LiteralPropertyElement
PluginAPIRef Module::getPluginAPIs() { // // return ref. to Plugin API, load module if not yet loaded // if ( !mPluginAPIs || mLoaded != kModuleLoaded ) { if ( !load() ) { XMP_Throw ( "Plugin API not available.", kXMPErr_Unavailable ); } } return mPluginAPIs; }
static void ExportIPTC_Date ( XMP_Uns8 dateID, const SXMPMeta & xmp, IPTC_Manager * iptc ) { XMP_Uns8 timeID; XMP_StringPtr xmpNS, xmpProp; if ( dateID == kIPTC_DateCreated ) { timeID = kIPTC_TimeCreated; xmpNS = kXMP_NS_Photoshop; xmpProp = "DateCreated"; } else if ( dateID == kIPTC_DigitalCreateDate ) { timeID = kIPTC_DigitalCreateTime; xmpNS = kXMP_NS_XMP; xmpProp = "CreateDate"; } else { XMP_Throw ( "Unrecognized dateID", kXMPErr_BadParam ); } iptc->DeleteDataSet ( dateID ); // ! Either the XMP does not exist and we want to iptc->DeleteDataSet ( timeID ); // ! delete the IPTC, or we're replacing the IPTC. XMP_DateTime xmpValue; bool found = xmp.GetProperty_Date ( xmpNS, xmpProp, &xmpValue, 0 ); if ( ! found ) return; char iimValue[16]; // AUDIT: Big enough for "YYYYMMDD" (8) and "HHMMSS+HHMM" (11). // Set the IIM date portion as YYYYMMDD with zeroes for unknown parts. snprintf ( iimValue, sizeof(iimValue), "%04d%02d%02d", // AUDIT: Use of sizeof(iimValue) is safe. xmpValue.year, xmpValue.month, xmpValue.day ); iptc->SetDataSet_UTF8 ( dateID, iimValue, 8 ); // Set the IIM time portion as HHMMSS+HHMM (or -HHMM). Allow a missing time zone. if ( xmpValue.hasTimeZone ) { snprintf ( iimValue, sizeof(iimValue), "%02d%02d%02d%c%02d%02d", // AUDIT: Use of sizeof(iimValue) is safe. xmpValue.hour, xmpValue.minute, xmpValue.second, ((xmpValue.tzSign == kXMP_TimeWestOfUTC) ? '-' : '+'), xmpValue.tzHour, xmpValue.tzMinute ); iptc->SetDataSet_UTF8 ( timeID, iimValue, 11 ); } else if ( xmpValue.hasTime ) { snprintf ( iimValue, sizeof(iimValue), "%02d%02d%02d", // AUDIT: Use of sizeof(iimValue) is safe. xmpValue.hour, xmpValue.minute, xmpValue.second ); iptc->SetDataSet_UTF8 ( timeID, iimValue, 6 ); } else { iptc->DeleteDataSet ( timeID ); } } // ExportIPTC_Date
static void RDF_PropertyElementList ( XMP_Node * xmpParent, const XML_Node & xmlParent, bool isTopLevel ) { XML_cNodePos currChild = xmlParent.content.begin(); XML_cNodePos endChild = xmlParent.content.end(); for ( ; currChild != endChild; ++currChild ) { if ( (*currChild)->IsWhitespaceNode() ) continue; if ( (*currChild)->kind != kElemNode ) { XMP_Throw ( "Expected property element node not found", kXMPErr_BadRDF ); } RDF_PropertyElement ( xmpParent, **currChild, isTopLevel ); } } // RDF_PropertyElementList
IMetadata* MetadataSet::getAt( XMP_Uns32 pos ) const { IMetadata* ret = NULL; if( mMeta != NULL && pos < mMeta->size() ) { ret = mMeta->at(pos); } else { XMP_Throw( "Index out of range.", kXMPErr_BadIndex ); } return ret; }
void PluginBase::FillAssociatedResources( StringVectorRef resourceList, SetStringVectorProc SetStringVector ) { if ( resourceList == 0 ) XMP_Throw ( "A result file list vector must be provided", kXMPErr_BadParam ); std::vector<std::string> resList; // Pass a local vector, not the client's. (*SetStringVector)( resourceList, 0, 0 ); // Clear the client's result vector. FillAssociatedResources( &resList ); if ( ! resList.empty() ) { const size_t fileCount = resList.size(); std::vector<XMP_StringPtr> ptrArray; ptrArray.reserve ( fileCount ); for ( size_t i = 0; i < fileCount; ++i ) { ptrArray.push_back ( resList[i].c_str() ); } (*SetStringVector) ( resourceList, ptrArray.data(), (XMP_Uns32)fileCount ); } }
void XMP_ProgressTracker::NotifyClient ( bool isStartStop ) { XMP_Bool ok = !kXMP_Bool_False; float fractionDone = 0.0; if ( this->cbInfo.clientProc == 0 ) return; XMP_Assert ( this->cbInfo.wrapperProc != 0 ); XMP_Assert ( (this->totalWork >= 0.0) && (this->workDone >= 0.0) && (this->cbInfo.interval >= 0.0) ); // ! Note that totalWork might be unknown or understimated, and workDone greater than totalWork. if ( isStartStop ) { float totalTime = 0.0; if ( this->workDone > 0.0 ) { fractionDone = 1.0; // This is the stop call. totalTime = PerfUtils::GetElapsedSeconds ( this->startTime, PerfUtils::NoteThisMoment() ); } ok = (*this->cbInfo.wrapperProc ) ( this->cbInfo.clientProc, this->cbInfo.context, totalTime, fractionDone, 0.0 ); } else { PerfUtils::MomentValue currentTime = PerfUtils::NoteThisMoment(); float elapsedTime = PerfUtils::GetElapsedSeconds ( this->prevTime, currentTime ); if ( elapsedTime < this->cbInfo.interval ) return; float remainingTime = 0.0; if ( (this->totalWork > 0.0) && (this->workDone > 0.0) ) { fractionDone = this->workDone / this->totalWork; if ( fractionDone > 1.0 ) fractionDone = 1.0; elapsedTime = PerfUtils::GetElapsedSeconds ( this->startTime, currentTime ); remainingTime = (elapsedTime / fractionDone) * (1.0 - fractionDone); } this->prevTime = currentTime; ok = (*this->cbInfo.wrapperProc ) ( this->cbInfo.clientProc, this->cbInfo.context, elapsedTime, fractionDone, remainingTime ); } if ( ok == kXMP_Bool_False ) XMP_Throw ( "Abort signaled by progress reporting callback", kXMPErr_ProgressAbort ); } // XMP_ProgressTracker::NotifyClient
bool PluginBase::IsMetadataWritable ( ) { XMP_OptionBits flags = this->getHandlerFlags(); const std::string & filePath = this->getPath(); if ( (flags & kXMPFiles_HandlerOwnsFile) || (flags & kXMPFiles_UsesSidecarXMP) || (flags & kXMPFiles_FolderBasedFormat) || filePath.empty() ) { XMP_Throw ( "IsMetadataWritable is not implemented for this file format", kXMPErr_PluginIsMetadataWritable ); } try { return Host_IO::Writable( this->getPath().c_str() ); } catch ( ... ) { } return false; }
// parsing creation Chunk::Chunk( ContainerChunk* parent_, RIFF_MetaHandler* handler, bool skip, ChunkType c ) { chunkType = c; // base class assumption this->parent = parent_; this->oldSize = 0; this->hasChange = false; // [2414649] valid assumption at creation time XMP_IO* file = handler->parent->ioRef; this->oldPos = file->Offset(); this->id = XIO::ReadUns32_LE( file ); this->oldSize = XIO::ReadUns32_LE( file ); this->oldSize += 8; // Make sure the size is within expected bounds. XMP_Int64 chunkEnd = this->oldPos + this->oldSize; XMP_Int64 chunkLimit = handler->oldFileSize; if ( parent_ != 0 ) chunkLimit = parent_->oldPos + parent_->oldSize; if ( chunkEnd > chunkLimit ) { bool isUpdate = XMP_OptionIsSet ( handler->parent->openFlags, kXMPFiles_OpenForUpdate ); bool repairFile = XMP_OptionIsSet ( handler->parent->openFlags, kXMPFiles_OpenRepairFile ); if ( (! isUpdate) || (repairFile && (parent_ == 0)) ) { this->oldSize = chunkLimit - this->oldPos; } else { XMP_Throw ( "Bad RIFF chunk size", kXMPErr_BadFileFormat ); } } this->newSize = this->oldSize; this->needSizeFix = false; if ( skip ) file->Seek ( (this->oldSize - 8), kXMP_SeekFromCurrent ); // "good parenting", essential for latter destruction. if ( this->parent != NULL ) { this->parent->children.push_back( this ); if( this->chunkType == chunk_VALUE ) this->parent->childmap.insert( std::make_pair( this->id, (ValueChunk*) this ) ); } }
const TIFF_MemoryReader::TweakedIFDEntry* TIFF_MemoryReader::FindTagInIFD ( XMP_Uns8 ifd, XMP_Uns16 id ) const { if ( ifd == kTIFF_KnownIFD ) { // ... lookup the tag in the known tag map } if ( ifd > kTIFF_LastRealIFD ) XMP_Throw ( "Invalid IFD requested", kXMPErr_InternalFailure ); const TweakedIFDInfo* thisIFD = &containedIFDs[ifd]; if ( thisIFD->count == 0 ) return 0; XMP_Uns32 spanLength = thisIFD->count; const TweakedIFDEntry* spanBegin = &(thisIFD->entries[0]); while ( spanLength > 1 ) { XMP_Uns32 halfLength = spanLength >> 1; // Since spanLength > 1, halfLength > 0. const TweakedIFDEntry* spanMiddle = spanBegin + halfLength; // There are halfLength entries below spanMiddle, then the spanMiddle entry, then // spanLength-halfLength-1 entries above spanMiddle (which can be none). XMP_Uns16 middleID = GetUns16AsIs ( &spanMiddle->id ); if ( middleID == id ) { spanBegin = spanMiddle; break; } else if ( middleID > id ) { spanLength = halfLength; // Discard the middle. } else { spanBegin = spanMiddle; // Keep a valid spanBegin for the return check, don't use spanMiddle+1. spanLength -= halfLength; } } if ( GetUns16AsIs(&spanBegin->id) != id ) spanBegin = 0; return spanBegin; } // TIFF_MemoryReader::FindTagInIFD
XMP_Uns32 XMPFiles_IO::Read ( void * buffer, XMP_Uns32 count, bool readAll /* = false */ ) { XMP_FILESIO_START XMP_Assert ( this->fileRef != Host_IO::noFileRef ); XMP_Assert ( this->currOffset == Host_IO::Offset ( this->fileRef ) ); XMP_Assert ( this->currLength == Host_IO::Length ( this->fileRef ) ); XMP_Assert ( this->currOffset <= this->currLength ); if ( count > (this->currLength - this->currOffset) ) { if ( readAll ) XMP_Throw ( "XMPFiles_IO::Read, not enough data", kXMPErr_EnforceFailure ); count = (XMP_Uns32) (this->currLength - this->currOffset); } XMP_Uns32 amountRead = Host_IO::Read ( this->fileRef, buffer, count ); XMP_Enforce ( amountRead == count ); this->currOffset += amountRead; return amountRead; XMP_FILESIO_END1 ( kXMPErrSev_FileFatal ) return 0; } // XMPFiles_IO::Read
void XMPFiles_IO::Truncate ( XMP_Int64 length ) { XMP_FILESIO_START XMP_Assert ( this->fileRef != Host_IO::noFileRef ); XMP_Assert ( this->currOffset == Host_IO::Offset ( this->fileRef ) ); XMP_Assert ( this->currLength == Host_IO::Length ( this->fileRef ) ); if ( this->readOnly ) XMP_Throw ( "New_XMPFiles_IO, truncate not permitted on read only file", kXMPErr_FilePermission ); XMP_Enforce ( length <= this->currLength ); Host_IO::SetEOF ( this->fileRef, length ); this->currLength = length; if ( this->currOffset > this->currLength ) this->currOffset = this->currLength; // ! Seek to the expected offset, some versions of Host_IO::SetEOF implicitly seek to EOF. Host_IO::Seek ( this->fileRef, this->currOffset, kXMP_SeekFromStart ); XMP_Assert ( this->currOffset == Host_IO::Offset ( this->fileRef ) ); XMP_FILESIO_END1 ( kXMPErrSev_FileFatal ) } // XMPFiles_IO::Truncate
void XMPFiles_IO::AbsorbTemp() { XMP_FILESIO_START XMP_Assert ( this->fileRef != Host_IO::noFileRef ); XMPFiles_IO * temp = this->derivedTemp; if ( temp == 0 ) { XMP_Throw ( "XMPFiles_IO::AbsorbTemp, no temp to absorb", kXMPErr_InternalFailure ); } XMP_Assert ( temp->isTemp ); this->Close(); temp->Close(); Host_IO::SwapData ( this->filePath.c_str(), temp->filePath.c_str() ); this->DeleteTemp(); this->fileRef = Host_IO::Open ( this->filePath.c_str(), Host_IO::openReadWrite ); this->currLength = Host_IO::Length ( this->fileRef ); this->currOffset = 0; XMP_FILESIO_END1 ( kXMPErrSev_FileFatal ) } // XMPFiles_IO::AbsorbTemp
void MOOV_Manager::ParseMemoryTree ( XMP_Uns8 fileMode1 ) { this->fileMode = fileMode1; this->moovNode.offset = this->moovNode.boxType = 0; this->moovNode.headerSize = this->moovNode.contentSize = 0; this->moovNode.children.clear(); this->moovNode.changedContent.clear(); this->moovNode.changed = false; if ( this->fullSubtree.empty() ) return; ISOMedia::BoxInfo moovInfo; const XMP_Uns8 * moovOrigin = &this->fullSubtree[0]; const XMP_Uns8 * moovLimit = moovOrigin + this->fullSubtree.size(); (void) ISOMedia::GetBoxInfo ( moovOrigin, moovLimit, &moovInfo ); XMP_Enforce ( moovInfo.boxType == ISOMedia::k_moov ); XMP_Uns64 fullMoovSize = moovInfo.headerSize + moovInfo.contentSize; if ( fullMoovSize > moovBoxSizeLimit ) { // From here on we know 32-bit offsets are safe. XMP_Throw ( "Oversize 'moov' box", kXMPErr_EnforceFailure ); } this->moovNode.boxType = ISOMedia::k_moov; this->moovNode.headerSize = moovInfo.headerSize; this->moovNode.contentSize = (XMP_Uns32)moovInfo.contentSize; bool ignoreMetaBoxes = (fileMode1 == kFileIsTraditionalQT); // ! Don't want, these don't follow ISO spec. #if TraceParseMoovTree fprintf ( stderr, "Parsing 'moov' subtree, moovNode @ 0x%X, ignoreMetaBoxes = %d\n", &this->moovNode, ignoreMetaBoxes ); #endif this->ParseNestedBoxes ( &this->moovNode, "moov", ignoreMetaBoxes ); } // MOOV_Manager::ParseMemoryTree
void PluginBase::FillMetadataFiles( StringVectorRef metadataFiles, SetStringVectorProc SetStringVector ) { if ( metadataFiles == 0 ) XMP_Throw ( "A result file list vector must be provided", kXMPErr_BadParam ); std::vector<std::string> fileList; // Pass a local vector, not the client's. (*SetStringVector)( metadataFiles, 0, 0 ); // Clear the client's result vector. FillMetadataFiles( &fileList ); // since we are dealing with STL ojbects across different DLL boundaries, // we are extracting const char* to actual path strings, constructing a vector // using these pointers and then passing the address of the underlying data // to the clients procedure which will repopulate its own vector of strings // using this information. if ( ! fileList.empty() ) { const size_t fileCount = fileList.size(); std::vector<XMP_StringPtr> ptrArray; ptrArray.reserve ( fileCount ); for ( size_t i = 0; i < fileCount; ++i ) { ptrArray.push_back ( fileList[i].c_str() ); } (*SetStringVector) ( metadataFiles, ptrArray.data(), (XMP_Uns32)fileCount ); } }
XMPIterator::XMPIterator ( const XMPMeta & xmpObj, XMP_StringPtr schemaNS, XMP_StringPtr propName, XMP_OptionBits options ) : clientRefs(0), info(IterInfo(options,&xmpObj)) { if ( (options & kXMP_IterClassMask) != kXMP_IterProperties ) { XMP_Throw ( "Unsupported iteration kind", kXMPErr_BadOptions ); } // *** Lock the XMPMeta object if we ever stop using a full DLL lock. if ( *propName != 0 ) { // An iterator rooted at a specific node. #if TraceIterators printf ( "\nNew XMP property iterator for \"%s\", options = %X\n Schema = %s, root = %s\n", xmpObj.tree.name.c_str(), options, schemaNS, propName ); #endif XMP_ExpandedXPath propPath; ExpandXPath ( schemaNS, propName, &propPath ); XMP_Node * propNode = FindConstNode ( &xmpObj.tree, propPath ); // If not found get empty iteration. if ( propNode != 0 ) { XMP_VarString rootName ( propPath[1].step ); // The schema is [0]. for ( size_t i = 2; i < propPath.size(); ++i ) { XMP_OptionBits stepKind = GetStepKind ( propPath[i].options ); if ( stepKind <= kXMP_QualifierStep ) rootName += '/'; rootName += propPath[i].step; } propName = rootName.c_str(); size_t leafOffset = rootName.size(); while ( (leafOffset > 0) && (propName[leafOffset] != '/') && (propName[leafOffset] != '[') ) --leafOffset; if ( propName[leafOffset] == '/' ) ++leafOffset; info.tree.children.push_back ( IterNode ( propNode->options, propName, leafOffset ) ); SetCurrSchema ( info, propPath[kSchemaStep].step.c_str() ); if ( info.options & kXMP_IterJustChildren ) { AddNodeOffspring ( info, info.tree.children.back(), propNode ); } } } else if ( *schemaNS != 0 ) { // An iterator for all properties in one schema. #if TraceIterators printf ( "\nNew XMP schema iterator for \"%s\", options = %X\n Schema = %s\n", xmpObj.tree.name.c_str(), options, schemaNS ); #endif info.tree.children.push_back ( IterNode ( kXMP_SchemaNode, schemaNS, 0 ) ); IterNode & iterSchema = info.tree.children.back(); XMP_Node * xmpSchema = FindConstSchema ( &xmpObj.tree, schemaNS ); if ( xmpSchema != 0 ) AddSchemaProps ( info, iterSchema, xmpSchema ); if ( info.options & kXMP_IterIncludeAliases ) AddSchemaAliases ( info, iterSchema, schemaNS ); if ( iterSchema.children.empty() ) { info.tree.children.pop_back(); // No properties, remove the schema node. } else { SetCurrSchema ( info, schemaNS ); } } else { // An iterator for all properties in all schema. First add schema that exist (have children), // adding aliases from them if appropriate. Then add schema that have no actual properties // but do have aliases to existing properties, if we're including aliases in the iteration. #if TraceIterators printf ( "\nNew XMP tree iterator for \"%s\", options = %X\n", xmpObj.tree.name.c_str(), options ); #endif // First pick up the schema that exist. for ( size_t schemaNum = 0, schemaLim = xmpObj.tree.children.size(); schemaNum != schemaLim; ++schemaNum ) { const XMP_Node * xmpSchema = xmpObj.tree.children[schemaNum]; info.tree.children.push_back ( IterNode ( kXMP_SchemaNode, xmpSchema->name, 0 ) ); IterNode & iterSchema = info.tree.children.back(); if ( ! (info.options & kXMP_IterJustChildren) ) { AddSchemaProps ( info, iterSchema, xmpSchema ); if ( info.options & kXMP_IterIncludeAliases ) AddSchemaAliases ( info, iterSchema, xmpSchema->name.c_str() ); if ( iterSchema.children.empty() ) info.tree.children.pop_back(); // No properties, remove the schema node. } } if ( info.options & kXMP_IterIncludeAliases ) { // Add the schema that only have aliases. The most convenient, and safest way, is to go // through the registered namespaces, see if it exists, and let AddSchemaAliases do its // thing if not. Don't combine with the above loop, it is nicer to have the "real" stuff // be in storage order (not subject to the namespace map order). // ! We don't do the kXMP_IterJustChildren handing in the same way here as above. The // ! existing schema (presumably) have actual children. We need to call AddSchemaAliases // ! here to determine if the namespace has any aliases to existing properties. We then // ! strip the children if necessary. XMP_cStringMapPos currNS = sNamespaceURIToPrefixMap->begin(); XMP_cStringMapPos endNS = sNamespaceURIToPrefixMap->end(); for ( ; currNS != endNS; ++currNS ) { XMP_StringPtr schemaName = currNS->first.c_str(); if ( FindConstSchema ( &xmpObj.tree, schemaName ) != 0 ) continue; info.tree.children.push_back ( IterNode ( kXMP_SchemaNode, schemaName, 0 ) ); IterNode & iterSchema = info.tree.children.back(); AddSchemaAliases ( info, iterSchema, schemaName ); if ( iterSchema.children.empty() ) { info.tree.children.pop_back(); // No aliases, remove the schema node. } else if ( info.options & kXMP_IterJustChildren ) { iterSchema.children.clear(); // Get rid of the children. } } } } // Set the current iteration position to the first node to be visited. info.currPos = info.tree.children.begin(); info.endPos = info.tree.children.end(); if ( (info.options & kXMP_IterJustChildren) && (info.currPos != info.endPos) && (*schemaNS != 0) ) { info.currPos->visitStage = kIter_VisitSelf; } #if TraceIterators if ( info.currPos == info.endPos ) { printf ( " ** Empty iteration **\n" ); } else { printf ( " Initial node %s, stage = %s, iterator @ %.8X\n", info.currPos->fullPath.c_str(), sStageNames[info.currPos->visitStage], this ); } #endif } // XMPIterator for XMPMeta objects
void XMP_WinXP_HGQueue::ReleaseAll() { this->releaseAll = true; BOOL ok = SetEvent ( this->queueEvent ); if ( ! ok ) XMP_Throw ( "Failure from SetEvent", kXMPErr_ExternalFailure ); }