=head1 NAME

SWISH-LIBRARY - Interface to the Swish-e C library

=head1 What is the Swish-e C library?

The C library in an interface to the Swish-e search code.  It provides
a way to embed Swish-e into your applications.
This API is based on Swish-e version 2.3.

B<Note:> This is a NEW API as of Swish-e version 2.3.
The C language interface has changed as has the perl interface to Swish-e.
The new Perl interface is the SWISH::API module and is included with the Swish-e
distribution.
The old SWISHE perl module has been rewritten to work with the new API.  The SWISHE perl module
is no longer included with the Swish-e distribution, but can be downloaded
from the Swish-e web site.

The advantage of the library is that the index files or files can be opened one time
and many queries made on the open index.  This saves the startup time required
to fork and run the swish-e binary, and the expensive time of opening up the
index file.  Some benchmarks have shown a three fold increase in speed.

The downside is that your program now has more code and data in it (the index tables can
use quite a bit of memory), and if a fatal error happens in swish it will bring down your
program.  These are things to think about, especially if embedding swish into a web server
such as Apache where there are many processes serving requests.

The best way to learn about the library is to look at two files included with
the Swish-e distribution that make use of the library.


=over 4

=item src/libtest.c

This file gives a basic overview of linking a C program with the Swish-e library.
Not all available functions are used in that example, but it should give you a good overview
of building a C program with swish-e.

To build and run libtest chdir to the src directory and run the commands:

    $ make libtest
    $ ./libtest [optional name of index file]

You will be prompted for the search words.  The default index used is F<index.swish-e>.
This can be overridden by placing a list of index files in a quote-protected string.

    $ ./libtest 'index1 index2 index3'

=item perl/API.xs

The F<API.xs> file is a Perl "xsub" interface to the C library and is part of the
SWISH::API Perl module.  This is an object-oriented interface to the Swish-e library
and demonstrates how the various search "objects" are created by C calls and how
they are destroyed when no longer needed.

=back

=head1 Installing the Swish-e library

The Swish-e library is installed when you run "make install" when building 
Swish-e.  No extra installation steps are required.

The library consists of a header file "swish-e.h" and a library
"libswish-e.*" that can either be a static or shared library depending on 
your platform.

=head1 Library Overview

When you first attach to an index file (or index files) you are returned a "swish handle".
From the handle you create one or more "search objects" which holds
the parameters to query the index, such as the query string, sort order, search phrase delimiter,
limit parameters and HTML structure bits.  The "object" is really just a pointer to a C structure, but
it's helpful to think of it as an object that data and functionality associated with it.

The search object is used to query the index.  A query returns a "results object".
The results object holds the number of hits, the parsed query per index, and the result set.
The results object keeps track of the current position in the result set.
You may "seek" to a specific record within the result set (useful for displaying a page of results).

Finally, a result object represents a single result from the result list.  A result object provides
access to the result's properties (such as file name, rank, etc.).

In addition to results, there are functions available to access the header values stored
in the index file, functions to check and report errors, and a few utility functions.


=head1 Available Functions

Below is the list of available function included in the Swish-e C language API.

These functions (and typedefs) are defined in the F<swish-e.h> header file.
The common objects (e.g. structures) used are:

    SW_HANDLE  - swish handle that associates with an index file
    SW_SEARCH  - search "object" that holds search parameters
    SW_RESULTS - results "object" that holds a result set
    SW_RESULT  - a single result used for accessing the result's properties
    

=head2 Searching

=over 4

=item SW_HANDLE SwishInit(char *IndexFiles);

This functions opens and reads the header info of the index files
included in IndexFiles string.  The string should contain a space-separated
list of index files.

    SW_HANDLE myhandle;
    myhandle = SwishInit("file1.idx");

Typically you will open a handle at the beginning of your program and use it to make
multiple queries on an index.

This function will always return a swish handle.  You must check for errors, and on
error free the memory used by the handle, or abort.

Here's an example of aborting:

    SW_HANDLE swish_handle;
    swish_handle = SwishInit("file1.idx file2.idx");
    if ( SwishError( swish_handle ) )
        SwishAbortLastError( swish_handle );

And here's an example of catching the error:        

    SW_HANDLE swish_handle;
    swish_handle = SwishInit("file1.idx file2.idx");
    if ( SwishError( swish_handle ) )
    {
        printf("Failed to connect to swish. %s\n", SwishErrorString( swish_handle ) );
        SwishClose( swish_handle );  /* free the memory used */
        return 0;
    }

You may have more than one handle active at a time.

Swish-e will not tell you if the index file changes on disk (such as after reindexing).
In a persistent environment (e.g. mod_perl) the calling program should check to see if
the index file has changed on disk.  A common way to do this is to store the inode
number before opening the index file(s), and then stat the file name every so often
and reopen the index files if the inode number changes.


=item void SwishClose(SW_HANDLE handle);

This function closes and frees the memory of a Swish handle.
Every swish handle should be freed when done searching the index.
Failing to close the handle will result in a memory leak.

=item SW_SEARCH New_Search_Object(SW_HANDLE handle, const char *query);

Returns a new search "object".  The search object holds the parameters used for searching
an index.  A single search object can be used to query the index multiple times.
The available settings listed below are "sticky" in that they remain set on the search
object until change.

=item void SwishSetStructure( SW_SEARCH srch, int structure );

Sets the "structure" flag in the search object.  The structure flag is used to limit
searches to parts of HTML files (such as to the title or headers).  The default
is to not limit.  This provides the functionality of the -H command line switch.

=item void SwishPhraseDelimiter( SW_SEARCH srch, char delimiter );

Sets the phrase delimiter character.  The default is double-quotes.

=item void SwishSetSort( SW_SEARCH srch, char *sort );

Sets the sort order of the results.  This is the same as the -s switch used
with the swish-e binary.

=item void SwishSetQuery( SW_SEARCH srch, char *query );

Sets the query string in the search object.  This typically is not needed since
it can be set when creating the search object or when executing a query.

=item void SwishSetSearchLimit( SW_SEARCH srch, char *propertyname, char *low, char *hi);

Sets the limit parameters for a search.  Provides the same functionality as the -L command
line switch.
You may specify a range of property values that search results must be within.
You may call SwishSetSearchLimit() only one time for each property (but can set
limits on more than one property at a time).

Unlike the other settings on the search object, once you run a query on the
search object you must call SwishResetSearchLimit() to change or clear
the limit parameters.

=item void SwishResetSearchLimit( SW_SEARCH srch );

Resets the limits set on a search object set by SwishSetSearchLimit().

=item void Free_Search_Object( SW_SEARCH srch );

Frees the search object.  This must be called when done with the 
search object.  Generally, you can reuse a search object for
multiple queries so typically you would call this right before
calling SwishClose().

You may free the search object before freeing and
generated results objects.

=item SW_RESULTS SwishExecute( SW_SEARCH search, const char *query);

Searches the index or indexes based on the parameters in the search object.
Returns a results object.  See below for functions to access the data stored
in the results object.

You should always check for errors after calling SwishExecute().


=item SW_RESULTS SwishQuery(SW_HANDLE, const char *words );

This is a short-cut function that bypasses the creation of a
search object (actually, bypasses the need to create and free a search object).
This only allows passing in a query string; other search parameters cannot be set.
The results are sorted by rank.

You should always check for errors after calling SwishQuery().

=back

=head2 Reading Results

=over 4

=item int SwishHits( SW_RESULTS results );

Returns the number of results in the results object.

=item SWISH_HEADER_VALUE SwishParsedWords( SW_RESULTS, const char *index_name );

Returns the tokenized query.  Words are split by WordCharacters and stopwords are
removed.  The parsed words are useful for highlighting search terms in your
program.

The "index_name" is the name of the index supplied in the SwishInit() function call.

Returns a SWISH_HEADER_VALUE union of type SWISH_LIST which is a char **.
See src/libtest.c for an example of accessing the strings in this list, but in
general you may cast this to a (char **).

=item SWISH_HEADER_VALUE SwishRemovedStopwords( SW_RESULTS, const char *index_name );

Returns a list of stopwords removed from the input query.

Returns a SWISH_HEADER_VALUE union of type SWISH_LIST which is a char **.
See src/libtest.c for an example of accessing the strings in this list, but in
general you may cast this to a (char **).

=item int SwishSeekResult( SW_RESULTS, int position );

Sets the current seek position in the list of results, with position zero
being the first record (unlike -b where one is the first result).

Returns the position or a negative number on error.

=item SW_RESULT SwishNextResult( SW_RESULTS );

Returns the next result, or NULL if not more results are available.

The result object returned does not need to be freed after use
(unlike the swish handle, search object, and results object).

=item const char *SwishResultPropertyStr(SW_RESULT, char *propertyname);

Returns a string value of the specified property.  
Returns the empty string "" if the current result does not have
the specified property assigned.
Returns the string "(null)" on invalid property name (i.e. property name
is not defined in the index).

The string returned does not need to be freed, but is only valid
for the current result.  If you wish to save the string you must
copy it locally.

Numeric properties are zero filled for some odd reason.  Dates are 
formatted.

=item unsigned long SwishResultPropertyULong(SW_RESULT, char *propertyname);

Returns a numeric property as an unsigned long.  Returns UMAX_LONG on
errors.  Use the error checking functions to determine the exact error.

Numeric properties are used for both PropertyNamesNumeric and PropertyNamesDate
type of properties.

=item PropValue *getResultPropValue (RESULT *r, char *pname, int ID );

This is a low-level function to fetch a property regardless of type.
The return PropValue is a structure that contains a flag to indicate the
type, and a union that holds the property value.  

The property must be copied locally and the returned "PropValue" value must be freed by 
calling freeResultPropValue().  See perl/API.xs for an example.

=item void freeResultPropValue(void)

Frees the "PropValue" returned after calling getResultPropValue().

=item void Free_Results_Object( SW_RESULTS results );

Frees the results object (frees the result set).  This must be called
when done reading the results and before calling SwishClose().


=back

=head2 Accessing the Index Header Values

Each index file has associated header values that describe the index.  These functions
provide access to this data.  The header data is returned as a union SWISH_HEADER_VALUE,
and a pointer to a SWISH_HEADER_TYPE is passed in and the returned value indicates the
type of data that is returned.  See src/libtest.c and perl/API.xs for examples.

=over 4

=item const char **SwishHeaderNames( SW_HANDLE );

Returns the list of possible header names.  This list is the same for all index
files of a given version of Swish-e.  It provides a way to gain access to all
headers without having to list them in your program.

=item const char **SwishIndexNames( SW_HANDLE );

Returns a list of index files opened.  This is just the list of index files
specified in the SwishInit() call.  You need the name of the index file
to access a specific index's header values.

=item SWISH_HEADER_VALUE SwishHeaderValue( SW_HANDLE, const char *index_name, const  char *cur_header, SWISH_HEADER_TYPE *type );

Fetches the header value for the given index file, and the header name.  The call
sets the "type" passed in to the type of value returned.

See src/libtest.c and perl/API.xs for examples.


=item SWISH_HEADER_VALUE SwishResultIndexValue( SW_RESULT, const char *name, SWISH_HEADER_TYPE *type );

This is like SwishHeaderValue() above, but instead of supplying an index file name and
a swish handle, supply a result object and the header value is fetched from the result's
related index file.

=back

=head2 Checking for Errors

You should check for errors after all calls.  The last error is stored in the
swish handle object, and is only valid until the next operation (which resets
the error flags).  

Currently, some errors are flagged as "critical" errors.  In these cases you should
destroy (by calling the SwishClose() function ) the current swish handle.  If you have
other objects in scope (e.g. a search object or results object) destroy those first.

The types of errors that are critical can be seen in src/error.c.
Currently the list includes:

    Could not open index file
    Unknown index file format
    Index file(s) is empty
    Index file error
    Invalid swish handle
    Invalid results object

=over 4    

=item int  SwishError( SW_HANDLE );

This returns true if an error condition exists.  It returns the error number, which
is a integer less than zero on error.  This should be checked before calling any of the other
error functions below.

=item const char *SwishErrorString( SW_HANDLE );

This returns a general text description of the current error.

=item const char *SwishLastErrorMsg( SW_HANDLE );

In some cases this will return a string with specifics about the current error.
For example, SwishErrorString() may return "Unknown metaname", but SwishLastErrorMsg()
will return a string with the name of the unknown metaname.

=item int  SwishCriticalError( SW_HANDLE );

Returns true if the current error condition is a critical error.
On critical errors you should free up any current objects and call SwishClose()
as swish may be in an unstable state.

=item void SwishAbortLastError( SW_HANDLE );

This is a convenience  function that will format and print the last error message, and
then abort the program.


=item void set_error_handle( FILE *where );

Sets where errors and warnings are printed (when printed by swish).
For historical reasons, when swish-e first starts up errors and warnings are
sent to stdout.

=item void SwishErrorsToStderr( void );

A convenience method to send errors to stderr instead of stdout.

=back

=head2 Utility Functions

=over 4

=item const char *SwishWordsByLetter(SWISH * sw, char *indexname, char c);

Returns all the words in the index "indexname" that begin with the letter passed in.
Returns NULL if the name of the index file is invalid.

This fuction may change in the future since only 8-bit chars can currently be used.

=item char * SwsishStemWord( SW_HANDLE, char *in_word );

This can be used to convert a word to its stem.

=back

=head1 Bug-Reports

Please report bug reports to the Swish-e discussion group.
Feel also free to improve or enhance this feature.

=head1 Author

Original interface: Aug 2000 Jose Ruiz jmruiz@boe.es

Updated: Aug 22, 2002 - Bill Moseley

Interface redesigned for Swish-e version 2.3 Oct 17, 2002 - Bill Moseley

=head1 Document Info

$Id: SWISH-LIBRARY.pod,v 1.9 2003/07/05 16:38:14 whmoseley Exp $

.

