/* 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 <stdlib.h>  /* malloc, free */

#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]) : 0u;
      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]) : 0u;
      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(lode): 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(lode): 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(eustas): 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 = (ManagedDictionary*)BrotliBootstrapAlloc(
      sizeof(ManagedDictionary), alloc_func, free_func, opaque);
  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) {
  if (!dictionary) return;
  BrotliBootstrapFree(dictionary, &dictionary->memory_manager_);
}

/* Escalate internal functions visibility; for testing purposes only. */
#if defined(BROTLI_TEST)
void InitEncoderDictionaryForTest(BrotliEncoderDictionary*);
void InitEncoderDictionaryForTest(BrotliEncoderDictionary* d) {
  InitEncoderDictionary(d);
}
#endif

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