// Copyright (c) 2012 The Chromium 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 "third_party/hunspell/google/bdict_reader.h"

#include <stdint.h>

#include "base/logging.h"

namespace hunspell {

// Like the "Visitor" design pattern, this lightweight object provides an
// interface around a serialized trie node at the given address in the memory.
class NodeReader {
 public:
  // Return values for GetChildAt.
  enum FindResult {
    // A node is found.
    FIND_NODE,

    // There are no more children for this node, no child node is returned.
    FIND_DONE,

    // There is no node at this location, but there are more if you continue
    // iterating. This happens when there is a lookup node with empty entries.
    FIND_NOTHING
  };

  // The default constructor makes an invalid reader.
  NodeReader();
  NodeReader(const unsigned char* bdict_data, size_t bdict_length,
             size_t node_offset, int node_depth);

  // Returns true if the reader is valid. False means you shouldn't use it.
  bool is_valid() const { return is_valid_; }

  // Recursively finds the given NULL terminated word.
  // See BDictReader::FindWord.
  int FindWord(const unsigned char* word,
               int affix_indices[BDict::MAX_AFFIXES_PER_WORD]) const;

  // Allows iterating over the children of this node. When it returns
  // FIND_NODE, |*result| will be populated with the reader for the found node.
  // The first index is 0. The single character for this node will be placed
  // into |*found_char|.
  FindResult GetChildAt(int index, char* found_char, NodeReader* result) const;

  // Leaf ----------------------------------------------------------------------

  inline bool is_leaf() const {
    // If id_byte() sets is_valid_ to false, we need an extra check to avoid
    // returning true for this type.
    return (id_byte() & BDict::LEAF_NODE_TYPE_MASK) ==
        BDict::LEAF_NODE_TYPE_VALUE && is_valid_;
  }

  // If this is a leaf node with an additional string, this function will return
  // a pointer to the beginning of the additional string. It will be NULL
  // terminated. If it is not a leaf or has no additional string, it will return
  // NULL.
  inline const unsigned char* additional_string_for_leaf() const {
    // Leaf nodes with additional strings start with bits "01" in the ID byte.
    if ((id_byte() & BDict::LEAF_NODE_ADDITIONAL_MASK) ==
      BDict::LEAF_NODE_ADDITIONAL_VALUE) {
      if (node_offset_ < (bdict_length_ - 2))
        return &bdict_data_[node_offset_ + 2];  // Starts after the 2 byte ID.
      // Otherwise the dictionary is corrupt.
      is_valid_ = false;
    }
    return NULL;
  }

  // Returns the first affix ID corresponding to the given leaf node. The
  // current node must be a leaf or this will do the wrong thing. There may be
  // additional affix IDs following the node when leaf_has_following is set,
  // but this will not handle those.
  inline int affix_id_for_leaf() const {
    if (node_offset_ >= bdict_length_ - 1) {
      is_valid_ = false;
      return 0;
    }
    // Take the lowest 6 bits of the first byte, and all 8 bits of the second.
    return ((bdict_data_[node_offset_ + 0] &
             BDict::LEAF_NODE_FIRST_BYTE_AFFIX_MASK) << 8) +
           bdict_data_[node_offset_ + 1];
  }

  // Returns true if there is a list of additional affix matches following this
  // leaf node.
  inline bool leaf_has_following() const {
    return ((id_byte() & BDict::LEAF_NODE_FOLLOWING_MASK) ==
        BDict::LEAF_NODE_FOLLOWING_VALUE);
  }

  // Fills the affix indices into the output array given a matching leaf node.
  // |additional_bytes| is the number of bytes of the additional string,
  // including the NULL terminator, following this leaf node. This will be 0 if
  // there is no additional string.
  int FillAffixesForLeafMatch(
      size_t additional_bytes,
      int affix_indices[BDict::MAX_AFFIXES_PER_WORD]) const;

  // Lookup --------------------------------------------------------------------

  inline bool is_lookup() const {
    return (id_byte() & BDict::LOOKUP_NODE_TYPE_MASK) ==
        BDict::LOOKUP_NODE_TYPE_VALUE;
  }

  inline bool is_lookup_32() const {
    return (id_byte() & BDict::LOOKUP_NODE_32BIT_MASK) ==
        BDict::LOOKUP_NODE_32BIT_VALUE;
  }

  inline bool lookup_has_0th() const {
    return (id_byte() & BDict::LOOKUP_NODE_0TH_MASK) ==
        BDict::LOOKUP_NODE_0TH_VALUE;
  }

  // Returns the first entry after the lookup table header. When there is a
  // magic 0th entry, it will be that address.
  // The caller checks that the result is in-bounds.
  inline size_t zeroth_entry_offset() const {
    return node_offset_ + 3;
  }

  // Returns the index of the first element in the lookup table. This skips any
  // magic 0th entry.
  // The caller checks that the result is in-bounds.
  size_t lookup_table_offset() const {
    size_t table_offset = zeroth_entry_offset();
    if (lookup_has_0th())
      return table_offset + (is_lookup_32() ? 4 : 2);
    return table_offset;
  }

  inline int lookup_first_char() const {
    if (node_offset_ >= bdict_length_ - 1) {
      is_valid_ = false;
      return 0;
    }
    return bdict_data_[node_offset_ + 1];
  }

  inline int lookup_num_chars() const {
    if (node_offset_ >= bdict_length_ - 2) {
      is_valid_ = false;
      return 0;
    }
    return bdict_data_[node_offset_ + 2];
  }

  // Computes a node reader for the magic 0th entry of the table. This assumes
  // it has a 0th entry. This will always return FOUND_NODE (for compatilibility
  // with GetChildAt).
  FindResult ReaderForLookup0th(NodeReader* result) const;

  // Gets a node reader for the |offset|th element in the table, not counting
  // the magic 0th element, if any (so passing 0 here will give you the first
  // element in the regular lookup table). The offset is assumed to be valid.
  //
  // |child_node_char| is the character value that the child node will
  // represent. The single character for this node will be placed into
  // |*found_char|.
  FindResult ReaderForLookupAt(size_t index, char* found_char,
                               NodeReader* result) const;

  // List ----------------------------------------------------------------------

  inline bool is_list() const {
    return (id_byte() & BDict::LIST_NODE_TYPE_MASK) ==
        BDict::LIST_NODE_TYPE_VALUE;
  }

  inline int is_list_16() const {
    // 16 bit lst nodes have the high 4 bits of 1.
    return (id_byte() & BDict::LIST_NODE_16BIT_MASK) ==
        BDict::LIST_NODE_16BIT_VALUE;
  }

  inline size_t list_item_count() const {
    // The list count is stored in the low 4 bits of the ID.
    return id_byte() & BDict::LIST_NODE_COUNT_MASK;
  }

  // Returns a NodeReader for the list item with the given index. The single
  // character for this node will be placed into |*found_char|.
  FindResult ReaderForListAt(size_t index, char* found_char,
                             NodeReader* result) const;

 private:
  inline unsigned char id_byte() const {
    if (!is_valid_)
      return 0;  // Don't continue with a corrupt node.
    if (node_offset_ >= bdict_length_) {
      // Return zero if out of bounds; we'll check is_valid_ in caller.
      is_valid_ = false;
      return 0;
    }
    return bdict_data_[node_offset_];
  }

  // Checks the given leaf node to see if it's a match for the given word.
  // The parameters and return values are the same as BDictReader::FindWord.
  int CompareLeafNode(const unsigned char* word,
                      int affix_indices[BDict::MAX_AFFIXES_PER_WORD]) const;

  // Recursive calls used by FindWord to look up child nodes of different types.
  int FindInLookup(const unsigned char* word,
                   int affix_indices[BDict::MAX_AFFIXES_PER_WORD]) const;
  int FindInList(const unsigned char* word,
                 int affix_indices[BDict::MAX_AFFIXES_PER_WORD]) const;

  // The entire bdict file. This will be NULL if it is invalid.
  const unsigned char* bdict_data_;
  size_t bdict_length_;
  // Points to the end of the file (for length checking convenience).
  const unsigned char* bdict_end_;

  // Absolute offset within |bdict_data_| of the beginning of this node.
  size_t node_offset_;

  // The character index into the word that this node represents.
  int node_depth_;

  // Signals that dictionary corruption was found during node traversal.
  mutable bool is_valid_;
};

NodeReader::NodeReader()
    : bdict_data_(NULL),
      bdict_length_(0),
      bdict_end_(NULL),
      node_offset_(0),
      node_depth_(0),
      is_valid_(false) {
}

NodeReader::NodeReader(const unsigned char* bdict_data, size_t bdict_length,
                       size_t node_offset, int node_depth)
    : bdict_data_(bdict_data),
      bdict_length_(bdict_length),
      bdict_end_(bdict_data + bdict_length),
      node_offset_(node_offset),
      node_depth_(node_depth),
      is_valid_(bdict_data != NULL && node_offset < bdict_length) {
}

int NodeReader::FindWord(const unsigned char* word,
                         int affix_indices[BDict::MAX_AFFIXES_PER_WORD]) const {
  // Return 0 if the dictionary is corrupt as BDictReader::FindWord() does.
  if (!bdict_data_ || node_offset_ > bdict_length_)
    return 0;

  if (is_leaf())
    return CompareLeafNode(word, affix_indices);

  if (is_lookup())
    return FindInLookup(word, affix_indices);
  if (is_list())
    return FindInList(word, affix_indices);
  return 0;  // Corrupt file.
}

NodeReader::FindResult NodeReader::GetChildAt(int index, char* found_char,
                                              NodeReader* result) const {
  if (is_lookup()) {
    if (lookup_has_0th()) {
      if (index == 0) {
        *found_char = 0;
        return ReaderForLookup0th(result);
      }
      index--;  // Make index relative to the non-0th-element table.
    }
    return ReaderForLookupAt(index, found_char, result);
  }
  if (is_list()) {
    return ReaderForListAt(index, found_char, result);
  }
  return FIND_DONE;
}

int NodeReader::CompareLeafNode(
    const unsigned char* word,
    int affix_indices[BDict::MAX_AFFIXES_PER_WORD]) const {
  // See if there is an additional string.
  const unsigned char* additional = additional_string_for_leaf();
  if (!additional) {
    // No additional string. This means we should have reached the end of the
    // word to get a match.
    if (word[node_depth_] != 0)
      return 0;
    return FillAffixesForLeafMatch(0, affix_indices);
  }

  // Check the additional string.
  int cur = 0;
  while (&additional[cur] < bdict_end_ && additional[cur]) {
    if (word[node_depth_ + cur] != additional[cur])
      return 0;  // Not a match.
    cur++;
  }

  if (&additional[cur] == bdict_end_) {
    is_valid_ = false;
    return 0;
  }

  // Got to the end of the additional string, the word should also be over for
  // a match (the same as above).
  if (word[node_depth_ + cur] != 0)
    return 0;
  return FillAffixesForLeafMatch(cur + 1, affix_indices);
}

int NodeReader::FillAffixesForLeafMatch(
    size_t additional_bytes,
    int affix_indices[BDict::MAX_AFFIXES_PER_WORD]) const {
  // The first match is easy, it always comes from the affix_id included in the
  // leaf node.
  affix_indices[0] = affix_id_for_leaf();

  if (!leaf_has_following() && affix_indices[0] != BDict::FIRST_AFFIX_IS_UNUSED)
    return 1;  // Common case: no additional affix group IDs.

  // We may or may not need to ignore that first value we just read, since it
  // could be a dummy placeholder value. The |list_offset| is the starting
  // position in the output list to write the rest of the values, which may
  // overwrite the first value.
  int list_offset = 1;
  if (affix_indices[0] == BDict::FIRST_AFFIX_IS_UNUSED)
    list_offset = 0;

  // Save the end pointer (accounting for an odd number of bytes).
  size_t array_start = node_offset_ + additional_bytes + 2;
  const uint16_t* const bdict_short_end = reinterpret_cast<const uint16_t*>(
      &bdict_data_[((bdict_length_ - array_start) & -2) + array_start]);
  // Process all remaining matches.
  const uint16_t* following_array =
      reinterpret_cast<const uint16_t*>(&bdict_data_[array_start]);
  for (int i = 0; i < BDict::MAX_AFFIXES_PER_WORD - list_offset; i++) {
    if (&following_array[i] >= bdict_short_end) {
      is_valid_ = false;
      return 0;
    }
    if (following_array[i] == BDict::LEAF_NODE_FOLLOWING_LIST_TERMINATOR)
      return i + list_offset;  // Found the end of the list.
    affix_indices[i + list_offset] = following_array[i];
  }
  return BDict::MAX_AFFIXES_PER_WORD;
}

int NodeReader::FindInLookup(
    const unsigned char* word,
    int affix_indices[BDict::MAX_AFFIXES_PER_WORD]) const {
  unsigned char next_char = word[node_depth_];

  NodeReader child_reader;
  if (next_char == 0 && lookup_has_0th()) {
    if (ReaderForLookup0th(&child_reader) != FIND_NODE)
      return 0;
  } else {
    // Look up in the regular part of the table.
    int offset_in_table = static_cast<int>(next_char) - lookup_first_char();
    if (offset_in_table < 0 || offset_in_table > lookup_num_chars())
      return 0;  // Table can not include this value.

    char dummy_char;
    if (ReaderForLookupAt(offset_in_table, &dummy_char, &child_reader) !=
        FIND_NODE)
      return 0;
    DCHECK(dummy_char == static_cast<char>(next_char));
  }

  if (!child_reader.is_valid())
    return 0;  // Something is messed up.

  // Now recurse into that child node.
  return child_reader.FindWord(word, affix_indices);
}

NodeReader::FindResult NodeReader::ReaderForLookup0th(
    NodeReader* result) const {
  size_t child_offset;
  if (is_lookup_32()) {
    child_offset = *reinterpret_cast<const unsigned int*>(
        &bdict_data_[zeroth_entry_offset()]);
  } else {
    child_offset = *reinterpret_cast<const unsigned short*>(
        &bdict_data_[zeroth_entry_offset()]);
    child_offset += node_offset_;
  }

  // Range check the offset;
  if (child_offset >= bdict_length_) {
    is_valid_ = false;
    return FIND_DONE;
  }

  // Now recurse into that child node. We don't advance to the next character
  // here since the 0th element will be a leaf (see ReaderForLookupAt).
  *result = NodeReader(bdict_data_, bdict_length_, child_offset, node_depth_);
  return FIND_NODE;
}

NodeReader::FindResult NodeReader::ReaderForLookupAt(
    size_t index,
    char* found_char,
    NodeReader* result) const {
  const unsigned char* table_begin = &bdict_data_[lookup_table_offset()];

  if (index >= static_cast<size_t>(lookup_num_chars()) || !is_valid_)
    return FIND_DONE;

  size_t child_offset;
  if (is_lookup_32()) {
    // Table contains 32-bit absolute offsets.
    child_offset =
        reinterpret_cast<const unsigned int*>(table_begin)[index];
    if (!child_offset)
      return FIND_NOTHING;  // This entry in the table is empty.
  } else {
    // Table contains 16-bit offsets relative to the current node.
    child_offset =
        reinterpret_cast<const unsigned short*>(table_begin)[index];
    if (!child_offset)
      return FIND_NOTHING;  // This entry in the table is empty.
    child_offset += node_offset_;
  }

  // Range check the offset;
  if (child_offset >= bdict_length_) {
    is_valid_ = false;
    return FIND_DONE;  // Error.
  }

  // This is a bit tricky. When we've just reached the end of a word, the word
  // itself will be stored in a leaf "node" off of this node. That node, of
  // course, will want to know that it's the end of the word and so we have to
  // have it use the same index into the word as we're using at this level.
  //
  // This happens when there is a word in the dictionary that is a strict
  // prefix of other words in the dictionary, and so we'll have a non-leaf
  // node representing the entire word before the ending leaf node.
  //
  // In all other cases, we want to advance to the next character. Even if the
  // child node is a leaf, it will have an additional character that it will
  // want to check.
  *found_char = static_cast<char>(index + lookup_first_char());
  if (!is_valid_)
    return FIND_DONE;
  int char_advance = *found_char == 0 ? 0 : 1;

  *result = NodeReader(bdict_data_, bdict_length_,
                       child_offset, node_depth_ + char_advance);
  return FIND_NODE;
}

int NodeReader::FindInList(
    const unsigned char* word,
    int affix_indices[BDict::MAX_AFFIXES_PER_WORD]) const {
  unsigned char next_char = word[node_depth_];

  // TODO(brettw) replace with binary search.
  size_t list_count = list_item_count();
  const unsigned char* list_begin = &bdict_data_[node_offset_ + 1];

  int bytes_per_index = (is_list_16() ? 3 : 2);

  for (size_t i = 0; i < list_count; i++) {
    const unsigned char* list_current = &list_begin[i * bytes_per_index];
    if (list_current >= bdict_end_) {
      is_valid_ = false;
      return 0;
    }
    if (*list_current == next_char) {
      // Found a match.
      char dummy_char;
      NodeReader child_reader;
      if (ReaderForListAt(i, &dummy_char, &child_reader) != FIND_NODE)
        return 0;
      DCHECK(dummy_char == static_cast<char>(next_char));
      return child_reader.FindWord(word, affix_indices);
    }
  }
  return 0;
}

NodeReader::FindResult NodeReader::ReaderForListAt(
    size_t index,
    char* found_char,
    NodeReader* result) const {
  size_t list_begin = node_offset_ + 1;

  if (index >= list_item_count())
    return FIND_DONE;

  size_t offset;
  if (is_list_16()) {
    const unsigned char* list_item_begin = bdict_data_ + list_begin + index * 3;
    *found_char = static_cast<char>(list_item_begin[0]);

    // The children begin right after the list.
    size_t children_begin = list_begin + list_item_count() * 3;
    offset = children_begin + *reinterpret_cast<const unsigned short*>(
        &list_item_begin[1]);
  } else {
    const unsigned char* list_item_begin = bdict_data_ + list_begin + index * 2;
    *found_char = list_item_begin[0];

    size_t children_begin = list_begin + list_item_count() * 2;
    offset = children_begin + list_item_begin[1];
  }

  if (offset == 0 || node_offset_ >= bdict_length_) {
    is_valid_ = false;
    return FIND_DONE;  // Error, should not happen except for corruption.
  }

  int char_advance = *found_char == 0 ? 0 : 1;  // See ReaderForLookupAt.
  *result = NodeReader(bdict_data_, bdict_length_,
                       offset, node_depth_ + char_advance);
  return FIND_NODE;
}

// WordIterator ----------------------------------------------------------------

struct WordIterator::NodeInfo {
  // The current offset is set to -1 so we start iterating at 0 when Advance
  // is called.
  NodeInfo(const NodeReader& rdr, char add)
      : reader(rdr),
        addition(add),
        cur_offset(-1) {
  }

  // The reader for this node level.
  NodeReader reader;

  // The character that this level represents. For the 0th level, this will
  // be 0 (since it is the root that represents no characters).
  char addition;

  // The current index into the reader that we're reading. Combined with the
  // |stack_|, this allows us to iterate over the tree in depth-first order.
  int cur_offset;
};

WordIterator::WordIterator(const NodeReader& reader) {
  NodeInfo info(reader, 0);
  stack_.push_back(info);
}

WordIterator::WordIterator(const WordIterator& other) {
  operator=(other);
}

WordIterator::~WordIterator() {
  // Can't be in the header for the NodeReader destructor.
}

WordIterator& WordIterator::operator=(const WordIterator& other) {
  stack_ = other.stack_;
  return *this;
}

int WordIterator::Advance(char* output_buffer, size_t output_len,
                          int affix_ids[BDict::MAX_AFFIXES_PER_WORD]) {
  // In-order tree walker. This uses a loop for fake tail recursion.
  while (!stack_.empty()) {
    NodeInfo& cur = stack_.back();
    cur.cur_offset++;
    char cur_char;
    NodeReader child_reader;

    /*if (cur.reader.is_leaf()) {
      child_reader = cur.reader;
      cur_char = cur.addition;
      stack_.pop_back();
      return FoundLeaf(child_reader, cur_char, output_buffer, output_len,
                       affix_ids);
    }*/

    switch (cur.reader.GetChildAt(cur.cur_offset, &cur_char, &child_reader)) {
      case NodeReader::FIND_NODE:
        // Got a valid child node.
        if (child_reader.is_leaf()) {
          return FoundLeaf(child_reader, cur_char, output_buffer, output_len,
                           affix_ids);
        }

        // Not a leaf. Add the new node to our stack and try again.
        stack_.push_back(NodeInfo(child_reader, cur_char));
        break;

      case NodeReader::FIND_NOTHING:
        // This one is empty, but we're not done. Continue on.
        break;

      case NodeReader::FIND_DONE:
        // No more children at this level, pop the stack and go back one.
        stack_.pop_back();
    }
  }

  return false;
}

int WordIterator::FoundLeaf(const NodeReader& reader, char cur_char,
                            char* output_buffer, size_t output_len,
                            int affix_ids[BDict::MAX_AFFIXES_PER_WORD]) {
  // Remember that the first item in the stack is the root and so doesn't count.
  int i;
  for (i = 0; i < static_cast<int>(stack_.size()) - 1 && i < static_cast<int>(output_len) - 1; i++)
    output_buffer[i] = stack_[i + 1].addition;
  output_buffer[i++] = cur_char;  // The one we just found.

  // Possibly add any extra parts.
  size_t additional_string_length = 0;
  const char* additional = reinterpret_cast<const char*>(
      reader.additional_string_for_leaf());
  for (; i < static_cast<int>(output_len) - 1 && additional &&
           additional[additional_string_length] != 0;
       i++, additional_string_length++)
    output_buffer[i] = additional[additional_string_length];
  if (additional_string_length)
    additional_string_length++;  // Account for the null terminator.
  output_buffer[i] = 0;

  return reader.FillAffixesForLeafMatch(additional_string_length,
                                        affix_ids);
}

// LineIterator ----------------------------------------------------------------

LineIterator::LineIterator(
    const unsigned char* bdict_data,
    size_t bdict_length,
    size_t first_offset)
    : bdict_data_(bdict_data),
      bdict_length_(bdict_length),
      cur_offset_(first_offset) {
}

// Returns true when all data has been read. We're done when we reach a
// double-NULL or a the end of the input (shouldn't happen).
bool LineIterator::IsDone() const {
  return cur_offset_ >= bdict_length_ || bdict_data_[cur_offset_] == 0;
}

const char* LineIterator::Advance() {
  if (IsDone())
    return NULL;

  const char* begin = reinterpret_cast<const char*>(&bdict_data_[cur_offset_]);

  // Advance over this word to find the end.
  while (cur_offset_ < bdict_length_ && bdict_data_[cur_offset_])
    cur_offset_++;
  cur_offset_++;  // Advance over the NULL terminator.

  return begin;
}

bool LineIterator::AdvanceAndCopy(char* buf, size_t buf_len) {
  if (IsDone())
    return false;

  const char* begin = reinterpret_cast<const char*>(&bdict_data_[cur_offset_]);

  // Advance over this word to find the end.
  size_t i;
  for (i = 0;
       i < buf_len && cur_offset_ < bdict_length_ && bdict_data_[cur_offset_];
       i++, cur_offset_++) {
    buf[i] = bdict_data_[cur_offset_];
  }
  // Handle the NULL terminator.
  cur_offset_++;  // Consume in the input
  if (i < buf_len)
    buf[i] = 0;  // Save in the output.
  else
    buf[buf_len - 1] = 0;  // Overflow, make sure it's terminated.

  return !!buf[0];
}

// ReplacementIterator ---------------------------------------------------------

// Fills pointers to NULL terminated strings into the given output params.
// Returns false if there are no more pairs and nothing was filled in.
bool ReplacementIterator::GetNext(const char** first, const char** second) {
  if (IsDone())
    return false;
  *first = Advance();
  *second = Advance();
  return *first && *second;
}

// BDictReader -----------------------------------------------------------------

BDictReader::BDictReader()
    : bdict_data_(NULL),
      bdict_length_(0),
      header_(NULL) {
}

bool BDictReader::Init(const unsigned char* bdict_data, size_t bdict_length) {
  if (bdict_length < sizeof(BDict::Header))
    return false;

  // Check header.
  header_ = reinterpret_cast<const BDict::Header*>(bdict_data);
  if (header_->signature != BDict::SIGNATURE ||
      header_->major_version > BDict::MAJOR_VERSION ||
      header_->dic_offset > bdict_length)
    return false;

  // Get the affix header, make sure there is enough room for it.
  if (header_->aff_offset + sizeof(BDict::AffHeader) > bdict_length)
    return false;
  aff_header_ = reinterpret_cast<const BDict::AffHeader*>(
      &bdict_data[header_->aff_offset]);

  // Make sure there is enough room for the affix group count dword.
  if (aff_header_->affix_group_offset > bdict_length - sizeof(uint32_t))
    return false;

  // This function is called from SpellCheck::SpellCheckWord(), which blocks
  // WebKit. To avoid blocking WebKit for a long time, we do not check the MD5
  // digest here. Instead we check the MD5 digest when Chrome finishes
  // downloading a dictionary.

  // Don't set these until the end. This way, NULL bdict_data_ will indicate
  // failure.
  bdict_data_ = bdict_data;
  bdict_length_ = bdict_length;
  return true;
}

int BDictReader::FindWord(
    const char* word,
    int affix_indices[BDict::MAX_AFFIXES_PER_WORD]) const {
  if (!bdict_data_ ||
      header_->dic_offset >= bdict_length_) {
    // When the dictionary is corrupt, we return 0 which means the word is valid
    // and has no rules. This means when there is some problem, we'll default
    // to no spellchecking rather than marking everything as misspelled.
    return 0;
  }
  NodeReader reader(bdict_data_, bdict_length_, header_->dic_offset, 0);
  return reader.FindWord(reinterpret_cast<const unsigned char*>(word),
                         affix_indices);
}

LineIterator BDictReader::GetAfLineIterator() const {
  if (!bdict_data_ ||
      aff_header_->affix_group_offset == 0 ||
      aff_header_->affix_group_offset >= bdict_length_)
    return LineIterator(bdict_data_, 0, 0);  // Item is empty or invalid.
  return LineIterator(bdict_data_, bdict_length_,
                      aff_header_->affix_group_offset);
}

LineIterator BDictReader::GetAffixLineIterator() const {
  if (!bdict_data_ ||
      aff_header_->affix_rule_offset == 0 ||
      aff_header_->affix_rule_offset >= bdict_length_)
    return LineIterator(bdict_data_, 0, 0);  // Item is empty or invalid.
  return LineIterator(bdict_data_, bdict_length_,
                      aff_header_->affix_rule_offset);
}

LineIterator BDictReader::GetOtherLineIterator() const {
  if (!bdict_data_ ||
      aff_header_->other_offset == 0 ||
      aff_header_->other_offset >= bdict_length_)
    return LineIterator(bdict_data_, 0, 0);  // Item is empty or invalid.
  return LineIterator(bdict_data_, bdict_length_,
                      aff_header_->other_offset);
}

ReplacementIterator BDictReader::GetReplacementIterator() const {
  if (!bdict_data_ ||
      aff_header_->rep_offset == 0 ||
      aff_header_->rep_offset >= bdict_length_)
    return ReplacementIterator(bdict_data_, 0, 0);  // Item is empty or invalid.
  return ReplacementIterator(bdict_data_, bdict_length_,
                             aff_header_->rep_offset);
}


WordIterator BDictReader::GetAllWordIterator() const {
  NodeReader reader(bdict_data_, bdict_length_, header_->dic_offset, 0);
  return WordIterator(reader);
}

}  // namespace hunspell
