Home modules.gotpike.org
Username: Password: [Create Account]
[Forgot Password?]

Modules

ADT
Database
GTK2
GUI
IP
PiJAX
Public
Sql
Stdio
Subversion
System
Tools
Xosd
lua
v4l2
wx

Recent Changes

Public.Parser.XML2 1.50
Public.ZeroMQ 1.1
Public.Template.Mustache 1.0
Public.Protocols.XMPP 1.4
Sql.Provider.jdbc 1.0

Popular Downloads

Public.Parser.JSON2 1.0
Public.Parser.JSON 0.2
GTK2 2.23
Public.Web.FCGI 1.8
Public.Parser.XML2 1.48


Module Information
Public.Xapian
Viewing contents of Public_Xapian-1.10/xapian.ccmod

#define DEFAULT_CMOD_STORAGE
/*! @module Public
 */

/*! @module Xapian
 *!  An interface to the Xapian full text engine.
 *! 
 *!  For details, please see http://www.xapian.org
 */

#define _GNU_SOURCE

extern "C" {
#include "xapian_config.h"
#include "util.h"

}

#include 

#include 
#include 
#include 
#include 

using namespace Xapian;
using namespace std;

#include 

#define OBJ2_MSET(o) ((struct Xapian_MSet_struct *)get_storage(o, Xapian_MSet_program))
#define OBJ2_ESET(o) ((struct Xapian_ESet_struct *)get_storage(o, Xapian_ESet_program))
#define OBJ2_STEM(o) ((struct Xapian_Stem_struct *)get_storage(o, Xapian_Stem_program))
#define OBJ2_RSET(o) ((struct Xapian_RSet_struct *)get_storage(o, Xapian_RSet_program))
#define OBJ2_STOPPER(o) ((struct Xapian_Stopper_struct *)get_storage(o, Xapian_Stopper_program))
#define OBJ2_WEIGHT(o) ((struct Xapian_Weight_struct *)get_storage(o, Xapian_Weight_program))
#define OBJ2_MSETITERATOR(o) ((struct Xapian_MSetIterator_struct *)get_storage(o, Xapian_MSetIterator_program))
#define OBJ2_ESETITERATOR(o) ((struct Xapian_ESetIterator_struct *)get_storage(o, Xapian_ESetIterator_program))
#define OBJ2_VALUEITERATOR(o) ((struct Xapian_ValueIterator_struct *)get_storage(o, Xapian_ValueIterator_program))
#define OBJ2_TERMITERATOR(o) ((struct Xapian_TermIterator_struct *)get_storage(o, Xapian_TermIterator_program))
#define OBJ2_POSITIONITERATOR(o) ((struct Xapian_PositionIterator_struct *)get_storage(o, Xapian_PositionIterator_program))
#define OBJ2_DOCUMENT(o) ((struct Xapian_Document_struct *)get_storage(o, Xapian_Document_program))
#define OBJ2_DATABASE(o) ((struct Xapian_Database_struct *)get_storage(o, Xapian_Database_program))
#define OBJ2_QUERY(o) ((struct Xapian_Query_struct *)get_storage(o, Xapian_Query_program))
#define OBJ2_TERMGENERATOR(o) ((struct Xapian_TermGenerator_struct *)get_storage(o, Xapian_TermGenerator_program))
#define OBJ2_VALUERANGEPROCESSOR(o) ((struct Xapian_ValueRangeProcessor_struct *)get_storage(o, Xapian_ValueRangeProcessor_program))


extern "C" struct program * Xapian_Document_program;
extern "C" struct program * Xapian_MSetIterator_program;
extern "C" struct program * Xapian_ValueIterator_program;
extern "C" struct program * Xapian_TermIterator_program;
extern "C" struct program * Xapian_PositionIterator_program;
extern "C" struct program * Xapian_MSet_program;
extern "C" struct program * Xapian_Stem_program;
extern "C" struct program * Xapian_TermGenerator_program;
extern "C" struct program * Xapian_ValueRangeProcessor_program;
extern "C" typedef struct
{
    Database *database;
} XAPIAN_DATABASE_OBJECT_DATA;

extern "C" typedef struct
{
    Stem *stem;
} XAPIAN_STEM_OBJECT_DATA;

extern "C" typedef struct
{
    Weight *weight;
} XAPIAN_WEIGHT_OBJECT_DATA;

extern "C" typedef struct
{
    TermGenerator *termgenerator;
} XAPIAN_TERMGENERATOR_OBJECT_DATA;

extern "C" typedef struct
{
    QueryParser *parser;
} XAPIAN_QUERYPARSER_OBJECT_DATA;

extern "C" typedef struct
{
    Stopper *stopper;
} XAPIAN_STOPPER_OBJECT_DATA;

extern "C" typedef struct
{
    Enquire *enquire;
} XAPIAN_ENQUIRE_OBJECT_DATA;

extern "C" typedef struct
{
    Query *query;
} XAPIAN_QUERY_OBJECT_DATA;

extern "C" typedef struct
{
    MSet *mset;
} XAPIAN_MSET_OBJECT_DATA;

extern "C" typedef struct
{
    RSet *rset;
} XAPIAN_RSET_OBJECT_DATA;

extern "C" typedef struct
{
    MSetIterator *mseti;
} XAPIAN_MSETITERATOR_OBJECT_DATA;

extern "C" typedef struct
{
    ValueIterator *valuei;
} XAPIAN_VALUEITERATOR_OBJECT_DATA;

extern "C" typedef struct
{
    PositionIterator *positioni;
} XAPIAN_POSITIONITERATOR_OBJECT_DATA;

extern "C" typedef struct
{
    ESet *eset;
} XAPIAN_ESET_OBJECT_DATA;

extern "C" typedef struct
{
    ESetIterator *eseti;
} XAPIAN_ESETITERATOR_OBJECT_DATA;

extern "C" typedef struct
{
    TermIterator *termi;
} XAPIAN_TERMITERATOR_OBJECT_DATA;

extern "C" typedef struct
{
    Document *document;
} XAPIAN_DOCUMENT_OBJECT_DATA;

extern "C" typedef struct
{
    ValueRangeProcessor *processor;
} XAPIAN_VALUERANGEPROCESSOR_OBJECT_DATA;

/*! @decl string sortable_serialise(float value)
 *! 
 *! Convert a floating point number to a string, preserving sort order.  
 */
PIKEFUN string sortable_serialise(float value)
{
  string str = sortable_serialise(value);
  pop_stack();
  push_text(str.c_str());  
}

/*! @decl float sortable_unserialise(string value)
 *!
 *! Convert a string encoded using sortable_serialise back to a floating 
 *! point number. 
 */
PIKEFUN float sortable_unserialise(string value)
{
   double f;
   string str((const char *)value->str, (size_t)value->len);
   f = sortable_unserialise(str);
   push_float(f);
}

/*! @decl int minor_version()
 */
PIKEFUN int minor_version()
{
  push_int(minor_version());
}

/*! @decl int major_version()
 */
PIKEFUN int major_version()
{
  push_int(major_version());
}

/*! @decl int revision()
 */
PIKEFUN int revision()
{
  push_int(revision());
}


/*! @decl string version_string()
 *! Report the version string of the library which the program is linked 
 *! with. 
 */
PIKEFUN string version_string()
{
   push_text(version_string());
}

/*! @class Weight
*/
PIKECLASS Weight
{
CVAR XAPIAN_WEIGHT_OBJECT_DATA   *object_data;

/*  Weight.int get_sumpart_needs_doclength() */
/*! @decl int get_sumpart_needs_doclength()
 *!
 *! returns false if the weight object doesn't need doclength   
 *! @returns
 *!  
 *!
 */
PIKEFUN int get_sumpart_needs_doclength()
{
#ifdef HAVE_WEIGHT_GET_SUMPART_NEEDS_DOCLENGTH
  Weight *weight;
  weight = THIS->object_data->weight;

  bool i = weight->get_sumpart_needs_doclength();

  push_int(i?1:0);
#else
  push_int(0);
#endif /* HAVE_WEIGHT_GET_SUMPART_NEEDS_DOCLENGTH */
}

/*  Weight.float get_maxpart() */
/*! @decl float get_maxpart()
 *!
 *!  Gets the maximum value that @[get_sumpart]() may return. 
 *!  
 *!  This is used in optimising searches, by having the postlist tree 
 *!  decay appropriately when parts of it can have limited, or no, further 
 *!  effect.
 *! @returns
 *!  
 *!
 */
PIKEFUN float get_maxpart()
{
  Weight *weight;
  weight = THIS->object_data->weight;

  Xapian::weight i = weight->get_maxpart();

  push_float((FLOAT_TYPE)i);
}

/*  Weight.float get_maxextra() */
/*! @decl float get_maxextra()
 *!
 *!  Gets the maximum value that @[get_sumextra]() may return. 
 *!  
 *!  This is used in optimising searches.
 *! @returns
 *!  
 *!
 */
PIKEFUN float get_maxextra()
{
  Weight *weight;
  weight = THIS->object_data->weight;

  Xapian::weight i = weight->get_maxextra();

  push_float((FLOAT_TYPE)i);
}

/*  Weight.float get_sumextra(int len) */
/*! @decl float get_sumextra(int len)
 *!
 *!  Get an extra weight for a document to add to the sum calculated over 
 *!  the query terms. 
 *! 
 *! This returns a weight for a given document, and is used by some 
 *! weighting schemes to account for influence such as document length.
 *! @param len
 *!  the (unnormalised) document length.
 *!
 *! @returns
 *!  
 *!
 */
PIKEFUN float get_sumextra(int len)
{
  Weight *weight;
  weight = THIS->object_data->weight;

  Xapian::weight i = weight->get_sumextra((doclength)len);

  push_float((FLOAT_TYPE)i);
}

/*  Weight.float get_sumpart(int wdf, int len) */
/*! @decl float get_sumpart(int wdf, int len)
 *!Get a weight which is part of the sum over terms being performed.
 *! 
 *! This returns a weight for a given term and document. These weights are 
 *! summed to give a total weight for the document.
 *!  
 *! @param wdf
 *!  the within document frequency of the term.
* !
 *! @param len
 *!  the (unnormalised) document length.
* !
 *! @returns
 *!  
 *!
 */
PIKEFUN float get_sumpart(int wdf, int len)
{
  Weight *weight;
  weight = THIS->object_data->weight;

  Xapian::weight i = weight->get_sumpart((termcount)wdf, (doclength)len);

  push_float((FLOAT_TYPE)i);
}


/*  Weight.string serialise() */
/*! @decl string serialise()
 *!
 *!  Serialise object parameters into a string.
 *! @returns
 *!  
 *!
 */
PIKEFUN string serialise()
{
  Weight *weight;
  weight = THIS->object_data->weight;

  string str = weight->serialise();

  push_text(str.c_str());
}

/*  Weight.string name() */
/*! @decl string name()
 *!
 *!  Name of the weighting scheme.
 *! 
 *! If the subclass is called FooWeight, this should return "Foo".
 *! @returns
 *!  
 *!
 */
PIKEFUN string name()
{
  Weight *weight;
  weight = THIS->object_data->weight;

  string str = weight->name();

  push_text(str.c_str());
}

INIT
{
    XAPIAN_WEIGHT_OBJECT_DATA * dta = 
	(XAPIAN_WEIGHT_OBJECT_DATA*)malloc(sizeof(XAPIAN_WEIGHT_OBJECT_DATA));
    if (!dta)
        Pike_error("init_sample: Out of memory!\n");

    dta->weight = NULL;
    THIS->object_data = dta;
}

/*  Weight.void destroy() */
/*! @decl void destroy()
 *!
 *!  
 *!
 */
PIKEFUN void destroy(int|void reason)
{

    Weight *weight;
    weight = THIS->object_data->weight;

    if(weight) 
    {
     delete weight;
    }

    pop_n_elems(args);
}

EXIT 
{
  if(THIS->object_data)
  {

    Weight  *weight;
    weight = THIS->object_data->weight;
//    printf("shutting down!\n");
    free(THIS->object_data);
  }
}

}

/*!  @endclass
*/

/*! @class BM25Weight
 *! @inherit Weight
 *! BM25 weighting scheme.
*/

PIKECLASS BM25Weight
{
  INHERIT Xapian_Weight;

  PIKEFUN void create(float k1, float k2, float k3, float b, float min_normlen)
  {
    BM25Weight * weight;
    
    weight = new BM25Weight((double)k1, (double)k2, (double)k3, (double)b, (double)min_normlen);

    THIS->object_data->weight = weight;
  }

}

/*!  @endclass
*/

/*! @class BoolWeight
 *! @inherit Weight
 *! Boolean weighting scheme (everything gets 0).
*/

PIKECLASS BoolWeight
{
  INHERIT Xapian_Weight;

  PIKEFUN void create()
  {
    BoolWeight * weight;
    
    weight = new BoolWeight();

    THIS->object_data->weight = weight;
  }
}

/*!  @endclass
*/

/*! @class TradWeight
 *! @inherit Weight
 *! Traditional probabilistic weighting scheme.
 *! 
 *! This class implements the Traditional Probabilistic Weighting scheme, 
 *! as described by the early papers on Probabilistic Retrieval. @[BM25Weight]
 *! generally gives better results. 
*/

PIKECLASS TradWeight
{
  INHERIT Xapian_Weight;

  PIKEFUN void create(float k)
  {
    TradWeight * weight;
    
    weight = new TradWeight((double)k);

    THIS->object_data->weight = weight;
  }
}

/*!  @endclass
*/

/*! @class ValueRangeProcessor
 *! Base class for value range processors. 
*/

PIKECLASS ValueRangeProcessor
{
CVAR XAPIAN_VALUERANGEPROCESSOR_OBJECT_DATA   *object_data;

/*! @decl int `()(string begin, string end)
 *!
 *!  	Is term a stop-word?   
 *! @returns
 *!  1 if true, 0 otherwise.
 *!
 */
PIKEFUN int `()(string begin, string end)
{
  ValueRangeProcessor * vrp;
  bool i;
  vrp = THIS->object_data->processor;
  string str1((const char *)begin->str, (size_t)begin->len);
  string str2((const char *)end->str, (size_t)end->len);

  i = (*vrp)(str1, str2);  

  push_int(i?1:0);
}

INIT
{
    XAPIAN_VALUERANGEPROCESSOR_OBJECT_DATA * dta = 
	(XAPIAN_VALUERANGEPROCESSOR_OBJECT_DATA*)malloc(sizeof(XAPIAN_VALUERANGEPROCESSOR_OBJECT_DATA));
    if (!dta)
        Pike_error("init_sample: Out of memory!\n");

    dta->processor = NULL;
    THIS->object_data = dta;
}

/*! @decl void destroy()
 *!
 *!  
 *!
 */
PIKEFUN void destroy(int|void reason)
{
    ValueRangeProcessor  *vrp;
    vrp = THIS->object_data->processor;

    if(vrp) 
    {
     delete vrp;
    }

    pop_n_elems(args);
}

EXIT 
{
  if(THIS->object_data)
  {

    ValueRangeProcessor  *vrp;
    vrp = THIS->object_data->processor;
 //   printf("shutting down!\n");
    free(THIS->object_data);
  }
}

}
/*!  @endclass
*/


/*! @class StringValueRangeProcessor
 *! @inherit ValueRangeProcessor
 *!
 *! Handle a string range.
 *!
 *! The end points can be any strings. 
 */

PIKECLASS StringValueRangeProcessor
{
  INHERIT Xapian_ValueRangeProcessor;

  PIKEFUN void create(int valueno)
  {
    StringValueRangeProcessor * vrp = new StringValueRangeProcessor(valueno);

    THIS_XAPIAN_VALUERANGEPROCESSOR->object_data->processor = (ValueRangeProcessor*) vrp ;
    pop_n_elems(args);
  }

}
/*!  @endclass
*/


/*! @class NumberValueRangeProcessor
 *! @inherit ValueRangeProcessor
 *!
 *! Handle a number range.
 *!
 *! This class must be used on values which have been encoded using 
 *! @[Public.Xapian.sortable_serialise]() which turns numbers into strings 
 *! which will sort in the same order as the numbers (the same values can 
 *! be used to implement a numeric sort).
 *!
 */

PIKECLASS NumberValueRangeProcessor
{
  INHERIT Xapian_ValueRangeProcessor;

  PIKEFUN void create(int valueno)
  {
    NumberValueRangeProcessor * vrp = new NumberValueRangeProcessor(valueno);

    THIS_XAPIAN_VALUERANGEPROCESSOR->object_data->processor = (ValueRangeProcessor*) vrp ;
    pop_n_elems(args);
  }

/*! @decl void create(int valueno, string _str, int is_prefix)
 *!
 *! The string supplied in str_ is used by operator() to decide whether 
 *! the pair of strings supplied to it constitute a valid range. If 
 *! prefix_ is true, the first value in a range must begin with str_ (and 
 *! the second value may optionally begin with str_); if prefix_ is 
 *! false, the second value in a range must end with str_ (and the first 
 *! value may optionally end with str_).
 *! 
 *! If str_ is empty, the setting of prefix_ is irrelevant, and no special 
 *! strings are required at the start or end of the strings defining the 
 *! range.
 *! 
 *! The remainder of both strings defining the endpoints must be valid 
 *! floating point numbers. (FIXME: define format recognised).
 *! 
 *! For example, if str_ is "$" and prefix_ is true, and the range 
 *! processor has been added to the queryparser, the queryparser will 
 *! accept "$10..50" or "$10..50", but not "10..50" or "10..$50" as valid 
 *! ranges. If str_ is 
 *! "kg" and prefix_ is false, the queryparser will accept "10..50kg" or 
 *! "10kg..50kg", but not "10..50" or "10kg..50" as valid ranges. 
 */
  PIKEFUN void create(int valueno, string _str, int is_prefix)
  {
    NumberValueRangeProcessor * vrp;
    string str((const char *)_str->str, (size_t)_str->len);

    vrp = new NumberValueRangeProcessor(valueno, str, is_prefix);

    THIS_XAPIAN_VALUERANGEPROCESSOR->object_data->processor = (ValueRangeProcessor*) vrp ;
    pop_n_elems(args);
  }

}

/*! @endclass
 *!
 */

/*! @class DateValueRangeProcessor
 *! @inherit ValueRangeProcessor
 *!
 */

PIKECLASS DateValueRangeProcessor
{
  INHERIT Xapian_ValueRangeProcessor;

/*! @decl void create(int valueno, int prefer_mdy, int epoch_year)
 *! @param valueno
 *!    The value number to return from `()().
 *! @param prefer_mdy
 *!    Should ambiguous dates be interpreted as month/day/year rather than 
 *!    day/month/year?
 *! @param epoch_year
 *!    Year to use as the epoch for dates with 2 digit years (default: 
 *!    1970, so 1/1/69 is 2069 while 1/1/70 is 1970).
 */
  PIKEFUN void create(int valueno, int prefer_mdy, int epoch_year)
  {
    DateValueRangeProcessor * vrp = new DateValueRangeProcessor(valueno, prefer_mdy, epoch_year);

    THIS_XAPIAN_VALUERANGEPROCESSOR->object_data->processor = (ValueRangeProcessor*) vrp ;
    pop_n_elems(args);
  }

}
/*!  @endclass
*/

/*! @class Stopper
 *! Base class for stop-word decision functor. 
*/

PIKECLASS Stopper
{
CVAR XAPIAN_STOPPER_OBJECT_DATA   *object_data;

/*! @decl int `()(string word)
 *!
 *!  	Is term a stop-word?   
 *! @returns
 *!  1 if true, 0 otherwise.
 *!
 */
PIKEFUN int `()(string word)
{
  Stopper  *stopper;
  bool i;
  stopper = THIS->object_data->stopper;
  string str((const char *)word->str, (size_t)word->len);

  i = (*stopper)(str);  

  push_int(i?1:0);
}

/*  Stopper.string get_description() */
/*! @decl string get_description()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN string get_description()
{
  Stopper  *stopper;
  stopper = THIS->object_data->stopper;

  string str = stopper->get_description();

  push_text(str.c_str());
}

PIKEFUN string _sprintf(int conversion_type, mapping params)
{
  Stopper  *stopper;
  if(THIS && THIS->object_data && conversion_type == 'O')
  {
    stopper = THIS->object_data->stopper;

    string str = stopper->get_description();
    pop_n_elems(args);
    push_text(str.c_str());
  }
  else
  {
    pop_n_elems(args);
    push_int(0);
  }
}


INIT
{
    XAPIAN_STOPPER_OBJECT_DATA * dta = 
	(XAPIAN_STOPPER_OBJECT_DATA*)malloc(sizeof(XAPIAN_STOPPER_OBJECT_DATA));
    if (!dta)
        Pike_error("init_sample: Out of memory!\n");

    dta->stopper = NULL;
    THIS->object_data = dta;
}

/*  Stopper.void destroy() */
/*! @decl void destroy()
 *!
 *!  
 *!
 */
PIKEFUN void destroy(int|void reason)
{

    Stopper  *stopper;
    stopper = THIS->object_data->stopper;

    if(stopper) 
    {
     delete stopper;
    }

    pop_n_elems(args);
}

EXIT 
{
  if(THIS->object_data)
  {

    Stopper  *stopper;
    stopper = THIS->object_data->stopper;
 //   printf("shutting down!\n");
    free(THIS->object_data);
  }
}

}

/*!  @endclass
*/

/*! @class SimpleStopper
 *! @inherit Stopper
 *! Simple implementation of Stopper class - this will suit most users.
 */

PIKECLASS SimpleStopper
{
  INHERIT Xapian_Stopper;

  PIKEFUN void create()
  {
    SimpleStopper * stopper = new SimpleStopper();

    THIS->object_data->stopper = (Stopper*) stopper;
    pop_n_elems(args);
  }

  PIKEFUN void create(array words)
  {
    int i;
    vector v;

    for(i = 0; i < words->size; i++)
    {  
       string str((const char *)(ITEM(words)[i].u.string->str), 
                  (size_t)(ITEM(words)[i].u.string->len));
       v.push_back(str);
    }
    
    SimpleStopper * stopper = new SimpleStopper(v.begin(), v.end());

    THIS_XAPIAN_STOPPER->object_data->stopper = (Stopper*) stopper;
    pop_n_elems(args);
  }

/*! @decl void add(string word)
 *! Add a single stop word.
 */
  PIKEFUN void add(string word)
  {
    SimpleStopper * stopper;
    string str((const char*)word->str, (size_t)word->len);
    stopper = (SimpleStopper *)THIS_XAPIAN_STOPPER->object_data->stopper;
    stopper->add(str);
    pop_stack();
    
  }

  
}

/*!  @endclass
*/

/*! @class Stem
 *! Class representing a stemming algorithm.
*/

PIKECLASS Stem
{
CVAR XAPIAN_STEM_OBJECT_DATA   *object_data;


/*  Stem.void create(string language) */
/*! @decl void create(string language)
 *!
 *!  Construct a @[Stem] object for a particular language.
 *! @param language
 *!      	Either the English name for the language or the two letter ISO639 code.
*!
*! The following language names are understood (aliases follow the name):
*!
*!    * none - don't stem terms
*!    * danish (da)
*!    * dutch (nl)
*!    * english (en) - Martin Porter's 2002 revision of his stemmer
*!    * english_lovins (lovins) - Lovin's stemmer
*!    * english_porter (porter) - Porter's stemmer as described in his 1980 paper
*!    * finnish (fi)
*!    * french (fr)
*!    * german (de)
*!    * italian (it)
*!    * norwegian (no)
*!    * portuguese (pt)
*!    * russian (ru)
*!    * spanish (es)
*!    * swedish (sv)
*!
* ! @note
 *!  an error will be thrown if the specified language is unknown.
 */
PIKEFUN void create(string language)
{
  Stem* stem;
  const string str((const char *)language->str, (size_t)language->len);

  try
  {
    stem = new Stem(str);
  }

  catch(const InvalidArgumentError &e)
  {
    pop_n_elems(args);
    Pike_error("InvalidArgumentError\n");
  }

  pop_n_elems(args);

  THIS->object_data->stem = stem;
}

/*  Stem.void create() */
/*! @decl void create()
 *!
 *!  
 *!
 */
PIKEFUN void create()
{
    Stem* stem = new Stem();

    pop_n_elems(args);

    THIS->object_data->stem = stem;
}

/*  Stem.string stem_word(string word) */
/*! @decl string `()(string word)
 *!   stem a word
 *!  
 *! @param word
 *!   word to be stemmed
* !
 *! @returns
 *!   the word stem  
 *!
 *! @note
 *!   this function is wide-string aware.
 *!
 */
PIKEFUN string `()(string word)
{
  Stem  *stem;
  string foo;

  ref_push_string(word);
  f_string_to_utf8(1);

  const string str((const char *)Pike_sp[-1].u.string->str, (size_t) Pike_sp[-1].u.string->len);

  stem = THIS->object_data->stem;

  foo = (*stem)(str);
  pop_n_elems(args+1);
  push_text(foo.c_str());
}

/*  Stem.string get_description() */
/*! @decl string get_description()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN string get_description()
{
  Stem  *stem;
  stem = THIS->object_data->stem;

  string str = stem->get_description();

  push_text(str.c_str());
}

PIKEFUN string _sprintf(int conversion_type, mapping params)
{
  Stem  *stem;
  if(THIS && THIS->object_data && conversion_type == 'O')
  {
    stem = THIS->object_data->stem;

    string str = stem->get_description();
    pop_n_elems(args);
    push_text(str.c_str());
  }
  else
  {
    pop_n_elems(args);
    push_int(0);
  }
}


INIT
{
    XAPIAN_STEM_OBJECT_DATA * dta = 
	(XAPIAN_STEM_OBJECT_DATA*)malloc(sizeof(XAPIAN_STEM_OBJECT_DATA));
    if (!dta)
        Pike_error("init_sample: Out of memory!\n");

    dta->stem = NULL;
    THIS->object_data = dta;
}

/*  Stem.void destroy() */
/*! @decl void destroy()
 *!
 *!  
 *!
 */
PIKEFUN void destroy(int|void reason)
{

    Stem  *stem;
    stem = THIS->object_data->stem;

    if(stem) 
    {
     delete stem;
    }

    pop_n_elems(args);
}

EXIT 
{
  if(THIS->object_data)
  {

    Stem  *stem;
    stem = THIS->object_data->stem;
 //   printf("shutting down!\n");
    free(THIS->object_data);
  }
}

}

/*!  @endclass
*/

/*! @class Query
*! Class representing a query.
*!
*! Queries are represented as a tree of objects. 
*/

PIKECLASS Query
{

CVAR XAPIAN_QUERY_OBJECT_DATA   *object_data;


/*  Query.void create() */
/*! @decl void create()
 *!
 *! Default constructor: makes an empty query which matches no documents.
 *! 
 *! Also useful for defining a Query object to be assigned to later.
 *!
 *! @note
 *! An exception will be thrown if an attempt is made to use an undefined 
 *! query when building up a composite query.
 *!
 */
PIKEFUN void create()
{
  try
  {
    Query* query = new Query();

    pop_n_elems(args);

    THIS->object_data->query = query;
  }

  catch(...) 
  {
    Pike_error("an error occurred!\n");
  }
}

/*  Query.void create(string term, int wqf, int pos) */
/*! @decl void create(string term, int wqf, int pos)
 *!
 *!    A query consisting of a single term.
 *! @param term
 *!  
* !
 *! @param wqf
 *!  
* !
 *! @param pos
 *!  
* !
 *!
 */
PIKEFUN void create(string term, int wqf, int pos)
{
  try
  {
	string str((const char *)term->str, (size_t)term->len);
    Query* query = new Query(str, (termcount)wqf, (termpos)pos);

    pop_n_elems(args);

    THIS->object_data->query = query;
  }

  catch(...) 
  {
    Pike_error("an error occurred!\n");
  }
}

/*  Query.void create(int op, string left, string right) */
/*! @decl void create(int op, string left, string right)
 *!
 *!  A query consisting of two terms, opp-ed together.
 *! @param op
 *!  
* !
 *! @param left
 *!  
* !
 *! @param right
 *!  
* !
 *!
 */
PIKEFUN void create(int op, string left, string right)
{
  try
  {
	string lstr((const char *)left->str, (size_t)left->len);
	string rstr((const char *)right->str, (size_t)right->len);
    Query* query = new Query((Xapian::Query::op)op, lstr, rstr);

    pop_n_elems(args);

    THIS->object_data->query = query;
  }

  catch(...) 
  {
    Pike_error("an error occurred!\n");
  }
}


/*  Query.void create(int op, object left, object right) */
/*! @decl void create(int op, object left, object right)
 *!
 *!  A query consisting of two subqueries, opp-ed together.
 *! @param op
 *!  
* !
 *! @param left
 *!  
* !
 *! @param right
 *!  
* !
 *!
 */
PIKEFUN void create(int op, object left, object right)
{
  Query * l;
  Query * r;

  l = OBJ2_QUERY(left)->object_data->query;
  r = OBJ2_QUERY(right)->object_data->query;

  try
  {
    Query* query = new Query((Xapian::Query::op)op, l, r);

    pop_n_elems(args);

    THIS->object_data->query = query;
  }

  catch(...) 
  {
    Pike_error("an error occurred!\n");
  }
}

/*  Query.void create(int op, Query query) */
/*! @decl void create(int op, Query query)
 *! Apply the specified operator to a single @[Query] object, with a 
 *! double parameter.
 *!  
 *! @param op
 *!  
* !
 *! @param query
 *!  
* !
 *!
 */
PIKEFUN void create(int op, object query, float param)
{
  Query * q;

  q = OBJ2_QUERY(query)->object_data->query;

  try
  {
    Query* qe = new Query((Xapian::Query::op)op, *q, param);

    pop_n_elems(args);

    THIS->object_data->query = qe;
  }

  catch(...) 
  {
    Pike_error("an error occurred!\n");
  }
}

/*  Query.int get_length() */
/*! @decl int get_length()
 *!
 *!  Get the length of the query, used by some ranking formulae.
 *!
 *! This value is calculated automatically - if you want to override it 
 *! you can pass a different value to @[Enquire.set_query]().
 *! @returns
 *!  
 *!
 */
PIKEFUN int get_length()
{
  Query  *query;
  query = THIS->object_data->query;
  termcount i = query->get_length();

  push_int(i);
}

/*  Query.int empty() */
/*! @decl int empty()
 *!  Test if the query is empty (i.e. was constructed using the default 
 *! constructor).
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN int empty()
{
  Query  *query;
  query = THIS->object_data->query;
  bool i = query->empty();

  push_int(i?1:0);
}


/*  Query.string get_description() */
/*! @decl string get_description()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN string get_description()
{
  Query  *query;
  query = THIS->object_data->query;

  string str = query->get_description();

  push_text(str.c_str());
}

PIKEFUN string _sprintf(int conversion_type, mapping params)
{
  Query  *query;
  if(THIS && THIS->object_data && conversion_type == 'O')
  {
    query = THIS->object_data->query;

    string str = query->get_description();
    pop_n_elems(args);
    push_text(str.c_str());
  }
  else
  {
    pop_n_elems(args);
    push_int(0);
  }
}

INIT
{
    XAPIAN_QUERY_OBJECT_DATA * dta = 
	(XAPIAN_QUERY_OBJECT_DATA*)malloc(sizeof(XAPIAN_QUERY_OBJECT_DATA));
    if (!dta)
        Pike_error("init_sample: Out of memory!\n");

    dta->query = NULL;
    THIS->object_data = dta;
}

EXIT 
{
  if(THIS->object_data)
  {
    Query  *query;
    query = THIS->object_data->query;
     if(query) delete query;
    free(THIS->object_data);
  }
}

EXTRA
{
/*! @decl constant OP_AND
 *! Return iff both subqueries are satisfied.
 */
add_integer_constant("OP_AND", Query::OP_AND, 0);
/*! @decl constant OP_OR
 *! Return if either subquery is satisfied. 
 */
add_integer_constant("OP_OR", Query::OP_OR, 0);
/*! @decl constant OP_AND_NOT
 *! Return if left but not right satisfied.
 */
add_integer_constant("OP_AND_NOT", Query::OP_AND_NOT, 0);
/*! @decl constant OP_XOR
 *! Return if one query satisfied, but not both.
 */
add_integer_constant("OP_XOR", Query::OP_XOR, 0);
/*! @decl constant OP_AND_MAYBE
 *! Return iff left satisfied, but use weights from both.
 */
add_integer_constant("OP_AND_MAYBE", Query::OP_AND_MAYBE, 0);
/*! @decl constant OP_FILTER
 *! As AND, but use only weights from left subquery.
 */
add_integer_constant("OP_FILTER", Query::OP_FILTER, 0);
/*! @decl constant OP_NEAR
 *! Find occurrences of a list of terms with all the terms occurring 
 *! within a specified window of positions.
 *! 
 *! Each occurrence of a term must be at a different position, but the 
 *! order they appear in is irrelevant.
 *! 
 *! The window parameter should be specified for this operation, but will 
 *! default to the number of terms in the list. 
 */
add_integer_constant("OP_NEAR", Query::OP_NEAR, 0);
/*! @decl constant OP_PHRASE
 *!  Find occurrences of a list of terms with all the terms occurring 
 *! within a specified window of positions, and all the terms appearing 
 *! in the order specified.
 *! 
 *! Each occurrence of a term must be at a different position.
 *! 
 *! The window parameter should be specified for this operation, but will 
 *! default to the number of terms in the list. 
 */
add_integer_constant("OP_PHRASE", Query::OP_PHRASE, 0);
/*! @decl constant OP_ELITE_SET
 *! Select an elite set from the subqueries, and perform a query with 
 *! these combined as an OR query. 
 */
add_integer_constant("OP_ELITE_SET", Query::OP_ELITE_SET, 0);
/*! @decl constant OP_VALUE_RANGE
 *! Filter by a range test on a document value.
 */
add_integer_constant("OP_VALUE_RANGE", Query::OP_VALUE_RANGE, 0);
/*! @decl constant OP_SCALE_WEIGHT
 *! Scale the weight of a subquery by the specified factor.
 *! 
 *! A factor of 0 means this subquery will contribute no weight to the 
 *! query - it will act as a purely boolean subquery.
 *! 
 *! If the factor is negative, an error will be 
 *! thrown. 
 */
add_integer_constant("OP_SCALE_WEIGHT", Query::OP_SCALE_WEIGHT, 0);
}

}

/*!  @endclass
*/

/*! @class PositionIterator
*/

PIKECLASS PositionIterator
{
  CVAR PositionIterator * pie;
  CVAR int current_index;
  CVAR XAPIAN_POSITIONITERATOR_OBJECT_DATA   *object_data;

  PIKEFUN object next()
  {
    ++(*(THIS->object_data->positioni));

   THIS->current_index++;
    push_object(this_object());    
  }

  PIKEFUN mixed index()
  {
    push_int(THIS->current_index);
  }

  PIKEFUN object value()
  {
    push_object(this_object());
  }

  PIKEFUN int `==(mixed arg)
  {
    struct object * o;
    PositionIterator  *posi;
    PositionIterator  *posb;
    struct Xapian_PositionIterator_struct * pis;    

    if(TYPEOF(*arg)!= T_OBJECT) RETURN(0);
    o = arg->u.object;
    posi = (PositionIterator*)THIS->object_data->positioni;
    pis = OBJ2_POSITIONITERATOR(o);
    if(!pis) RETURN(0);

    posb = pis->object_data->positioni;
    if(*posi == *posb) RETURN(1);
    else RETURN(0);
  }

/*! @decl void skip_to(int pos)
 *!
 *!  
 *! @returns
 *!  
 *!
 */
  PIKEFUN void skip_to(int pos)
  {
    
    PositionIterator  *posi;
    try 
    {
      posi = (PositionIterator*)THIS->object_data->positioni;
      posi->skip_to(pos);
      pop_stack();
      push_int(0);
    }
    catch(const RangeError &e)
    {
      pop_n_elems(args);
      Pike_error("RangeError\n");
    }


  }

/*! @decl int get_position()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
  PIKEFUN int get_position()
  {
    PositionIterator  *posi;
    int i;
    try
    {
      posi = (PositionIterator*)THIS->object_data->positioni;
      i = (*(*posi));
      push_int(i);
    }
    catch(const RangeError &e)
    {
      pop_n_elems(args);
      Pike_error("RangeError\n");
    }
  }

  PIKEFUN int `!()
  {
    PositionIterator  *pi;
    pi = THIS->object_data->positioni;
    if(*pi == *(THIS->pie)) { push_int(1); }
    else
      push_int(0);
  }

/*! @decl string get_description()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN string get_description()
{
  PositionIterator  *pi;
  pi = THIS->object_data->positioni;

  string str = pi->get_description();

  push_text(str.c_str());
}

PIKEFUN string _sprintf(int conversion_type, mapping params)
{
  PositionIterator  *it;
  if(THIS && THIS->object_data && conversion_type == 'O')
  {
    it = THIS->object_data->positioni;

    string str = it->get_description();
    pop_n_elems(args);
    push_text(str.c_str());
  }
  else
  {
    pop_n_elems(args);
    push_int(0);
  }
}


INIT
{
    XAPIAN_POSITIONITERATOR_OBJECT_DATA * dta = 
	(XAPIAN_POSITIONITERATOR_OBJECT_DATA*)malloc(sizeof(XAPIAN_POSITIONITERATOR_OBJECT_DATA));
    if (!dta)
        Pike_error("init_positioniterator: Out of memory!\n");

    dta->positioni = NULL;
    THIS->object_data = dta;
}

EXIT 
{
  if(THIS->object_data)
  {
    PositionIterator  *positioni;
    positioni = THIS->object_data->positioni;
    if(positioni) delete positioni;
    free(THIS->object_data);
  }
}

}

/*!  @endclass
*/

/*! @class ValueIterator
*/

PIKECLASS ValueIterator
{
  CVAR ValueIterator * vie;
  CVAR int current_index;
  CVAR XAPIAN_VALUEITERATOR_OBJECT_DATA   *object_data;

  PIKEFUN object next()
  {
    ValueIterator v;
    ++(*(THIS->object_data->valuei));

    push_object(this_object());    
  }

  PIKEFUN mixed index()
  {
    int i = 21;

    try
    {
      ValueIterator v = *(THIS->object_data->valuei);
      i = v.get_valueno();
    }    
    catch(const RangeError &e)
    {
      pop_n_elems(args);
      Pike_error("RangeError\n");
    }
    push_int(i);
  }

  PIKEFUN string value()
  {
    string i;

    try
    {
      i = (*(*(THIS->object_data->valuei)));
      push_text(i.c_str());
    }
    catch(const RangeError &e)
    {
      pop_n_elems(args);
      Pike_error("RangeError\n");
    }
  }

  PIKEFUN int `==(mixed arg)
  {
    struct object * o;
    ValueIterator  *valuei;
    ValueIterator  *valueb;
    struct Xapian_ValueIterator_struct * vis;    

    if(TYPEOF(*arg)!= T_OBJECT) RETURN(0);
    o = arg->u.object;
    valuei = (ValueIterator*)THIS->object_data->valuei;
    vis = OBJ2_VALUEITERATOR(o);
    if(!vis) RETURN(0);

    valueb = vis->object_data->valuei;
    if(*valuei == *valueb) RETURN(1);
    else RETURN(0);
  }

/*! @decl int get_valueno()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
  PIKEFUN int get_valueno()
  {
    valueno i;

    try 
    { 
      ValueIterator v;
      v = *(THIS->object_data->valuei);
      i = v.get_valueno();
      push_int((INT_TYPE)i);
    }
    catch(const RangeError &e)
    {
      pop_n_elems(args);
      Pike_error("RangeError\n");
    }
  }

/*! @decl int get_value()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
  PIKEFUN string get_value()
  {
    string i;
    printf("calling get_value()\n");

    try
    {
      i = (*(*(THIS->object_data->valuei)));
      push_text(i.c_str());
    }
    catch(const RangeError &e)
    {
      pop_n_elems(args);
      Pike_error("RangeError\n");
    }
  }

  PIKEFUN int `!()
  {
    if(!THIS->vie)
      Pike_error("No end position specified. Did you create this iterator yourself?\n");

    if(*(THIS->object_data->valuei) == *(THIS->vie)) { push_int(1); }
    else
      push_int(0);
  }

/*  ValueIterator.string get_description() */
/*! @decl string get_description()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN string get_description()
{
  string str = THIS->object_data->valuei->get_description();

  push_text(str.c_str());
}

PIKEFUN string _sprintf(int conversion_type, mapping params)
{
  ValueIterator  *it;
  if(THIS && THIS->object_data && conversion_type == 'O')
  {
    string str = THIS->object_data->valuei->get_description();
    pop_n_elems(args);
    push_text(str.c_str());
  }
  else
  {
    pop_n_elems(args);
    push_int(0);
  }
}


INIT
{
    XAPIAN_VALUEITERATOR_OBJECT_DATA * dta = 
	(XAPIAN_VALUEITERATOR_OBJECT_DATA*)malloc(sizeof(XAPIAN_VALUEITERATOR_OBJECT_DATA));
    if (!dta)
        Pike_error("init_sample: Out of memory!\n");

    dta->valuei = NULL;
    THIS->object_data = dta;
}

EXIT 
{
  if(THIS->object_data)
  {
    ValueIterator  *valuei;
    valuei = THIS->object_data->valuei;
    if(valuei) delete valuei;
    free(THIS->object_data);
  }
}

}

/*!  @endclass
*/

/*! @class TermIterator
*/

PIKECLASS TermIterator
{
  CVAR TermIterator * tie;
  CVAR int current_index;
  CVAR XAPIAN_TERMITERATOR_OBJECT_DATA   *object_data;

  PIKEFUN object next()
  {
    ++(*(THIS->object_data->termi));
    push_object(this_object());    
  }

  PIKEFUN mixed index()
  {
    push_int(THIS->current_index);
  }

  PIKEFUN object value()
  {
    push_object(this_object());
  }

  PIKEFUN int `==(mixed arg)
  {
    struct object * o;
    TermIterator  *termi;
    TermIterator  *termb;
    struct Xapian_TermIterator_struct * tis;    

    if(TYPEOF(*arg)!= T_OBJECT) RETURN(0);
    o = arg->u.object;
    termi = (TermIterator*)THIS->object_data->termi;
    tis = OBJ2_TERMITERATOR(o);
    if(!tis) RETURN(0);

    termb = tis->object_data->termi;
    if(*termi == *termb) RETURN(1);
    else RETURN(0);
  }

/*! @decl object position_iterator()
 *!
 *!  @returns
 *!    an object which can be passed to @[foreach]()
 *!  
 *!
 */
  PIKEFUN object position_iterator()
  {
    TermIterator  *ti;
    ti = THIS->object_data->termi;

    PositionIterator pi;
    PositionIterator * pi2;
    struct object * o;

    pi = ti->positionlist_begin();
    pi2 = new PositionIterator(pi);

    o = fast_clone_object(Xapian_PositionIterator_program);

    OBJ2_POSITIONITERATOR(o)->object_data->positioni = pi2;
    OBJ2_POSITIONITERATOR(o)->pie = new PositionIterator(ti->positionlist_end());

    push_object(o);    
  }

/*! @decl int get_wdf()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
  PIKEFUN int get_wdf()
  {
    TermIterator  *termi;
    termcount i;
    termi = (TermIterator*)THIS->object_data->termi;
    i = termi->get_wdf();
    push_int((INT_TYPE)i);
  }

/*! @decl int get_termfreq()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
  PIKEFUN int get_termfreq()
  {
    TermIterator  *termi;
    doccount i;
    termi = (TermIterator*)THIS->object_data->termi;
    i = termi->get_termfreq();
    push_int((INT_TYPE)i);
  }

/*! @decl int positionlist_count()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
  PIKEFUN int positionlist_count()
  {
    TermIterator  *termi;
    termcount i;
    termi = (TermIterator*)THIS->object_data->termi;
    i = termi->positionlist_count();
    push_int((INT_TYPE)i);
  }


/*! @decl string get_term()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
  PIKEFUN string get_term()
  {
    TermIterator  *termi;
    string i;
    termi = (TermIterator*)THIS->object_data->termi;
    i = (*(*termi));
    push_text(i.c_str());
  }

  PIKEFUN mixed `+=(int i)
  {
    TermIterator  *ti;
    ti = THIS->object_data->termi;
    
    for(int x = 0; x < i; x++)
    {
      (*ti)++;
      if(*ti == *(THIS->tie)) {
        pop_stack(); push_int(0); return;}
    }
    THIS->current_index++;
    pop_stack();
    push_object(this_object());
  }
 
  PIKEFUN int `!()
  {
    TermIterator  *ti;
    ti = THIS->object_data->termi;
    if(*ti == *(THIS->tie)) { push_int(1); }
    else
      push_int(0);
  }

/*  TermIterator.string get_description() */
/*! @decl string get_description()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN string get_description()
{
  TermIterator  *termi;
  termi = THIS->object_data->termi;

  string str = termi->get_description();

  push_text(str.c_str());
}

PIKEFUN string _sprintf(int conversion_type, mapping params)
{
  TermIterator  *it;
  if(THIS && THIS->object_data && conversion_type == 'O')
  {
    it = THIS->object_data->termi;

    string str = it->get_description();
    pop_n_elems(args);
    push_text(str.c_str());
  }
  else
  {
    pop_n_elems(args);
    push_int(0);
  }
}


INIT
{
    XAPIAN_TERMITERATOR_OBJECT_DATA * dta = 
	(XAPIAN_TERMITERATOR_OBJECT_DATA*)malloc(sizeof(XAPIAN_TERMITERATOR_OBJECT_DATA));
    if (!dta)
        Pike_error("init_sample: Out of memory!\n");

    dta->termi = NULL;
    THIS->object_data = dta;
}

EXIT 
{
  if(THIS->object_data)
  {
    TermIterator  *termi;
    termi = THIS->object_data->termi;
    if(termi) delete termi;
    free(THIS->object_data);
  }
}

}

/*!  @endclass
*/

/*! @class Document
 *! A document in the database - holds data, values, terms, and postings.
*/

PIKECLASS Document
{

CVAR XAPIAN_DOCUMENT_OBJECT_DATA   *object_data;


/*  Document.void create() */
/*! @decl void create()
 *!
 *!  
 *!
 */
PIKEFUN void create()
{
  try
  {
    Document* document = new Document();

    pop_n_elems(args);

    THIS->object_data->document = document;
  }

  catch(...) 
  {
    Pike_error("an error occurred!\n");
  }
}

/*  Document.void set_data(string data) */
/*! @decl void set_data(string data)
 *!
 *!  Set data stored in the document.
 *!
 *! @param data
 *!  
* !
 *!
 */
PIKEFUN void set_data(string data)
{
  Document  *doc;
  doc = THIS->object_data->document;
  string str((const char *)data->str, (size_t)data->len);

  doc->set_data(str);  

  pop_n_elems(args);
}

/*! @decl ValueIterator value_iterator()
 *! Get an iterator for the values in this document.
 *!  @returns
 *!    a @[ValueIterator] object which can be passed to @[foreach]()
 *!  
 *!
 */
PIKEFUN object value_iterator()
{
  Document  *doc;
  ValueIterator b, e, *a, *c;
  doc = THIS->object_data->document;

  struct object * o;

  o = fast_clone_object(Xapian_ValueIterator_program);

  (OBJ2_VALUEITERATOR(o)->object_data->valuei) = new ValueIterator(doc->values_begin());
  (OBJ2_VALUEITERATOR(o)->vie) = new ValueIterator(doc->values_end());
  push_object(o);
}

/*! @decl TermIterator term_iterator()
 *!  Get an iterator for the terms in this document.
 *!  @returns
 *!    a @[TermIterator] object which can be passed to @[foreach]()
 */
PIKEFUN object term_iterator()
{
  Document  *doc;
  doc = THIS->object_data->document;

  TermIterator ti;
  TermIterator * ti2;
  struct object * o;

  ti = doc->termlist_begin();
  ti2 = new TermIterator(ti);

  o = fast_clone_object(Xapian_TermIterator_program);

  OBJ2_TERMITERATOR(o)->object_data->termi = ti2;
  OBJ2_TERMITERATOR(o)->tie = new TermIterator(doc->termlist_end());

  push_object(o);    
}

/*  Document.void clear_terms() */
/*! @decl void clear_terms()
 *!
 *! Remove all terms (and postings) from the document.  
 *!
 */
PIKEFUN void clear_terms()
{
  Document  *doc;
  doc = THIS->object_data->document;

  doc->clear_terms();
}

/*  Document.void clear_values() */
/*! @decl void clear_values()
 *!
 *!  Remove all values associated with the document.
 *!
 */
PIKEFUN void clear_values()
{
  Document  *doc;
  doc = THIS->object_data->document;

  doc->clear_values();
}

/*  Document.string get_data() */
/*! @decl string get_data()
 *!  Get data stored in the document.
 *! This is a potentially expensive operation, and shouldn't normally be 
 *! used in a match decider function. Put data for use by match deciders 
 *! in a value instead.
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN string get_data()
{
  Document  *doc;
  doc = THIS->object_data->document;

  string str = doc->get_data();

  push_text(str.c_str());
}

/*  Document.string get_description() */
/*! @decl string get_description()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN string get_description()
{
  Document  *doc;
  doc = THIS->object_data->document;

  string str = doc->get_description();

  push_text(str.c_str());
}

PIKEFUN string _sprintf(int conversion_type, mapping params)
{
  Document  *doc;
  if(THIS && THIS->object_data && conversion_type == 'O')
  {
    doc = THIS->object_data->document;

    string str = doc->get_description();
    pop_n_elems(args);
    push_text(str.c_str());
  }
  else
  {
    pop_n_elems(args);
    push_int(0);
  }
}


/*  Document.string get_value(int val) */
/*! @decl string get_value(int val)
 *!  Get value by number.
 *!  
 *! @param val
 *!   	The number of the value.
* !
 *! @returns
 *! Returns an empty string if no value with the given number is present 
 *! in the document.
 *!  
 *!
 */
PIKEFUN string get_value(int val)
{
  Document  *doc;
  doc = THIS->object_data->document;

  string str = doc->get_value(val);

  pop_n_elems(args);

  if(str.length())
    push_text(str.c_str());
  else 
    push_int(0);
}

/*  Document.void remove_value(int val) */
/*! @decl void remove_value(int val)
 *!
 *! Remove any value with the given number.  
 *! @param val
 *!  
* !
 *!
 */
PIKEFUN void remove_value(int val)
{
  Document  *doc;
  doc = THIS->object_data->document;

  doc->remove_value(val);

  pop_n_elems(args);
}

/*  Document.void add_term(string tname, int termcount) */
/*! @decl void add_term(string tname, int termcount)
 *!
 *! Add a term to the document, without positional information.
 *!
 *! Any existing positional information for the term will be left unmodified.  
 *! @param tname
 *!  The name of the term.
* !
 *! @param termcount
 *!  The increment that will be applied to the wdf for this term. 
* !
 *!
 */
PIKEFUN void add_term(string tname, int termcount)
{
  Document  *doc;
  doc = THIS->object_data->document;

  string str(tname->str, tname->len);
  
  doc->add_term(str, (unsigned int)termcount);

  pop_n_elems(args);
}

/*  Document.void add_posting(string tname, int termpos, int termcount) */
/*! @decl void add_posting(string tname, int termpos, int termcount)
 *!Add an occurrence of a term at a particular position.
 *!
 *! Multiple occurrences of the term at the same position are represented 
 *! only once in the positional information, but do increase the wdf.
 *!
 *! If the term is not already in the document, it will be added to it.
 *!  
 *! @param tname
 *!  The name of the term.
* !
 *! @param termpos
 *!  The position of the term.
* !
 *! @param termcount
 *!  The increment that will be applied to the wdf for this term.
* !
 *!
 */
PIKEFUN void add_posting(string tname, int termpos, int termcount)
{
  Document  *doc;
  doc = THIS->object_data->document;

  string str(tname->str, tname->len);

  try 
  {  

    doc->add_posting(str, (unsigned int)termpos, (unsigned int)termcount);
  }

  catch(const InvalidArgumentError &e)
  {
    pop_n_elems(args);
    Pike_error(e.get_msg().c_str());
  }
  
  pop_n_elems(args);
}

/*  Document.void remove_term(string tname) */
/*! @decl void remove_term(string tname)
 *!  Remove a term and all postings associated with it.
 *!  
 *! @param tname
 *!  The name of the term.
* ! @note
 *!  An error will be thrown if the term is not present in the document.
 */
PIKEFUN void remove_term(string tname)
{
  Document  *doc;
  doc = THIS->object_data->document;

  string str(tname->str, tname->len);
  
  try
  {
    doc->remove_term(str);
  }
  catch(const InvalidArgumentError &e)
  {
    pop_n_elems(args);
    Pike_error("InvalidArgumentError\n");
  }

  pop_n_elems(args);
}

/*! @decl void remove_posting(string tname, int tpos, int wdfdec)
 *!Remove a posting of a term from the document.
 *!
 *! Note that the term will still index the document even if all 
 *! occurrences are removed. To remove a term from a document completely, 
 *! use @[remove_term]().
 *!
 *! @param tname
 *!  The name of the term.
 *! @param tpos
 *!  The position of the term.
 *! @param wdfdec
 *!   The decrement that will be applied to the wdf when removing this 
 *!   posting. The wdf will not go below the value of 0.
 *! 
 *! @note
 *!   An error will be thrown if the term is not at the position specified 
 *!   in the position list for this term in this document or if the term 
 *!   is not in the document.
 */
PIKEFUN void remove_posting(string tname, int tpos, int wdfdec)
{
  Document  *doc;
  doc = THIS->object_data->document;

  string str(tname->str, tname->len);
  
  try
  {
    doc->remove_posting(str, tpos, wdfdec);
  }
  catch(const InvalidArgumentError &e)
  {
    pop_n_elems(args);
    Pike_error("InvalidArgumentError\n");
  }

  pop_n_elems(args);
}

/*  Document.void add_value(int valueno, string value) */
/*! @decl void add_value(int valueno, string value)
 *!Add a new value.
 *!
 *! It will replace any existing value with the same number. 
 *!  
 *! @param valueno
 *!  
* !
 *! @param value
 *!  
* !
 *!
 */
PIKEFUN void add_value(int valueno, string value)
{
  Document  *doc;
  doc = THIS->object_data->document;
  string str(value->str, value->len);

  doc->add_value(valueno, str);

  pop_n_elems(args);
}

/*  Document.int termlist_count() */
/*! @decl int termlist_count()
 *!
 *! Count the terms in this document.  
 *! @returns
 *!  the number of terms in the document.
 *!
 */
PIKEFUN int termlist_count()
{
  Document  *doc;
  doc = THIS->object_data->document;
  unsigned int i;

  i = doc->termlist_count();

  push_int((INT_TYPE)i);

  return;
}

/*  Document.int values_count() */
/*! @decl int values_count()
 *!
 *!  Count the values in this document. 
 *! @returns
 *!  the number of values in the document.
 *!
 */
PIKEFUN int values_count()
{
  Document  *doc;
  doc = THIS->object_data->document;
  unsigned int i;

  i = doc->values_count();

  push_int((INT_TYPE)i);

  return;
}


INIT
{
    XAPIAN_DOCUMENT_OBJECT_DATA * dta = 
	(XAPIAN_DOCUMENT_OBJECT_DATA*)malloc(sizeof(XAPIAN_DOCUMENT_OBJECT_DATA));
    if (!dta)
        Pike_error("init_sample: Out of memory!\n");

    dta->document = NULL;
    THIS->object_data = dta;
}

EXIT 
{
  if(THIS->object_data)
  {
    
    Document  *doc;
    doc = THIS->object_data->document;
    if(doc) delete doc;
// hrm... odd.
      free(THIS->object_data);
  }
}

}

/*!  @endclass
*/


/*
     here are some important helper classes that we'll include 
     rather than compile separately.
*/
#include "PikeMatchDeciderProxy.cc"
#include "PikeExpandDeciderProxy.cc"



/*! @class MSetIterator
*/

PIKECLASS MSetIterator
{
  CVAR int current_index;
  CVAR MSetIterator * msete;
  CVAR XAPIAN_MSETITERATOR_OBJECT_DATA   *object_data;

  PIKEFUN object get_document()
  {
    MSetIterator  *mseti;
    Document doc;
    Document *doc2;
    struct object * o;
    try {
    mseti = (MSetIterator*)THIS->object_data->mseti;
    doc = mseti->get_document();    
    doc2 = new Document(doc);

    o = fast_clone_object(Xapian_Document_program);
    OBJ2_DOCUMENT(o)->object_data->document = doc2;

    push_object(o);
  }
  catch(const RangeError &e)
  {
    pop_n_elems(args);
    Pike_error("RangeError\n");
  }

  }

  PIKEFUN mixed index()
  {
    push_int(THIS->current_index);
  }

  PIKEFUN object value()
  {
    push_object(this_object());
  }

  PIKEFUN int get_docid()
  {
    MSetIterator  *mseti;
    docid i;
    mseti = (MSetIterator*)THIS->object_data->mseti;
    i = (*(*mseti));
    push_int((INT_TYPE)i);
  }

  PIKEFUN int get_percent()
  {
    MSetIterator  *mseti;
    docid i;
    mseti = (MSetIterator*)THIS->object_data->mseti;
    i = mseti->get_percent();
    push_int((INT_TYPE)i);
  }
  
  PIKEFUN float get_weight()
  {
    MSetIterator  *mseti;
    weight i;
    mseti = (MSetIterator*)THIS->object_data->mseti;
    i = mseti->get_weight();
    push_float((FLOAT_TYPE)i);
  }
  
  PIKEFUN int get_collapse_count()
  {
    MSetIterator  *mseti;
    docid i;
    mseti = (MSetIterator*)THIS->object_data->mseti;
    i = mseti->get_collapse_count();
    push_int((INT_TYPE)i);
  }
  
  PIKEFUN object next()
  {
    MSetIterator  *mseti;
    mseti = THIS->object_data->mseti;
    MSetIterator *mseti2;

    struct object * o;
(*mseti)++;

   THIS->current_index++;
    if(*mseti == *(THIS->msete)) {push_int(0); return;}
    push_int(1);    
  }
/*
  PIKEFUN object prev()
  {
    MSetIterator  *mseti;
    mseti = THIS->object_data->mseti;
    MSetIterator *mseti2;

    struct object * o;

    mseti2 = new MSetIterator((*mseti)--);

    o = fast_clone_object(Xapian_MSetIterator_program);

    OBJ2_MSETITERATOR(o)->object_data->mseti = mseti2;

    push_object(o);    
  }
*/
  PIKEFUN mixed `+=(int i)
  {
    MSetIterator  *mseti;
    mseti = THIS->object_data->mseti;
    
    for(int x = 0; x < i; x++)
    {
      (*mseti)++;
      if(*mseti == *(THIS->msete)) {
        pop_stack(); push_int(0); return;}
    }
    THIS->current_index++;
    pop_stack();
    push_object(this_object());
  }
 
  PIKEFUN int `!()
  {
    MSetIterator  *mseti;
    mseti = THIS->object_data->mseti;
    if(*mseti == *(THIS->msete)) { push_int(1); }
    else
      push_int(0);
  }

  PIKEFUN int `==(mixed arg)
  {
    struct object * o;
    struct Xapian_MSetIterator_struct * msis;    
    MSetIterator  *mseti;
    MSetIterator  *msetb;
    if(TYPEOF(*arg)!= T_OBJECT) {RETURN(0);}
    o = arg->u.object;
    mseti = (MSetIterator*)THIS->object_data->mseti;
    msis = OBJ2_MSETITERATOR(o);
    if(!msis) {RETURN(0);}

    msetb = msis->object_data->mseti;
    if(*mseti == *msetb) {RETURN(1);}
    else {RETURN(0);}
  }

INIT
{
    XAPIAN_MSETITERATOR_OBJECT_DATA * dta = 
	(XAPIAN_MSETITERATOR_OBJECT_DATA*)malloc(sizeof(XAPIAN_MSETITERATOR_OBJECT_DATA));
    if (!dta)
        Pike_error("init_sample: Out of memory!\n");

    dta->mseti = NULL;
    THIS->object_data = dta;
}

EXIT 
{
  if(THIS->object_data)
  {
    MSetIterator  *mseti;
    mseti = THIS->object_data->mseti;
    if(mseti) delete mseti;
    free(THIS->object_data);
  }
}

}

/*!  @endclass
*/

/*! @class ESetIterator
*/

PIKECLASS ESetIterator
{
  CVAR int current_index;
  CVAR ESetIterator * esete;
  CVAR XAPIAN_ESETITERATOR_OBJECT_DATA   *object_data;

  PIKEFUN string get_term()
  {
    ESetIterator  *eseti;
    string i;
    eseti = (ESetIterator*)THIS->object_data->eseti;
    i = (*(*eseti));
    push_text(i.c_str());
  }

  PIKEFUN float get_weight()
  {
    ESetIterator  *eseti;
    weight i;
    eseti = (ESetIterator*)THIS->object_data->eseti;
    i = eseti->get_weight();
    push_float((FLOAT_TYPE)i);
  }  

  PIKEFUN mixed index()
  {
    push_int(THIS->current_index);
  }

  PIKEFUN object value()
  {
    push_object(this_object());
  }

  PIKEFUN object next()
  {
    ESetIterator  *eseti;
    eseti = THIS->object_data->eseti;
    ESetIterator *eseti2;

(*eseti)++;

   THIS->current_index++;
    if(*eseti == *(THIS->esete)) {push_int(0); return;}
    push_int(1);    
  }

/*
  PIKEFUN object prev()
  {
    ESetIterator  *eseti;
    eseti = THIS->object_data->eseti;
    ESetIterator *eseti2;

    struct object * o;

    eseti2 = new ESetIterator((*eseti)--);

    o = fast_clone_object(Xapian_ESetIterator_program);

    OBJ2_ESETITERATOR(o)->object_data->eseti = eseti2;

    push_object(o);    
  }
*/

  PIKEFUN mixed `+=(int i)
  {
    ESetIterator  *eseti;
    eseti = THIS->object_data->eseti;
    
    for(int x = 0; x < i; x++)
    {
      (*eseti)++;
      if(*eseti == *(THIS->esete)) {
        pop_stack(); push_int(0); return;}
    }
    THIS->current_index++;
    pop_stack();
    push_object(this_object());
  }

  PIKEFUN int `!()
  {
    ESetIterator  *eseti;
    eseti = THIS->object_data->eseti;
    if(*eseti == *(THIS->esete)) { push_int(1); }
    else
      push_int(0);
  }

  PIKEFUN int `==(mixed arg)
  {
    struct object * o;
    ESetIterator  *eseti;
    ESetIterator  *esetb;
    struct Xapian_ESetIterator_struct * esis;    

    if(TYPEOF(*arg)!= T_OBJECT) RETURN(0);
    o = arg->u.object;
    eseti = (ESetIterator*)THIS->object_data->eseti;

    esis = OBJ2_ESETITERATOR(o);
    if(!esis) RETURN(0);

    esetb = esis->object_data->eseti;
    if(eseti == esetb) RETURN(1);
    else RETURN(0);
  }

INIT
{
    XAPIAN_ESETITERATOR_OBJECT_DATA * dta = 
	(XAPIAN_ESETITERATOR_OBJECT_DATA*)malloc(sizeof(XAPIAN_ESETITERATOR_OBJECT_DATA));
    if (!dta)
        Pike_error("init_sample: Out of memory!\n");

    dta->eseti = NULL;
    THIS->object_data = dta;
}

EXIT 
{
  if(THIS->object_data)
  {
    ESetIterator  *eseti;
    eseti = THIS->object_data->eseti;
    if(eseti) delete eseti;
    free(THIS->object_data);
  }
}

}

/*!  @endclass
*/

/*! @class MSet
*/

PIKECLASS MSet
{
CVAR XAPIAN_MSET_OBJECT_DATA *object_data;

INIT
{
    XAPIAN_MSET_OBJECT_DATA * dta = 
	(XAPIAN_MSET_OBJECT_DATA*)malloc(sizeof(XAPIAN_MSET_OBJECT_DATA));
//printf("allocated mset data.\n");
    if (!dta)
        Pike_error("init_sample: Out of memory!\n");

    dta->mset = NULL;
    THIS->object_data = dta;
}

EXIT 
{
  if(THIS->object_data)
  {
    MSet  *mset;
    mset = THIS->object_data->mset;
    if(mset) delete mset;
    free(THIS->object_data);
  }
}


/*  MSet.void create() */
/*! @decl void create()
 *!
 *!  
 *!
 */
PIKEFUN void create()
{
  try
  {
    MSet * mset = new MSet();

    pop_n_elems(args);

    THIS->object_data->mset = mset;
  }

  catch(...) 
  {
    Pike_error("an error occurred!\n");
  }
}

/*  MSet.object begin() */
/*! @decl object begin()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN object begin()
{
  MSet  *mset;
  mset = THIS->object_data->mset;

  MSetIterator mseti;
  MSetIterator *mseti2;
  struct object * o;

  mseti = mset->begin();

  mseti2 = new MSetIterator(mseti);

  o = fast_clone_object(Xapian_MSetIterator_program);

  OBJ2_MSETITERATOR(o)->object_data->mseti = mseti2;

  push_object(o);    
}

PIKEFUN object _get_iterator()
{
  MSet  *mset;
  mset = THIS->object_data->mset;

  MSetIterator mseti;
  MSetIterator *mseti2;
  struct object * o;

  mseti = mset->begin();

  mseti2 = new MSetIterator(mseti);

  o = fast_clone_object(Xapian_MSetIterator_program);

  OBJ2_MSETITERATOR(o)->object_data->mseti = mseti2;
  OBJ2_MSETITERATOR(o)->msete = new MSetIterator(mset->end());

  push_object(o);    
}

/*  MSet.object end() */
/*! @decl object end()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN object end()
{
  MSet  *mset;
  mset = THIS->object_data->mset;

  MSetIterator mseti;
  MSetIterator *mseti2;
  struct object * o;

  mseti = mset->end();

  mseti2 = new MSetIterator(mseti);
  o = fast_clone_object(Xapian_MSetIterator_program);

  OBJ2_MSETITERATOR(o)->object_data->mseti = mseti2;

  push_object(o);    
}

/*  MSet.object back() */
/*! @decl object back()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN object back()
{
  MSet  *mset;
  mset = THIS->object_data->mset;

  MSetIterator mseti;
  MSetIterator *mseti2;
  struct object * o;

  mseti = mset->back();

  mseti2 = new MSetIterator(mseti);

  o = fast_clone_object(Xapian_MSetIterator_program);

  OBJ2_MSETITERATOR(o)->object_data->mseti = mseti2;

  push_object(o);    
}

/*  MSet.void fetch() */
/*! @decl void fetch()
 *!
 *!  
 *!
 */
PIKEFUN void fetch()
{
  MSet  *mset;
  mset = THIS->object_data->mset;

  mset->fetch();
}

/*  MSet.int size() */
/*! @decl int size()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN int size()
{
  MSet  *mset;
  mset = THIS->object_data->mset;
  doccount i;

  i = mset->size();

  push_int(i);
}

/*  MSet.int get_matches_estimated() */
/*! @decl int get_matches_estimated()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN int get_matches_estimated()
{
  MSet  *mset;
  mset = THIS->object_data->mset;
  doccount i;

  i = mset->get_matches_estimated();

  push_int(i);
}

/*  MSet.int get_matches_upper_bound() */
/*! @decl int get_matches_upper_bound()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN int get_matches_upper_bound()
{
  MSet  *mset;
  mset = THIS->object_data->mset;
  doccount i;

  i = mset->get_matches_upper_bound();

  push_int(i);
}

/*  MSet.int get_firstitem() */
/*! @decl int get_firstitem()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN int get_firstitem()
{
  MSet  *mset;
  mset = THIS->object_data->mset;
  doccount i;

  i = mset->get_firstitem();

  push_int(i);
}

/*  MSet.int get_matches_lower_bound() */
/*! @decl int get_matches_lower_bound()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN int get_matches_lower_bound()
{
  MSet  *mset;
  mset = THIS->object_data->mset;
  doccount i;

  i = mset->get_matches_lower_bound();

  push_int(i);
}

/*  MSet.string get_description() */
/*! @decl string get_description()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN string get_description()
{
  MSet  *mset;
  mset = THIS->object_data->mset;

  string str = mset->get_description();

  push_text(str.c_str());
}

PIKEFUN string _sprintf(int conversion_type, mapping params)
{
  MSet  *mset;
  if(THIS && THIS->object_data && conversion_type == 'O')
  {
    mset = THIS->object_data->mset;

    string str = mset->get_description();
    pop_n_elems(args);
    push_text(str.c_str());
  }
  else
  {
    pop_n_elems(args);
    push_int(0);
  }
}



}

/*!  @endclass
*/

/*! @class RSet
*/

PIKECLASS RSet
{
CVAR XAPIAN_RSET_OBJECT_DATA *object_data;

INIT
{
    XAPIAN_RSET_OBJECT_DATA * dta = 
	(XAPIAN_RSET_OBJECT_DATA*)malloc(sizeof(XAPIAN_RSET_OBJECT_DATA));
//printf("allocated eset data.\n");
    if (!dta)
        Pike_error("init_sample: Out of memory!\n");

    dta->rset = NULL;
    THIS->object_data = dta;
}

EXIT 
{
  if(THIS->object_data)
  {
    RSet  *rset;
    rset = THIS->object_data->rset;
    if(rset) delete rset;
    free(THIS->object_data);
  }
}

/*  RSet.void create() */
/*! @decl void create()
 *!
 *!  
 *!
 */
PIKEFUN void create()
{
  try
  {
    RSet * rset = new RSet();

    pop_n_elems(args);

    THIS->object_data->rset = rset;
  }

  catch(...) 
  {
    Pike_error("an error occurred!\n");
  }
}

/*  RSet.int size() */
/*! @decl int size()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN int size()
{
  RSet  *rset;
  rset = THIS->object_data->rset;
  doccount i;

  i = rset->size();

  push_int(i);
}

/*  RSet.int empty() */
/*! @decl int empty()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN int empty()
{
  RSet  *rset;
  rset = THIS->object_data->rset;
  bool i;

  i = rset->empty();

  push_int(i?1:0);
}

/*  RSet.void add_document(int docid) */
/*! @decl void add_document(int docid)
 *!
 *!  
 *! @param docid
 *!  
* !
 *!
 */
PIKEFUN void add_document(int docid)
{
  RSet  *rset;
  rset = THIS->object_data->rset;

  rset->add_document((Xapian::docid)docid);

  pop_n_elems(args);
}

/*  RSet.void add_document(object iterator) */
/*! @decl void add_document(object iterator)
 *!
 *!  
 *! @param iterator
 *!  
* !
 *!
 */
PIKEFUN void add_document(object iterator)
{
  RSet  *rset;
  rset = THIS->object_data->rset;

  MSetIterator * i;

  i = OBJ2_MSETITERATOR(iterator)->object_data->mseti;

  rset->add_document(*i);

  pop_n_elems(args);
}

/*  RSet.void remove_document(int docid) */
/*! @decl void remove_document(int docid)
 *!
 *!  
 *! @param docid
 *!  
* !
 *!
 */
PIKEFUN void remove_document(int docid)
{
  RSet  *rset;
  rset = THIS->object_data->rset;

  rset->remove_document((Xapian::docid)docid);

  pop_n_elems(args);
}

/*  RSet.void remove_document(object iterator) */
/*! @decl void remove_document(object iterator)
 *!
 *!  
 *! @param iterator
 *!  
* !
 *!
 */
PIKEFUN void remove_document(object iterator)
{
  RSet  *rset;
  rset = THIS->object_data->rset;

  MSetIterator * i;

  i = OBJ2_MSETITERATOR(iterator)->object_data->mseti;

  rset->remove_document(*i);

  pop_n_elems(args);
}

/*  RSet.int contains(int docid) */
/*! @decl int contains(int docid)
 *!
 *!  
 *! @param docid
 *!  
* !
 *! @returns
 *!  
 *!
 */
PIKEFUN int contains(int docid)
{
  RSet  *rset;
  rset = THIS->object_data->rset;
  bool r;

  r = rset->contains((Xapian::docid)docid);

  pop_n_elems(args);
  push_int(r?1:0);
}

/*  RSet.int contains(object iterator) */
/*! @decl int contains(object iterator)
 *!
 *!  
 *! @param iterator
 *!  
* !
 *! @returns
 *!  
 *!
 */
PIKEFUN int contains(object iterator)
{
  RSet  *rset;
  rset = THIS->object_data->rset;
  bool r;
  MSetIterator * i;

  i = OBJ2_MSETITERATOR(iterator)->object_data->mseti;

  r = rset->contains(*i);

  pop_n_elems(args);

  push_int(r?1:0);
}

/*  RSet.string get_description() */
/*! @decl string get_description()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN string get_description()
{
  RSet  *rset;
  rset = THIS->object_data->rset;

  string str = rset->get_description();

  push_text(str.c_str());
}

PIKEFUN string _sprintf(int conversion_type, mapping params)
{
  RSet  *rset;
  if(THIS && THIS->object_data && conversion_type == 'O')
  {
    rset = THIS->object_data->rset;

    string str = rset->get_description();
    pop_n_elems(args);
    push_text(str.c_str());
  }
  else
  {
    pop_n_elems(args);
    push_int(0);
  }
}


}

/*!  @endclass
*/

/*! @class ESet
*/

PIKECLASS ESet
{
CVAR XAPIAN_ESET_OBJECT_DATA *object_data;

INIT
{
    XAPIAN_ESET_OBJECT_DATA * dta = 
	(XAPIAN_ESET_OBJECT_DATA*)malloc(sizeof(XAPIAN_ESET_OBJECT_DATA));
//printf("allocated eset data.\n");
    if (!dta)
        Pike_error("init_sample: Out of memory!\n");

    dta->eset = NULL;
    THIS->object_data = dta;
}

EXIT 
{
  if(THIS->object_data)
  {
    ESet  *eset;
    eset = THIS->object_data->eset;
    if(eset) delete eset;
    free(THIS->object_data);
  }
}


/*  ESet.void create() */
/*! @decl void create()
 *!
 *!  
 *!
 */
PIKEFUN void create()
{
  try
  {
    ESet * eset = new ESet();

    pop_n_elems(args);

    THIS->object_data->eset = eset;
  }

  catch(...) 
  {
    Pike_error("an error occurred!\n");
  }
}

/*  ESet.object begin() */
/*! @decl object begin()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN object begin()
{
  ESet  *eset;
  eset = THIS->object_data->eset;

  ESetIterator eseti;
  ESetIterator *eseti2;
  struct object * o;

  eseti = eset->begin();

  eseti2 = new ESetIterator(eseti);

  o = fast_clone_object(Xapian_ESetIterator_program);

  OBJ2_ESETITERATOR(o)->object_data->eseti = eseti2;

  push_object(o);    
}

/*  ESet.object end() */
/*! @decl object end()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN object end()
{
  ESet  *eset;
  eset = THIS->object_data->eset;

  ESetIterator eseti;
  ESetIterator *eseti2;
  struct object * o;

  eseti = eset->end();

  eseti2 = new ESetIterator(eseti);

  o = fast_clone_object(Xapian_ESetIterator_program);

  OBJ2_ESETITERATOR(o)->object_data->eseti = eseti2;

  push_object(o);    
}

/*  ESet.object back() */
/*! @decl object back()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN object back()
{
  ESet  *eset;
  eset = THIS->object_data->eset;

  ESetIterator eseti;
  ESetIterator *eseti2;
  struct object * o;

  eseti = eset->back();

  eseti2 = new ESetIterator(eseti);

  o = fast_clone_object(Xapian_ESetIterator_program);

  OBJ2_ESETITERATOR(o)->object_data->eseti = eseti2;

  push_object(o);    
}

/*  ESet.object `[](int i) */
/*! @decl object `[](int i)
 *!
 *!  
 *! @param i
 *!  
* !
 *! @returns
 *!  
 *!
 */
PIKEFUN object `[](int i)
{
  ESet  *eset;
  eset = THIS->object_data->eset;

  ESetIterator eseti;
  ESetIterator *eseti2;
  struct object * o;

  eseti = (*eset)[(termcount)i];

  eseti2 = new ESetIterator(eseti);

  o = fast_clone_object(Xapian_ESetIterator_program);

  OBJ2_ESETITERATOR(o)->object_data->eseti = eseti2;

  push_object(o);    
}

/*  ESet.int size() */
/*! @decl int size()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN int size()
{
  ESet  *eset;
  eset = THIS->object_data->eset;
  termcount i;

  i = eset->size();

  push_int(i);
}

/*  ESet.int empty() */
/*! @decl int empty()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN int empty()
{
  ESet  *eset;
  eset = THIS->object_data->eset;
  bool i;

  i = eset->empty();

  push_int(i?1:0);
}

/*  ESet.int max_size() */
/*! @decl int max_size()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN int max_size()
{
  ESet  *eset;
  eset = THIS->object_data->eset;
  termcount i;

  i = eset->max_size();

  push_int(i);
}

/*  ESet.int get_ebound() */
/*! @decl int get_ebound()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN int get_ebound()
{
  ESet  *eset;
  eset = THIS->object_data->eset;
  termcount i;

  i = eset->get_ebound();

  push_int(i);
}

/*  ESet.string get_description() */
/*! @decl string get_description()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN string get_description()
{
  ESet  *eset;
  eset = THIS->object_data->eset;

  string str = eset->get_description();

  push_text(str.c_str());
}

PIKEFUN string _sprintf(int conversion_type, mapping params)
{
  ESet  *eset;
  if(THIS && THIS->object_data && conversion_type == 'O')
  {
    eset = THIS->object_data->eset;

    string str = eset->get_description();
    pop_n_elems(args);
    push_text(str.c_str());
  }
  else
  {
    pop_n_elems(args);
    push_int(0);
  }
}


}

/*!  @endclass
*/

/*! @class Database
*/

PIKECLASS Database
{
CVAR XAPIAN_DATABASE_OBJECT_DATA   *object_data;

/*  Database.void create(string path) */
/*! @decl void create(string path)
 *!
 *!  
 *! @param path
 *!  
* !
 *!
 */
PIKEFUN void create(string path)
{
  string str((const char *)path->str, (size_t)path->len);
  try
  {
   Database * db = new Database(str);
   THIS->object_data->database = db;
   pop_n_elems(args);
  }
  catch(const DatabaseLockError& e)
  {
  pop_n_elems(args);  
    Pike_error("DatabaseLockError\n");
  }
  catch(const DatabaseOpeningError& e) 
  {
  pop_n_elems(args);  
    Pike_error("DatabaseOpeningError\n");
  }
  catch(const InvalidArgumentError& e) 
  {
  pop_n_elems(args);  
    Pike_error("InvalidArgumentError\n");
  }
  catch(...){
  pop_n_elems(args);  
    Pike_error("an error occurred while opening the database.\n");
  }
}

/*  Database.void create() */
/*! @decl void create()
 *!
 *!  
 *!
 */
PIKEFUN void create()
{
  Database * db = new Database();

  THIS->object_data->database = db;
}

/*  Database.void reopen() */
/*! @decl void reopen()
 *!
 *!  
 *!
 */
PIKEFUN void reopen()
{
  Database * db = THIS->object_data->database;

  db->reopen();
}

/*  Database.void keep_alive() */
/*! @decl void keep_alive()
 *!
 *!  
 *!
 */
PIKEFUN void keep_alive()
{
  Database * db = THIS->object_data->database;

  db->keep_alive();
}


/*  Database.int get_doclength(int did) */
/*! @decl int get_doclength(int did)
 *!
 *!  
 *! @param did
 *!  
* !
 *! @returns
 *!  
 *!
 */
PIKEFUN int get_doclength(int did)
{
  Database  *db;
  db = THIS->object_data->database;

  doclength i = db->get_doclength((docid)did);
  pop_n_elems(args);
  push_int((INT_TYPE)i);
}

/*  Database.int get_doccount() */
/*! @decl int get_doccount()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN int get_doccount()
{
  Database  *db;
  db = THIS->object_data->database;

  doccount i = db->get_doccount();
  push_int(i);
}

/*  Database.int get_avlength() */
/*! @decl int get_avlength()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN int get_avlength()
{
  Database  *db;
  db = THIS->object_data->database;

  doclength i = db->get_avlength();
  push_int((INT_TYPE)i);
}

/*  Database.int get_lastdocid() */
/*! @decl int get_lastdocid()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN int get_lastdocid()
{
  Database  *db;
  db = THIS->object_data->database;

  docid i = db->get_lastdocid();
  push_int((INT_TYPE)i);
}


/*  Database.int has_positions() */
/*! @decl int has_positions()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN int has_positions()
{
  Database  *db;
  db = THIS->object_data->database;

  bool i = db->has_positions();

  push_int(i?1:0);
}

/*! @decl TermIterator synonyms_iterator(string term)
 *!  Get an iterator for the synonyms of a term.
 *!  @returns
 *!    a @[TermIterator] object which can be passed to @[foreach]()
 */
PIKEFUN object synonyms_iterator(string term)
{
  Database  *db;

  db = (Database*)THIS->object_data->database;


  TermIterator ti;
  TermIterator * ti2;
  struct object * o;

  string str((const char *)term->str, (size_t)term->len);

  ti = db->synonyms_begin(str);
  ti2 = new TermIterator(ti);

  o = fast_clone_object(Xapian_TermIterator_program);

  OBJ2_TERMITERATOR(o)->object_data->termi = ti2;
  OBJ2_TERMITERATOR(o)->tie = new TermIterator(db->synonyms_end(str));

  push_object(o);    
}



/*  Database.object get_document(int id) */
/*! @decl object get_document(int id)
 *!
 *!  
 *! @param id
 *!  
* !
 *! @returns
 *!  
 *!
 */
PIKEFUN object get_document(int id)
{
  Database  *db;
  Document doc;
  struct object * obj;
  struct Xapian_Document_struct * od;

  db = (Database*)THIS->object_data->database;

  try
  {
    doc = db->get_document((docid)id);
  }

  catch(const DocNotFoundError &e)
  {
    pop_n_elems(args);
    Pike_error("DocumentNotFoundError\n");
  }

  pop_n_elems(args);

  obj = fast_clone_object(Xapian_Document_program);

  od = OBJ2_DOCUMENT(obj);

  od->object_data->document = new Document(doc);
    
  push_object(obj);

}

/*! @decl object get_spelling_terms()
 *!
 *! @returns
 *!   a @[TermIterator] object which can also be passed to @[foreach]()
 */
PIKEFUN object get_spelling_terms()
{
  TermIterator ti;
  TermIterator * ti2;
  struct object * o;

  Database  *db;
  db = THIS->object_data->database;


  ti = db->spellings_begin();
  ti2 = new TermIterator(ti);

  o = fast_clone_object(Xapian_TermIterator_program);

  OBJ2_TERMITERATOR(o)->object_data->termi = ti2;
  OBJ2_TERMITERATOR(o)->tie = new TermIterator(db->spellings_end());

  push_object(o);    
}

/*! @decl object get_synonym_terms(string)
 *!
 *! @returns
 *!   a @[TermIterator] object which can also be passed to @[foreach]()
 */
PIKEFUN object get_spelling_terms(string term)
{
  TermIterator ti;
  TermIterator * ti2;
  struct object * o;

  Database  *db;
  db = THIS->object_data->database;


  ti = db->synonyms_begin(term->str);
  ti2 = new TermIterator(ti);

  o = fast_clone_object(Xapian_TermIterator_program);

  OBJ2_TERMITERATOR(o)->object_data->termi = ti2;
  OBJ2_TERMITERATOR(o)->tie = new TermIterator(db->synonyms_end(term->str));

  push_object(o);    
}


/*! @decl string get_spelling_suggestion(string word, int max_edit_distance)
 *! Suggest a spelling correction.
 *!
 *! @param word
 *! The potentially misspelled word.
 *! @param max_edit_distance 	
 *! Only consider words which are at most max_edit_distance edits from 
 *! word. An edit is a character insertion, deletion, or the transposition 
 *! of two adjacent characters (a reasonable starting value is 2).
 */
PIKEFUN string get_spelling_suggestion(string word, int max_edit_distance)
{
  Database  *db;

  db = (Database*)THIS->object_data->database;

  string str((const char *)word->str, (size_t)word->len);
  string nstr = db->get_spelling_suggestion(str, max_edit_distance);

  pop_n_elems(args);

  push_text(str.c_str());
}
/*  Database.string get_description() */
/*! @decl string get_description()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN string get_description()
{
  Database  *db;
  db = THIS->object_data->database;

  string str = db->get_description();

  push_text(str.c_str());
}

PIKEFUN string _sprintf(int conversion_type, mapping params)
{
  Database  *db;
  if(THIS && THIS->object_data && conversion_type == 'O')
  {
    db = THIS->object_data->database;

    string str = db->get_description();
    pop_n_elems(args);
    push_text(str.c_str());
  }
  else
  {
    pop_n_elems(args);
    push_int(0);
  }
}


INIT
{
    XAPIAN_DATABASE_OBJECT_DATA * dta = 
	(XAPIAN_DATABASE_OBJECT_DATA*)malloc(sizeof(XAPIAN_DATABASE_OBJECT_DATA));
    if (!dta)
        Pike_error("init_sample: Out of memory!\n");

    dta->database = NULL;
    THIS->object_data = dta;
}

/*  Database.void destroy() */
/*! @decl void destroy()
 *!
 *!  
 *!
 */
PIKEFUN void destroy(int|void reason)
{
    Database  *db;
    db = THIS->object_data->database;

    if(db) 
    {
      //printf("deleting db\n");
      delete db;
    }

    pop_n_elems(args);

}

EXIT 
{
  if(THIS->object_data)
  {   
    Database  *db;
    db = THIS->object_data->database;
    free(THIS->object_data);
  }
}

}

/*!  @endclass
*/

/*! @class WriteableDatabase
 *! @inherit Database
*/

PIKECLASS WriteableDatabase
{
INHERIT Xapian_Database;

/*  WriteableDatabase.void create(string path, int mode) */
/*! @decl void create(string path, int mode)
 *!
 *!  
 *! @param path
 *!  
* !
 *! @param mode
 *!  
* !
 *!
 */
PIKEFUN void create(string path, int mode)
{
  try
  {
    const string str((const char *)path->str, (size_t)path->len);

    WritableDatabase* database;
    try
    {
      database  = new WritableDatabase(str, mode);
    }
    catch (const Error &error) 
    {
      Pike_error("Exception: %s\n", error.get_msg().c_str());
    }
    pop_n_elems(args);

    THIS->object_data->database = database;
  }

  catch(const DatabaseLockError& e)
  {
    pop_n_elems(args);
    Pike_error("DatabaseLockError\n");
  }
  catch(const DatabaseOpeningError &e) 
  {
    pop_n_elems(args);
    Pike_error("DatabaseOpeningError\n");
  }
  catch(const InvalidArgumentError &e) 
  {
    pop_n_elems(args);
    Pike_error("InvalidArgumentError\n");
  }
  catch(...){
    pop_n_elems(args);
    Pike_error("an error occurred while opening the database.\n");
  }
}

/*  WriteableDatabase.void flush() */
/*! @decl void flush()
 *!
 *!  
 *!
 */
PIKEFUN void flush()
{
  WritableDatabase  *db;
  db = (WritableDatabase*)THIS->object_data->database;

  try
  {
    db->flush();
  }
  catch(Xapian::DatabaseCorruptError &e)
  {
    Pike_error("DatabaseCorruptError\n");
  }
  catch(Xapian::DatabaseLockError &e)
  {
    Pike_error("DatabaseLockError\n");
  }
  catch(Xapian::DatabaseError &e)
  {
    Pike_error("DatabaseError\n");
  }
}

/*  WriteableDatabase.int add_document(object document) */
/*! @decl int add_document(object document)
 *!
 *!  
 *! @param document
 *!  
* !
 *! @returns
 *!  
 *!
 */
PIKEFUN int add_document(object document)
{
  WritableDatabase  *db;
  Document * doc;
  docid id;

  struct Xapian_Document_struct * od;

  db = (WritableDatabase*)THIS->object_data->database;
  od = OBJ2_DOCUMENT(document);

  if(!od) Pike_error("Not a Document!\n");

  doc = od->object_data->document;

  try
  {
    id = db->add_document(*doc);
  }
  catch(Xapian::DatabaseCorruptError &e)
  {
    Pike_error("DatabaseCorruptError\n");
  }
  catch(Xapian::DatabaseError &e)
  {
    Pike_error("DatabaseError\n");
  }
  catch(Xapian::InvalidArgumentError &e)
  {
    //printf("%s\n",e.get_msg().c_str());
    Pike_error("InvalidArgumentError\n");
  }
  pop_n_elems(args);
  push_int(id);  
}


/*  WriteableDatabase.void replace_document(int did, object document) */
/*! @decl void replace_document(int did, object document)
 *!
 *!  
 *! @param did
 *!  
* !
 *! @param document
 *!  
* !
 *!
 */
PIKEFUN void replace_document(int did, object document)
{
  WritableDatabase  *db;
  Document * doc;
  docid id;

  struct Xapian_Document_struct * od;

  db = (WritableDatabase*)THIS->object_data->database;
  od = OBJ2_DOCUMENT(document);

  if(!od) Pike_error("Not a Document!\n");

  doc = od->object_data->document;

  try
  {
    db->replace_document((unsigned int)did, *doc);
  }
  catch(Xapian::DatabaseCorruptError &e)
  {
    Pike_error("DatabaseCorruptError\n");
  }
  catch(Xapian::DatabaseError &e)
  {
    Pike_error("DatabaseError\n");
  }

  pop_n_elems(args);
}

/*  WriteableDatabase.void replace_document(string term, object document) */
/*! @decl void replace_document(string term, object document)
 *!
 *!  
 *! @param term
 *!  
* !
 *! @param document
 *!  
* !
 *!
 */
PIKEFUN void replace_document(string term, object document)
{
  WritableDatabase  *db;
  Document * doc;
  docid id;
  string str;
  struct Xapian_Document_struct * od;

  db = (WritableDatabase*)THIS->object_data->database;
  od = OBJ2_DOCUMENT(document);

  if(!od) Pike_error("Not a Document!\n");


  doc = od->object_data->document;

  try
  {
    const string str((const char *)term->str, (size_t)term->len);
    db->replace_document(str, *doc);
  }
  catch(Xapian::DatabaseCorruptError &e)
  {
    Pike_error("DatabaseCorruptError\n");
  }
  catch(Xapian::DatabaseError &e)
  {
    Pike_error("DatabaseError\n");
  }

  pop_n_elems(args);
}

/*  WriteableDatabase.void delete_document(string unique_term) */
/*! @decl void delete_document(string unique_term)
 *!
 *!  
 *! @param unique_term
 *!  
* !
 *!
 */
PIKEFUN void delete_document(string unique_term)
{
  WritableDatabase  *db;
  db = (WritableDatabase*)THIS->object_data->database;
  const string str((const char *)unique_term->str, (size_t)unique_term->len);
  pop_n_elems(args);

  try
  {
    db->delete_document(str);
  }
  catch(Xapian::DatabaseCorruptError &e)
  {
    Pike_error("DatabaseCorruptError\n");
  }
  catch(Xapian::DatabaseError &e)
  {
    Pike_error("DatabaseError\n");
  }

}

/*  WriteableDatabase.void delete_document(int did) */
/*! @decl void delete_document(int did)
 *!
 *!  
 *! @param did
 *!  
* !
 *!
 */
PIKEFUN void delete_document(int did)
{
  WritableDatabase  *db;
  db = (WritableDatabase*)THIS->object_data->database;

  try
  {
    db->delete_document((docid)did);
  }
  catch(Xapian::DatabaseCorruptError &e)
  {
    pop_n_elems(args);
    Pike_error("DatabaseCorruptError\n");
  }
  catch(Xapian::DatabaseError &e)
  {
    pop_n_elems(args);
    Pike_error("DatabaseError\n");
  }

}


/*  WriteableDatabase.void begin_transaction(int flushed) */
/*! @decl void begin_transaction(int flushed)
 *!
 *!  
 *! @param flushed
 *!  
* !
 *!
 */
PIKEFUN void begin_transaction(int flushed)
{
  WritableDatabase  *db;
  db = (WritableDatabase*)THIS->object_data->database;

  try
  {
    db->begin_transaction((bool)flushed);
  }
  catch(Xapian::InvalidOperationError &e)
  {
    pop_n_elems(args);
    Pike_error("InvalidOperationError\n");
  }
  catch(Xapian::UnimplementedError &e)
  {
    pop_n_elems(args);
    Pike_error("UnimplementedError\n");
  }

}

/*  WriteableDatabase.void commit_transaction() */
/*! @decl void commit_transaction()
 *!
 *!  
 *!
 */
PIKEFUN void commit_transaction()
{
  WritableDatabase  *db;
  db = (WritableDatabase*)THIS->object_data->database;

  try
  {
    db->commit_transaction();
  }
  catch(Xapian::InvalidOperationError &e)
  {
    Pike_error("InvalidOperationError\n");
  }
  catch(Xapian::DatabaseCorruptError &e)
  {
    Pike_error("DatabaseCorruptError\n");
  }
  catch(Xapian::DatabaseError &e)
  {
    Pike_error("DatabaseError\n");
  }
  catch(Xapian::UnimplementedError &e)
  {
    Pike_error("UnimplementedError\n");
  }

}


/*  WriteableDatabase.void cancel_transaction() */
/*! @decl void cancel_transaction()
 *!
 *!  
 *!
 */
PIKEFUN void cancel_transaction()
{
  WritableDatabase  *db;
  db = (WritableDatabase*)THIS->object_data->database;

  try
  {
    db->cancel_transaction();
  }
  catch(Xapian::InvalidOperationError &e)
  {
    Pike_error("InvalidOperationError\n");
  }
  catch(Xapian::DatabaseCorruptError &e)
  {
    Pike_error("DatabaseCorruptError\n");
  }
  catch(Xapian::DatabaseError &e)
  {
    Pike_error("DatabaseError\n");
  }
  catch(Xapian::UnimplementedError &e)
  {
    Pike_error("UnimplementedError\n");
  }

}

/*  WriteableDatabase.string get_description() */
/*! @decl string get_description()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN string get_description()
{
  WritableDatabase  *db;
  db = (WritableDatabase*)THIS->object_data->database;

  string str = db->get_description();

  push_text(str.c_str());
}

PIKEFUN string _sprintf(int conversion_type, mapping params)
{
  WritableDatabase  *db;
  if(THIS && THIS->object_data && conversion_type == 'O')
  {
    db = (WritableDatabase*)THIS->object_data->database;

    string str = db->get_description();
    pop_n_elems(args);
    push_text(str.c_str());
  }
  else
  {
    pop_n_elems(args);
    push_int(0);
  }
}


}

/*!  @endclass
*/


/*! @class QueryParser
*/

PIKECLASS QueryParser
{
CVAR XAPIAN_QUERYPARSER_OBJECT_DATA   *object_data;

/*  QueryParser.void create() */
/*! @decl void create()
 *!
 *!  
 *!
 */
PIKEFUN void create()
{
  QueryParser * parser = new QueryParser();

  THIS->object_data->parser = parser;
}

/*! @decl string get_corrected_query_string()
 *!
 */
PIKEFUN string get_corrected_query_string()
{
  QueryParser * parser;

  parser = THIS->object_data->parser;
  string nstr = parser->get_corrected_query_string();

  pop_n_elems(args);

  push_text(nstr.c_str());
}

/*  QueryParser.void set_stemmer(object stemmer) */
/*! @decl void set_stemmer(object stemmer)
 *!
 *!  
 *! @param stemmer
 *!  
* !
 *!
 */
PIKEFUN void set_stemmer(object stemmer)
{
  QueryParser * parser;
  Stem * s;

  parser = THIS->object_data->parser;
  s = OBJ2_STEM(stemmer)->object_data->stem; 
  parser->set_stemmer((const Stem)*s);

  pop_n_elems(args);
}

/*  QueryParser.void set_stopper(object stopper) */
/*! @decl void set_stopper(object stopper)
 *!
 *!  
 *! @param stopper
 *!  
* !
 *!
 */
PIKEFUN void set_stopper(object stopper)
{
  QueryParser * parser;
  Stopper * s;

  parser = THIS->object_data->parser;
  s = OBJ2_STOPPER(stopper)->object_data->stopper; 
  parser->set_stopper((const Stopper*)s);

  pop_n_elems(args);
}

/*  QueryParser.void set_database(object database) */
/*! @decl void set_database(object database)
 *!
 *!  
 *! @param database
 *!  
 *!
 *!
 */
PIKEFUN void set_database(object database)
{
  QueryParser * parser;
  Database * d;

  parser = THIS->object_data->parser;
  d = OBJ2_DATABASE(database)->object_data->database; 
  parser->set_database((const Database)*d);

  pop_n_elems(args);
}

/*  QueryParser.void set_default_op(int op) */
/*! @decl void set_default_op(int op)
 *!
 *!  
 *! @param op
 *!  
* !
 *!
 */
PIKEFUN void set_default_op(int op)
{
  QueryParser * parser;

  parser = THIS->object_data->parser;

  parser->set_default_op((Query::op)op);
  pop_n_elems(args);
}


/*! @decl void set_stemming_strategy(int strat)
 *! Set the stemming strategy.
 *!
 *! This controls how the query parser will apply the stemming algorithm. 
 *! The default value is STEM_NONE. The possible values are:
 *! 
 *!   * STEM_NONE: Don't perform any stemming.
 *!
 *!   * STEM_SOME: Search for stemmed forms of terms except for those 
 *!  which start with a capital letter, or are followed by certain 
 *! characters (currently: (/@@<>=*[{" ), or are used with operators which 
 *! need positional information. Stemmed terms are prefixed with 'Z'.
 *!
 *!   * STEM_ALL: Search for stemmed forms of all words (note: no 'Z' 
 *! prefix is added).
 *!
 *! Note that the stemming algorithm is only applied to words in 
 *! probabilistic fields - boolean filter terms are never stemmed.
 *! 
 */
PIKEFUN void set_stemming_strategy(int strat)
{
  QueryParser * parser;

  parser = THIS->object_data->parser;

  parser->set_stemming_strategy((Xapian::QueryParser::stem_strategy)strat);
  pop_n_elems(args);
}

/*  QueryParser.object parse_query(string query, int flags) */
/*! @decl object parse_query(string query, int flags)
 *!
 *!  
 *! @param query
 *!   a plain text query string
* !
 *! @param flags
 *!  
* !
 *! @returns
 *!   a @[Query] object
 *!
 *! @note
 *!   this function is wide-string aware
 */
PIKEFUN object parse_query(string query, int flags)
{
  Query q;
  Query * q1;
  QueryParser *parser;
  struct object *o;
  parser = THIS->object_data->parser;

  ref_push_string(query);
  f_string_to_utf8(1);

  string str((const char *)Pike_sp[-1].u.string->str, (size_t) Pike_sp[-1].u.string->len);

  q = parser->parse_query(str, flags);

  q1 = new Query(q);  

  o = fast_clone_object(Xapian_Query_program);
  if(!o) Pike_error("unable to clone the query program.\n");
  if(!q1) Pike_error("unable to parse the query.\n");
  OBJ2_QUERY(o)->object_data->query = q1;
  pop_n_elems(args+1);
  push_object(o);
}

/*  QueryParser.void add_prefix(string field, string prefix) */
/*! @decl void add_prefix(string field, string prefix)
 *!
 *!  
 *! @param field
 *!  
* !
 *! @param prefix
 *!  
* !
 *!
 */
PIKEFUN void add_prefix(string field, string prefix)
{
  QueryParser *parser;
  parser = THIS->object_data->parser;
  
  string f((const char *)field->str, (size_t)field->len);
  string p((const char *)prefix->str, (size_t)prefix->len);

  parser->add_prefix(f, p);
  pop_n_elems(args);
}

/*  QueryParser.void add_boolean_prefix(string field, string prefix) */
/*! @decl void add_boolean_prefix(string field, string prefix)
 *!
 *!  
 *! @param field
 *!  
* !
 *! @param prefix
 *!  
* !
 *!
 */
PIKEFUN void add_boolean_prefix(string field, string prefix)
{
  QueryParser *parser;
  parser = THIS->object_data->parser;
  
  string f((const char *)field->str, (size_t)field->len);
  string p((const char *)prefix->str, (size_t)prefix->len);

  parser->add_boolean_prefix(f, p);
  pop_n_elems(args);
}

/*  QueryParser.string get_description() */
/*! @decl string get_description()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN string get_description()
{
  QueryParser *parser;
  parser = THIS->object_data->parser;

  string str = parser->get_description();

  push_text(str.c_str());
}

PIKEFUN string _sprintf(int conversion_type, mapping params)
{
  QueryParser  *query;
  if(THIS && THIS->object_data && conversion_type == 'O')
  {
    query = THIS->object_data->parser;

    string str = query->get_description();
    pop_n_elems(args);
    push_text(str.c_str());
  }
  else
  {
    pop_n_elems(args);
    push_int(0);
  }
}

INIT
{
    XAPIAN_QUERYPARSER_OBJECT_DATA * dta = 
	(XAPIAN_QUERYPARSER_OBJECT_DATA*)malloc(sizeof(XAPIAN_QUERYPARSER_OBJECT_DATA));
    if (!dta)
        Pike_error("init_sample: Out of memory!\n");

    dta->parser = NULL;
    THIS->object_data = dta;
}

EXIT 
{
  if(THIS->object_data)
  {
    QueryParser  *parser;
    parser = THIS->object_data->parser;
    if(parser) delete parser;
    free(THIS->object_data);
  }
}

EXTRA
{
  QueryParser::feature_flag flag;
  int sflag;

  flag = QueryParser::FLAG_BOOLEAN;
  add_integer_constant("FLAG_BOOLEAN", flag, 0);
  flag = QueryParser::FLAG_PHRASE;
  add_integer_constant("FLAG_PHRASE", flag, 0);
  flag = QueryParser::FLAG_LOVEHATE;
  add_integer_constant("FLAG_LOVEHATE", flag, 0);
  flag = QueryParser::FLAG_BOOLEAN_ANY_CASE;
  add_integer_constant("FLAG_BOOLEAN_ANY_CASE", flag, 0);
  flag = QueryParser::FLAG_WILDCARD;
  add_integer_constant("FLAG_WILDCARD", flag, 0);
  flag = QueryParser::FLAG_SPELLING_CORRECTION;
  add_integer_constant("FLAG_SPELLING_CORRECTION", flag, 0);

  flag = QueryParser::FLAG_PURE_NOT;
  add_integer_constant("FLAG_PURE_NOT", flag, 0);
  flag = QueryParser::FLAG_PARTIAL;
  add_integer_constant("FLAG_PARTIAL", flag, 0);
  flag = QueryParser::FLAG_SYNONYM;
  add_integer_constant("FLAG_SYNONYM", flag, 0);
  flag = QueryParser::FLAG_AUTO_SYNONYMS;
  add_integer_constant("FLAG_AUTO_SYNONYMS", flag, 0);

/*
  flag = QueryParser::FLAG_MULTIWORD_SYNONYMS;
  add_integer_constant("FLAG_MULTIWORD_SYNONYMS", flag, 0);
*/

  sflag = QueryParser::STEM_NONE;
  add_integer_constant("STEM_NONE", sflag, 0);
  sflag = QueryParser::STEM_SOME;
  add_integer_constant("STEM_SOME", sflag, 0);
  sflag = QueryParser::STEM_ALL;
  add_integer_constant("STEM_ALL", sflag, 0);
}

}

/*!  @endclass
*/


/*! @class Enquire
*/

PIKECLASS Enquire
{

CVAR XAPIAN_ENQUIRE_OBJECT_DATA   *object_data;


/*  Enquire.void create(object database) */
/*! @decl void create(object database)
 *!
 *!  
 *! @param database
 *!  
* !
 *!
 */
PIKEFUN void create(object database)
{
  try
  {
    Database * db;
    db = OBJ2_DATABASE(database)->object_data->database;

    Enquire * enquire = new Enquire(*db);

    pop_n_elems(args);

    THIS->object_data->enquire = enquire;
  }

  catch(...) 
  {
    Pike_error("an error occurred!\n");
  }
}

/*  Enquire.void set_weighting_scheme(object weight) */
/*! @decl void set_weighting_scheme(object weight)
 *!
 *!  
 *! @param weight
 *!  
* !
 *!
 */
PIKEFUN void set_weighting_scheme(object weight)
{
  Enquire * e = THIS->object_data->enquire;
  Weight * w = (OBJ2_WEIGHT(weight)->object_data->weight);

  e->set_weighting_scheme(*w);
  pop_n_elems(args);  
}

/*  Enquire.void set_query(object query, int termcount) */
/*! @decl void set_query(object query, int termcount)
 *!
 *!  
 *! @param query
 *!  
* !
 *! @param termcount
 *!  
* !
 *!
 */
PIKEFUN void set_query(object query, int termcount)
{
  Query * q;
  Enquire  *enquire;
  enquire = THIS->object_data->enquire;

  q = OBJ2_QUERY(query)->object_data->query;

  enquire->set_query(*q, (Xapian::termcount)termcount);
  pop_n_elems(args);  
}

/*  Enquire.void set_cutoff(int percent_cutoff, float weight_cutoff) */
/*! @decl void set_cutoff(int percent_cutoff, float weight_cutoff)
 *!
 *!  
 *! @param percent_cutoff
 *!  
* !
 *! @param weight_cutoff
 *!  
* !
 *!
 */
PIKEFUN void set_cutoff(int percent_cutoff, float weight_cutoff)
{
  Enquire  *enquire;
  enquire = THIS->object_data->enquire;

  enquire->set_cutoff((percent)percent_cutoff, (weight)weight_cutoff);
  pop_n_elems(args);  
}

/*  Enquire.void set_docid_order(int docid_order) */
/*! @decl void set_docid_order(int docid_order)
 *!
 *!  
 *! @param docid_order
 *!  
* !
 *!
 */
PIKEFUN void set_docid_order(int docid_order)
{
  Enquire  *enquire;
  enquire = THIS->object_data->enquire;

  enquire->set_docid_order((Xapian::Enquire::docid_order)docid_order);
  pop_n_elems(args);  
}

/*  Enquire.void set_collapse_key(int collapse_key) */
/*! @decl void set_collapse_key(int collapse_key)
 *!
 *!  
 *! @param collapse_key
 *!  
* !
 *!
 */
PIKEFUN void set_collapse_key(int collapse_key)
{
  Enquire  *enquire;
  enquire = THIS->object_data->enquire;

  enquire->set_collapse_key((valueno)collapse_key);
  pop_n_elems(args);  
}

/*  Enquire.void set_sort_by_relevance_then_value(int sort_key, int ascending) */
/*! @decl void set_sort_by_relevance_then_value(int sort_key, int ascending)
 *!
 *!  
 *! @param sort_key
 *!  
* !
 *! @param ascending
 *!  
* !
 *!
 */
PIKEFUN void set_sort_by_relevance_then_value(int sort_key, int ascending)
{
  Enquire  *enquire;
  enquire = THIS->object_data->enquire;

  enquire->set_sort_by_relevance_then_value((valueno)sort_key, ascending?true:false);
  pop_n_elems(args);  
}

/*  Enquire.void set_sort_by_value_then_relevance(int sort_key, int ascending) */
/*! @decl void set_sort_by_value_then_relevance(int sort_key, int ascending)
 *!
 *!  
 *! @param sort_key
 *!  
* !
 *! @param ascending
 *!  
* !
 *!
 */
PIKEFUN void set_sort_by_value_then_relevance(int sort_key, int ascending)
{
  Enquire  *enquire;
  enquire = THIS->object_data->enquire;

  enquire->set_sort_by_value_then_relevance((valueno)sort_key, ascending?true:false);
  pop_n_elems(args);  
}

/*  Enquire.void set_sort_value(int sort_key, int ascending) */
/*! @decl void set_sort_value(int sort_key, int ascending)
 *!
 *!  
 *! @param sort_key
 *!  
* !
 *! @param ascending
 *!  
* !
 *!
 */
PIKEFUN void set_sort_value(int sort_key, int ascending)
{
  Enquire  *enquire;
  enquire = THIS->object_data->enquire;

  enquire->set_sort_by_value((valueno)sort_key, ascending?true:false);
  pop_n_elems(args);  
}

/*  Enquire.void set_sort_by_relevence() */
/*! @decl void set_sort_by_relevence()
 *!
 *!  
 *!
 */
PIKEFUN void set_sort_by_relevence()
{
  Enquire  *enquire;
  enquire = THIS->object_data->enquire;

  enquire->set_sort_by_relevance();
}


/*  Enquire.object get_query() */
/*! @decl object get_query()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN object get_query()
{
  Enquire  *enquire;
  Query q;
  Query * q2;
  struct object* r;
  enquire = THIS->object_data->enquire;

  q = enquire->get_query();  

  q2 = new Query(q);  

  r = fast_clone_object(Xapian_Query_program);

  OBJ2_QUERY(r)->object_data->query = q2;

  push_object(r);
}

/*  Enquire.object get_mset(int first, int maxitems, object rset, function|void mdecider) */
/*! @decl object get_mset(int first, int maxitems, object rset, function|void mdecider)
 *!
 *!  
 *! @param first
 *!  
* !
 *! @param maxitems
 *!  
* !
 *! @param rset
 *!  
* !
 *! @returns
 *!  
 *!
 */
PIKEFUN object get_mset(int first, int maxitems, object rset)
{
  Enquire  *enquire;
  enquire = THIS->object_data->enquire;
  MSet mset;
  MSet * mset1;
  struct object * o;
  RSet * rseto;

  rseto = OBJ2_RSET(rset)->object_data->rset;

  try
  {
    mset = enquire->get_mset((doccount)first, (doccount)maxitems, 
            rseto, 0);

  }
  catch(InvalidArgumentError &e)
  {
    pop_n_elems(args);
    Pike_error("InvalidArgumentError\n");
  }  

  pop_n_elems(args);

  o = fast_clone_object(Xapian_MSet_program);
  mset1 = new MSet(mset);
  OBJ2_MSET(o)->object_data->mset = mset1;

  push_object(o);


}

PIKEFUN object get_mset(int first, int maxitems, object rset, function mdecider)
{
  Enquire  *enquire;
  enquire = THIS->object_data->enquire;
  MSet mset;
  MSet * mset1;
  struct object * o;
  RSet * rseto;
  PikeMatchDeciderProxy * md;

  rseto = OBJ2_RSET(rset)->object_data->rset;
  
  md = new PikeMatchDeciderProxy(mdecider);

  try
  {
    mset = enquire->get_mset((doccount)first, (doccount)maxitems, 
            rseto, md);

  }
  catch(InvalidArgumentError &e)
  {
    pop_n_elems(args);
    Pike_error("InvalidArgumentError\n");
  }  

  pop_n_elems(args);

  o = fast_clone_object(Xapian_MSet_program);
  mset1 = new MSet(mset);
  OBJ2_MSET(o)->object_data->mset = mset1;

  push_object(o);

}

/*  Enquire.object get_mset(int first, int maxitems, int checkatleast) */
/*! @decl object get_mset(int first, int maxitems, int checkatleast)
 *!
 *!  
 *! @param first
 *!  
* !
 *! @param maxitems
 *!  
* !
 *! @param checkatleast
 *!  
* !
 *! @returns
 *!  
 *!
 */
PIKEFUN object get_mset(int first, int maxitems, int checkatleast)
{
  Enquire  *enquire;
  enquire = THIS->object_data->enquire;
  MSet mset;
  MSet * mset1;
  struct object * o;

  try
  {
    mset = enquire->get_mset((doccount)first, (doccount)maxitems, 
           (doccount)checkatleast);

  }
  catch(InvalidArgumentError &e)
  {
    pop_n_elems(args);
    Pike_error("InvalidArgumentError\n");
  }  

  pop_n_elems(args);

  o = fast_clone_object(Xapian_MSet_program);
  mset1 = new MSet(mset);
  OBJ2_MSET(o)->object_data->mset = mset1;

  push_object(o);
}


/*  Enquire.object get_eset(int maxitems, object rset, function|void edecider) */
/*! @decl object get_eset(int maxitems, object rset, function|void edecider)
 *!
 *!  
 *! @param maxitems
 *!  
* !
 *! @param rset
 *!  
* !
 *! @param edecider
 *!  
* !
 *! @returns
 *!  
 *!
 */
PIKEFUN object get_eset(int maxitems, object rset)
{
  Enquire  *enquire;
  enquire = THIS->object_data->enquire;
  ESet eset;
  ESet * eset1;
  RSet * rseto;
  struct object * o;

  rseto = OBJ2_RSET(rset)->object_data->rset;
 
  try
  {
    eset = enquire->get_eset((termcount)maxitems, *rseto, 0);

  }
  catch(InvalidArgumentError &e)
  {
    pop_n_elems(args);
    Pike_error("InvalidArgumentError\n");
  }  

  pop_n_elems(args);

  o = fast_clone_object(Xapian_ESet_program);
  eset1 = new ESet(eset);
  OBJ2_ESET(o)->object_data->eset = eset1;

  push_object(o);
}

PIKEFUN object get_eset(int maxitems, object rset, function edecider)
{
  Enquire  *enquire;
  enquire = THIS->object_data->enquire;
  ESet eset;
  ESet * eset1;
  RSet * rseto;
  struct object * o;
  PikeExpandDeciderProxy * ed;

  ed = new PikeExpandDeciderProxy(edecider);

  rseto = OBJ2_RSET(rset)->object_data->rset;
 
  try
  {
    eset = enquire->get_eset((termcount)maxitems, *rseto, ed);

  }
  catch(InvalidArgumentError &e)
  {
    pop_n_elems(args);
    Pike_error("InvalidArgumentError\n");
  }  

  pop_n_elems(args);

  o = fast_clone_object(Xapian_ESet_program);
  eset1 = new ESet(eset);
  OBJ2_ESET(o)->object_data->eset = eset1;

  push_object(o);
}

/*  Enquire.object get_eset(int maxitems, object rset, int flags, float k, function|void edecider) */
/*! @decl object get_eset(int maxitems, object rset, int flags, float k, function|void edecider)
 *!
 *!  
 *! @param maxitems
 *!  
* !
 *! @param rset
 *!  
* !
 *! @param flags
 *!  
* !
 *! @param k
 *!  
* !
 *! @param edecider
 *!  
* !
 *! @returns
 *!  
 *!
 */
PIKEFUN object get_eset(int maxitems, object rset, int flags, float k, function edecider)
{
  Enquire  *enquire;
  enquire = THIS->object_data->enquire;
  ESet eset;
  ESet * eset1;
  RSet * rseto;
  struct object * o;
  PikeExpandDeciderProxy * ed;

  ed = new PikeExpandDeciderProxy(edecider);

  rseto = OBJ2_RSET(rset)->object_data->rset;
 
  try
  {
    eset = enquire->get_eset((termcount)maxitems, *rseto, (int)flags, (double)k, ed);

  }
  catch(InvalidArgumentError &e)
  {
    pop_n_elems(args);
    Pike_error("InvalidArgumentError\n");
  }  

  pop_n_elems(args);

  o = fast_clone_object(Xapian_ESet_program);
  eset1 = new ESet(eset);
  OBJ2_ESET(o)->object_data->eset = eset1;

  push_object(o);
}

PIKEFUN object get_eset(int maxitems, object rset, int flags, float k)
{
  Enquire  *enquire;
  enquire = THIS->object_data->enquire;
  ESet eset;
  ESet * eset1;
  RSet * rseto;
  struct object * o;

  rseto = OBJ2_RSET(rset)->object_data->rset;
 
  try
  {
    eset = enquire->get_eset((termcount)maxitems, *rseto, (int)flags, (double)k, 0);

  }
  catch(InvalidArgumentError &e)
  {
    pop_n_elems(args);
    Pike_error("InvalidArgumentError\n");
  }  

  pop_n_elems(args);

  o = fast_clone_object(Xapian_ESet_program);
  eset1 = new ESet(eset);
  OBJ2_ESET(o)->object_data->eset = eset1;

  push_object(o);
}

/*! @decl object get_matching_terms(int docid)
 *!
 *! @returns
 *!   a @[TermIterator] object which can also be passed to @[foreach]()
 */
PIKEFUN object get_matching_terms(int docid)
{
  TermIterator ti;
  TermIterator * ti2;
  struct object * o;

  Enquire  *enquire;
  enquire = THIS->object_data->enquire;


  ti = enquire->get_matching_terms_begin(docid);
  ti2 = new TermIterator(ti);

  o = fast_clone_object(Xapian_TermIterator_program);

  OBJ2_TERMITERATOR(o)->object_data->termi = ti2;
  OBJ2_TERMITERATOR(o)->tie = new TermIterator(enquire->get_matching_terms_end(docid));

  push_object(o);    

}

/*  Enquire.string get_description() */
/*! @decl string get_description()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN string get_description()
{
  Enquire  *enquire;
  enquire = THIS->object_data->enquire;

  string str = enquire->get_description();

  push_text(str.c_str());
}

PIKEFUN string _sprintf(int conversion_type, mapping params)
{
  Enquire  *enquire;
  if(THIS && THIS->object_data && conversion_type == 'O')
  {
    enquire = THIS->object_data->enquire;

    string str = enquire->get_description();
    pop_n_elems(args);
    push_text(str.c_str());
  }
  else
  {
    pop_n_elems(args);
    push_int(0);
  }
}


INIT
{
    XAPIAN_ENQUIRE_OBJECT_DATA * dta = 
	(XAPIAN_ENQUIRE_OBJECT_DATA*)malloc(sizeof(XAPIAN_ENQUIRE_OBJECT_DATA));
    if (!dta)
        Pike_error("init_sample: Out of memory!\n");

    dta->enquire = NULL;
    THIS->object_data = dta;
}

EXIT 
{
  if(THIS->object_data)
  {
    Enquire  *enquire;
    enquire = THIS->object_data->enquire;
    // if(enquire) delete enquire;
    free(THIS->object_data);
  }
}

EXTRA
{
  add_integer_constant("ASCENDING", Enquire::ASCENDING, 0);
  add_integer_constant("DESCENDING", Enquire::DESCENDING, 0);
  add_integer_constant("DONT_CARE", Enquire::DONT_CARE, 0);
}

}


INIT
{
}
EXIT
{
}
EXTRA
{
/*! @decl constant DB_CREATE_OR_OPEN 
 *! @decl constant DB_CREATE
 *! @decl constant DB_CREATE_OR_OVERWRITE
 *! @decl constant DB_OPEN
 *! @decl constant BAD_VALUENO
 */
add_integer_constant("DB_CREATE_OR_OPEN", DB_CREATE_OR_OPEN, 0);
add_integer_constant("DB_CREATE", DB_CREATE, 0);
add_integer_constant("DB_CREATE_OR_OVERWRITE", DB_CREATE_OR_OVERWRITE, 0);
add_integer_constant("DB_OPEN", DB_OPEN, 0);
add_integer_constant("BAD_VALUENO", BAD_VALUENO, 0);
}

/*!  @endclass
 */


/*! @class TermGenerator
*/
PIKECLASS TermGenerator
{
CVAR XAPIAN_TERMGENERATOR_OBJECT_DATA   *object_data;

  PIKEFUN void create()
  {
    TermGenerator * termgenerator;
    termgenerator = new TermGenerator();

    THIS->object_data->termgenerator = termgenerator;
  }


PIKEFUN int set_flags(int flags, int mask)
{
  TermGenerator * termgenerator;
  termgenerator = (TermGenerator*)THIS->object_data->termgenerator;

  TermGenerator::flags f;
  TermGenerator::flags m;

  f = (TermGenerator::flags)flags;
  m = (TermGenerator::flags)mask;

  termgenerator->set_flags(f, m);

  pop_n_elems(args);
}

/*  TermGenerator.void set_document(object document) */
/*! @decl void set_document(object document)
 *!
 *!  
 *! @param document
 *!  
* !
 *! @returns
 *!  
 *!
 */
PIKEFUN void set_document(object document)
{
  TermGenerator * termgenerator;
  Document * doc;
  struct Xapian_Document_struct * od;

  termgenerator = (TermGenerator*)THIS->object_data->termgenerator;

  od = OBJ2_DOCUMENT(document);

  if(!od) Pike_error("Not a Document!\n");

  doc = od->object_data->document;

  try
  {
    termgenerator->set_document(*doc);
  }
  catch(Xapian::DatabaseCorruptError &e)
  {
    Pike_error("DatabaseCorruptError\n");
  }
  catch(Xapian::DatabaseError &e)
  {
    Pike_error("DatabaseError\n");
  }
  catch(Xapian::InvalidArgumentError &e)
  {
    //printf("%s\n",e.get_msg().c_str());
    Pike_error("InvalidArgumentError\n");
  }
  pop_n_elems(args);
}

/*! @decl object get_document()
*!
*/
  PIKEFUN object get_document()
  {
    TermGenerator * termgenerator;
    Document doc;
    Document *doc2;
    struct object * o;
    try {
    termgenerator = (TermGenerator*)THIS->object_data->termgenerator;
    doc = termgenerator->get_document();    
    doc2 = new Document(doc);

    o = fast_clone_object(Xapian_Document_program);
    OBJ2_DOCUMENT(o)->object_data->document = doc2;

    push_object(o);
  }
  catch(RangeError &e)
  {
    pop_n_elems(args);
    Pike_error("RangeError\n");
  }

  }

/*  TermGenerator.void set_stemmer(object stemmer) */
/*! @decl void set_stemmer(object stemmer)
 *!
 *!  
 *! @param stemmer
 *!  
* !
 *!
 */
PIKEFUN void set_stemmer(object stemmer)
{
  TermGenerator * termgenerator;
  Stem * s;

  termgenerator = THIS->object_data->termgenerator;
  s = OBJ2_STEM(stemmer)->object_data->stem; 
  termgenerator->set_stemmer((const Stem)*s);

  pop_n_elems(args);
}

/*  TermGenerator.void set_stopper(object stopper) */
/*! @decl void set_stopper(object stopper)
 *!
 *!  
 *! @param stopper
 *!  
* !
 *!
 */
PIKEFUN void set_stopper(object stopper)
{
  TermGenerator * termgenerator;
  Stopper * s;

  termgenerator = THIS->object_data->termgenerator;
  s = OBJ2_STOPPER(stopper)->object_data->stopper; 
  termgenerator->set_stopper((const Stopper*)s);

  pop_n_elems(args);
}

/*  TermGenerator.void set_database(object database) */
/*! @decl void set_database(object database)
 *!
 *!  
 *! @param database
 *!  
 *!
 *!
 */
PIKEFUN void set_database(object database)
{
  TermGenerator * termgenerator;
  Database * d;

  termgenerator = THIS->object_data->termgenerator;
  d = OBJ2_DATABASE(database)->object_data->database; 

  termgenerator->set_database((const Xapian::WritableDatabase&)*d);

  pop_n_elems(args);
}



/*! @decl void set_termpos(int termpos)
 *!
 */
PIKEFUN void set_termpos(int termpos)
{
  TermGenerator * termgenerator;

  termgenerator = THIS->object_data->termgenerator;

  termgenerator->set_termpos((Xapian::termcount)termpos);

  pop_n_elems(args);
}


/*! @decl int get_termpos()
 *!
 */
PIKEFUN int get_termpos()
{
  TermGenerator * termgenerator;

  termgenerator = THIS->object_data->termgenerator;

  Xapian::termcount termpos;

  termpos = termgenerator->get_termpos();

  push_int((int)termpos);
}


/*! @decl void index_text(string text, int weight, string prefix)
 *!
 *! @note
 *!   this function is wide-string aware.
*/
PIKEFUN void index_text(string text, int weight, string prefix)
{
  TermGenerator * termgenerator;

  ref_push_string(text);
  f_string_to_utf8(1);

  Xapian::Utf8Iterator * text_iter = new Xapian::Utf8Iterator((const char *)Pike_sp[-1].u.string->str, (size_t) Pike_sp[-1].u.string->len);
  string prefix_str((const char *)prefix->str, (size_t)prefix->len);

  termgenerator = THIS->object_data->termgenerator;

  termgenerator->index_text(*text_iter, (Xapian::termcount) weight, prefix_str);

  pop_n_elems(args+1);
}


/*! @decl void index_text_without_positions(string text, int weight, string prefix)
 *!
 *! @note
 *!   this function is wide-string aware.
*/
PIKEFUN void index_text_without_positions(string text, int weight, string prefix)
{
  TermGenerator * termgenerator;

  ref_push_string(text);
  f_string_to_utf8(1);

  Xapian::Utf8Iterator * text_iter = new Xapian::Utf8Iterator((const char *)Pike_sp[-1].u.string->str, (size_t) Pike_sp[-1].u.string->len);
  string prefix_str((const char *)prefix->str, (size_t)prefix->len);

  termgenerator = THIS->object_data->termgenerator;

  termgenerator->index_text_without_positions(*text_iter, (Xapian::termcount) weight, prefix_str);

  pop_n_elems(args+1);
}


/*  Stopper.string get_description() */
/*! @decl string get_description()
 *!
 *!  
 *! @returns
 *!  
 *!
 */
PIKEFUN string get_description()
{
  TermGenerator * termgenerator;
  termgenerator = THIS->object_data->termgenerator;

  string str = termgenerator->get_description();

  push_text(str.c_str());
}

PIKEFUN string _sprintf(int conversion_type, mapping params)
{
  TermGenerator * termgenerator;


  if(THIS && THIS->object_data && conversion_type == 'O')
  {
    termgenerator = THIS->object_data->termgenerator;

    string str = termgenerator->get_description();
    pop_n_elems(args);
    push_text(str.c_str());
  }
  else
  {
    pop_n_elems(args);
    push_int(0);
  }
}

INIT
{
    XAPIAN_TERMGENERATOR_OBJECT_DATA * dta = 
	(XAPIAN_TERMGENERATOR_OBJECT_DATA*)malloc(sizeof(XAPIAN_TERMGENERATOR_OBJECT_DATA));
    if (!dta)
        Pike_error("init_sample: Out of memory!\n");

    dta->termgenerator = NULL;
    THIS->object_data = dta;
}

/*  Weight.void destroy() */
/*! @decl void destroy()
 *!
 *!  
 *!
 */
PIKEFUN void destroy(int|void reason)
{

    TermGenerator * termgenerator;
    termgenerator = THIS->object_data->termgenerator;

    if(termgenerator) 
    {
     delete termgenerator;
    }

    pop_n_elems(args);
}

EXTRA
{
/*! @decl constant OP_AND
 *! Return iff both subqueries are satisfied.
 */
add_integer_constant("FLAG_SPELLING", TermGenerator::FLAG_SPELLING, 0);

}

EXIT 
{
  if(THIS->object_data)
  {

    TermGenerator  *termgenerator;
    termgenerator = THIS->object_data->termgenerator;
//    printf("shutting down!\n");
    free(THIS->object_data);
  }
}

}

/*!  @endclass
*/


/*! @endmodule
 */

/*! @endmodule
 */




gotpike.org | Copyright © 2004 - 2019 | Pike is a trademark of Department of Computer and Information Science, Linköping University