Added: incubator/lucene4c/trunk/src/search/scorer.c URL: http://svn.apache.org/viewcvs/incubator/lucene4c/trunk/src/search/scorer.c?view=auto&rev=155552 ============================================================================== --- incubator/lucene4c/trunk/src/search/scorer.c (added) +++ incubator/lucene4c/trunk/src/search/scorer.c Sat Feb 26 08:47:57 2005 @@ -0,0 +1,201 @@ +/* Copyright 2004-2005 Garrett Rooney + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "lcn_scorer.h" +#include "lcn_query.h" + +typedef lcn_error_t * (*scorer_next_internal_t) (lcn_scorer_t *scorer); + +struct lcn_scorer_t { + apr_uint32_t doc; + float score; + + scorer_next_internal_t next_internal; + + void *baton; +}; + +static lcn_error_t * +term_scorer_next_internal (lcn_scorer_t *scorer) +{ + lcn_doc_iter_t *iter = scorer->baton; + + LCN_ERR (lcn_doc_iter_next (iter)); + + scorer->doc = lcn_doc_iter_doc (iter); + + scorer->score = 1.0; /* XXX */ + + return LCN_NO_ERROR; +} + +lcn_error_t * +lcn_term_scorer_create (lcn_scorer_t **scorer, + lcn_doc_iter_t *iter, + apr_pool_t *pool) +{ + *scorer = apr_pcalloc (pool, sizeof (**scorer)); + + (*scorer)->baton = iter; + + (*scorer)->next_internal = term_scorer_next_internal; + + (*scorer)->doc = lcn_doc_iter_doc (iter); + + (*scorer)->score = 1.0; /* XXX */ + + return LCN_NO_ERROR; +} + +typedef struct { + apr_array_header_t *must; + apr_array_header_t *should; + apr_array_header_t *must_not; +} boolean_scorer_baton_t; + +static lcn_error_t * +boolean_scorer_find_doc (apr_uint32_t *doc, boolean_scorer_baton_t *bsb) +{ + if (bsb->should->nelts) + return lcn_error_create (APR_ENOTIMPL, NULL, "should isn't implemented"); + if (bsb->must_not->nelts) + return lcn_error_create (APR_ENOTIMPL, NULL, "must_not isn't implemented"); + + for (;;) + { + int i; + + *doc = lcn_scorer_doc (APR_ARRAY_IDX (bsb->must, 0, lcn_scorer_t *)); + + /* XXX make sure that calling lcn_scorer_next isn't making us bail + * without checking the final doc in the scorer... */ + + LCN_ERR (lcn_scorer_next (APR_ARRAY_IDX (bsb->must, 0, lcn_scorer_t *))); + + for (i = 1; i < bsb->must->nelts; ++i) + { + apr_uint32_t otherdoc + = lcn_scorer_doc (APR_ARRAY_IDX (bsb->must, i, lcn_scorer_t *)); + + while (otherdoc < *doc) + { + LCN_ERR (lcn_scorer_next (APR_ARRAY_IDX (bsb->must, + i, + lcn_scorer_t *))); + + otherdoc + = lcn_scorer_doc (APR_ARRAY_IDX (bsb->must, + i, + lcn_scorer_t *)); + } + + if (otherdoc != *doc) + break; + } + + if (i == bsb->must->nelts) + return LCN_NO_ERROR; + } +} + +static lcn_error_t * +boolean_scorer_next_internal (lcn_scorer_t *scorer) +{ + boolean_scorer_baton_t *bsb = scorer->baton; + + LCN_ERR (boolean_scorer_find_doc (&scorer->doc, bsb)); + + scorer->score = 1.0; /* XXX */ + + return LCN_NO_ERROR; +} + +static lcn_error_t * +fill_scorers_array (apr_array_header_t *query_array, + apr_array_header_t *scorer_array, + lcn_index_t *index, + apr_pool_t *pool) +{ + int i; + + for (i = 0; i < query_array->nelts; ++i) + { + lcn_scorer_t *scorer; + + LCN_ERR (lcn_query_scorer (&scorer, + APR_ARRAY_IDX (query_array, i, lcn_query_t *), + index, + pool)); + + /* XXX it is unclear why using APR_ARRAY_PUSH doesn't work... */ +#ifdef FIGUREMEOUT + APR_ARRAY_PUSH (scorer_array, lcn_scorer_t *) = scorer; +#else + APR_ARRAY_IDX (scorer_array, i, lcn_scorer_t *) = scorer; + scorer_array->nelts = i + 1; +#endif + } + + return LCN_NO_ERROR; +} + +lcn_error_t * +lcn_boolean_scorer_create (lcn_scorer_t **scorer, + apr_array_header_t *must, + apr_array_header_t *should, + apr_array_header_t *must_not, + lcn_index_t *index, + apr_pool_t *pool) +{ + boolean_scorer_baton_t *bsb = apr_pcalloc (pool, sizeof (*bsb)); + + *scorer = apr_pcalloc (pool, sizeof (lcn_scorer_t)); + + (*scorer)->baton = bsb; + + bsb->must = apr_array_make (pool, + must->nelts, + sizeof (lcn_scorer_t)); + + LCN_ERR (fill_scorers_array (must, bsb->must, index, pool)); + + bsb->should = apr_array_make (pool, + should->nelts, + sizeof (lcn_scorer_t)); + + LCN_ERR (fill_scorers_array (should, bsb->should, index, pool)); + + bsb->must_not = apr_array_make (pool, + must_not->nelts, + sizeof (lcn_scorer_t)); + + LCN_ERR (fill_scorers_array (must_not, bsb->must_not, index, pool)); + + (*scorer)->next_internal = boolean_scorer_next_internal; + + LCN_ERR (boolean_scorer_find_doc (&(*scorer)->doc, bsb)); + + (*scorer)->score = 1.0; /* XXX */ + + return LCN_NO_ERROR; +} + +apr_uint32_t lcn_scorer_doc (lcn_scorer_t *scorer) { return scorer->doc; } + +lcn_error_t * +lcn_scorer_next (lcn_scorer_t *scorer) +{ + return scorer->next_internal (scorer); +}
Propchange: incubator/lucene4c/trunk/src/store/ ------------------------------------------------------------------------------ --- svn:ignore (added) +++ svn:ignore Sat Feb 26 08:47:57 2005 @@ -0,0 +1,2 @@ +.deps +.dirstamp Added: incubator/lucene4c/trunk/src/store/directory.c URL: http://svn.apache.org/viewcvs/incubator/lucene4c/trunk/src/store/directory.c?view=auto&rev=155552 ============================================================================== --- incubator/lucene4c/trunk/src/store/directory.c (added) +++ incubator/lucene4c/trunk/src/store/directory.c Sat Feb 26 08:47:57 2005 @@ -0,0 +1,789 @@ +/* Copyright 2005 Garrett Rooney + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "lcn_directory.h" + +#include <apr_strings.h> +#include <apr_file_info.h> + +typedef lcn_error_t * (*dir_list_internal_t) (apr_array_header_t **contents, + const lcn_directory_t *dir, + apr_pool_t *pool); + +typedef lcn_error_t * (*dir_file_exists_internal_t) (lcn_boolean_t *result, + const lcn_directory_t *dir, + const char *name, + apr_pool_t *pool); + +typedef lcn_error_t * (*dir_file_modified_internal_t) (apr_time_t *result, + const lcn_directory_t *d, + const char *name, + apr_pool_t *pool); + +typedef lcn_error_t * (*dir_touch_file_internal_t) (lcn_directory_t *d, + const char *name, + apr_pool_t *pool); + +typedef lcn_error_t * (*dir_delete_file_internal_t) (lcn_directory_t *d, + const char *name, + apr_pool_t *pool); + +typedef lcn_error_t * (*dir_rename_file_internal_t) (lcn_directory_t *d, + const char *from, + const char *to, + apr_pool_t *pool); + +typedef lcn_error_t * (*dir_open_file_internal_t) (lcn_istream_t **is, + const lcn_directory_t *d, + const char *name, + apr_pool_t *pool); + +typedef lcn_error_t * (*dir_close_internal_t) (lcn_directory_t *d, + apr_pool_t *pool); + +struct lcn_directory_t { + dir_list_internal_t list_internal; + dir_file_exists_internal_t file_exists_internal; + dir_file_modified_internal_t file_modified_internal; + dir_touch_file_internal_t touch_file_internal; + dir_delete_file_internal_t delete_file_internal; + dir_rename_file_internal_t rename_file_internal; + dir_open_file_internal_t open_file_internal; + dir_close_internal_t close_internal; + + void *baton; +}; + +static lcn_error_t * +ram_list_internal (apr_array_header_t **contents, + const lcn_directory_t *d, + apr_pool_t *pool) +{ + apr_hash_t *h = d->baton; + apr_hash_index_t *hi; + + apr_array_header_t *c = apr_array_make (pool, + apr_hash_count (h), + sizeof (char *)); + + for (hi = apr_hash_first (pool, h); hi; hi = apr_hash_next (hi)) + { + const void *key; + + apr_hash_this (hi, &key, NULL, NULL); + + APR_ARRAY_PUSH (c, char *) = apr_pstrdup (pool, key); + } + + *contents = c; + + return LCN_NO_ERROR; +} + +static lcn_error_t * +ram_file_exists_internal (lcn_boolean_t *result, + const lcn_directory_t *d, + const char *name, + apr_pool_t *pool) +{ + apr_hash_t *h = d->baton; + + *result = (apr_hash_get (h, name, APR_HASH_KEY_STRING) != NULL); + + return LCN_NO_ERROR; +} + +static lcn_error_t * +ram_file_modified_internal (apr_time_t *result, + const lcn_directory_t *d, + const char *name, + apr_pool_t *pool) +{ + apr_hash_t *h = d->baton; + + lcn_directory_entry_t *ent = apr_hash_get (h, name, APR_HASH_KEY_STRING); + + if (ent == NULL) + return lcn_error_createf (APR_ENOENT, + NULL, + "file '%s' doesn't exist", + name); + + *result = ent->mtime; + + return LCN_NO_ERROR; +} + +static lcn_error_t * +ram_touch_file_internal (lcn_directory_t *d, + const char *name, + apr_pool_t *pool) +{ + apr_hash_t *h = d->baton; + + lcn_directory_entry_t *ent = apr_hash_get (h, name, APR_HASH_KEY_STRING); + + if (ent == NULL) + return lcn_error_createf (APR_ENOENT, + NULL, + "file '%s' doesn't exist", + name); + + ent->mtime = apr_time_now (); + + return LCN_NO_ERROR; +} + +static lcn_error_t * +ram_delete_file_internal (lcn_directory_t *d, + const char *name, + apr_pool_t *pool) +{ + apr_hash_t *h = d->baton; + + apr_hash_set (h, name, APR_HASH_KEY_STRING, NULL); + + return LCN_NO_ERROR; +} + +static lcn_error_t * +ram_rename_file_internal (lcn_directory_t *d, + const char *from, + const char *to, + apr_pool_t *pool) +{ + apr_hash_t *h = d->baton; + + lcn_directory_entry_t *ent = apr_hash_get (h, from, APR_HASH_KEY_STRING); + + if (ent == NULL) + return lcn_error_createf (APR_ENOENT, + NULL, + "file '%s' doesn't exist", + from); + + apr_hash_set (h, from, APR_HASH_KEY_STRING, NULL); + + /* XXX should we check to see if the destination exists already? */ + + apr_hash_set (h, to, APR_HASH_KEY_STRING, ent); + + return LCN_NO_ERROR; +} + +static lcn_error_t * +ram_open_file_internal (lcn_istream_t **result, + const lcn_directory_t *d, + const char *name, + apr_pool_t *pool) +{ + apr_hash_t *h = d->baton; + + lcn_directory_entry_t *ent = apr_hash_get (h, name, APR_HASH_KEY_STRING); + + if (ent == NULL) + return lcn_error_createf (APR_ENOENT, + NULL, + "file '%s' doesn't exist", + name); + + *result = lcn_ram_istream_create (ent->bytes, ent->len, pool); + + return LCN_NO_ERROR; +} + +static lcn_error_t * +ram_close_internal (lcn_directory_t *d, apr_pool_t *pool) +{ + d->baton = NULL; + + return LCN_NO_ERROR; +} + +lcn_error_t * +lcn_ram_directory_open (lcn_directory_t **dir, + apr_hash_t *contents, + apr_pool_t *pool) +{ + lcn_directory_t *d = apr_pcalloc (pool, sizeof (*d)); + + d->list_internal = ram_list_internal; + d->file_exists_internal = ram_file_exists_internal; + d->file_modified_internal = ram_file_modified_internal; + d->touch_file_internal = ram_touch_file_internal; + d->delete_file_internal = ram_delete_file_internal; + d->rename_file_internal = ram_rename_file_internal; + d->open_file_internal = ram_open_file_internal; + d->close_internal = ram_close_internal; + + d->baton = apr_hash_make (pool); + + /* if we were given a hash dirents we need to copy them into the new hash, + * otherwise they might go out of scope when the pool they were allocated + * in goes away. */ + if (contents) + { + apr_hash_index_t *hi; + + for (hi = apr_hash_first (pool, contents); hi; hi = apr_hash_next (hi)) + { + lcn_directory_entry_t *ent; + apr_ssize_t keylen; + const void *key; + void *val; + + apr_hash_this (hi, &key, &keylen, &val); + + ent = apr_pmemdup (pool, val, sizeof (*ent)); + + /* XXX it's unfortunate that we're copying all this data around, + * but it's the only way to be safe with pools... eventually when + * we're actually creating these things for the purpose of writing + * out indices we'll need a more efficient way of handling this + * problem. */ + ent->bytes = apr_pmemdup (pool, + ((lcn_directory_entry_t *) val)->bytes, + ((lcn_directory_entry_t *) val)->len); + + apr_hash_set (d->baton, + apr_pmemdup (pool, key, keylen), + keylen, + ent); + } + } + + *dir = d; + + return LCN_NO_ERROR; +} + +typedef struct { + const char *path; + apr_dir_t *dir; +} fs_dir_baton_t; + +static lcn_error_t * +fs_list_internal (apr_array_header_t **contents, + const lcn_directory_t *d, + apr_pool_t *pool) +{ + fs_dir_baton_t *db = d->baton; + apr_status_t apr_err; + apr_finfo_t finfo; + + apr_array_header_t *c = apr_array_make (pool, 10, sizeof (char *)); + + apr_err = apr_dir_rewind (db->dir); + if (apr_err) + return lcn_error_createf (apr_err, + NULL, + "error rewinding dir '%s'", + db->path); + + for (apr_err = apr_dir_read (&finfo, APR_FINFO_NAME, db->dir); + apr_err == APR_SUCCESS; + apr_err = apr_dir_read (&finfo, APR_FINFO_NAME, db->dir)) + { + APR_ARRAY_PUSH(c, const char *) = apr_pstrdup (pool, finfo.name); + } + + if (! APR_STATUS_IS_ENOENT (apr_err)) + return lcn_error_createf (apr_err, + NULL, + "error reading from dir '%s'", + db->path); + + *contents = c; + + return LCN_NO_ERROR; +} + +static lcn_error_t * +fs_file_exists_internal (lcn_boolean_t *result, + const lcn_directory_t *d, + const char *name, + apr_pool_t *pool) +{ + fs_dir_baton_t *db = d->baton; + apr_finfo_t finfo; + + const char *full_path = apr_psprintf (pool, "%s/%s", db->path, name); + + apr_status_t apr_err = apr_stat (&finfo, full_path, APR_FINFO_MIN, pool); + if (apr_err) + { + *result = FALSE; + + if (apr_err != APR_ENOENT) + return lcn_error_createf (apr_err, + NULL, + "error stating file '%s'", + full_path); + } + else + { + *result = TRUE; + } + + return LCN_NO_ERROR; +} + +static lcn_error_t * +fs_file_modified_internal (apr_time_t *result, + const lcn_directory_t *d, + const char *name, + apr_pool_t *pool) +{ + fs_dir_baton_t *db = d->baton; + apr_finfo_t finfo; + + const char *full_path = apr_psprintf (pool, "%s/%s", db->path, name); + + apr_status_t apr_err = apr_stat (&finfo, full_path, APR_FINFO_MIN, pool); + if (apr_err) + { + return lcn_error_createf (apr_err, + NULL, + "error stating file '%s'", + full_path); + } + else + { + *result = finfo.mtime; + } + + + return LCN_NO_ERROR; +} + +static lcn_error_t * +fs_touch_file_internal (lcn_directory_t *d, + const char *name, + apr_pool_t *pool) +{ + fs_dir_baton_t *db = d->baton; + + const char *full_path = apr_psprintf (pool, "%s/%s", db->path, name); + + apr_status_t apr_err = apr_file_mtime_set (full_path, apr_time_now (), pool); + if (apr_err) + return lcn_error_createf (apr_err, + NULL, + "error updating mtime on '%s'", + full_path); + return LCN_NO_ERROR; +} + +static lcn_error_t * +fs_delete_file_internal (lcn_directory_t *d, + const char *name, + apr_pool_t *pool) +{ + fs_dir_baton_t *db = d->baton; + + const char *full_path = apr_psprintf (pool, "%s/%s", db->path, name); + + apr_status_t apr_err = apr_file_remove (full_path, pool); + if (apr_err) + return lcn_error_createf (apr_err, + NULL, + "error deleting file '%s'", + full_path); + return LCN_NO_ERROR; +} + +static lcn_error_t * +fs_rename_file_internal (lcn_directory_t *d, + const char *from, + const char *to, + apr_pool_t *pool) +{ + fs_dir_baton_t *db = d->baton; + + const char *from_full = apr_psprintf (pool, "%s/%s", db->path, from); + const char *to_full = apr_psprintf (pool, "%s/%s", db->path, to); + + apr_status_t apr_err = apr_file_rename (from_full, to_full, pool); + if (apr_err) + return lcn_error_createf (apr_err, + NULL, + "error renaming file '%s' to '%s'", + from_full, + to_full); + return LCN_NO_ERROR; +} + +static lcn_error_t * +fs_open_file_internal (lcn_istream_t **result, + const lcn_directory_t *d, + const char *name, + apr_pool_t *pool) +{ + fs_dir_baton_t *db = d->baton; + apr_file_t *file; + + const char *full_path = apr_psprintf (pool, "%s/%s", db->path, name); + + apr_status_t apr_err = apr_file_open (&file, + full_path, + APR_READ, + APR_OS_DEFAULT, + pool); + if (apr_err) + return lcn_error_createf (apr_err, + NULL, + "error opening file '%s'", + full_path); + + *result = lcn_file_istream_create (file, pool); + + return LCN_NO_ERROR; +} + +static lcn_error_t * +fs_close_internal (lcn_directory_t *d, apr_pool_t *pool) +{ + fs_dir_baton_t *db = d->baton; + + apr_dir_close (db->dir); + + d->baton = NULL; + + return LCN_NO_ERROR; +} + +lcn_error_t * +lcn_fs_directory_open (lcn_directory_t **dir, + const char *path, + apr_pool_t *pool) +{ + lcn_directory_t *d = apr_pcalloc (pool, sizeof (*d)); + fs_dir_baton_t *baton; + apr_status_t apr_err; + + d->list_internal = fs_list_internal; + d->file_exists_internal = fs_file_exists_internal; + d->file_modified_internal = fs_file_modified_internal; + d->touch_file_internal = fs_touch_file_internal; + d->delete_file_internal = fs_delete_file_internal; + d->rename_file_internal = fs_rename_file_internal; + d->open_file_internal = fs_open_file_internal; + d->close_internal = fs_close_internal; + + baton = apr_pcalloc (pool, sizeof (*d->baton)); + baton->path = apr_pstrdup (pool, path); + + apr_err = apr_dir_open (&baton->dir, path, pool); + if (apr_err) + return lcn_error_createf (apr_err, + NULL, + "failed to open directory '%s'", + path); + d->baton = baton; + + *dir = d; + + return LCN_NO_ERROR; +} + +typedef struct { + /* filename (in lcn_char_t * form) -> pointer to two apr_uint64_ts, the + * first is the start offset, the second is the length of the file. */ + apr_hash_t *contents; + + /* the file in question... */ + lcn_istream_t *cfsfile; + +#if APR_HAS_THREADS + apr_thread_mutex_t *mutex; +#endif +} cfs_directory_baton_t; + +static lcn_error_t * +cfs_delete_file_internal (lcn_directory_t *d, + const char *name, + apr_pool_t *pool) +{ + return lcn_error_create (APR_ENOTIMPL, NULL, "unsupported operation"); +} + +static lcn_error_t * +cfs_rename_file_internal (lcn_directory_t *d, + const char *from, + const char *to, + apr_pool_t *pool) +{ + return lcn_error_create (APR_ENOTIMPL, NULL, "unsupported operation"); +} + +static lcn_error_t * +cfs_list_internal (apr_array_header_t **contents, + const lcn_directory_t *d, + apr_pool_t *pool) +{ + cfs_directory_baton_t *cdb = d->baton; + apr_hash_index_t *hi; + + apr_array_header_t *c = apr_array_make (pool, + apr_hash_count (cdb->contents), + sizeof (const char *)); + + for (hi = apr_hash_first (pool, cdb->contents); hi; hi = apr_hash_next (hi)) + { + const void *key; + char *cstring; + + apr_hash_this (hi, &key, NULL, NULL); + + LCN_ERR (lcn_str_to_cstring (&cstring, key, pool)); + + APR_ARRAY_PUSH (c, const char *) = cstring; + } + + *contents = c; + + return LCN_NO_ERROR; +} + +static lcn_error_t * +cfs_file_exists_internal (lcn_boolean_t *result, + const lcn_directory_t *d, + const char *name, + apr_pool_t *pool) +{ + cfs_directory_baton_t *cdb = d->baton; + + lcn_char_t *cname = lcn_str_from_cstring (name, pool); + + *result = (apr_hash_get (cdb->contents, + cname, + LCN_STRING_SIZE (cname)) != NULL); + + return LCN_NO_ERROR; +} + +static lcn_error_t * +cfs_file_modified_internal (apr_time_t *result, + const lcn_directory_t *d, + const char *name, + apr_pool_t *pool) +{ + /* XXX the Lucene version of this gets the mtime of the underlying cfs + * file. if we want to do that we'll need to implement that on istream, + * but so far i'm not convinced that's needed... */ + + return lcn_error_create (APR_ENOTIMPL, NULL, "unsupported operation"); +} + +static lcn_error_t * +cfs_touch_file_internal (lcn_directory_t *d, + const char *name, + apr_pool_t *pool) +{ + /* XXX the Lucene version of this updates the mtime of the underlying cfs + * file. if we want to do that we'll need to implement that on istream, + * but so far i'm not convinced that's needed... */ + + return lcn_error_create (APR_ENOTIMPL, NULL, "unsupported operation"); +} + +static lcn_error_t * +cfs_close_internal (lcn_directory_t *d, apr_pool_t *pool) +{ + cfs_directory_baton_t *cdb = d->baton; + + LCN_ERR (lcn_istream_close (cdb->cfsfile, pool)); + + d->baton = NULL; + + return LCN_NO_ERROR; +} + +extern lcn_istream_t * lcn__cfs_istream_create (lcn_istream_t *cont, + apr_uint64_t begin, + apr_uint64_t len, +#if APR_HAS_THREADS + apr_thread_mutex_t *mutex, +#endif + apr_pool_t *pool); + +static lcn_error_t * +cfs_open_file_internal (lcn_istream_t **result, + const lcn_directory_t *d, + const char *name, + apr_pool_t *pool) +{ + cfs_directory_baton_t *cdb = d->baton; + + lcn_char_t *cstr = lcn_str_from_cstring (name, pool); + + apr_uint64_t *counts = apr_hash_get (cdb->contents, + cstr, + LCN_STRING_SIZE (cstr)); + + if (counts) + { + *result = lcn__cfs_istream_create (cdb->cfsfile, + counts[0], + counts[1], +#if APR_HAS_THREADS + cdb->mutex, +#endif + pool); + return LCN_NO_ERROR; + } + else + { + *result = NULL; + return lcn_error_createf (APR_ENOENT, NULL, "file '%s' not found", name); + } +} + +lcn_error_t * +lcn_cfs_directory_open (lcn_directory_t **dir, + lcn_istream_t *cfsfile, + apr_pool_t *pool) +{ + lcn_directory_t *d = apr_pcalloc (pool, sizeof (*d)); + cfs_directory_baton_t *baton; + apr_uint32_t count, idx; + apr_uint64_t *offsets; + apr_size_t length; + lcn_char_t *str; + + d->list_internal = cfs_list_internal; + d->file_exists_internal = cfs_file_exists_internal; + d->file_modified_internal = cfs_file_modified_internal; + d->touch_file_internal = cfs_touch_file_internal; + d->delete_file_internal = cfs_delete_file_internal; + d->rename_file_internal = cfs_rename_file_internal; + d->open_file_internal = cfs_open_file_internal; + d->close_internal = cfs_close_internal; + + baton = apr_pcalloc (pool, sizeof (cfs_directory_baton_t)); + + d->baton = baton; + + baton->contents = apr_hash_make (pool); + + /* it would be nice if we could confirm that the stream came from the + * pool we're using, but we can't, so we have to duplicate it. */ + LCN_ERR (lcn_istream_duplicate (&baton->cfsfile, cfsfile, pool)); + +#if APR_HAS_THREADS + { + apr_status_t apr_err = apr_thread_mutex_create (&baton->mutex, + APR_THREAD_MUTEX_DEFAULT, + pool); + if (apr_err) + return lcn_error_create (apr_err, NULL, "error creating mutex"); + } +#endif + + LCN_ERR (lcn_istream_read_vint (cfsfile, &count, pool)); + + offsets = apr_pcalloc (pool, sizeof (apr_uint64_t) * count * 2); + + for (idx = 0; idx < count * 2; idx += 2) + { + LCN_ERR (lcn_istream_read_long (cfsfile, &offsets[idx], pool)); + + if (idx != 0) + { + offsets[idx - 1] = offsets[idx] - offsets[idx - 2]; + } + + LCN_ERR (lcn_istream_read_string (cfsfile, &str, pool)); + + apr_hash_set (baton->contents, + str, + LCN_STRING_SIZE (str), + &offsets[idx]); + } + + LCN_ERR (lcn_istream_length (cfsfile, &length, pool)); + + offsets[(count * 2) - 1] = length - offsets[(count * 2) - 2]; + + *dir = d; + + return LCN_NO_ERROR; +} + +lcn_error_t * +lcn_directory_list (apr_array_header_t **contents, + const lcn_directory_t *d, + apr_pool_t *pool) +{ + return d->list_internal (contents, d, pool); +} + +lcn_error_t * +lcn_directory_file_exists (lcn_boolean_t *result, + const lcn_directory_t *d, + const char *name, + apr_pool_t *pool) +{ + return d->file_exists_internal (result, d, name, pool); +} + +lcn_error_t * +lcn_directory_file_modified (apr_time_t *result, + const lcn_directory_t *d, + const char *name, + apr_pool_t *pool) +{ + return d->file_modified_internal (result, d, name, pool); +} + +lcn_error_t * +lcn_directory_touch_file (lcn_directory_t *d, + const char *name, + apr_pool_t *pool) +{ + return d->touch_file_internal (d, name, pool); +} + +lcn_error_t * +lcn_directory_delete_file (lcn_directory_t *d, + const char *name, + apr_pool_t *pool) +{ + return d->delete_file_internal (d, name, pool); +} + +lcn_error_t * +lcn_directory_rename_file (lcn_directory_t *d, + const char *from, + const char *to, + apr_pool_t *pool) +{ + return d->rename_file_internal (d, from, to, pool); +} + +lcn_error_t * +lcn_directory_open_file (lcn_istream_t **result, + const lcn_directory_t *d, + const char *name, + apr_pool_t *pool) +{ + return d->open_file_internal (result, d, name, pool); +} + +lcn_error_t * +lcn_directory_close (lcn_directory_t *d, apr_pool_t *pool) +{ + return d->close_internal (d, pool); +} Added: incubator/lucene4c/trunk/src/store/istream.c URL: http://svn.apache.org/viewcvs/incubator/lucene4c/trunk/src/store/istream.c?view=auto&rev=155552 ============================================================================== --- incubator/lucene4c/trunk/src/store/istream.c (added) +++ incubator/lucene4c/trunk/src/store/istream.c Sat Feb 26 08:47:57 2005 @@ -0,0 +1,638 @@ +/* Copyright 2004-2005 Garrett Rooney + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "lcn_istream.h" + +#include <apr_strings.h> +#include <stdio.h> +#include <assert.h> + +#define BUFFER_SIZE 1024 + +typedef lcn_error_t * (*istream_read_internal_t) (lcn_istream_t *istream, + char *buffer, + apr_size_t len, + apr_pool_t *pool); + +typedef lcn_error_t * (*istream_seek_internal_t) (lcn_istream_t *istream, + apr_off_t position, + apr_pool_t *pool); + +typedef lcn_error_t * (*istream_close_internal_t) (lcn_istream_t *istream, + apr_pool_t *pool); + +typedef lcn_error_t * (*istream_dup_internal_t) (lcn_istream_t **dest, + lcn_istream_t *source, + apr_pool_t *pool); + +struct lcn_istream_t { + char buffer[BUFFER_SIZE]; + + apr_size_t buffer_start; + apr_size_t buffer_length; + apr_size_t buffer_position; + + apr_size_t length; + + istream_seek_internal_t seek_internal; + istream_read_internal_t read_internal; + istream_close_internal_t close_internal; + istream_dup_internal_t dup_internal; + + void *baton; +}; + +static lcn_istream_t * +istream_create (void *baton, + istream_read_internal_t read, + istream_seek_internal_t seek, + istream_close_internal_t close, + istream_dup_internal_t dup, + apr_pool_t *pool) +{ + lcn_istream_t *istream = apr_pcalloc (pool, sizeof (*istream)); + + istream->length = 0; /* caller must to set this */ + + istream->seek_internal = seek; + istream->read_internal = read; + istream->close_internal = close; + istream->dup_internal = dup; + + istream->baton = baton; + + return istream; +} + +/* NOTE: in the java lucene implementation the ram based file class stores + a vector of buffers instead of just one, probably so that you can + more efficiently implement writable files. in the future we may + want to move to such a scheme for the same reason. */ +struct ram_istream_baton { + char *buffer; + apr_off_t offset; +}; + +static lcn_error_t * +ram_read (lcn_istream_t *istream, char *dest, apr_size_t len, apr_pool_t *pool) +{ + struct ram_istream_baton *rib = istream->baton; + + int remainder = len; + int start = rib->offset; + int dest_offset = 0; + + while (remainder != 0) + { + int bytes_in_buffer = istream->length - start; + + int bytes_to_copy = bytes_in_buffer >= remainder + ? remainder + : bytes_in_buffer; + + memcpy (dest + dest_offset, rib->buffer + start, bytes_to_copy); + + dest_offset += bytes_to_copy; + start += bytes_to_copy; + remainder -= bytes_to_copy; + } + + rib->offset += len; + + return LCN_NO_ERROR; +} + +static lcn_error_t * +ram_seek (lcn_istream_t *istream, apr_off_t offset, apr_pool_t *pool) +{ + struct ram_istream_baton *rib = istream->baton; + + if (offset >= 0 && offset < istream->length) + rib->offset = offset; + else + return lcn_error_create (APR_EINVAL, NULL, "Invalid seek"); + + return LCN_NO_ERROR; +} + +static lcn_error_t * +ram_close (lcn_istream_t *istream, apr_pool_t *pool) +{ + istream->baton = NULL; + + return LCN_NO_ERROR; +} + +static lcn_error_t * +ram_dup (lcn_istream_t **dest, lcn_istream_t *source, apr_pool_t *pool) +{ + return lcn_error_create (APR_ENOTIMPL, + NULL, + "duplication of ram istreams is not implemented"); +} + +lcn_istream_t * +lcn_ram_istream_create (const char *b, apr_size_t length, apr_pool_t *pool) +{ + struct ram_istream_baton *rib = apr_palloc (pool, sizeof (*rib)); + lcn_istream_t *istream; + + rib->buffer = apr_pmemdup (pool, b, length); + rib->offset = 0; + + istream = istream_create (rib, ram_read, ram_seek, ram_close, ram_dup, pool); + + istream->length = length; + + return istream; +} + +struct file_istream_baton { + apr_file_t *file; +}; + +static lcn_error_t * +file_read (lcn_istream_t *istream, + char *dest, + apr_size_t len, + apr_pool_t *pool) +{ + struct file_istream_baton *fib = istream->baton; + apr_status_t apr_err; + apr_size_t try = len; + + apr_err = apr_file_read (fib->file, dest, &try); + if (apr_err) + return lcn_error_create (apr_err, NULL, "Error reading from file"); + + /* XXX should we return errors for short reads? */ + + return LCN_NO_ERROR; +} + +static lcn_error_t * +file_seek (lcn_istream_t *istream, apr_off_t offset, apr_pool_t *pool) +{ + struct file_istream_baton *fib = istream->baton; + + apr_status_t apr_err = apr_file_seek (fib->file, APR_SET, &offset); + if (apr_err) + return lcn_error_create (apr_err, NULL, "Error seeking"); + + return LCN_NO_ERROR; +} + +static lcn_error_t * +file_close (lcn_istream_t *istream, apr_pool_t *pool) +{ + struct file_istream_baton *fib = istream->baton; + + apr_status_t apr_err = apr_file_close (fib->file); + if (apr_err) + return lcn_error_create (apr_err, NULL, "Error closing file"); + + return LCN_NO_ERROR; +} + +static lcn_error_t * +file_dup (lcn_istream_t **dest, lcn_istream_t *source, apr_pool_t *pool) +{ + struct file_istream_baton *fib = source->baton; + apr_status_t apr_err; + + *dest = apr_pmemdup (pool, source, sizeof (*source)); + + (*dest)->baton = apr_pmemdup (pool, fib, sizeof (*fib)); + + apr_err = apr_file_dup (&((struct file_istream_baton *)(*dest)->baton)->file, + fib->file, + pool); + if (apr_err) + return lcn_error_create (apr_err, NULL, "Error duping file"); + + return LCN_NO_ERROR; +} + +lcn_istream_t * +lcn_file_istream_create (apr_file_t *file, apr_pool_t *pool) +{ + struct file_istream_baton *fib = apr_palloc (pool, sizeof (*fib)); + lcn_istream_t *istream; + apr_off_t offset = 0; + + fib->file = file; + + istream = istream_create (fib, + file_read, + file_seek, + file_close, + file_dup, + pool); + + /* get the offset at the end of the file */ + apr_file_seek (file, APR_END, &offset); + + istream->length = offset; + + offset = 0; + + /* return to the beginning of the file */ + apr_file_seek (file, APR_SET, &offset); + + return istream; +} + +typedef struct { + apr_uint64_t offset; + apr_uint64_t end; + lcn_istream_t *cont; + +#if APR_HAS_THREADS + apr_thread_mutex_t *mutex; +#endif +} cfs_istream_baton_t; + +static lcn_error_t * +cfs_read (lcn_istream_t *istream, + char *dest, + apr_size_t len, + apr_pool_t *pool) +{ + cfs_istream_baton_t *cib = istream->baton; + lcn_error_t *err = LCN_NO_ERROR; + apr_status_t apr_err; + apr_off_t start; + +#if APR_HAS_THREADS + apr_err = apr_thread_mutex_lock (cib->mutex); + if (apr_err) + return lcn_error_create (apr_err, NULL, "error locking mutex"); +#endif + + LCN_ERR (lcn_istream_offset (istream, &start, pool)); + + if (start + len > cib->end) + { + err = lcn_error_create (APR_EOF, NULL, "read past EOF"); + goto unlock; + } + + err = lcn_istream_seek (cib->cont, cib->offset + start, pool); + if (err) + goto unlock; + + err = lcn_istream_read_bytes (cib->cont, dest, len, pool); + if (err) + goto unlock; + +unlock: + +#if APR_HAS_THREADS + apr_err = apr_thread_mutex_unlock (cib->mutex); + if (apr_err) + return lcn_error_create (apr_err, NULL, "error unlocking mutex"); +#endif + + return err; +} + +static lcn_error_t * +cfs_seek (lcn_istream_t *istream, apr_off_t offset, apr_pool_t *pool) +{ + return LCN_NO_ERROR; +} + +static lcn_error_t * +cfs_close (lcn_istream_t *istream, apr_pool_t *pool) +{ + return LCN_NO_ERROR; +} + +static lcn_error_t * +cfs_dup (lcn_istream_t **dest, lcn_istream_t *source, apr_pool_t *pool) +{ + return lcn_error_create (APR_ENOTIMPL, + NULL, + "duplication of cfs istreams is not implemented"); +} + +lcn_istream_t * +lcn__cfs_istream_create (lcn_istream_t *cont, + apr_uint64_t begin, + apr_uint64_t size, +#if APR_HAS_THREADS + apr_thread_mutex_t *mutex, +#endif + apr_pool_t *pool) +{ + cfs_istream_baton_t *cib = apr_pcalloc (pool, sizeof (*cib)); + lcn_istream_t *istream; + + cib->offset = begin; + cib->end = begin + size; + cib->cont = cont; + +#if APR_HAS_THREADS + cib->mutex = mutex; +#endif + + istream = istream_create (cib, cfs_read, cfs_seek, cfs_close, cfs_dup, pool); + + istream->length = size; + + return istream; +} + +static lcn_error_t * +refill (lcn_istream_t *istream, apr_pool_t *pool) +{ + apr_size_t start = istream->buffer_start + istream->buffer_position; + apr_size_t end = start + BUFFER_SIZE; + + if (end > istream->length) + end = istream->length; + + istream->buffer_length = end - start; + if (istream->buffer_length <= 0) + return lcn_error_create (APR_EOF, NULL, "read past eof"); + + LCN_ERR (istream->read_internal (istream, + istream->buffer, + istream->buffer_length, + pool)); + + istream->buffer_start = start; + istream->buffer_position = 0; + + return LCN_NO_ERROR; +} + +lcn_error_t * +lcn_istream_read_byte (lcn_istream_t *istream, char *b, apr_pool_t *pool) +{ + if (istream->buffer_position >= istream->buffer_length) + LCN_ERR (refill (istream, pool)); + + *b = istream->buffer[istream->buffer_position++]; + + return LCN_NO_ERROR; +} + +lcn_error_t * +lcn_istream_read_bytes (lcn_istream_t *istream, + char *b, + apr_size_t len, + apr_pool_t *pool) +{ + if (len <= BUFFER_SIZE) + { + int i; + + for (i = 0; i < len; ++i) + { + char tmp; + + LCN_ERR (lcn_istream_read_byte (istream, &tmp, pool)); + + b[i] = tmp; + } + } + else + { + apr_off_t start; + + LCN_ERR (lcn_istream_offset (istream, &start, pool)); + + LCN_ERR (lcn_istream_seek (istream, start, pool)); + + LCN_ERR (istream->read_internal (istream, b, len, pool)); + + istream->buffer_start = start + len; + istream->buffer_position = 0; + istream->buffer_length = 0; + } + + return LCN_NO_ERROR; +} + +lcn_error_t * +lcn_istream_read_int (lcn_istream_t *istream, + apr_uint32_t *i, + apr_pool_t *pool) +{ + int shift; + + *i = 0; + + for (shift = 24; shift >= 0; shift -= 8) + { + char b; + + LCN_ERR (lcn_istream_read_byte (istream, &b, pool)); + + *i |= ((b & 0xFF) << shift); + } + + return LCN_NO_ERROR; +} + +lcn_error_t * +lcn_istream_read_vint (lcn_istream_t *istream, + apr_uint32_t *i, + apr_pool_t *pool) +{ + apr_uint32_t tmp; + int shift; + char byte; + + *i = 0; + + LCN_ERR (lcn_istream_read_byte (istream, &byte, pool)); + + tmp = byte & 0x7F; + + for (shift = 7; (byte & 0x80) != 0; shift += 7) + { + LCN_ERR (lcn_istream_read_byte (istream, &byte, pool)); + + tmp |= (byte & 0x7F) << shift; + } + + *i = tmp; + + return LCN_NO_ERROR; +} + +lcn_error_t * +lcn_istream_read_long (lcn_istream_t *istream, + apr_uint64_t *l, + apr_pool_t *pool) +{ + apr_uint32_t i = 0; + + *l = 0; + + LCN_ERR (lcn_istream_read_int (istream, &i, pool)); + + *l |= (((apr_uint64_t) i) << 32); + + LCN_ERR (lcn_istream_read_int (istream, &i, pool)); + + *l |= (i & 0xFFFFFFFFL); + + return LCN_NO_ERROR; +} + +lcn_error_t * +lcn_istream_read_vlong (lcn_istream_t *istream, + apr_uint64_t *l, + apr_pool_t *pool) +{ + apr_uint64_t tmp; + int shift; + char byte; + + *l = 0; + + LCN_ERR (lcn_istream_read_byte (istream, &byte, pool)); + + tmp = byte & 0x7F; + + for (shift = 7; (byte & 0x80) != 0; shift += 7) + { + LCN_ERR (lcn_istream_read_byte (istream, &byte, pool)); + + tmp |= (apr_uint64_t ) (byte & 0x7F) << shift; + } + + *l = tmp; + + return LCN_NO_ERROR; +} + +lcn_error_t * +lcn_istream_read_chars (lcn_istream_t *istream, + lcn_char_t **buffer, + apr_size_t length, + apr_pool_t *pool) +{ + int i; + + *buffer = apr_pcalloc (pool, sizeof (lcn_char_t) * (length + 1)); + + for (i = 0; i < length; ++i) + { + char b; + + LCN_ERR (lcn_istream_read_byte (istream, &b, pool)); + + if ((b & 0x80) == 0) + { + (*buffer)[i] = b & 0x7F; + } + else if ((b & 0xE0) != 0xE0) + { + (*buffer)[i] = b & 0x0F << 6; + + LCN_ERR (lcn_istream_read_byte (istream, &b, pool)); + + (*buffer)[i] |= b & 0x3F; + } + else + { + (*buffer)[i] = b & 0x0F << 12; + + LCN_ERR (lcn_istream_read_byte (istream, &b, pool)); + + (*buffer)[i] |= b & 0x3F << 6; + + LCN_ERR (lcn_istream_read_byte (istream, &b, pool)); + + (*buffer)[i] |= b & 0x3F; + } + } + + return LCN_NO_ERROR; +} + +lcn_error_t * +lcn_istream_read_string (lcn_istream_t *istream, + lcn_char_t **str, + apr_pool_t *pool) +{ + apr_uint32_t length; + + LCN_ERR (lcn_istream_read_vint (istream, &length, pool)); + + LCN_ERR (lcn_istream_read_chars (istream, str, length, pool)); + + return LCN_NO_ERROR; +} + +lcn_error_t * +lcn_istream_seek (lcn_istream_t *istream, apr_off_t offset, apr_pool_t *pool) +{ + if (offset >= istream->buffer_start + && offset < (istream->buffer_start + istream->buffer_length)) + { + istream->buffer_position = (apr_size_t) (offset - istream->buffer_start); + } + else + { + istream->buffer_start = offset; + istream->buffer_position = 0; + istream->buffer_length = 0; + + LCN_ERR (istream->seek_internal (istream, offset, pool)); + } + + return LCN_NO_ERROR; +} + +lcn_error_t * +lcn_istream_close (lcn_istream_t *istream, apr_pool_t *pool) +{ + LCN_ERR (istream->close_internal (istream, pool)); + + return LCN_NO_ERROR; +} + +lcn_error_t * +lcn_istream_length (lcn_istream_t *istream, + apr_size_t *length, + apr_pool_t *pool) +{ + *length = istream->length; + + return LCN_NO_ERROR; +} + +lcn_error_t * +lcn_istream_offset (lcn_istream_t *istream, + apr_off_t *offset, + apr_pool_t *pool) +{ + *offset = istream->buffer_start + istream->buffer_position; + + return LCN_NO_ERROR; +} + +lcn_error_t * +lcn_istream_duplicate (lcn_istream_t **dest, + lcn_istream_t *source, + apr_pool_t *pool) +{ + return source->dup_internal (dest, source, pool); +} Propchange: incubator/lucene4c/trunk/src/util/ ------------------------------------------------------------------------------ --- svn:ignore (added) +++ svn:ignore Sat Feb 26 08:47:57 2005 @@ -0,0 +1,2 @@ +.deps +.dirstamp Added: incubator/lucene4c/trunk/src/util/error.c URL: http://svn.apache.org/viewcvs/incubator/lucene4c/trunk/src/util/error.c?view=auto&rev=155552 ============================================================================== --- incubator/lucene4c/trunk/src/util/error.c (added) +++ incubator/lucene4c/trunk/src/util/error.c Sat Feb 26 08:47:57 2005 @@ -0,0 +1,82 @@ +/* Copyright 2004-2005 Garrett Rooney + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdlib.h> + +#include <apr_strings.h> + +#include "lcn_types.h" + +static lcn_error_t * +make_error_internal (apr_status_t apr_err, lcn_error_t *child) +{ + apr_pool_t *pool; + lcn_error_t *new_error; + + if (child) + pool = child->pool; + else + { + pool = lcn_pool_create (NULL); + if (! pool) + abort (); + } + + new_error = apr_pcalloc (pool, sizeof (*new_error)); + + new_error->apr_err = apr_err; + new_error->child = child; + new_error->pool = pool; + + return new_error; +} + +lcn_error_t * +lcn_error_create (apr_status_t apr_err, lcn_error_t *child, const char *msg) +{ + lcn_error_t *err = make_error_internal (apr_err, child); + + if (msg) + err->message = apr_pstrdup (err->pool, msg); + + return err; +} + +lcn_error_t * +lcn_error_createf (apr_status_t apr_err, + lcn_error_t *child, + const char *fmt, + ...) +{ + lcn_error_t *err = make_error_internal (apr_err, child); + va_list ap; + + va_start (ap, fmt); + + err->message = apr_pvsprintf (err->pool, fmt, ap); + + va_end (ap); + + return err; +} + +void +lcn_error_clear (lcn_error_t *err) +{ + if (err) + { + lcn_pool_destroy (err->pool); + } +} Added: incubator/lucene4c/trunk/src/util/pools.c URL: http://svn.apache.org/viewcvs/incubator/lucene4c/trunk/src/util/pools.c?view=auto&rev=155552 ============================================================================== --- incubator/lucene4c/trunk/src/util/pools.c (added) +++ incubator/lucene4c/trunk/src/util/pools.c Sat Feb 26 08:47:57 2005 @@ -0,0 +1,35 @@ +/* Copyright 2004-2005 Garrett Rooney + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdlib.h> + +#include <apr_pools.h> + +static int +abort_on_pool_failure (int rc) +{ + abort (); + return -1; +} + +apr_pool_t * +lcn_pool_create (apr_pool_t *parent) +{ + apr_pool_t *pool; + + apr_pool_create_ex (&pool, parent, abort_on_pool_failure, NULL); + + return pool; +} Added: incubator/lucene4c/trunk/src/util/string.c URL: http://svn.apache.org/viewcvs/incubator/lucene4c/trunk/src/util/string.c?view=auto&rev=155552 ============================================================================== --- incubator/lucene4c/trunk/src/util/string.c (added) +++ incubator/lucene4c/trunk/src/util/string.c Sat Feb 26 08:47:57 2005 @@ -0,0 +1,101 @@ +/* Copyright 2004-2005 Garrett Rooney + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "lcn_types.h" + +apr_size_t +lcn_strlen (const lcn_char_t *str) +{ + const lcn_char_t *itr = str; + + while (*itr != 0) + ++itr; + + return itr - str; +} + +int +lcn_strcmp (const lcn_char_t *first, const lcn_char_t *second) +{ + if (first == NULL && second == NULL) + return 0; + else if (first == NULL) + return -1; + else if (second == NULL) + return 1; + + /* as long as everything is the same... */ + while (*first == *second++) + { + /* if we're at the end return. */ + if (*first++ == 0) + return 0; + } + + /* otherwise return the difference between the chars that didn't match. */ + return (*first - *(second - 1)); +} + +lcn_char_t * +lcn_strcpy (const lcn_char_t *str, apr_pool_t *pool) +{ + apr_size_t len = LCN_STRING_SIZE (str); + + lcn_char_t *rv = apr_palloc (pool, len); + + memcpy (rv, str, len); + + return rv; +} + +lcn_error_t * +lcn_str_to_cstring (char **out, const lcn_char_t *in, apr_pool_t *pool) +{ + char *o = apr_pcalloc (pool, lcn_strlen (in) + 1); + const lcn_char_t *iitr = in; + char *oitr = o; + + while (*iitr != 0) + { + if (*iitr <= 127) + *oitr++ = *iitr++; + else + return lcn_error_create (APR_EINVAL, + NULL, + "can only convert ascii text to cstrings"); + } + + *oitr = 0; /* zero out the final byte in the string, to placate valgrind */ + + *out = o; + + return LCN_NO_ERROR; +} + +lcn_char_t * +lcn_str_from_cstring (const char *in, apr_pool_t *pool) +{ + apr_size_t len = strlen (in); + int i; + + lcn_char_t *out = apr_pcalloc (pool, sizeof (lcn_char_t) * (len + 1)); + + for (i = 0; i <= len; ++i) + { + out[i] = in[i]; + } + + return out; +} Propchange: incubator/lucene4c/trunk/test/ ------------------------------------------------------------------------------ --- svn:ignore (added) +++ svn:ignore Sat Feb 26 08:47:57 2005 @@ -0,0 +1,3 @@ +tests +.deps +.dirstamp Added: incubator/lucene4c/trunk/test/abts.c URL: http://svn.apache.org/viewcvs/incubator/lucene4c/trunk/test/abts.c?view=auto&rev=155552 ============================================================================== --- incubator/lucene4c/trunk/test/abts.c (added) +++ incubator/lucene4c/trunk/test/abts.c Sat Feb 26 08:47:57 2005 @@ -0,0 +1,412 @@ +/* Copyright 2000-2004 Ryan Bloom + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Portions of this file were taken from testall.c in the APR test suite, + * written by members of the Apache Software Foundation. + */ + +#include "abts.h" +#include "abts_tests.h" +#include "lcn_tests.h" + +#define ABTS_STAT_SIZE 6 +static char status[ABTS_STAT_SIZE] = {'|', '/', '-', '|', '\\', '-'}; +static int curr_char; +static int verbose = 0; +static int exclude = 0; +static int quiet = 0; +static int list_tests = 0; + +const char **testlist = NULL; + +static int find_test_name(const char *testname) { + int i; + for (i = 0; testlist[i] != NULL; i++) { + if (!strcmp(testlist[i], testname)) { + return 1; + } + } + return 0; +} + +/* Determine if the test should be run at all */ +static int should_test_run(const char *testname) { + int found = 0; + if (list_tests == 1) { + return 0; + } + if (testlist == NULL) { + return 1; + } + found = find_test_name(testname); + if ((found && !exclude) || (!found && exclude)) { + return 1; + } + return 0; +} + +static void reset_status(void) +{ + curr_char = 0; +} + +static void update_status(void) +{ + if (!quiet) { + curr_char = (curr_char + 1) % ABTS_STAT_SIZE; + fprintf(stdout, "\b%c", status[curr_char]); + fflush(stdout); + } +} + +static void end_suite(abts_suite *suite) +{ + if (suite != NULL) { + sub_suite *last = suite->tail; + if (!quiet) { + fprintf(stdout, "\b"); + fflush(stdout); + } + if (last->failed == 0) { + fprintf(stdout, "SUCCESS\n"); + fflush(stdout); + } + else { + fprintf(stdout, "FAILED %d of %d\n", last->failed, last->num_test); + fflush(stdout); + } + } +} + +abts_suite *abts_add_suite(abts_suite *suite, const char *suite_name_full) +{ + sub_suite *subsuite; + char *p; + const char *suite_name; + curr_char = 0; + + /* Only end the suite if we actually ran it */ + if (suite && suite->tail &&!suite->tail->not_run) { + end_suite(suite); + } + + subsuite = malloc(sizeof(*subsuite)); + subsuite->num_test = 0; + subsuite->failed = 0; + subsuite->next = NULL; + /* suite_name_full may be an absolute path depending on __FILE__ + * expansion */ + suite_name = strrchr(suite_name_full, '/'); + if (suite_name) { + suite_name++; + } else { + suite_name = suite_name_full; + } + p = strrchr(suite_name, '.'); + if (p) { + subsuite->name = memcpy(calloc(p - suite_name + 1, 1), + suite_name, p - suite_name); + } + else { + subsuite->name = suite_name; + } + + if (list_tests) { + fprintf(stdout, "%s\n", subsuite->name); + } + + subsuite->not_run = 0; + + if (suite == NULL) { + suite = malloc(sizeof(*suite)); + suite->head = subsuite; + suite->tail = subsuite; + } + else { + suite->tail->next = subsuite; + suite->tail = subsuite; + } + + if (!should_test_run(subsuite->name)) { + subsuite->not_run = 1; + return suite; + } + + reset_status(); + fprintf(stdout, "%-20s: ", subsuite->name); + update_status(); + fflush(stdout); + + return suite; +} + +void abts_run_test(abts_suite *ts, test_func f, void *value) +{ + abts_case tc; + sub_suite *ss; + + if (!should_test_run(ts->tail->name)) { + return; + } + ss = ts->tail; + + tc.failed = 0; + tc.suite = ss; + + ss->num_test++; + update_status(); + + f(&tc, value); + + if (tc.failed) { + ss->failed++; + } +} + +static int report(abts_suite *suite) +{ + int count = 0; + sub_suite *dptr; + + if (suite && suite->tail &&!suite->tail->not_run) { + end_suite(suite); + } + + for (dptr = suite->head; dptr; dptr = dptr->next) { + count += dptr->failed; + } + + if (list_tests) { + return 0; + } + + if (count == 0) { + printf("All tests passed.\n"); + return 0; + } + + dptr = suite->head; + fprintf(stdout, "%-15s\t\tTotal\tFail\tFailed %%\n", "Failed Tests"); + fprintf(stdout, "===================================================\n"); + while (dptr != NULL) { + if (dptr->failed != 0) { + float percent = ((float)dptr->failed / (float)dptr->num_test); + fprintf(stdout, "%-15s\t\t%5d\t%4d\t%6.2f%%\n", dptr->name, + dptr->num_test, dptr->failed, percent * 100); + } + dptr = dptr->next; + } + return 1; +} + +void abts_log_message(const char *fmt, ...) +{ + va_list args; + update_status(); + + if (verbose) { + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + fprintf(stderr, "\n"); + fflush(stderr); + } +} + +void abts_int_equal(abts_case *tc, const int expected, const int actual, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (expected == actual) return; + + tc->failed = TRUE; + if (verbose) { + fprintf(stderr, "Line %d: expected <%d>, but saw <%d>\n", lineno, expected, actual); + fflush(stderr); + } +} + +void abts_int_nequal(abts_case *tc, const int expected, const int actual, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (expected != actual) return; + + tc->failed = TRUE; + if (verbose) { + fprintf(stderr, "Line %d: expected <%d>, but saw <%d>\n", lineno, expected, actual); + fflush(stderr); + } +} + +void abts_str_equal(abts_case *tc, const char *expected, const char *actual, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (!expected && !actual) return; + if (expected && actual) + if (!strcmp(expected, actual)) return; + + tc->failed = TRUE; + if (verbose) { + fprintf(stderr, "Line %d: expected <%s>, but saw <%s>\n", lineno, expected, actual); + fflush(stderr); + } +} + +void abts_str_nequal(abts_case *tc, const char *expected, const char *actual, + size_t n, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (!strncmp(expected, actual, n)) return; + + tc->failed = TRUE; + if (verbose) { + fprintf(stderr, "Line %d: expected <%s>, but saw <%s>\n", lineno, expected, actual); + fflush(stderr); + } +} + +void abts_ptr_notnull(abts_case *tc, const void *ptr, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (ptr != NULL) return; + + tc->failed = TRUE; + if (verbose) { + fprintf(stderr, "Line %d: Expected NULL, but saw <%p>\n", lineno, ptr); + fflush(stderr); + } +} + +void abts_ptr_equal(abts_case *tc, const void *expected, const void *actual, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (expected == actual) return; + + tc->failed = TRUE; + if (verbose) { + fprintf(stderr, "Line %d: expected <%p>, but saw <%p>\n", lineno, expected, actual); + fflush(stderr); + } +} + +void abts_fail(abts_case *tc, const char *message, int lineno) +{ + update_status(); + if (tc->failed) return; + + tc->failed = TRUE; + if (verbose) { + fprintf(stderr, "Line %d: %s\n", lineno, message); + fflush(stderr); + } +} + +void abts_assert(abts_case *tc, const char *message, int condition, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (condition) return; + + tc->failed = TRUE; + if (verbose) { + fprintf(stderr, "Line %d: %s\n", lineno, message); + fflush(stderr); + } +} + +void abts_true(abts_case *tc, int condition, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (condition) return; + + tc->failed = TRUE; + if (verbose) { + fprintf(stderr, "Line %d: Condition is false, but expected true\n", lineno); + fflush(stderr); + } +} + +void abts_not_impl(abts_case *tc, const char *message, int lineno) +{ + update_status(); + + tc->suite->not_impl++; + if (verbose) { + fprintf(stderr, "Line %d: %s\n", lineno, message); + fflush(stderr); + } +} + +int main(int argc, const char *const argv[]) { + int i; + int rv; + int list_provided = 0; + abts_suite *suite = NULL; + + initialize(); + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-v")) { + verbose = 1; + continue; + } + if (!strcmp(argv[i], "-x")) { + exclude = 1; + continue; + } + if (!strcmp(argv[i], "-l")) { + list_tests = 1; + continue; + } + if (!strcmp(argv[i], "-q")) { + quiet = 1; + continue; + } + if (argv[i][0] == '-') { + fprintf(stderr, "Invalid option: `%s'\n", argv[i]); + exit(1); + } + list_provided = 1; + } + + if (list_provided) { + /* Waste a little space here, because it is easier than counting the + * number of tests listed. Besides it is at most three char *. + */ + testlist = calloc(argc + 1, sizeof(char *)); + for (i = 1; i < argc; i++) { + testlist[i - 1] = argv[i]; + } + } + + for (i = 0; i < (sizeof(alltests) / sizeof(struct testlist *)); i++) { + suite = alltests[i].func(suite); + } + + rv = report(suite); + return rv; +} Added: incubator/lucene4c/trunk/test/abts.h URL: http://svn.apache.org/viewcvs/incubator/lucene4c/trunk/test/abts.h?view=auto&rev=155552 ============================================================================== --- incubator/lucene4c/trunk/test/abts.h (added) +++ incubator/lucene4c/trunk/test/abts.h Sat Feb 26 08:47:57 2005 @@ -0,0 +1,97 @@ +/* Copyright 2000-2004 Ryan Bloom + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#ifndef ABTS_H +#define ABTS_H + +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif + +struct sub_suite { + const char *name; + int num_test; + int failed; + int not_run; + int not_impl; + struct sub_suite *next; +}; +typedef struct sub_suite sub_suite; + +struct abts_suite { + sub_suite *head; + sub_suite *tail; +}; +typedef struct abts_suite abts_suite; + +struct abts_case { + int failed; + sub_suite *suite; +}; +typedef struct abts_case abts_case; + +typedef void (*test_func)(abts_case *tc, void *data); + +#define ADD_SUITE(suite) abts_add_suite(suite, __FILE__); + +abts_suite *abts_add_suite(abts_suite *suite, const char *suite_name); +void abts_run_test(abts_suite *ts, test_func f, void *value); +void abts_log_message(const char *fmt, ...); + +void abts_int_equal(abts_case *tc, const int expected, const int actual, int lineno); +void abts_int_nequal(abts_case *tc, const int expected, const int actual, int lineno); +void abts_str_equal(abts_case *tc, const char *expected, const char *actual, int lineno); +void abts_str_nequal(abts_case *tc, const char *expected, const char *actual, + size_t n, int lineno); +void abts_ptr_notnull(abts_case *tc, const void *ptr, int lineno); +void abts_ptr_equal(abts_case *tc, const void *expected, const void *actual, int lineno); +void abts_true(abts_case *tc, int condition, int lineno); +void abts_fail(abts_case *tc, const char *message, int lineno); +void abts_not_impl(abts_case *tc, const char *message, int lineno); +void abts_assert(abts_case *tc, const char *message, int condition, int lineno); + +/* Convenience macros. Ryan hates these! */ +#define ABTS_INT_EQUAL(a, b, c) abts_int_equal(a, b, c, __LINE__) +#define ABTS_INT_NEQUAL(a, b, c) abts_int_nequal(a, b, c, __LINE__) +#define ABTS_STR_EQUAL(a, b, c) abts_str_equal(a, b, c, __LINE__) +#define ABTS_STR_NEQUAL(a, b, c, d) abts_str_nequal(a, b, c, d, __LINE__) +#define ABTS_PTR_NOTNULL(a, b) abts_ptr_notnull(a, b, __LINE__) +#define ABTS_PTR_EQUAL(a, b, c) abts_ptr_equal(a, b, c, __LINE__) +#define ABTS_TRUE(a, b) abts_true(a, b, __LINE__); +#define ABTS_FAIL(a, b) abts_fail(a, b, __LINE__); +#define ABTS_NOT_IMPL(a, b) abts_not_impl(a, b, __LINE__); +#define ABTS_ASSERT(a, b, c) abts_assert(a, b, c, __LINE__); + +abts_suite *run_tests(abts_suite *suite); +abts_suite *run_tests1(abts_suite *suite); + + +#endif + +#ifdef __cplusplus +} +#endif Added: incubator/lucene4c/trunk/test/abts_tests.h URL: http://svn.apache.org/viewcvs/incubator/lucene4c/trunk/test/abts_tests.h?view=auto&rev=155552 ============================================================================== --- incubator/lucene4c/trunk/test/abts_tests.h (added) +++ incubator/lucene4c/trunk/test/abts_tests.h Sat Feb 26 08:47:57 2005 @@ -0,0 +1,39 @@ +/* Copyright 2000-2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ABTS_TEST_H +#define ABTS_TEST_H + +#include "abts.h" + +#include "lcn_tests.h" + +const struct testlist { + abts_suite *(*func)(abts_suite *suite); +} alltests[] = { + { test_string }, + { test_istream }, + { test_directory }, + { test_segments }, + { test_segment }, + { test_fieldinfos }, + { test_fielddata }, + { test_terminfos }, + { test_frequencies }, + { test_index }, + { test_scorer } +}; + +#endif /* ABTS_TEST_H */ Added: incubator/lucene4c/trunk/test/data/index-cfs/_1or.cfs URL: http://svn.apache.org/viewcvs/incubator/lucene4c/trunk/test/data/index-cfs/_1or.cfs?view=auto&rev=155552 ============================================================================== Binary file - no diff available. Propchange: incubator/lucene4c/trunk/test/data/index-cfs/_1or.cfs ------------------------------------------------------------------------------ svn:mime-type = application/octet-stream Added: incubator/lucene4c/trunk/test/data/index-cfs/deletable URL: http://svn.apache.org/viewcvs/incubator/lucene4c/trunk/test/data/index-cfs/deletable?view=auto&rev=155552 ============================================================================== Binary file - no diff available. Propchange: incubator/lucene4c/trunk/test/data/index-cfs/deletable ------------------------------------------------------------------------------ svn:mime-type = application/octet-stream Added: incubator/lucene4c/trunk/test/data/index-cfs/segments URL: http://svn.apache.org/viewcvs/incubator/lucene4c/trunk/test/data/index-cfs/segments?view=auto&rev=155552 ============================================================================== Binary file - no diff available. Propchange: incubator/lucene4c/trunk/test/data/index-cfs/segments ------------------------------------------------------------------------------ svn:mime-type = application/octet-stream Added: incubator/lucene4c/trunk/test/data/index/_c7.f1 URL: http://svn.apache.org/viewcvs/incubator/lucene4c/trunk/test/data/index/_c7.f1?view=auto&rev=155552 ============================================================================== --- incubator/lucene4c/trunk/test/data/index/_c7.f1 (added) +++ incubator/lucene4c/trunk/test/data/index/_c7.f1 Sat Feb 26 08:47:57 2005 @@ -0,0 +1 @@ +uwxsvxyuxyuxpuxmlntxhehmdinhlmljklilyvxqiuvxyuxlkmuxptxjkhukmnmqllfptxuhjmmlfokntxkoilliiodljmkjnnmontuxquxjhhqiikuxhnilmieeigqnjmnggiillkklmmiimpihknuxkjoidemeljlhiljjuxjlmkihlhgnjlljlniiilphlihnjljlkjlnkljkglhlohntxhklkkjmllljjjnmmmjouxkghjiqiolkilpuxqjmyvxhqpvxtrppiuuxryvxyuxruxstxmlntxoomannkllakmllouxuuxjmuxikmutxpifilmlkflmkjiilkiluuxflluxnjstxgklmjljiimnkhjllkkljehjkkmuuxkjjjquxknikyvx \ No newline at end of file Added: incubator/lucene4c/trunk/test/data/index/_c7.f2 URL: http://svn.apache.org/viewcvs/incubator/lucene4c/trunk/test/data/index/_c7.f2?view=auto&rev=155552 ============================================================================== --- incubator/lucene4c/trunk/test/data/index/_c7.f2 (added) +++ incubator/lucene4c/trunk/test/data/index/_c7.f2 Sat Feb 26 08:47:57 2005 @@ -0,0 +1 @@ +||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| \ No newline at end of file Added: incubator/lucene4c/trunk/test/data/index/_c7.f3 URL: http://svn.apache.org/viewcvs/incubator/lucene4c/trunk/test/data/index/_c7.f3?view=auto&rev=155552 ============================================================================== --- incubator/lucene4c/trunk/test/data/index/_c7.f3 (added) +++ incubator/lucene4c/trunk/test/data/index/_c7.f3 Sat Feb 26 08:47:57 2005 @@ -0,0 +1 @@ +||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| \ No newline at end of file Added: incubator/lucene4c/trunk/test/data/index/_c7.fdt URL: http://svn.apache.org/viewcvs/incubator/lucene4c/trunk/test/data/index/_c7.fdt?view=auto&rev=155552 ============================================================================== Binary file - no diff available. Propchange: incubator/lucene4c/trunk/test/data/index/_c7.fdt ------------------------------------------------------------------------------ svn:mime-type = application/octet-stream Added: incubator/lucene4c/trunk/test/data/index/_c7.fdx URL: http://svn.apache.org/viewcvs/incubator/lucene4c/trunk/test/data/index/_c7.fdx?view=auto&rev=155552 ============================================================================== Binary file - no diff available. Propchange: incubator/lucene4c/trunk/test/data/index/_c7.fdx ------------------------------------------------------------------------------ svn:mime-type = application/octet-stream Added: incubator/lucene4c/trunk/test/data/index/_c7.fnm URL: http://svn.apache.org/viewcvs/incubator/lucene4c/trunk/test/data/index/_c7.fnm?view=auto&rev=155552 ============================================================================== Binary file - no diff available. Propchange: incubator/lucene4c/trunk/test/data/index/_c7.fnm ------------------------------------------------------------------------------ svn:mime-type = application/octet-stream
