//===-- CFCMutableDictionary.cpp --------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "CFCMutableDictionary.h"
#include "CFCString.h"
// CFCString constructor
CFCMutableDictionary::CFCMutableDictionary(CFMutableDictionaryRef s)
    : CFCReleaser<CFMutableDictionaryRef>(s) {}

// CFCMutableDictionary copy constructor
CFCMutableDictionary::CFCMutableDictionary(const CFCMutableDictionary &rhs)
    : CFCReleaser<CFMutableDictionaryRef>(rhs) {}

// CFCMutableDictionary copy constructor
const CFCMutableDictionary &CFCMutableDictionary::
operator=(const CFCMutableDictionary &rhs) {
  if (this != &rhs)
    *this = rhs;
  return *this;
}

// Destructor
CFCMutableDictionary::~CFCMutableDictionary() {}

CFIndex CFCMutableDictionary::GetCount() const {
  CFMutableDictionaryRef dict = get();
  if (dict)
    return ::CFDictionaryGetCount(dict);
  return 0;
}

CFIndex CFCMutableDictionary::GetCountOfKey(const void *key) const

{
  CFMutableDictionaryRef dict = get();
  if (dict)
    return ::CFDictionaryGetCountOfKey(dict, key);
  return 0;
}

CFIndex CFCMutableDictionary::GetCountOfValue(const void *value) const

{
  CFMutableDictionaryRef dict = get();
  if (dict)
    return ::CFDictionaryGetCountOfValue(dict, value);
  return 0;
}

void CFCMutableDictionary::GetKeysAndValues(const void **keys,
                                            const void **values) const {
  CFMutableDictionaryRef dict = get();
  if (dict)
    ::CFDictionaryGetKeysAndValues(dict, keys, values);
}

const void *CFCMutableDictionary::GetValue(const void *key) const

{
  CFMutableDictionaryRef dict = get();
  if (dict)
    return ::CFDictionaryGetValue(dict, key);
  return NULL;
}

Boolean
CFCMutableDictionary::GetValueIfPresent(const void *key,
                                        const void **value_handle) const {
  CFMutableDictionaryRef dict = get();
  if (dict)
    return ::CFDictionaryGetValueIfPresent(dict, key, value_handle);
  return false;
}

CFMutableDictionaryRef CFCMutableDictionary::Dictionary(bool can_create) {
  CFMutableDictionaryRef dict = get();
  if (can_create && dict == NULL) {
    dict = ::CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
                                       &kCFTypeDictionaryKeyCallBacks,
                                       &kCFTypeDictionaryValueCallBacks);
    reset(dict);
  }
  return dict;
}

bool CFCMutableDictionary::AddValue(CFStringRef key, const void *value,
                                    bool can_create) {
  CFMutableDictionaryRef dict = Dictionary(can_create);
  if (dict != NULL) {
    // Let the dictionary own the CFNumber
    ::CFDictionaryAddValue(dict, key, value);
    return true;
  }
  return false;
}

bool CFCMutableDictionary::SetValue(CFStringRef key, const void *value,
                                    bool can_create) {
  CFMutableDictionaryRef dict = Dictionary(can_create);
  if (dict != NULL) {
    // Let the dictionary own the CFNumber
    ::CFDictionarySetValue(dict, key, value);
    return true;
  }
  return false;
}

bool CFCMutableDictionary::AddValueSInt8(CFStringRef key, int8_t value,
                                         bool can_create) {
  CFMutableDictionaryRef dict = Dictionary(can_create);
  if (dict != NULL) {
    CFCReleaser<CFNumberRef> cf_number(
        ::CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt8Type, &value));
    if (cf_number.get()) {
      // Let the dictionary own the CFNumber
      ::CFDictionaryAddValue(dict, key, cf_number.get());
      return true;
    }
  }
  return false;
}

bool CFCMutableDictionary::SetValueSInt8(CFStringRef key, int8_t value,
                                         bool can_create) {
  CFMutableDictionaryRef dict = Dictionary(can_create);
  if (dict != NULL) {
    CFCReleaser<CFNumberRef> cf_number(
        ::CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt8Type, &value));
    if (cf_number.get()) {
      // Let the dictionary own the CFNumber
      ::CFDictionarySetValue(dict, key, cf_number.get());
      return true;
    }
  }
  return false;
}

bool CFCMutableDictionary::AddValueSInt16(CFStringRef key, int16_t value,
                                          bool can_create) {
  CFMutableDictionaryRef dict = Dictionary(can_create);
  if (dict != NULL) {
    CFCReleaser<CFNumberRef> cf_number(
        ::CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt16Type, &value));
    if (cf_number.get()) {
      // Let the dictionary own the CFNumber
      ::CFDictionaryAddValue(dict, key, cf_number.get());
      return true;
    }
  }
  return false;
}

bool CFCMutableDictionary::SetValueSInt16(CFStringRef key, int16_t value,
                                          bool can_create) {
  CFMutableDictionaryRef dict = Dictionary(can_create);
  if (dict != NULL) {
    CFCReleaser<CFNumberRef> cf_number(
        ::CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt16Type, &value));
    if (cf_number.get()) {
      // Let the dictionary own the CFNumber
      ::CFDictionarySetValue(dict, key, cf_number.get());
      return true;
    }
  }
  return false;
}

bool CFCMutableDictionary::AddValueSInt32(CFStringRef key, int32_t value,
                                          bool can_create) {
  CFMutableDictionaryRef dict = Dictionary(can_create);
  if (dict != NULL) {
    CFCReleaser<CFNumberRef> cf_number(
        ::CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &value));
    if (cf_number.get()) {
      // Let the dictionary own the CFNumber
      ::CFDictionaryAddValue(dict, key, cf_number.get());
      return true;
    }
  }
  return false;
}

bool CFCMutableDictionary::SetValueSInt32(CFStringRef key, int32_t value,
                                          bool can_create) {
  CFMutableDictionaryRef dict = Dictionary(can_create);
  if (dict != NULL) {
    CFCReleaser<CFNumberRef> cf_number(
        ::CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &value));
    if (cf_number.get()) {
      // Let the dictionary own the CFNumber
      ::CFDictionarySetValue(dict, key, cf_number.get());
      return true;
    }
  }
  return false;
}

bool CFCMutableDictionary::AddValueSInt64(CFStringRef key, int64_t value,
                                          bool can_create) {
  CFMutableDictionaryRef dict = Dictionary(can_create);
  if (dict != NULL) {
    CFCReleaser<CFNumberRef> cf_number(
        ::CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &value));
    if (cf_number.get()) {
      // Let the dictionary own the CFNumber
      ::CFDictionaryAddValue(dict, key, cf_number.get());
      return true;
    }
  }
  return false;
}

bool CFCMutableDictionary::SetValueSInt64(CFStringRef key, int64_t value,
                                          bool can_create) {
  CFMutableDictionaryRef dict = Dictionary(can_create);
  if (dict != NULL) {
    CFCReleaser<CFNumberRef> cf_number(
        ::CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &value));
    if (cf_number.get()) {
      // Let the dictionary own the CFNumber
      ::CFDictionarySetValue(dict, key, cf_number.get());
      return true;
    }
  }
  return false;
}

bool CFCMutableDictionary::AddValueUInt8(CFStringRef key, uint8_t value,
                                         bool can_create) {
  CFMutableDictionaryRef dict = Dictionary(can_create);
  if (dict != NULL) {
    // Have to promote to the next size type so things don't appear negative of
    // the MSBit is set...
    int16_t sval = value;
    CFCReleaser<CFNumberRef> cf_number(
        ::CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt16Type, &sval));
    if (cf_number.get()) {
      // Let the dictionary own the CFNumber
      ::CFDictionaryAddValue(dict, key, cf_number.get());
      return true;
    }
  }
  return false;
}

bool CFCMutableDictionary::SetValueUInt8(CFStringRef key, uint8_t value,
                                         bool can_create) {
  CFMutableDictionaryRef dict = Dictionary(can_create);
  if (dict != NULL) {
    // Have to promote to the next size type so things don't appear negative of
    // the MSBit is set...
    int16_t sval = value;
    CFCReleaser<CFNumberRef> cf_number(
        ::CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt16Type, &sval));
    if (cf_number.get()) {
      // Let the dictionary own the CFNumber
      ::CFDictionarySetValue(dict, key, cf_number.get());
      return true;
    }
  }
  return false;
}

bool CFCMutableDictionary::AddValueUInt16(CFStringRef key, uint16_t value,
                                          bool can_create) {
  CFMutableDictionaryRef dict = Dictionary(can_create);
  if (dict != NULL) {
    // Have to promote to the next size type so things don't appear negative of
    // the MSBit is set...
    int32_t sval = value;
    CFCReleaser<CFNumberRef> cf_number(
        ::CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &sval));
    if (cf_number.get()) {
      // Let the dictionary own the CFNumber
      ::CFDictionaryAddValue(dict, key, cf_number.get());
      return true;
    }
  }
  return false;
}

bool CFCMutableDictionary::SetValueUInt16(CFStringRef key, uint16_t value,
                                          bool can_create) {
  CFMutableDictionaryRef dict = Dictionary(can_create);
  if (dict != NULL) {
    // Have to promote to the next size type so things don't appear negative of
    // the MSBit is set...
    int32_t sval = value;
    CFCReleaser<CFNumberRef> cf_number(
        ::CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &sval));
    if (cf_number.get()) {
      // Let the dictionary own the CFNumber
      ::CFDictionarySetValue(dict, key, cf_number.get());
      return true;
    }
  }
  return false;
}

bool CFCMutableDictionary::AddValueUInt32(CFStringRef key, uint32_t value,
                                          bool can_create) {
  CFMutableDictionaryRef dict = Dictionary(can_create);
  if (dict != NULL) {
    // Have to promote to the next size type so things don't appear negative of
    // the MSBit is set...
    int64_t sval = value;
    CFCReleaser<CFNumberRef> cf_number(
        ::CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &sval));
    if (cf_number.get()) {
      // Let the dictionary own the CFNumber
      ::CFDictionaryAddValue(dict, key, cf_number.get());
      return true;
    }
  }
  return false;
}

bool CFCMutableDictionary::SetValueUInt32(CFStringRef key, uint32_t value,
                                          bool can_create) {
  CFMutableDictionaryRef dict = Dictionary(can_create);
  if (dict != NULL) {
    // Have to promote to the next size type so things don't appear negative of
    // the MSBit is set...
    int64_t sval = value;
    CFCReleaser<CFNumberRef> cf_number(
        ::CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &sval));
    if (cf_number.get()) {
      // Let the dictionary own the CFNumber
      ::CFDictionarySetValue(dict, key, cf_number.get());
      return true;
    }
  }
  return false;
}

bool CFCMutableDictionary::AddValueUInt64(CFStringRef key, uint64_t value,
                                          bool can_create) {
  CFMutableDictionaryRef dict = Dictionary(can_create);
  if (dict != NULL) {
    // The number may appear negative if the MSBit is set in "value". Due to a
    // limitation of CFNumber, there isn't a way to have it show up otherwise
    // as of this writing.
    CFCReleaser<CFNumberRef> cf_number(
        ::CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &value));
    if (cf_number.get()) {
      // Let the dictionary own the CFNumber
      ::CFDictionaryAddValue(dict, key, cf_number.get());
      return true;
    }
  }
  return false;
}

bool CFCMutableDictionary::SetValueUInt64(CFStringRef key, uint64_t value,
                                          bool can_create) {
  CFMutableDictionaryRef dict = Dictionary(can_create);
  if (dict != NULL) {
    // The number may appear negative if the MSBit is set in "value". Due to a
    // limitation of CFNumber, there isn't a way to have it show up otherwise
    // as of this writing.
    CFCReleaser<CFNumberRef> cf_number(
        ::CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &value));
    if (cf_number.get()) {
      // Let the dictionary own the CFNumber
      ::CFDictionarySetValue(dict, key, cf_number.get());
      return true;
    }
  }
  return false;
}

bool CFCMutableDictionary::AddValueDouble(CFStringRef key, double value,
                                          bool can_create) {
  CFMutableDictionaryRef dict = Dictionary(can_create);
  if (dict != NULL) {
    // The number may appear negative if the MSBit is set in "value". Due to a
    // limitation of CFNumber, there isn't a way to have it show up otherwise
    // as of this writing.
    CFCReleaser<CFNumberRef> cf_number(
        ::CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &value));
    if (cf_number.get()) {
      // Let the dictionary own the CFNumber
      ::CFDictionaryAddValue(dict, key, cf_number.get());
      return true;
    }
  }
  return false;
}

bool CFCMutableDictionary::SetValueDouble(CFStringRef key, double value,
                                          bool can_create) {
  CFMutableDictionaryRef dict = Dictionary(can_create);
  if (dict != NULL) {
    // The number may appear negative if the MSBit is set in "value". Due to a
    // limitation of CFNumber, there isn't a way to have it show up otherwise
    // as of this writing.
    CFCReleaser<CFNumberRef> cf_number(
        ::CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &value));
    if (cf_number.get()) {
      // Let the dictionary own the CFNumber
      ::CFDictionarySetValue(dict, key, cf_number.get());
      return true;
    }
  }
  return false;
}

bool CFCMutableDictionary::AddValueCString(CFStringRef key, const char *cstr,
                                           bool can_create) {
  CFMutableDictionaryRef dict = Dictionary(can_create);
  if (dict != NULL) {
    CFCString cf_str(cstr, kCFStringEncodingUTF8);
    if (cf_str.get()) {
      // Let the dictionary own the CFNumber
      ::CFDictionaryAddValue(dict, key, cf_str.get());
      return true;
    }
  }
  return false;
}

bool CFCMutableDictionary::SetValueCString(CFStringRef key, const char *cstr,
                                           bool can_create) {
  CFMutableDictionaryRef dict = Dictionary(can_create);
  if (dict != NULL) {
    CFCString cf_str(cstr, kCFStringEncodingUTF8);
    if (cf_str.get()) {
      // Let the dictionary own the CFNumber
      ::CFDictionarySetValue(dict, key, cf_str.get());
      return true;
    }
  }
  return false;
}

void CFCMutableDictionary::RemoveAllValues() {
  CFMutableDictionaryRef dict = get();
  if (dict)
    ::CFDictionaryRemoveAllValues(dict);
}

void CFCMutableDictionary::RemoveValue(const void *value) {
  CFMutableDictionaryRef dict = get();
  if (dict)
    ::CFDictionaryRemoveValue(dict, value);
}
void CFCMutableDictionary::ReplaceValue(const void *key, const void *value) {
  CFMutableDictionaryRef dict = get();
  if (dict)
    ::CFDictionaryReplaceValue(dict, key, value);
}
