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

File Contents

Contents of /Public_Xapian-1.4/xapian.ccmod:

/*! @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 <xapian.h>

#include <algorithm>
#include <iostream>
#include <string>
#include <vector>

using namespace Xapian;
using namespace std;

#include <ctype.h>

#define OBJ2_MSET(o) ((struct MSet_struct *)get_storage(o, MSet_program))
#define OBJ2_ESET(o) ((struct ESet_struct *)get_storage(o, ESet_program))
#define OBJ2_STEM(o) ((struct Stem_struct *)get_storage(o, Stem_program))
#define OBJ2_STOPPER(o) ((struct Stopper_struct *)get_storage(o, Stopper_program))
#define OBJ2_MSETITERATOR(o) ((struct MSetIterator_struct *)get_storage(o, MSetIterator_program))
#define OBJ2_ESETITERATOR(o) ((struct ESetIterator_struct *)get_storage(o, ESetIterator_program))
#define OBJ2_VALUEITERATOR(o) ((struct ValueIterator_struct *)get_storage(o, ValueIterator_program))
#define OBJ2_TERMITERATOR(o) ((struct TermIterator_struct *)get_storage(o, TermIterator_program))
#define OBJ2_POSITIONITERATOR(o) ((struct PositionIterator_struct *)get_storage(o, PositionIterator_program))
#define OBJ2_DOCUMENT(o) ((struct Document_struct *)get_storage(o, Document_program))
#define OBJ2_DATABASE(o) ((struct Database_struct *)get_storage(o, Database_program))
#define OBJ2_QUERY(o) ((struct Query_struct *)get_storage(o, Query_program))
#define OBJ2_TERMGENERATOR(o) ((struct TermGenerator_struct *)get_storage(o, TermGenerator_program))
#define OBJ2_VALUERANGEPROCESSOR(o) ((struct ValueRangeProcessor_struct *)get_storage(o, ValueRangeProcessor_program))


extern "C" struct program * Document_program;
extern "C" struct program * MSetIterator_program;
extern "C" struct program * ValueIterator_program;
extern "C" struct program * TermIterator_program;
extern "C" struct program * PositionIterator_program;
extern "C" struct program * MSet_program;
extern "C" struct program * Stem_program;
extern "C" struct program * TermGenerator_program;
extern "C" struct program * 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()
{
  Weight *weight;
  weight = THIS->object_data->weight;

  bool i = weight->get_sumpart_needs_doclength();

  push_int(i?1:0);
}

/*  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()
{

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

    if(weight) 
    {
     delete weight;
    }

}

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 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;
  }

  PIKEFUN object clone()
  {
    BM25Weight * weight;
    BM25Weight * weight2;
    struct object * obj;

    weight = (BM25Weight *)THIS->object_data->weight;
    weight2 = weight->clone();

    obj = fast_clone_object(BM25Weight_program);
    OBJ2_WEIGHT(obj)->object_data->weight = (Weight *)weight2;

    push_object(obj);    
  }
}

/*!  @endclass
*/

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

PIKECLASS BoolWeight
{
  INHERIT 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 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()
{
    ValueRangeProcessor  *vrp;
    vrp = THIS->object_data->processor;

    if(vrp) 
    {
     delete vrp;
    }
}

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 ValueRangeProcessor;

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

    THIS_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 ValueRangeProcessor;

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

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

/*! @decl void create(int valueno, string _str, int[0..1] 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_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 DateValueRangeProcessor
{
  INHERIT ValueRangeProcessor;

/*! @decl void create(int valueno, int[0..1] 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_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()
{

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

    if(stopper) 
    {
     delete stopper;
    }

}

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 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<string> 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_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_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()
{

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

    if(stem) 
    {
     delete stem;
    }

}

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);

    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()
  {
    PositionIterator  *pi;
    pi = THIS->object_data->positioni;

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

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

  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 PositionIterator_struct * pis;    

    if(arg->type!= 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 mixed `+=(int i)
  {
    PositionIterator  *pi;
    pi = THIS->object_data->positioni;
    
    for(int x = 0; x < i; x++)
    {
      (*pi)++;
      if(*pi == *(THIS->pie)) {
        pop_stack(); push_int(0); return;}
    }
    THIS->current_index++;
    pop_stack();
    push_object(this_object());
  }
 
  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_sample: 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  *valuei;
    valuei = THIS->object_data->valuei;
    ValueIterator *valuei2;

    struct object * o;

    valuei2 = new ValueIterator((*valuei)++);

    o = fast_clone_object(ValueIterator_program);

    OBJ2_VALUEITERATOR(o)->object_data->valuei = valuei;

    push_object(o);    
  }

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

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

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

    if(arg->type!= 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()
  {
    
    ValueIterator  *valuei;
    valueno i;
    try 
    {
      valuei = (ValueIterator*)THIS->object_data->valuei;
      i = valuei->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()
  {
    ValueIterator  *valuei;
    string i;

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

  PIKEFUN mixed `+=(int i)
  {
    ValueIterator  *vi;
    vi = THIS->object_data->valuei;
    
    for(int x = 0; x < i; x++)
    {
      (*vi)++;
      if(*vi == *(THIS->vie)) {
        pop_stack(); push_int(0); return;}
    }
    THIS->current_index++;
    pop_stack();
    push_object(this_object());
  }
 
  PIKEFUN int `!()
  {
    ValueIterator  *vi;
    vi = THIS->object_data->valuei;
    if(*vi == *(THIS->vie)) { push_int(1); }
    else
      push_int(0);
  }

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

  string str = 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')
  {
    it = THIS->object_data->valuei;

    string str = it->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()
  {
    TermIterator  * termi;
    termi = THIS->object_data->termi;
    TermIterator *termi2;

    struct object * o;

    termi2 = new TermIterator(++(*termi));

    o = fast_clone_object(TermIterator_program);

    OBJ2_TERMITERATOR(o)->object_data->termi = termi;

    push_object(o);    
  }

  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 TermIterator_struct * tis;    

    if(arg->type!= 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(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;
  doc = THIS->object_data->document;

  ValueIterator vi;
  ValueIterator * vi2;
  struct object * o;

  vi = doc->values_begin();
  vi2 = new ValueIterator(vi);

  o = fast_clone_object(ValueIterator_program);

  OBJ2_VALUEITERATOR(o)->object_data->valuei = vi2;
  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(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(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(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 MSetIterator_struct * msis;    
    MSetIterator  *mseti;
    MSetIterator  *msetb;
    if(arg->type!= 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(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 ESetIterator_struct * esis;    

    if(arg->type!= 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(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(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(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(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(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(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(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(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(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 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(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(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(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()
{
    Database  *db;
    db = THIS->object_data->database;

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

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

}

/*!  @endclass
*/

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

PIKECLASS WriteableDatabase
{
INHERIT 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 = new WritableDatabase(str, mode);

    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 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 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 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(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(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(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(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(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(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(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(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(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(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 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(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()
{

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

    if(termgenerator) 
    {
     delete termgenerator;
    }

}

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 - 2011 | Pike is a trademark of Department of Computer and Information Science, Linköping University