/*
 * Copyright 2017 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "cros-camera/exif_utils.h"

#include <cstdlib>
#include <ctime>

#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/strings/string_split.h>

#include "cros-camera/common.h"

namespace std {

template <>
struct default_delete<ExifEntry> {
  inline void operator()(ExifEntry* entry) const { exif_entry_unref(entry); }
};

}  // namespace std

namespace cros {

const base::FilePath kCameraPropertyPath("/var/cache/camera/camera.prop");

#define SET_SHORT(ifd, tag, value)                \
  do {                                            \
    if (SetShort(ifd, tag, value, #tag) == false) \
      return false;                               \
  } while (0);

#define SET_LONG(ifd, tag, value)                \
  do {                                           \
    if (SetLong(ifd, tag, value, #tag) == false) \
      return false;                              \
  } while (0);

#define SET_RATIONAL(ifd, tag, numerator, denominator)                \
  do {                                                                \
    if (SetRational(ifd, tag, numerator, denominator, #tag) == false) \
      return false;                                                   \
  } while (0);

#define SET_SRATIONAL(ifd, tag, numerator, denominator)                \
  do {                                                                 \
    if (SetSRational(ifd, tag, numerator, denominator, #tag) == false) \
      return false;                                                    \
  } while (0);

#define SET_STRING(ifd, tag, format, buffer)                \
  do {                                                      \
    if (SetString(ifd, tag, format, buffer, #tag) == false) \
      return false;                                         \
  } while (0);

// This comes from the Exif Version 2.2 standard table 6.
const char gExifAsciiPrefix[] = {0x41, 0x53, 0x43, 0x49, 0x49, 0x0, 0x0, 0x0};

static void SetLatitudeOrLongitudeData(unsigned char* data, double num) {
  // Take the integer part of |num|.
  ExifLong degrees = static_cast<ExifLong>(num);
  ExifLong minutes = static_cast<ExifLong>(60 * (num - degrees));
  ExifLong microseconds =
      static_cast<ExifLong>(3600000000u * (num - degrees - minutes / 60.0));
  exif_set_rational(data, EXIF_BYTE_ORDER_INTEL, {degrees, 1});
  exif_set_rational(data + sizeof(ExifRational), EXIF_BYTE_ORDER_INTEL,
                    {minutes, 1});
  exif_set_rational(data + 2 * sizeof(ExifRational), EXIF_BYTE_ORDER_INTEL,
                    {microseconds, 1000000});
}

ExifUtils::ExifUtils()
    : exif_data_(nullptr), app1_buffer_(nullptr), app1_length_(0) {}

ExifUtils::~ExifUtils() {
  Reset();
}

bool ExifUtils::Initialize() {
  Reset();
  exif_data_ = exif_data_new();
  if (exif_data_ == nullptr) {
    LOGF(ERROR) << "allocate memory for exif_data_ failed";
    return false;
  }
  // Set the image options.
  exif_data_set_option(exif_data_, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION);
  exif_data_set_data_type(exif_data_, EXIF_DATA_TYPE_COMPRESSED);
  exif_data_set_byte_order(exif_data_, EXIF_BYTE_ORDER_INTEL);

  // Set exif version to 2.2.
  if (!SetExifVersion("0220")) {
    return false;
  }

  if (!ReadProperty()) {
    LOGF(WARNING) << "Cannot setup manufacturer and model";
  }
  return true;
}

bool ExifUtils::SetAperture(uint32_t numerator, uint32_t denominator) {
  SET_RATIONAL(EXIF_IFD_EXIF, EXIF_TAG_APERTURE_VALUE, numerator, denominator);
  return true;
}

bool ExifUtils::SetBrightness(int32_t numerator, int32_t denominator) {
  SET_SRATIONAL(EXIF_IFD_EXIF, EXIF_TAG_BRIGHTNESS_VALUE, numerator,
                denominator);
  return true;
}

bool ExifUtils::SetColorSpace(uint16_t color_space) {
  SET_SHORT(EXIF_IFD_EXIF, EXIF_TAG_COLOR_SPACE, color_space);
  return true;
}

bool ExifUtils::SetComponentsConfiguration(
    const std::string& components_configuration) {
  SET_STRING(EXIF_IFD_EXIF, EXIF_TAG_COMPONENTS_CONFIGURATION,
             EXIF_FORMAT_UNDEFINED, components_configuration);
  return true;
}

bool ExifUtils::SetCompression(uint16_t compression) {
  SET_SHORT(EXIF_IFD_0, EXIF_TAG_COMPRESSION, compression);
  return true;
}

bool ExifUtils::SetContrast(uint16_t contrast) {
  SET_SHORT(EXIF_IFD_EXIF, EXIF_TAG_CONTRAST, contrast);
  return true;
}

bool ExifUtils::SetDateTime(const struct tm& t) {
  // The length is 20 bytes including NULL for termination in Exif standard.
  char str[20];
  int result = snprintf(str, sizeof(str), "%04i:%02i:%02i %02i:%02i:%02i",
                        t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour,
                        t.tm_min, t.tm_sec);
  if (result != sizeof(str) - 1) {
    LOGF(WARNING) << "Input time is invalid";
    return false;
  }
  std::string buffer(str);
  SET_STRING(EXIF_IFD_0, EXIF_TAG_DATE_TIME, EXIF_FORMAT_ASCII, buffer);
  SET_STRING(EXIF_IFD_EXIF, EXIF_TAG_DATE_TIME_ORIGINAL, EXIF_FORMAT_ASCII,
             buffer);
  SET_STRING(EXIF_IFD_EXIF, EXIF_TAG_DATE_TIME_DIGITIZED, EXIF_FORMAT_ASCII,
             buffer);
  return true;
}

bool ExifUtils::SetDescription(const std::string& description) {
  SET_STRING(EXIF_IFD_0, EXIF_TAG_IMAGE_DESCRIPTION, EXIF_FORMAT_ASCII,
             description);
  return true;
}

bool ExifUtils::SetDigitalZoomRatio(uint32_t numerator, uint32_t denominator) {
  SET_RATIONAL(EXIF_IFD_EXIF, EXIF_TAG_DIGITAL_ZOOM_RATIO, numerator,
               denominator);
  return true;
}

bool ExifUtils::SetExposureBias(int32_t numerator, int32_t denominator) {
  SET_SRATIONAL(EXIF_IFD_EXIF, EXIF_TAG_EXPOSURE_BIAS_VALUE, numerator,
                denominator);
  return true;
}

bool ExifUtils::SetExposureMode(uint16_t exposure_mode) {
  SET_SHORT(EXIF_IFD_EXIF, EXIF_TAG_EXPOSURE_MODE, exposure_mode);
  return true;
}

bool ExifUtils::SetExposureProgram(uint16_t exposure_program) {
  SET_SHORT(EXIF_IFD_EXIF, EXIF_TAG_EXPOSURE_PROGRAM, exposure_program);
  return true;
}

bool ExifUtils::SetExposureTime(uint32_t numerator, uint32_t denominator) {
  SET_RATIONAL(EXIF_IFD_EXIF, EXIF_TAG_EXPOSURE_TIME, numerator, denominator);
  return true;
}

bool ExifUtils::SetFlash(uint16_t flash) {
  SET_SHORT(EXIF_IFD_EXIF, EXIF_TAG_FLASH, flash);
  return true;
}

bool ExifUtils::SetFNumber(uint32_t numerator, uint32_t denominator) {
  SET_RATIONAL(EXIF_IFD_EXIF, EXIF_TAG_FNUMBER, numerator, denominator);
  return true;
}

bool ExifUtils::SetFocalLength(uint32_t numerator, uint32_t denominator) {
  SET_RATIONAL(EXIF_IFD_EXIF, EXIF_TAG_FOCAL_LENGTH, numerator, denominator);
  return true;
}

bool ExifUtils::SetGainControl(uint16_t gain_control) {
  SET_SHORT(EXIF_IFD_EXIF, EXIF_TAG_GAIN_CONTROL, gain_control);
  return true;
}

bool ExifUtils::SetGpsAltitude(double altitude) {
  ExifTag refTag = static_cast<ExifTag>(EXIF_TAG_GPS_ALTITUDE_REF);
  std::unique_ptr<ExifEntry> refEntry =
      AddVariableLengthEntry(EXIF_IFD_GPS, refTag, EXIF_FORMAT_BYTE, 1, 1);
  if (!refEntry) {
    LOGF(ERROR) << "Adding GPSAltitudeRef exif entry failed";
    return false;
  }
  if (altitude >= 0) {
    *refEntry->data = 0;
  } else {
    *refEntry->data = 1;
    altitude *= -1;
  }

  ExifTag tag = static_cast<ExifTag>(EXIF_TAG_GPS_ALTITUDE);
  std::unique_ptr<ExifEntry> entry = AddVariableLengthEntry(
      EXIF_IFD_GPS, tag, EXIF_FORMAT_RATIONAL, 1, sizeof(ExifRational));
  if (!entry) {
    exif_content_remove_entry(exif_data_->ifd[EXIF_IFD_GPS], refEntry.get());
    LOGF(ERROR) << "Adding GPSAltitude exif entry failed";
    return false;
  }
  exif_set_rational(entry->data, EXIF_BYTE_ORDER_INTEL,
                    {static_cast<ExifLong>(altitude * 1000), 1000});

  return true;
}

bool ExifUtils::SetGpsLatitude(double latitude) {
  const ExifTag refTag = static_cast<ExifTag>(EXIF_TAG_GPS_LATITUDE_REF);
  std::unique_ptr<ExifEntry> refEntry =
      AddVariableLengthEntry(EXIF_IFD_GPS, refTag, EXIF_FORMAT_ASCII, 2, 2);
  if (!refEntry) {
    LOGF(ERROR) << "Adding GPSLatitudeRef exif entry failed";
    return false;
  }
  if (latitude >= 0) {
    memcpy(refEntry->data, "N", sizeof("N"));
  } else {
    memcpy(refEntry->data, "S", sizeof("S"));
    latitude *= -1;
  }

  const ExifTag tag = static_cast<ExifTag>(EXIF_TAG_GPS_LATITUDE);
  std::unique_ptr<ExifEntry> entry = AddVariableLengthEntry(
      EXIF_IFD_GPS, tag, EXIF_FORMAT_RATIONAL, 3, 3 * sizeof(ExifRational));
  if (!entry) {
    exif_content_remove_entry(exif_data_->ifd[EXIF_IFD_GPS], refEntry.get());
    LOGF(ERROR) << "Adding GPSLatitude exif entry failed";
    return false;
  }
  SetLatitudeOrLongitudeData(entry->data, latitude);

  return true;
}

bool ExifUtils::SetGpsLongitude(double longitude) {
  ExifTag refTag = static_cast<ExifTag>(EXIF_TAG_GPS_LONGITUDE_REF);
  std::unique_ptr<ExifEntry> refEntry =
      AddVariableLengthEntry(EXIF_IFD_GPS, refTag, EXIF_FORMAT_ASCII, 2, 2);
  if (!refEntry) {
    LOGF(ERROR) << "Adding GPSLongitudeRef exif entry failed";
    return false;
  }
  if (longitude >= 0) {
    memcpy(refEntry->data, "E", sizeof("E"));
  } else {
    memcpy(refEntry->data, "W", sizeof("W"));
    longitude *= -1;
  }

  ExifTag tag = static_cast<ExifTag>(EXIF_TAG_GPS_LONGITUDE);
  std::unique_ptr<ExifEntry> entry = AddVariableLengthEntry(
      EXIF_IFD_GPS, tag, EXIF_FORMAT_RATIONAL, 3, 3 * sizeof(ExifRational));
  if (!entry) {
    exif_content_remove_entry(exif_data_->ifd[EXIF_IFD_GPS], refEntry.get());
    LOGF(ERROR) << "Adding GPSLongitude exif entry failed";
    return false;
  }
  SetLatitudeOrLongitudeData(entry->data, longitude);

  return true;
}

bool ExifUtils::SetGpsProcessingMethod(const std::string& method) {
  std::string buffer =
      std::string(gExifAsciiPrefix, sizeof(gExifAsciiPrefix)) + method;
  SET_STRING(EXIF_IFD_GPS, static_cast<ExifTag>(EXIF_TAG_GPS_PROCESSING_METHOD),
             EXIF_FORMAT_UNDEFINED, buffer);
  return true;
}

bool ExifUtils::SetGpsTimestamp(const struct tm& t) {
  const ExifTag dateTag = static_cast<ExifTag>(EXIF_TAG_GPS_DATE_STAMP);
  const size_t kGpsDateStampSize = 11;
  std::unique_ptr<ExifEntry> entry =
      AddVariableLengthEntry(EXIF_IFD_GPS, dateTag, EXIF_FORMAT_ASCII,
                             kGpsDateStampSize, kGpsDateStampSize);
  if (!entry) {
    LOGF(ERROR) << "Adding GPSDateStamp exif entry failed";
    return false;
  }
  int result =
      snprintf(reinterpret_cast<char*>(entry->data), kGpsDateStampSize,
               "%04i:%02i:%02i", t.tm_year + 1900, t.tm_mon + 1, t.tm_mday);
  if (result != kGpsDateStampSize - 1) {
    LOGF(WARNING) << "Input time is invalid";
    return false;
  }

  const ExifTag timeTag = static_cast<ExifTag>(EXIF_TAG_GPS_TIME_STAMP);
  entry = AddVariableLengthEntry(EXIF_IFD_GPS, timeTag, EXIF_FORMAT_RATIONAL, 3,
                                 3 * sizeof(ExifRational));
  if (!entry) {
    LOGF(ERROR) << "Adding GPSTimeStamp exif entry failed";
    return false;
  }
  exif_set_rational(entry->data, EXIF_BYTE_ORDER_INTEL,
                    {static_cast<ExifLong>(t.tm_hour), 1});
  exif_set_rational(entry->data + sizeof(ExifRational), EXIF_BYTE_ORDER_INTEL,
                    {static_cast<ExifLong>(t.tm_min), 1});
  exif_set_rational(entry->data + 2 * sizeof(ExifRational),
                    EXIF_BYTE_ORDER_INTEL,
                    {static_cast<ExifLong>(t.tm_sec), 1});

  return true;
}

bool ExifUtils::SetImageLength(uint32_t length) {
  SET_SHORT(EXIF_IFD_0, EXIF_TAG_IMAGE_LENGTH, length);
  SET_LONG(EXIF_IFD_EXIF, EXIF_TAG_PIXEL_Y_DIMENSION, length);
  return true;
}

bool ExifUtils::SetImageWidth(uint32_t width) {
  SET_SHORT(EXIF_IFD_0, EXIF_TAG_IMAGE_WIDTH, width);
  SET_LONG(EXIF_IFD_EXIF, EXIF_TAG_PIXEL_X_DIMENSION, width);
  return true;
}

bool ExifUtils::SetIsoSpeedRating(uint16_t iso_speed_ratings) {
  SET_SHORT(EXIF_IFD_EXIF, EXIF_TAG_ISO_SPEED_RATINGS, iso_speed_ratings);
  return true;
}

bool ExifUtils::SetLightSource(uint16_t light_source) {
  SET_SHORT(EXIF_IFD_EXIF, EXIF_TAG_LIGHT_SOURCE, light_source);
  return true;
}

bool ExifUtils::SetMaxAperture(uint32_t numerator, uint32_t denominator) {
  SET_RATIONAL(EXIF_IFD_EXIF, EXIF_TAG_MAX_APERTURE_VALUE, numerator,
               denominator);
  return true;
}

bool ExifUtils::SetMeteringMode(uint16_t metering_mode) {
  SET_SHORT(EXIF_IFD_EXIF, EXIF_TAG_METERING_MODE, metering_mode);
  return true;
}

bool ExifUtils::SetOrientation(uint16_t orientation) {
  /*
   * Orientation value:
   *  1      2      3      4      5          6          7          8
   *
   *  888888 888888     88 88     8888888888 88                 88 8888888888
   *  88         88     88 88     88  88     88  88         88  88     88  88
   *  8888     8888   8888 8888   88         8888888888 8888888888         88
   *  88         88     88 88
   *  88         88 888888 888888
   */
  int value = 1;
  switch (orientation) {
    case 90:
      value = 6;
      break;
    case 180:
      value = 3;
      break;
    case 270:
      value = 8;
      break;
    default:
      break;
  }
  SET_SHORT(EXIF_IFD_0, EXIF_TAG_ORIENTATION, value);
  return true;
}

bool ExifUtils::SetResolutionUnit(uint16_t resolution_unit) {
  SET_SHORT(EXIF_IFD_EXIF, EXIF_TAG_RESOLUTION_UNIT, resolution_unit);
  return true;
}

bool ExifUtils::SetSaturation(uint16_t saturation) {
  SET_SHORT(EXIF_IFD_EXIF, EXIF_TAG_SATURATION, saturation);
  return true;
}

bool ExifUtils::SetSceneCaptureType(uint16_t type) {
  SET_SHORT(EXIF_IFD_EXIF, EXIF_TAG_SCENE_CAPTURE_TYPE, type);
  return true;
}

bool ExifUtils::SetSharpness(uint16_t sharpness) {
  SET_SHORT(EXIF_IFD_EXIF, EXIF_TAG_SHARPNESS, sharpness);
  return true;
}

bool ExifUtils::SetShutterSpeed(int32_t numerator, int32_t denominator) {
  SET_SRATIONAL(EXIF_IFD_EXIF, EXIF_TAG_SHUTTER_SPEED_VALUE, numerator,
                denominator);
  return true;
}

bool ExifUtils::SetSubjectDistance(uint32_t numerator, uint32_t denominator) {
  SET_RATIONAL(EXIF_IFD_EXIF, EXIF_TAG_SUBJECT_DISTANCE, numerator,
               denominator);
  return true;
}

bool ExifUtils::SetSubsecTime(const std::string& subsec_time) {
  SET_STRING(EXIF_IFD_EXIF, EXIF_TAG_SUB_SEC_TIME, EXIF_FORMAT_ASCII,
             subsec_time);
  SET_STRING(EXIF_IFD_EXIF, EXIF_TAG_SUB_SEC_TIME_ORIGINAL, EXIF_FORMAT_ASCII,
             subsec_time);
  SET_STRING(EXIF_IFD_EXIF, EXIF_TAG_SUB_SEC_TIME_DIGITIZED, EXIF_FORMAT_ASCII,
             subsec_time);
  return true;
}

bool ExifUtils::SetWhiteBalance(uint16_t white_balance) {
  SET_SHORT(EXIF_IFD_EXIF, EXIF_TAG_WHITE_BALANCE, white_balance);
  return true;
}

bool ExifUtils::SetXResolution(uint32_t numerator, uint32_t denominator) {
  SET_RATIONAL(EXIF_IFD_EXIF, EXIF_TAG_X_RESOLUTION, numerator, denominator);
  return true;
}

bool ExifUtils::SetYCbCrPositioning(uint16_t ycbcr_positioning) {
  SET_SHORT(EXIF_IFD_0, EXIF_TAG_YCBCR_POSITIONING, ycbcr_positioning);
  return true;
}

bool ExifUtils::SetYResolution(uint32_t numerator, uint32_t denominator) {
  SET_RATIONAL(EXIF_IFD_EXIF, EXIF_TAG_Y_RESOLUTION, numerator, denominator);
  return true;
}

bool ExifUtils::GenerateApp1(const void* thumbnail_buffer, uint32_t size) {
  DestroyApp1();
  exif_data_->data =
      const_cast<uint8_t*>(static_cast<const uint8_t*>(thumbnail_buffer));
  exif_data_->size = size;
  // Save the result into |app1_buffer_|.
  exif_data_save_data(exif_data_, &app1_buffer_, &app1_length_);
  if (!app1_length_) {
    LOGF(ERROR) << "Allocate memory for app1_buffer_ failed";
    return false;
  }
  /*
   * The JPEG segment size is 16 bits in spec. The size of APP1 segment should
   * be smaller than 65533 because there are two bytes for segment size field.
   */
  if (app1_length_ > 65533) {
    DestroyApp1();
    LOGF(ERROR) << "The size of APP1 segment is too large";
    return false;
  }
  return true;
}

const uint8_t* ExifUtils::GetApp1Buffer() {
  return app1_buffer_;
}

unsigned int ExifUtils::GetApp1Length() {
  return app1_length_;
}

bool ExifUtils::SetExifVersion(const std::string& exif_version) {
  SET_STRING(EXIF_IFD_EXIF, EXIF_TAG_EXIF_VERSION, EXIF_FORMAT_UNDEFINED,
             exif_version);
  return true;
}

bool ExifUtils::SetMake(const std::string& make) {
  SET_STRING(EXIF_IFD_0, EXIF_TAG_MAKE, EXIF_FORMAT_ASCII, make);
  return true;
}

bool ExifUtils::SetModel(const std::string& model) {
  SET_STRING(EXIF_IFD_0, EXIF_TAG_MODEL, EXIF_FORMAT_ASCII, model);
  return true;
}

bool ExifUtils::ReadProperty() {
  std::string content;
  // If camera.prop doesn't exist, leave Make and Model tags as empty.
  if (!base::PathExists(kCameraPropertyPath)) {
    return false;
  }

  if (!base::ReadFileToString(kCameraPropertyPath, &content)) {
    LOGF(ERROR) << "Read file failed: " << kCameraPropertyPath.value();
    return false;
  }

  std::vector<std::string> properties = base::SplitString(
      content, "\n", base::WhitespaceHandling::TRIM_WHITESPACE,
      base::SplitResult::SPLIT_WANT_NONEMPTY);
  const std::string kManufacturer = "ro.product.manufacturer";
  const std::string kModel = "ro.product.model";

  std::string camera_properties;
  for (const auto& property : properties) {
    VLOGF(1) << "property: " << property;
    std::vector<std::string> key_value = base::SplitString(
        property, "=", base::WhitespaceHandling::TRIM_WHITESPACE,
        base::SplitResult::SPLIT_WANT_ALL);

    if (!key_value[0].compare(0, kManufacturer.length(), kManufacturer)) {
      if (!SetMake(key_value[1])) {
        return false;
      }
    } else if (!key_value[0].compare(0, kModel.length(), kModel)) {
      if (!SetModel(key_value[1])) {
        return false;
      }
    }
  }
  return true;
}

void ExifUtils::Reset() {
  DestroyApp1();
  if (exif_data_) {
    /*
     * Since we decided to ignore the original APP1, we are sure that there is
     * no thumbnail allocated by libexif. |exif_data_->data| is actually
     * allocated by JpegCompressor. Sets |exif_data_->data| to nullptr to
     * prevent exif_data_unref() destroy it incorrectly.
     */
    exif_data_->data = nullptr;
    exif_data_->size = 0;
    exif_data_unref(exif_data_);
    exif_data_ = nullptr;
  }
}

std::unique_ptr<ExifEntry> ExifUtils::AddVariableLengthEntry(
    ExifIfd ifd,
    ExifTag tag,
    ExifFormat format,
    uint64_t components,
    unsigned int size) {
  // Remove old entry if exists.
  exif_content_remove_entry(exif_data_->ifd[ifd],
                            exif_content_get_entry(exif_data_->ifd[ifd], tag));
  ExifMem* mem = exif_mem_new_default();
  if (!mem) {
    LOGF(ERROR) << "Allocate memory for exif entry failed";
    return nullptr;
  }
  std::unique_ptr<ExifEntry> entry(exif_entry_new_mem(mem));
  if (!entry) {
    LOGF(ERROR) << "Allocate memory for exif entry failed";
    exif_mem_unref(mem);
    return nullptr;
  }
  void* tmpBuffer = exif_mem_alloc(mem, size);
  if (!tmpBuffer) {
    LOGF(ERROR) << "Allocate memory for exif entry failed";
    exif_mem_unref(mem);
    return nullptr;
  }

  entry->data = static_cast<unsigned char*>(tmpBuffer);
  entry->tag = tag;
  entry->format = format;
  entry->components = components;
  entry->size = size;

  exif_content_add_entry(exif_data_->ifd[ifd], entry.get());
  exif_mem_unref(mem);

  return entry;
}

std::unique_ptr<ExifEntry> ExifUtils::AddEntry(ExifIfd ifd, ExifTag tag) {
  std::unique_ptr<ExifEntry> entry(
      exif_content_get_entry(exif_data_->ifd[ifd], tag));
  if (entry) {
    // exif_content_get_entry() won't ref the entry, so we ref here.
    exif_entry_ref(entry.get());
    return entry;
  }
  entry.reset(exif_entry_new());
  if (!entry) {
    LOGF(ERROR) << "Allocate memory for exif entry failed";
    return nullptr;
  }
  entry->tag = tag;
  exif_content_add_entry(exif_data_->ifd[ifd], entry.get());
  exif_entry_initialize(entry.get(), tag);
  return entry;
}

bool ExifUtils::SetShort(ExifIfd ifd,
                         ExifTag tag,
                         uint16_t value,
                         const std::string& msg) {
  std::unique_ptr<ExifEntry> entry = AddEntry(ifd, tag);
  if (!entry) {
    LOGF(ERROR) << "Adding " << msg << " entry failed";
    return false;
  }
  exif_set_short(entry->data, EXIF_BYTE_ORDER_INTEL, value);
  return true;
}

bool ExifUtils::SetLong(ExifIfd ifd,
                        ExifTag tag,
                        uint32_t value,
                        const std::string& msg) {
  std::unique_ptr<ExifEntry> entry = AddEntry(ifd, tag);
  if (!entry) {
    LOGF(ERROR) << "Adding " << msg << " entry failed";
    return false;
  }
  exif_set_long(entry->data, EXIF_BYTE_ORDER_INTEL, value);
  return true;
}

bool ExifUtils::SetRational(ExifIfd ifd,
                            ExifTag tag,
                            uint32_t numerator,
                            uint32_t denominator,
                            const std::string& msg) {
  std::unique_ptr<ExifEntry> entry = AddEntry(ifd, tag);
  if (!entry) {
    LOGF(ERROR) << "Adding " << msg << " entry failed";
    return false;
  }
  exif_set_rational(entry->data, EXIF_BYTE_ORDER_INTEL,
                    {numerator, denominator});
  return true;
}

bool ExifUtils::SetSRational(ExifIfd ifd,
                             ExifTag tag,
                             int32_t numerator,
                             int32_t denominator,
                             const std::string& msg) {
  std::unique_ptr<ExifEntry> entry = AddEntry(ifd, tag);
  if (!entry) {
    LOGF(ERROR) << "Adding " << msg << " entry failed";
    return false;
  }
  exif_set_srational(entry->data, EXIF_BYTE_ORDER_INTEL,
                     {numerator, denominator});
  return true;
}

bool ExifUtils::SetString(ExifIfd ifd,
                          ExifTag tag,
                          ExifFormat format,
                          const std::string& buffer,
                          const std::string& msg) {
  size_t entry_size = buffer.length();
  // Since the exif format is undefined, NULL termination is not necessary.
  if (format == EXIF_FORMAT_ASCII) {
    entry_size++;
  }
  std::unique_ptr<ExifEntry> entry =
      AddVariableLengthEntry(ifd, tag, format, entry_size, entry_size);
  if (!entry) {
    LOGF(ERROR) << "Adding " << msg << " entry failed";
    return false;
  }
  memcpy(entry->data, buffer.c_str(), entry_size);
  return true;
}

void ExifUtils::DestroyApp1() {
  /*
   * Since there is no API to access ExifMem in ExifData->priv, we use free
   * here, which is the default free function in libexif. See
   * exif_data_save_data() for detail.
   */
  free(app1_buffer_);
  app1_buffer_ = nullptr;
  app1_length_ = 0;
}

}  // namespace cros
