/* Copyright 2017 Google Inc. All Rights Reserved.

   Distributed under MIT license.
   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/

#include "./encoder_dict.h"

#include "../common/dictionary.h"
#include "../common/platform.h"
#include "../common/shared_dictionary_internal.h"
#include "../common/transform.h"
#include "./compound_dictionary.h"
#include "./dictionary_hash.h"
#include "./memory.h"
#include "./quality.h"
#include "./hash.h"

#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif

#define NUM_HASH_BITS 15u
#define NUM_HASH_BUCKETS (1u << NUM_HASH_BITS)

static void BrotliTrieInit(BrotliTrie* trie) {
  trie->pool_capacity = 0;
  trie->pool_size = 0;
  trie->pool = 0;

  /* Set up the root node */
  trie->root.single = 0;
  trie->root.len_ = 0;
  trie->root.idx_ = 0;
  trie->root.sub = 0;
}

static void BrotliTrieFree(MemoryManager* m, BrotliTrie* trie) {
  BrotliFree(m, trie->pool);
}

/* Initializes to RFC 7932 static dictionary / transforms. */
static void InitEncoderDictionary(BrotliEncoderDictionary* dict) {
  dict->words = BrotliGetDictionary();
  dict->num_transforms = (uint32_t)BrotliGetTransforms()->num_transforms;

  dict->hash_table_words = kStaticDictionaryHashWords;
  dict->hash_table_lengths = kStaticDictionaryHashLengths;
  dict->buckets = kStaticDictionaryBuckets;
  dict->dict_words = kStaticDictionaryWords;

  dict->cutoffTransformsCount = kCutoffTransformsCount;
  dict->cutoffTransforms = kCutoffTransforms;

  dict->parent = 0;

  dict->hash_table_data_words_ = 0;
  dict->hash_table_data_lengths_ = 0;
  dict->buckets_alloc_size_ = 0;
  dict->buckets_data_ = 0;
  dict->dict_words_alloc_size_ = 0;
  dict->dict_words_data_ = 0;
  dict->words_instance_ = 0;
  dict->has_words_heavy = BROTLI_FALSE;
  BrotliTrieInit(&dict->trie);
}

static void BrotliDestroyEncoderDictionary(MemoryManager* m,
    BrotliEncoderDictionary* dict) {
  BrotliFree(m, dict->hash_table_data_words_);
  BrotliFree(m, dict->hash_table_data_lengths_);
  BrotliFree(m, dict->buckets_data_);
  BrotliFree(m, dict->dict_words_data_);
  BrotliFree(m, dict->words_instance_);
  BrotliTrieFree(m, &dict->trie);
}

/* Word length must be at least 4 bytes */
static uint32_t Hash(const uint8_t* data, int bits) {
  uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kHashMul32;
  /* The higher bits contain more mixture from the multiplication,
     so we take our results from there. */
  return h >> (32 - bits);
}

/* Theoretical max possible word size after transform */
#define kTransformedBufferSize \
    (256 + 256 + SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH)

/* To be safe buffer must have at least kTransformedBufferSize */
static void TransformedDictionaryWord(uint32_t word_idx, int len, int transform,
    const BrotliTransforms* transforms,
    const BrotliEncoderDictionary* dict,
    uint8_t* buffer, size_t* size) {
  const uint8_t* dict_word = &dict->words->data[
      dict->words->offsets_by_length[len] + (uint32_t)len * word_idx];
  *size = (size_t)BrotliTransformDictionaryWord(buffer, dict_word, len,
      transforms, transform);
}

static DictWord MakeDictWord(uint8_t len, uint8_t transform, uint16_t idx) {
  DictWord result;
  result.len = len;
  result.transform = transform;
  result.idx = idx;
  return result;
}

static uint32_t BrotliTrieAlloc(MemoryManager* m, size_t num, BrotliTrie* trie,
                                BrotliTrieNode** keep) {
  uint32_t result;
  uint32_t keep_index = 0;
  if (keep && *keep != &trie->root) {
    /* Optional node to keep, since address may change after re-allocating */
    keep_index = (uint32_t)(*keep - trie->pool);
  }
  if (trie->pool_size == 0) {
    /* Have a dummy node in the front. We do not want the result to be 0, it
    must be at least 1, 0 represents "null pointer" */
    trie->pool_size = 1;
  }
  BROTLI_ENSURE_CAPACITY(m, BrotliTrieNode, trie->pool, trie->pool_capacity,
                         trie->pool_size + num);
  if (BROTLI_IS_OOM(m)) return 0;
  /* Init the new nodes to empty */
  memset(trie->pool + trie->pool_size, 0, sizeof(*trie->pool) * num);
  result = (uint32_t)trie->pool_size;
  trie->pool_size += num;
  if (keep && *keep != &trie->root) {
    *keep = trie->pool + keep_index;
  }
  return result;
}

/**
 * len and idx: payload for last node
 * word, size: the string
 * index: position in the string
 */
static BROTLI_BOOL BrotliTrieNodeAdd(MemoryManager* m, uint8_t len,
    uint32_t idx, const uint8_t* word, size_t size, int index,
    BrotliTrieNode* node, BrotliTrie* trie) {
  BrotliTrieNode* child = 0;
  uint8_t c;
  if ((size_t)index == size) {
    if (!node->len_ || idx < node->idx_) {
      node->len_ = len;
      node->idx_ = idx;
    }
    return BROTLI_TRUE;
  }
  c = word[index];
  if (node->single && c != node->c) {
    BrotliTrieNode old = trie->pool[node->sub];
    uint32_t new_nodes = BrotliTrieAlloc(m, 32, trie, &node);
    if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;
    node->single = 0;
    node->sub = new_nodes;
    trie->pool[node->sub + (node->c >> 4)].sub = new_nodes + 16;
    trie->pool[trie->pool[node->sub + (node->c >> 4)].sub + (node->c & 15)] =
        old;
  }
  if (!node->sub) {
    uint32_t new_node = BrotliTrieAlloc(m, 1, trie, &node);
    if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;
    node->single = 1;
    node->c = c;
    node->sub = new_node;
  }
  if (node->single) {
    child = &trie->pool[node->sub];
  } else {
    if (!trie->pool[node->sub + (c >> 4)].sub) {
      uint32_t new_nodes = BrotliTrieAlloc(m, 16, trie, &node);
      if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;
      trie->pool[node->sub + (c >> 4)].sub = new_nodes;
    }
    child = &trie->pool[trie->pool[node->sub + (c >> 4)].sub + (c & 15)];
  }
  return BrotliTrieNodeAdd(m, len, idx, word, size, index + 1, child, trie);
}

static BROTLI_BOOL BrotliTrieAdd(MemoryManager* m, uint8_t len, uint32_t idx,
                          const uint8_t* word, size_t size, BrotliTrie* trie) {
  return BrotliTrieNodeAdd(m, len, idx, word, size, 0, &trie->root, trie);
}

const BrotliTrieNode* BrotliTrieSub(const BrotliTrie* trie,
                                    const BrotliTrieNode* node, uint8_t c) {
  BrotliTrieNode* temp_node;
  if (node->single) {
    if (node->c == c) return &trie->pool[node->sub];
    return 0;
  }
  if (!node->sub) return 0;
  temp_node = &trie->pool[node->sub + (c >> 4)];
  if (!temp_node->sub) return 0;
  return &trie->pool[temp_node->sub + (c & 15)];
}

static const BrotliTrieNode* BrotliTrieFind(const BrotliTrie* trie,
                                            const uint8_t* word, size_t size) {
  const BrotliTrieNode* node = &trie->root;
  size_t i;
  for (i = 0; i < size; i++) {
    node = BrotliTrieSub(trie, node, word[i]);
    if (!node) return 0;
  }
  return node;
}

static BROTLI_BOOL BuildDictionaryLut(MemoryManager* m,
    const BrotliTransforms* transforms,
    BrotliEncoderDictionary* dict) {
  uint32_t i;
  DictWord* dict_words;
  uint16_t* buckets;
  DictWord** words_by_hash;
  size_t* words_by_hash_size;
  size_t* words_by_hash_capacity;
  BrotliTrie dedup;
  uint8_t word[kTransformedBufferSize];
  size_t word_size;
  size_t total = 0;
  uint8_t l;
  uint16_t idx;

  BrotliTrieInit(&dedup);

  words_by_hash = (DictWord**)BrotliAllocate(m,
      sizeof(*words_by_hash) * NUM_HASH_BUCKETS);
  words_by_hash_size = (size_t*)BrotliAllocate(m,
      sizeof(*words_by_hash_size) * NUM_HASH_BUCKETS);
  words_by_hash_capacity = (size_t*)BrotliAllocate(m,
      sizeof(*words_by_hash_capacity) * NUM_HASH_BUCKETS);
  if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;
  memset(words_by_hash, 0, sizeof(*words_by_hash) * NUM_HASH_BUCKETS);
  memset(words_by_hash_size, 0, sizeof(*words_by_hash_size) * NUM_HASH_BUCKETS);
  memset(words_by_hash_capacity, 0,
         sizeof(*words_by_hash_capacity) * NUM_HASH_BUCKETS);

  if (transforms->num_transforms > 0) {
    for (l = SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH;
        l <= SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH; ++l) {
      uint16_t n = dict->words->size_bits_by_length[l] ?
          (uint16_t)(1 << dict->words->size_bits_by_length[l]) : 0;
      for (idx = 0; idx < n; ++idx) {
        uint32_t key;
        /* First transform (usually identity) */
        TransformedDictionaryWord(idx, l, 0, transforms, dict, word,
                                  &word_size);
        /* Cannot hash words smaller than 4 bytes */
        if (word_size < 4) {
          /* Break instead of continue, all next words of this length will have
             same length after transform */
          break;
        }
        if (!BrotliTrieAdd(m, 0, idx, word, word_size, &dedup)) {
          return BROTLI_FALSE;
        }
        key = Hash(word, NUM_HASH_BITS);
        BROTLI_ENSURE_CAPACITY_APPEND(m, DictWord, words_by_hash[key],
            words_by_hash_capacity[key], words_by_hash_size[key],
            MakeDictWord(l, 0, idx));
        ++total;
      }
    }
  }

  /* These LUT transforms only supported if no custom transforms. This is
     ok, we will use the heavy trie instead. */
  if (transforms == BrotliGetTransforms()) {
    for (l = SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH;
        l <= SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH; ++l) {
      uint16_t n = dict->words->size_bits_by_length[l] ?
          (uint16_t)(1 << dict->words->size_bits_by_length[l]) : 0;
      for (idx = 0; idx < n; ++idx) {
        int k;
        BROTLI_BOOL is_ascii = BROTLI_TRUE;
        size_t offset = dict->words->offsets_by_length[l] + (size_t)l * idx;
        const uint8_t* data = &dict->words->data[offset];
        for (k = 0; k < l; ++k) {
          if (data[k] >= 128) is_ascii = BROTLI_FALSE;
        }
        if (data[0] < 128) {
          int transform = 9;  /* {empty, uppercase first, empty} */
          uint32_t ix = idx + (uint32_t)transform * n;
          const BrotliTrieNode* it;
          TransformedDictionaryWord(idx, l, transform, transforms,
                                   dict, word, &word_size);
          it = BrotliTrieFind(&dedup, word, word_size);
          if (!it || it->idx_ > ix) {
            uint32_t key = Hash(word, NUM_HASH_BITS);
            if (!BrotliTrieAdd(m, 0, ix, word, word_size, &dedup)) {
              return BROTLI_FALSE;
            }
            BROTLI_ENSURE_CAPACITY_APPEND(m, DictWord, words_by_hash[key],
                words_by_hash_capacity[key], words_by_hash_size[key],
                MakeDictWord(l, BROTLI_TRANSFORM_UPPERCASE_FIRST, idx));
            ++total;
          }
        }
        if (is_ascii) {
          int transform = 44;  /* {empty, uppercase all, empty} */
          uint32_t ix = idx + (uint32_t)transform * n;
          const BrotliTrieNode* it;
          TransformedDictionaryWord(idx, l, transform, transforms,
                                    dict, word, &word_size);
          it = BrotliTrieFind(&dedup, word, word_size);
          if (!it || it->idx_ > ix) {
            uint32_t key = Hash(word, NUM_HASH_BITS);
            if (!BrotliTrieAdd(m, 0, ix, word, word_size, &dedup)) {
              return BROTLI_FALSE;
            }
            BROTLI_ENSURE_CAPACITY_APPEND(m, DictWord, words_by_hash[key],
                words_by_hash_capacity[key], words_by_hash_size[key],
                MakeDictWord(l, BROTLI_TRANSFORM_UPPERCASE_ALL, idx));
            ++total;
          }
        }
      }
    }
  }

  dict_words = (DictWord*)BrotliAllocate(m,
      sizeof(*dict->dict_words) * (total + 1));
  buckets = (uint16_t*)BrotliAllocate(m,
      sizeof(*dict->buckets) * NUM_HASH_BUCKETS);
  if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;
  dict->dict_words_alloc_size_ = total + 1;
  dict->dict_words = dict->dict_words_data_ = dict_words;
  dict->buckets_alloc_size_ = NUM_HASH_BUCKETS;
  dict->buckets = dict->buckets_data_ = buckets;

  /* Unused; makes offsets start from 1. */
  dict_words[0] = MakeDictWord(0, 0, 0);
  total = 1;
  for (i = 0; i < NUM_HASH_BUCKETS; ++i) {
    size_t num_words = words_by_hash_size[i];
    if (num_words > 0) {
      buckets[i] = (uint16_t)(total);
      memcpy(&dict_words[total], &words_by_hash[i][0],
          sizeof(dict_words[0]) * num_words);
      total += num_words;
      dict_words[total - 1].len |= 0x80;
    } else {
      buckets[i] = 0;
    }
  }

  for (i = 0; i < NUM_HASH_BUCKETS; ++i) {
    BrotliFree(m, words_by_hash[i]);
  }
  BrotliFree(m, words_by_hash);
  BrotliFree(m, words_by_hash_size);
  BrotliFree(m, words_by_hash_capacity);
  BrotliTrieFree(m, &dedup);

  return BROTLI_TRUE;
}

static void BuildDictionaryHashTable(uint16_t* hash_table_words,
    uint8_t* hash_table_lengths, const BrotliDictionary* dict) {
  int j, len;
  /* The order of the loops is such that in case of collision, words with
     shorter length are preferred, and in case of same length, words with
     smaller index. There is only a single word per bucket. */
  /* TODO: consider adding optional user-supplied frequency_map to use
     for preferred words instead, this can make the encoder better for
     quality 9 and below without affecting the decoder */
  memset(hash_table_words, 0, sizeof(kStaticDictionaryHashWords));
  memset(hash_table_lengths, 0, sizeof(kStaticDictionaryHashLengths));
  for (len = SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH;
      len >= SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH; --len) {
    const size_t num_words = dict->size_bits_by_length[len] ?
        (1u << dict->size_bits_by_length[len]) : 0;
    for (j = (int)num_words - 1; j >= 0; --j) {
      size_t offset = dict->offsets_by_length[len] +
          (size_t)len * (size_t)j;
      const uint8_t* word = &dict->data[offset];
      const uint32_t key = Hash(word, 14);
      int idx = (int)(key << 1) + (len < 8 ? 1 : 0);
      BROTLI_DCHECK(idx < (int)NUM_HASH_BUCKETS);
      hash_table_words[idx] = (uint16_t)j;
      hash_table_lengths[idx] = (uint8_t)len;
    }
  }
}

static BROTLI_BOOL GenerateWordsHeavy(MemoryManager* m,
    const BrotliTransforms* transforms,
    BrotliEncoderDictionary* dict) {
  int i, j, l;
  for (j = (int)transforms->num_transforms - 1; j >= 0 ; --j) {
    for (l = 0; l < 32; l++) {
      int num = (int)((1u << dict->words->size_bits_by_length[l]) & ~1u);
      for (i = 0; i < num; i++) {
        uint8_t transformed[kTransformedBufferSize];
        size_t size;
        TransformedDictionaryWord(
            (uint32_t)i, l, j, transforms, dict, transformed, &size);
        if (size < 4) continue;
        if (!BrotliTrieAdd(m, (uint8_t)l, (uint32_t)(i + num * j),
            transformed, size, &dict->trie)) {
          return BROTLI_FALSE;
        }
      }
    }
  }
  return BROTLI_TRUE;
}

/* Computes cutoffTransformsCount (in count) and cutoffTransforms (in data) for
   the custom transforms, where possible within the limits of the
   cutoffTransforms encoding. The fast encoder uses this to do fast lookup for
   transforms that remove the N last characters (OmitLast). */
static void ComputeCutoffTransforms(
    const BrotliTransforms* transforms,
    uint32_t* count, uint64_t* data) {
  int i;
  /* The encoding in a 64-bit integer of transform N in the data is: (N << 2) +
     ((cutoffTransforms >> (N * 6)) & 0x3F), so for example the identity
     transform code must be 0-63, for N=1 the transform code must be 4-67, ...,
     for N=9 it must be 36-99.
     TODO: consider a simple flexible uint8_t[10] instead of the uint64_t
     for the cutoff transforms, so that shared dictionaries can have the
     OmitLast transforms anywhere without loss. */
  *count = 0;
  *data = 0;
  for (i = 0; i < BROTLI_TRANSFORMS_MAX_CUT_OFF + 1; i++) {
    int idx = transforms->cutOffTransforms[i];
    if (idx == -1) break;  /* Not found */
    if (idx < (i << 2)) break;  /* Too small for the encoding */
    if (idx >= (i << 2) + 64) break;  /* Too large for the encoding */
    (*count)++;
    *data |= (uint64_t)(((uint64_t)idx -
        ((uint64_t)i << 2u)) << ((uint64_t)i * 6u));
  }
}

static BROTLI_BOOL ComputeDictionary(MemoryManager* m, int quality,
    const BrotliTransforms* transforms,
    BrotliEncoderDictionary* current) {
  int default_words = current->words == BrotliGetDictionary();
  int default_transforms = transforms == BrotliGetTransforms();

  if (default_words && default_transforms) {
    /* hashes are already set to Brotli defaults */
    return BROTLI_TRUE;
  }

  current->hash_table_data_words_ = (uint16_t*)BrotliAllocate(
      m, sizeof(kStaticDictionaryHashWords));
  current->hash_table_data_lengths_ = (uint8_t*)BrotliAllocate(
      m, sizeof(kStaticDictionaryHashLengths));
  if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;
  current->hash_table_words = current->hash_table_data_words_;
  current->hash_table_lengths = current->hash_table_data_lengths_;

  BuildDictionaryHashTable(current->hash_table_data_words_,
      current->hash_table_data_lengths_, current->words);

  ComputeCutoffTransforms(transforms,
      &current->cutoffTransformsCount, &current->cutoffTransforms);

  /* Only compute the data for slow encoder if the requested quality is high
     enough to need it */
  if (quality >= ZOPFLIFICATION_QUALITY) {
    if (!BuildDictionaryLut(m, transforms, current)) return BROTLI_FALSE;

    /* For the built-in Brotli transforms, there is a hard-coded function to
       handle all transforms, but for custom transforms, we use the following
       large hammer instead */
    current->has_words_heavy = !default_transforms;
    if (current->has_words_heavy) {
      if (!GenerateWordsHeavy(m, transforms, current)) return BROTLI_FALSE;
    }
  }

  return BROTLI_TRUE;
}

void BrotliInitSharedEncoderDictionary(SharedEncoderDictionary* dict) {
  dict->magic = kSharedDictionaryMagic;

  dict->compound.num_chunks = 0;
  dict->compound.total_size = 0;
  dict->compound.chunk_offsets[0] = 0;
  dict->compound.num_prepared_instances_ = 0;

  dict->contextual.context_based = 0;
  dict->contextual.num_dictionaries = 1;
  dict->contextual.instances_ = 0;
  dict->contextual.num_instances_ = 1;  /* The instance_ field */
  dict->contextual.dict[0] = &dict->contextual.instance_;
  InitEncoderDictionary(&dict->contextual.instance_);
  dict->contextual.instance_.parent = &dict->contextual;

  dict->max_quality = BROTLI_MAX_QUALITY;
}

/* TODO: make sure that tooling will warn user if not all the cutoff
   transforms are available (for low-quality encoder). */
static BROTLI_BOOL InitCustomSharedEncoderDictionary(
    MemoryManager* m, const BrotliSharedDictionary* decoded_dict,
    int quality, SharedEncoderDictionary* dict) {
  ContextualEncoderDictionary* contextual;
  CompoundDictionary* compound;
  BrotliEncoderDictionary* instances;
  int i;
  BrotliInitSharedEncoderDictionary(dict);

  contextual = &dict->contextual;
  compound = &dict->compound;

  for (i = 0; i < (int)decoded_dict->num_prefix; i++) {
    PreparedDictionary* prepared = CreatePreparedDictionary(m,
        decoded_dict->prefix[i], decoded_dict->prefix_size[i]);
    AttachPreparedDictionary(compound, prepared);
    /* remember for cleanup */
    compound->prepared_instances_[
        compound->num_prepared_instances_++] = prepared;
  }

  dict->max_quality = quality;
  contextual->context_based = decoded_dict->context_based;
  if (decoded_dict->context_based) {
    memcpy(contextual->context_map, decoded_dict->context_map,
        SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS);
  }

  contextual->num_dictionaries = decoded_dict->num_dictionaries;
  contextual->num_instances_ = decoded_dict->num_dictionaries;
  if (contextual->num_instances_ == 1) {
    instances = &contextual->instance_;
  } else {
    contextual->instances_ = (BrotliEncoderDictionary*)
        BrotliAllocate(m, sizeof(*contextual->instances_) *
        contextual->num_instances_);
    if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;
    instances = contextual->instances_;
  }
  for (i = 0; i < (int)contextual->num_instances_; i++) {
    BrotliEncoderDictionary* current = &instances[i];
    InitEncoderDictionary(current);
    current->parent = &dict->contextual;
    if (decoded_dict->words[i] == BrotliGetDictionary()) {
      current->words = BrotliGetDictionary();
    } else {
      current->words_instance_ = (BrotliDictionary*)BrotliAllocate(
          m, sizeof(BrotliDictionary));
      if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;
      *current->words_instance_ = *decoded_dict->words[i];
      current->words = current->words_instance_;
    }
    current->num_transforms =
        (uint32_t)decoded_dict->transforms[i]->num_transforms;
    if (!ComputeDictionary(
        m, quality, decoded_dict->transforms[i], current)) {
      return BROTLI_FALSE;
    }

    contextual->dict[i] = current;
  }

  return BROTLI_TRUE;  /* success */
}

BROTLI_BOOL BrotliInitCustomSharedEncoderDictionary(
    MemoryManager* m, const uint8_t* encoded_dict, size_t size,
    int quality, SharedEncoderDictionary* dict) {
  BROTLI_BOOL success = BROTLI_FALSE;
  BrotliSharedDictionary* decoded_dict = BrotliSharedDictionaryCreateInstance(
      m->alloc_func, m->free_func, m->opaque);
  if (!decoded_dict) {  /* OOM */
    return BROTLI_FALSE;
  }
  success = BrotliSharedDictionaryAttach(
      decoded_dict, BROTLI_SHARED_DICTIONARY_SERIALIZED, size, encoded_dict);
  if (success) {
    success = InitCustomSharedEncoderDictionary(m,
        decoded_dict, quality, dict);
  }
  BrotliSharedDictionaryDestroyInstance(decoded_dict);
  return success;
}

void BrotliCleanupSharedEncoderDictionary(MemoryManager* m,
                                          SharedEncoderDictionary* dict) {
  size_t i;
  for (i = 0; i < dict->compound.num_prepared_instances_; i++) {
    DestroyPreparedDictionary(m,
        (PreparedDictionary*)dict->compound.prepared_instances_[i]);
  }
  if (dict->contextual.num_instances_ == 1) {
    BrotliDestroyEncoderDictionary(m, &dict->contextual.instance_);
  } else if (dict->contextual.num_instances_ > 1) {
    for (i = 0; i < dict->contextual.num_instances_; i++) {
      BrotliDestroyEncoderDictionary(m, &dict->contextual.instances_[i]);
    }
    BrotliFree(m, dict->contextual.instances_);
  }
}

ManagedDictionary* BrotliCreateManagedDictionary(
    brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) {
  ManagedDictionary* result = NULL;

  /* TODO: Refactor this snippet to macros. */
  if (!alloc_func && !free_func) {
    result = (ManagedDictionary*)malloc(sizeof(ManagedDictionary));
  } else if (alloc_func && free_func) {
    result = (ManagedDictionary*)alloc_func(opaque, sizeof(ManagedDictionary));
  }
  if (result == NULL) return NULL;

  result->magic = kManagedDictionaryMagic;
  BrotliInitMemoryManager(
      &result->memory_manager_, alloc_func, free_func, opaque);
  result->dictionary = NULL;

  return result;
}

void BrotliDestroyManagedDictionary(ManagedDictionary* dictionary) {
  MemoryManager* m = NULL;
  if (!dictionary) return;
  m = &dictionary->memory_manager_;
  {
    brotli_free_func free_func = m->free_func;
    void* opaque = m->opaque;
    free_func(opaque, dictionary);
  }
}

#if defined(__cplusplus) || defined(c_plusplus)
}  /* extern "C" */
#endif
