/*
 * Copyright 2023 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "src/codec/SkTiffUtility.h"

#include "include/core/SkData.h"
#include "src/codec/SkCodecPriv.h"

#include <cstddef>
#include <utility>

namespace SkTiff {

bool ImageFileDirectory::IsValidType(uint16_t type) { return type >= 1 && type <= 12; }

size_t ImageFileDirectory::BytesForType(uint16_t type) {
    switch (type) {
        case kTypeUnsignedByte:
            return 1;
        case kTypeAsciiString:
            return 1;
        case kTypeUnsignedShort:
            return kSizeShort;
        case kTypeUnsignedLong:
            return kSizeLong;
        case kTypeUnsignedRational:
            return 8;
        case kTypeSignedByte:
            return 1;
        case kTypeUndefined:
            return 1;
        case kTypeSignedShort:
            return kSizeShort;
        case kTypeSignedLong:
            return kSizeLong;
        case kTypeSignedRational:
            return 8;
        case kTypeSingleFloat:
            return 4;
        case kTypeDoubleFloat:
            return 8;
    }
    return 0;
}

// Helper function for computing the address of an entry.
static const uint8_t* get_entry_address(const SkData* data,
                                        uint32_t ifdOffset,
                                        uint16_t entryIndex) {
    return data->bytes() +           // Base address
           ifdOffset +               // IFD offset
           kSizeShort +              // IFD number of entries
           kSizeEntry * entryIndex;  // Entries
}

// Return true if the IFD starting at |ifdOffset| contains valid number of entries (that doesn't
// overrun |data|).
static bool validate_ifd(const SkData* data,
                         bool littleEndian,
                         uint32_t ifdOffset,
                         bool allowTruncated,
                         uint16_t* outNumEntries,
                         uint32_t* outNextIfdOffset) {
    const uint8_t* dataCurrent = data->bytes();
    size_t dataSize = data->size();

    // Seek to the IFD offset.
    if (dataSize < ifdOffset) {
        SkCodecPrintf("IFD offset is too large.\n");
        return false;
    }
    dataCurrent += ifdOffset;
    dataSize -= ifdOffset;

    // Read the number of entries.
    if (dataSize < kSizeShort) {
        SkCodecPrintf("Insufficient space to store number of entries.\n");
        return false;
    }
    uint16_t numEntries = get_endian_short(dataCurrent, littleEndian);
    dataCurrent += kSizeShort;
    dataSize -= kSizeShort;

    // Check that there is enough space for all entries.
    if (dataSize < kSizeEntry * numEntries) {
        SkCodecPrintf("Insufficient space (%u) to store all %u entries.\n",
                      static_cast<uint32_t>(data->size()),
                      numEntries);
        if (allowTruncated) {
            // Set the number of entries to the number of entries that can be fully read, and set
            // the next IFD offset to 0 (indicating that there is no next IFD).
            *outNumEntries = dataSize / kSizeEntry;
            *outNextIfdOffset = 0;
            return true;
        }
        return false;
    }

    // Save the number of entries.
    *outNumEntries = numEntries;

    // Seek past the entries.
    dataCurrent += kSizeEntry * numEntries;
    dataSize -= kSizeEntry * numEntries;

    // Read the next IFD offset.
    if (dataSize < kSizeLong) {
        SkCodecPrintf("Insufficient space to store next IFD offset.\n");
        if (allowTruncated) {
            // Set the next IFD offset to 0 (indicating that there is no next IFD).
            *outNextIfdOffset = 0;
            return true;
        }
        return false;
    }

    // Save the next IFD offset.
    *outNextIfdOffset = get_endian_int(dataCurrent, littleEndian);
    return true;
}

bool ImageFileDirectory::ParseHeader(const SkData* data,
                                     bool* outLittleEndian,
                                     uint32_t* outIfdOffset) {
    // Read the endianness (4 bytes) and IFD offset (4 bytes).
    if (data->size() < 8) {
        SkCodecPrintf("Tiff header must be at least 8 bytes.\n");
        return false;
    }
    if (!is_valid_endian_marker(data->bytes(), outLittleEndian)) {
        SkCodecPrintf("Tiff header had invalid endian marker 0x%x,0x%x,0x%x,0x%x.\n",
                      data->bytes()[0],
                      data->bytes()[1],
                      data->bytes()[2],
                      data->bytes()[3]);
        return false;
    }
    *outIfdOffset = get_endian_int(data->bytes() + 4, *outLittleEndian);
    return true;
}

std::unique_ptr<ImageFileDirectory> ImageFileDirectory::MakeFromOffset(sk_sp<SkData> data,
                                                                       bool littleEndian,
                                                                       uint32_t ifdOffset,
                                                                       bool allowTruncated) {
    uint16_t numEntries = 0;
    uint32_t nextOffset = 0;
    if (!validate_ifd(
                data.get(), littleEndian, ifdOffset, allowTruncated, &numEntries, &nextOffset)) {
        SkCodecPrintf("Failed to validate IFD.\n");
        return nullptr;
    }
    return std::unique_ptr<ImageFileDirectory>(new ImageFileDirectory(
            std::move(data), littleEndian, ifdOffset, numEntries, nextOffset));
}

ImageFileDirectory::ImageFileDirectory(sk_sp<SkData> data,
                                       bool littleEndian,
                                       uint32_t offset,
                                       uint16_t numEntries,
                                       uint32_t nextIfdOffset)
        : fData(std::move(data))
        , fLittleEndian(littleEndian)
        , fOffset(offset)
        , fNumEntries(numEntries)
        , fNextIfdOffset(nextIfdOffset) {}

uint16_t ImageFileDirectory::getEntryTag(uint16_t entryIndex) const {
    const uint8_t* entry = get_entry_address(fData.get(), fOffset, entryIndex);
    return get_endian_short(entry, fLittleEndian);
}

bool ImageFileDirectory::getEntryRawData(uint16_t entryIndex,
                                         uint16_t* outTag,
                                         uint16_t* outType,
                                         uint32_t* outCount,
                                         const uint8_t** outData,
                                         size_t* outDataSize) const {
    const uint8_t* entry = get_entry_address(fData.get(), fOffset, entryIndex);

    // Read the tag
    const uint16_t tag = get_endian_short(entry, fLittleEndian);
    entry += kSizeShort;

    // Read the type.
    const uint16_t type = get_endian_short(entry, fLittleEndian);
    entry += kSizeShort;
    if (!IsValidType(type)) {
        return false;
    }

    // Read the count.
    const uint32_t count = get_endian_int(entry, fLittleEndian);
    entry += kSizeLong;

    // If the entry fits in the remaining 4 bytes, use that.
    const size_t entryDataBytes = BytesForType(type) * count;
    const uint8_t* entryData = nullptr;
    if (entryDataBytes <= kSizeLong) {
        entryData = entry;
    } else {
        // Otherwise, the next 4 bytes specify an offset where the data can be found.
        const uint32_t entryDataOffset = get_endian_int(entry, fLittleEndian);
        if (fData->size() < entryDataOffset || fData->size() - entryDataOffset < entryDataBytes) {
            return false;
        }
        entryData = fData->bytes() + entryDataOffset;
    }

    if (outTag) *outTag = tag;
    if (outType) *outType = type;
    if (outCount) *outCount = count;
    if (outData) *outData = entryData;
    if (outDataSize) *outDataSize = entryDataBytes;
    return true;
}

sk_sp<SkData> ImageFileDirectory::getEntryUndefinedData(uint16_t entryIndex) const {
    uint16_t type = 0;
    uint32_t count = 0;
    const uint8_t* data = nullptr;
    size_t size = 0;
    if (!getEntryRawData(entryIndex, nullptr, &type, &count, &data, &size)) {
        return nullptr;
    }
    if (type != kTypeUndefined) {
        return nullptr;
    }
    return SkData::MakeSubset(fData.get(), data - fData->bytes(), size);
}

bool ImageFileDirectory::getEntryValuesGeneric(uint16_t entryIndex,
                                               uint16_t type,
                                               uint32_t count,
                                               void* values) const {
    uint16_t entryType = 0;
    uint32_t entryCount = 0;
    const uint8_t* entryData = nullptr;
    if (!getEntryRawData(entryIndex, nullptr, &entryType, &entryCount, &entryData, nullptr)) {
        return false;
    }
    if (type != entryType) {
        return false;
    }
    if (count != entryCount) {
        return false;
    }
    for (uint32_t i = 0; i < count; ++i) {
        const uint8_t* data = entryData + i * BytesForType(kTypeUnsignedLong);
        switch (type) {
            case kTypeUnsignedShort:
                reinterpret_cast<uint16_t*>(values)[i] = get_endian_short(data, fLittleEndian);
                break;
            case kTypeUnsignedLong:
                reinterpret_cast<uint32_t*>(values)[i] = get_endian_int(data, fLittleEndian);
                break;
            case kTypeSignedRational: {
                uint32_t numerator = get_endian_int(data, fLittleEndian);
                uint32_t denominator = get_endian_int(data + kSizeLong, fLittleEndian);
                if (denominator == 0) {
                    // The TIFF specification does not indicate a behavior when the denominator is
                    // zero.  The behavior of returning zero for a denominator of zero is a
                    // preservation of the behavior introduced in https://crrev.com/767874.
                    reinterpret_cast<float*>(values)[i] = 0;
                } else {
                    reinterpret_cast<float*>(values)[i] =
                            numerator / static_cast<float>(denominator);
                }
                break;
            }
            case kTypeUnsignedRational: {
                uint32_t numerator = get_endian_int(data, fLittleEndian);
                uint32_t denominator = get_endian_int(data + kSizeLong, fLittleEndian);
                if (denominator == 0) {
                    // See comments in kTypeSignedRational.
                    reinterpret_cast<float*>(values)[i] = 0.f;
                } else {
                    reinterpret_cast<float*>(values)[i] =
                            numerator / static_cast<float>(denominator);
                }
                break;
            }
            default:
                SkCodecPrintf("Unsupported type %u\n", type);
                return false;
                break;
        }
    }
    return true;
}

}  // namespace SkTiff
