ReturnType getValue()

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;
	}