普通文本  |  382行  |  10.96 KB

#include "trie.h"

extern "C" {

namespace {

class FindCallback {
 public:
  typedef int (*Func)(void *, marisa_alpha_uint32, size_t);

  FindCallback(Func func, void *first_arg)
      : func_(func), first_arg_(first_arg) {}
  FindCallback(const FindCallback &callback)
      : func_(callback.func_), first_arg_(callback.first_arg_) {}

  bool operator()(marisa_alpha::UInt32 key_id, std::size_t key_length) const {
    return func_(first_arg_, key_id, key_length) != 0;
  }

 private:
  Func func_;
  void *first_arg_;

  // Disallows assignment.
  FindCallback &operator=(const FindCallback &);
};

class PredictCallback {
 public:
  typedef int (*Func)(void *, marisa_alpha_uint32, const char *, size_t);

  PredictCallback(Func func, void *first_arg)
      : func_(func), first_arg_(first_arg) {}
  PredictCallback(const PredictCallback &callback)
      : func_(callback.func_), first_arg_(callback.first_arg_) {}

  bool operator()(marisa_alpha::UInt32 key_id, const std::string &key) const {
    return func_(first_arg_, key_id, key.c_str(), key.length()) != 0;
  }

 private:
  Func func_;
  void *first_arg_;

  // Disallows assignment.
  PredictCallback &operator=(const PredictCallback &);
};

}  // namespace

struct marisa_alpha_trie_ {
 public:
  marisa_alpha_trie_() : trie(), mapper() {}

  marisa_alpha::Trie trie;
  marisa_alpha::Mapper mapper;

 private:
  // Disallows copy and assignment.
  marisa_alpha_trie_(const marisa_alpha_trie_ &);
  marisa_alpha_trie_ &operator=(const marisa_alpha_trie_ &);
};

marisa_alpha_status marisa_alpha_init(marisa_alpha_trie **h) {
  if ((h == NULL) || (*h != NULL)) {
    return MARISA_ALPHA_HANDLE_ERROR;
  }
  *h = new (std::nothrow) marisa_alpha_trie_();
  return (*h != NULL) ? MARISA_ALPHA_OK : MARISA_ALPHA_MEMORY_ERROR;
}

marisa_alpha_status marisa_alpha_end(marisa_alpha_trie *h) {
  if (h == NULL) {
    return MARISA_ALPHA_HANDLE_ERROR;
  }
  delete h;
  return MARISA_ALPHA_OK;
}

marisa_alpha_status marisa_alpha_build(marisa_alpha_trie *h,
    const char * const *keys, size_t num_keys, const size_t *key_lengths,
    const double *key_weights, marisa_alpha_uint32 *key_ids, int flags) try {
  if (h == NULL) {
    return MARISA_ALPHA_HANDLE_ERROR;
  }
  h->trie.build(keys, num_keys, key_lengths, key_weights, key_ids, flags);
  h->mapper.clear();
  return MARISA_ALPHA_OK;
} catch (const marisa_alpha::Exception &ex) {
  return ex.status();
}

marisa_alpha_status marisa_alpha_mmap(marisa_alpha_trie *h,
    const char *filename, long offset, int whence) try {
  if (h == NULL) {
    return MARISA_ALPHA_HANDLE_ERROR;
  }
  h->trie.mmap(&h->mapper, filename, offset, whence);
  return MARISA_ALPHA_OK;
} catch (const marisa_alpha::Exception &ex) {
  return ex.status();
}

marisa_alpha_status marisa_alpha_map(marisa_alpha_trie *h, const void *ptr,
    size_t size) try {
  if (h == NULL) {
    return MARISA_ALPHA_HANDLE_ERROR;
  }
  h->trie.map(ptr, size);
  h->mapper.clear();
  return MARISA_ALPHA_OK;
} catch (const marisa_alpha::Exception &ex) {
  return ex.status();
}

marisa_alpha_status marisa_alpha_load(marisa_alpha_trie *h,
    const char *filename, long offset, int whence) try {
  if (h == NULL) {
    return MARISA_ALPHA_HANDLE_ERROR;
  }
  h->trie.load(filename, offset, whence);
  h->mapper.clear();
  return MARISA_ALPHA_OK;
} catch (const marisa_alpha::Exception &ex) {
  return ex.status();
}

marisa_alpha_status marisa_alpha_fread(marisa_alpha_trie *h, FILE *file) try {
  if (h == NULL) {
    return MARISA_ALPHA_HANDLE_ERROR;
  }
  h->trie.fread(file);
  h->mapper.clear();
  return MARISA_ALPHA_OK;
} catch (const marisa_alpha::Exception &ex) {
  return ex.status();
}

marisa_alpha_status marisa_alpha_read(marisa_alpha_trie *h, int fd) try {
  if (h == NULL) {
    return MARISA_ALPHA_HANDLE_ERROR;
  }
  h->trie.read(fd);
  h->mapper.clear();
  return MARISA_ALPHA_OK;
} catch (const marisa_alpha::Exception &ex) {
  return ex.status();
}

marisa_alpha_status marisa_alpha_save(const marisa_alpha_trie *h,
    const char *filename, int trunc_flag, long offset, int whence) try {
  if (h == NULL) {
    return MARISA_ALPHA_HANDLE_ERROR;
  }
  h->trie.save(filename, trunc_flag != 0, offset, whence);
  return MARISA_ALPHA_OK;
} catch (const marisa_alpha::Exception &ex) {
  return ex.status();
}

marisa_alpha_status marisa_alpha_fwrite(const marisa_alpha_trie *h,
    FILE *file) try {
  if (h == NULL) {
    return MARISA_ALPHA_HANDLE_ERROR;
  }
  h->trie.fwrite(file);
  return MARISA_ALPHA_OK;
} catch (const marisa_alpha::Exception &ex) {
  return ex.status();
}

marisa_alpha_status marisa_alpha_write(const marisa_alpha_trie *h, int fd) try {
  if (h == NULL) {
    return MARISA_ALPHA_HANDLE_ERROR;
  }
  h->trie.write(fd);
  return MARISA_ALPHA_OK;
} catch (const marisa_alpha::Exception &ex) {
  return ex.status();
}

marisa_alpha_status marisa_alpha_restore(const marisa_alpha_trie *h,
    marisa_alpha_uint32 key_id, char *key_buf, size_t key_buf_size,
    size_t *key_length) try {
  if (h == NULL) {
    return MARISA_ALPHA_HANDLE_ERROR;
  } else if (key_length == NULL) {
    return MARISA_ALPHA_PARAM_ERROR;
  }
  *key_length = h->trie.restore(key_id, key_buf, key_buf_size);
  return MARISA_ALPHA_OK;
} catch (const marisa_alpha::Exception &ex) {
  return ex.status();
}

marisa_alpha_status marisa_alpha_lookup(const marisa_alpha_trie *h,
    const char *ptr, size_t length, marisa_alpha_uint32 *key_id) try {
  if (h == NULL) {
    return MARISA_ALPHA_HANDLE_ERROR;
  } else if (key_id == NULL) {
    return MARISA_ALPHA_PARAM_ERROR;
  }
  if (length == MARISA_ALPHA_ZERO_TERMINATED) {
    *key_id = h->trie.lookup(ptr);
  } else {
    *key_id = h->trie.lookup(ptr, length);
  }
  return MARISA_ALPHA_OK;
} catch (const marisa_alpha::Exception &ex) {
  return ex.status();
}

marisa_alpha_status marisa_alpha_find(const marisa_alpha_trie *h,
    const char *ptr, size_t length,
    marisa_alpha_uint32 *key_ids, size_t *key_lengths,
    size_t max_num_results, size_t *num_results) try {
  if (h == NULL) {
    return MARISA_ALPHA_HANDLE_ERROR;
  } else if (num_results == NULL) {
    return MARISA_ALPHA_PARAM_ERROR;
  }
  if (length == MARISA_ALPHA_ZERO_TERMINATED) {
    *num_results = h->trie.find(ptr, key_ids, key_lengths, max_num_results);
  } else {
    *num_results = h->trie.find(ptr, length,
        key_ids, key_lengths, max_num_results);
  }
  return MARISA_ALPHA_OK;
} catch (const marisa_alpha::Exception &ex) {
  return ex.status();
}

marisa_alpha_status marisa_alpha_find_first(const marisa_alpha_trie *h,
    const char *ptr, size_t length,
    marisa_alpha_uint32 *key_id, size_t *key_length) {
  if (h == NULL) {
    return MARISA_ALPHA_HANDLE_ERROR;
  } else if (key_id == NULL) {
    return MARISA_ALPHA_PARAM_ERROR;
  }
  if (length == MARISA_ALPHA_ZERO_TERMINATED) {
    *key_id = h->trie.find_first(ptr, key_length);
  } else {
    *key_id = h->trie.find_first(ptr, length, key_length);
  }
  return MARISA_ALPHA_OK;
}

marisa_alpha_status marisa_alpha_find_last(const marisa_alpha_trie *h,
    const char *ptr, size_t length,
    marisa_alpha_uint32 *key_id, size_t *key_length) {
  if (h == NULL) {
    return MARISA_ALPHA_HANDLE_ERROR;
  } else if (key_id == NULL) {
    return MARISA_ALPHA_PARAM_ERROR;
  }
  if (length == MARISA_ALPHA_ZERO_TERMINATED) {
    *key_id = h->trie.find_last(ptr, key_length);
  } else {
    *key_id = h->trie.find_last(ptr, length, key_length);
  }
  return MARISA_ALPHA_OK;
}

marisa_alpha_status marisa_alpha_find_callback(const marisa_alpha_trie *h,
    const char *ptr, size_t length,
    int (*callback)(void *, marisa_alpha_uint32, size_t),
    void *first_arg_to_callback) try {
  if (h == NULL) {
    return MARISA_ALPHA_HANDLE_ERROR;
  } else if (callback == NULL) {
    return MARISA_ALPHA_PARAM_ERROR;
  }
  if (length == MARISA_ALPHA_ZERO_TERMINATED) {
    h->trie.find_callback(ptr,
        ::FindCallback(callback, first_arg_to_callback));
  } else {
    h->trie.find_callback(ptr, length,
        ::FindCallback(callback, first_arg_to_callback));
  }
  return MARISA_ALPHA_OK;
} catch (const marisa_alpha::Exception &ex) {
  return ex.status();
}

marisa_alpha_status marisa_alpha_predict(const marisa_alpha_trie *h,
    const char *ptr, size_t length, marisa_alpha_uint32 *key_ids,
    size_t max_num_results, size_t *num_results) {
  return marisa_alpha_predict_breadth_first(h, ptr, length,
      key_ids, max_num_results, num_results);
}

marisa_alpha_status marisa_alpha_predict_breadth_first(
    const marisa_alpha_trie *h, const char *ptr, size_t length,
    marisa_alpha_uint32 *key_ids, size_t max_num_results,
    size_t *num_results) try {
  if (h == NULL) {
    return MARISA_ALPHA_HANDLE_ERROR;
  } else if (num_results == NULL) {
    return MARISA_ALPHA_PARAM_ERROR;
  }
  if (length == MARISA_ALPHA_ZERO_TERMINATED) {
    *num_results = h->trie.predict_breadth_first(
        ptr, key_ids, NULL, max_num_results);
  } else {
    *num_results = h->trie.predict_breadth_first(
        ptr, length, key_ids, NULL, max_num_results);
  }
  return MARISA_ALPHA_OK;
} catch (const marisa_alpha::Exception &ex) {
  return ex.status();
}

marisa_alpha_status marisa_alpha_predict_depth_first(
    const marisa_alpha_trie *h, const char *ptr, size_t length,
    marisa_alpha_uint32 *key_ids, size_t max_num_results,
    size_t *num_results) try {
  if (h == NULL) {
    return MARISA_ALPHA_HANDLE_ERROR;
  } else if (num_results == NULL) {
    return MARISA_ALPHA_PARAM_ERROR;
  }
  if (length == MARISA_ALPHA_ZERO_TERMINATED) {
    *num_results = h->trie.predict_depth_first(
        ptr, key_ids, NULL, max_num_results);
  } else {
    *num_results = h->trie.predict_depth_first(
        ptr, length, key_ids, NULL, max_num_results);
  }
  return MARISA_ALPHA_OK;
} catch (const marisa_alpha::Exception &ex) {
  return ex.status();
}

marisa_alpha_status marisa_alpha_predict_callback(const marisa_alpha_trie *h,
    const char *ptr, size_t length,
    int (*callback)(void *, marisa_alpha_uint32, const char *, size_t),
    void *first_arg_to_callback) try {
  if (h == NULL) {
    return MARISA_ALPHA_HANDLE_ERROR;
  } else if (callback == NULL) {
    return MARISA_ALPHA_PARAM_ERROR;
  }
  if (length == MARISA_ALPHA_ZERO_TERMINATED) {
    h->trie.predict_callback(ptr,
        ::PredictCallback(callback, first_arg_to_callback));
  } else {
    h->trie.predict_callback(ptr, length,
        ::PredictCallback(callback, first_arg_to_callback));
  }
  return MARISA_ALPHA_OK;
} catch (const marisa_alpha::Exception &ex) {
  return ex.status();
}

size_t marisa_alpha_get_num_tries(const marisa_alpha_trie *h) {
  return (h != NULL) ? h->trie.num_tries() : 0;
}

size_t marisa_alpha_get_num_keys(const marisa_alpha_trie *h) {
  return (h != NULL) ? h->trie.num_keys() : 0;
}

size_t marisa_alpha_get_num_nodes(const marisa_alpha_trie *h) {
  return (h != NULL) ? h->trie.num_nodes() : 0;
}

size_t marisa_alpha_get_total_size(const marisa_alpha_trie *h) {
  return (h != NULL) ? h->trie.total_size() : 0;
}

marisa_alpha_status marisa_alpha_clear(marisa_alpha_trie *h) {
  if (h == NULL) {
    return MARISA_ALPHA_HANDLE_ERROR;
  }
  h->trie.clear();
  h->mapper.clear();
  return MARISA_ALPHA_OK;
}

}  // extern "C"