in imagecore/formats/exif/exifreader.h [50:139]
ReturnType getValue(ReturnType DefaultValue, ExifCommon::kTagId inId)
{
if(m_cachedEntries[(uint32_t)inId]) { // value already been found and cached?
return *(ReturnType*)m_cachedEntries[(uint32_t)inId];
}
if((!m_valid) || (m_directoryInfo == NULL)) {
return DefaultValue;
}
do
{
const uint8_t* directoryData = m_directoryInfo->m_data;
MemoryStreamReader memoryStream(directoryData, (uint16_t)(m_dataSize - (directoryData - m_TIFFHeader)), m_isBe);
uint16_t dirSize = memoryStream.get_short_advance();
if(!memoryStream.isLastReadValid()) {
return DefaultValue;
}
for(; m_tagIndex < dirSize; m_tagIndex++ ) {
memoryStream.seek(2 + m_tagIndex * kDirectoryEntrySize); // advance to current tag index
uint16_t exifTagId = memoryStream.get_short_advance(); // exif id
if(!memoryStream.isLastReadValid()) {
m_tagIndex++;
return DefaultValue;
}
int32_t tagId = ExifCommon::Instance().getTagId((uint32_t)m_directoryInfo->m_type, exifTagId); // translate exif id to our internal id
if(tagId != -1) // is this an id that we potentially care about?
{
switch((ExifCommon::kExifTagID)exifTagId)
{
// offset to another subdirectory
case ExifCommon::kExifTagID::kExifOffset:
case ExifCommon::kExifTagID::kExifGPSInfo:
{
memoryStream.advance(6); // skip type and count
uint32_t offset = memoryStream.get_uint_advance();
if(!memoryStream.isLastReadValid()) {
m_tagIndex++;
return DefaultValue;
}
if(validateOffset(offset, sizeof(uint16_t) + kDirectoryEntrySize)) { // should have at least enough space for dir size and one entry.
if(m_directoryQueue.push(m_TIFFHeader + offset, ExifCommon::Instance().getDirectoryType((ExifCommon::kExifTagID)exifTagId)) != 0) {
m_tagIndex++;
return DefaultValue;
}
}
break;
}
default:
{
uint16_t tagType = memoryStream.get_short_advance();
if(!memoryStream.isLastReadValid()) {
m_tagIndex++;
return DefaultValue;
}
uint32_t tagCount = memoryStream.get_uint_advance();
if(!memoryStream.isLastReadValid()) {
m_tagIndex++;
return DefaultValue;
}
const ExifCommon::TagHeaderType* TagHeaderRef = ExifCommon::Instance().getTagHeader((ExifCommon::kTagId)tagId);
if(TagHeaderRef->verifyTypeAndCount(tagType, tagCount)) {
uint8_t readBuffer[512]; // we currently dont have any data type that exceeds 512 bytes, biggest one is ExifString at 258 bytes
uint32_t size;
readValue(readBuffer, size, memoryStream, tagType, tagCount);
if(!memoryStream.isLastReadValid()) {
m_tagIndex++;
return DefaultValue;
}
if( TagHeaderRef->m_rangeValidator(readBuffer, tagCount)) {
m_cachedEntries[tagId] = createCacheEntry(size, readBuffer);
if((uint32_t)inId == tagId) { // is it the actual value we are looking for?
m_tagIndex++;
ReturnType res;
memcpy(&res, readBuffer, sizeof(ReturnType));
return res;
}
}
}
break;
}
}
}
}
m_directoryInfo = m_directoryQueue.pop(); // returns null if queue is empty
m_tagIndex = 0;
}while(m_directoryInfo != nullptr);
return DefaultValue;
}