230 lines
6.0 KiB
C++
230 lines
6.0 KiB
C++
/*------------------------------------------------------------------------------
|
|
* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team
|
|
*
|
|
* Distributable under the terms of either the Apache License (Version 2.0) or
|
|
* the GNU Lesser General Public License, as specified in the COPYING file.
|
|
------------------------------------------------------------------------------*/
|
|
#include "CLucene/StdHeader.h"
|
|
#include "Document.h"
|
|
#include "Field.h"
|
|
#include "CLucene/util/StringBuffer.h"
|
|
|
|
CL_NS_USE(util)
|
|
CL_NS_DEF(document)
|
|
|
|
DocumentFieldList::DocumentFieldList(Field* f, DocumentFieldList* n ) {
|
|
//Func - Constructor
|
|
//Pre - f != NULL
|
|
// n may be NULL
|
|
//Post - Instance has been created
|
|
CND_PRECONDITION(f != NULL, "f is NULL");
|
|
|
|
field = f;
|
|
next = n;
|
|
}
|
|
DocumentFieldList::~DocumentFieldList(){
|
|
//Func - Destructor
|
|
//Pre - true
|
|
//Post - Instance has been destroyed
|
|
|
|
// Instead of recursively deleting the field list we do
|
|
// it iteratively to avoid stack overflows when
|
|
// dealing with several thousands of fields.
|
|
|
|
DocumentFieldList* cur = next;
|
|
while (cur != NULL)
|
|
{
|
|
DocumentFieldList* temp = cur->next;
|
|
cur->next = NULL;
|
|
|
|
_CLDELETE(cur);
|
|
cur = temp;
|
|
}
|
|
_CLDELETE(field);
|
|
}
|
|
|
|
|
|
DocumentFieldEnumeration::DocumentFieldEnumeration(const DocumentFieldList* fl){
|
|
//Func - Constructor
|
|
//Pre - fl may be NULL
|
|
//Post - Instance has been created
|
|
|
|
fields = fl;
|
|
}
|
|
|
|
DocumentFieldEnumeration::~DocumentFieldEnumeration(){
|
|
//Func - Destructor
|
|
//Pre - true
|
|
//Post - Instance has been destroyed
|
|
}
|
|
|
|
bool DocumentFieldEnumeration::hasMoreElements() const {
|
|
return fields == NULL ? false : true;
|
|
}
|
|
|
|
Field* DocumentFieldEnumeration::nextElement() {
|
|
//Func - Return the next element in the enumeration
|
|
//Pre - true
|
|
//Post - The next element is returned or NULL
|
|
|
|
|
|
Field* result = NULL;
|
|
//Check if fields is still valid
|
|
if (fields){
|
|
result = fields->field;
|
|
fields = fields->next;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/** Constructs a new document with no fields. */
|
|
Document::Document(){
|
|
//Func - Constructor
|
|
//Pre - true
|
|
//Post - Instance has been created
|
|
boost = 1.0f;
|
|
fieldList = NULL;
|
|
}
|
|
|
|
Document::~Document(){
|
|
//Func - Destructor
|
|
//Pre - true
|
|
//Post - Instance has been destroyed
|
|
|
|
_CLDELETE(fieldList);
|
|
}
|
|
|
|
void Document::add(Field& field) {
|
|
fieldList = _CLNEW DocumentFieldList(&field, fieldList);
|
|
}
|
|
|
|
void Document::setBoost(float_t boost) {
|
|
this->boost = boost;
|
|
}
|
|
|
|
float_t Document::getBoost() const {
|
|
return boost;
|
|
}
|
|
|
|
|
|
Field* Document::getField(const TCHAR* name) const{
|
|
CND_PRECONDITION(name != NULL, "name is NULL");
|
|
|
|
for (DocumentFieldList* list = fieldList; list != NULL; list = list->next)
|
|
//cannot use interning here, because name is probably not interned
|
|
if ( _tcscmp(list->field->name(), name) == 0 ){
|
|
return list->field;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
const TCHAR* Document::get(const TCHAR* field) const {
|
|
CND_PRECONDITION(field != NULL, "field is NULL");
|
|
Field *f = getField(field);
|
|
if (f!=NULL)
|
|
return f->stringValue(); //this returns null it is a binary(reader)
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
DocumentFieldEnumeration* Document::fields() const {
|
|
return _CLNEW DocumentFieldEnumeration(fieldList);
|
|
}
|
|
|
|
|
|
TCHAR* Document::toString() const {
|
|
StringBuffer ret(_T("Document<"));
|
|
for (DocumentFieldList* list = fieldList; list != NULL; list = list->next) {
|
|
TCHAR* tmp = list->field->toString();
|
|
ret.append( tmp );
|
|
if (list->next != NULL)
|
|
ret.append(_T(" "));
|
|
_CLDELETE_ARRAY( tmp );
|
|
}
|
|
ret.append(_T(">"));
|
|
return ret.toString();
|
|
}
|
|
|
|
|
|
|
|
void Document::removeField(const TCHAR* name) {
|
|
CND_PRECONDITION(name != NULL, "name is NULL");
|
|
|
|
DocumentFieldList* previous = NULL;
|
|
DocumentFieldList* current = fieldList;
|
|
while (current != NULL) {
|
|
//cannot use interning here, because name is probably not interned
|
|
if ( _tcscmp(current->field->name(),name) == 0 ){
|
|
if (previous){
|
|
previous->next = current->next;
|
|
}else
|
|
fieldList = current->next;
|
|
current->next=NULL; //ensure fieldlist destructor doesnt delete it
|
|
_CLDELETE(current);
|
|
return;
|
|
}
|
|
previous = current;
|
|
current = current->next;
|
|
}
|
|
}
|
|
|
|
void Document::removeFields(const TCHAR* name) {
|
|
CND_PRECONDITION(name != NULL, "name is NULL");
|
|
|
|
DocumentFieldList* previous = NULL;
|
|
DocumentFieldList* current = fieldList;
|
|
while (current != NULL) {
|
|
//cannot use interning here, because name is probably not interned
|
|
if ( _tcscmp(current->field->name(),name) == 0 ){
|
|
if (previous){
|
|
previous->next = current->next;
|
|
}else
|
|
fieldList = current->next;
|
|
|
|
current->next=NULL; //ensure fieldlist destructor doesnt delete it
|
|
_CLDELETE(current);
|
|
|
|
if ( previous )
|
|
current = previous->next;
|
|
else
|
|
current = fieldList;
|
|
}else{
|
|
previous = current;
|
|
current = current->next;
|
|
}
|
|
}
|
|
}
|
|
|
|
TCHAR** Document::getValues(const TCHAR* name) {
|
|
DocumentFieldEnumeration* it = fields();
|
|
int32_t count = 0;
|
|
while ( it->hasMoreElements() ){
|
|
Field* f = it->nextElement();
|
|
//cannot use interning here, because name is probably not interned
|
|
if ( _tcscmp(f->name(),name) == 0 && f->stringValue() != NULL )
|
|
count++;
|
|
}
|
|
_CLDELETE(it);
|
|
it = fields();
|
|
|
|
//todo: there must be a better way of doing this, we are doing two iterations of the fields
|
|
TCHAR** ret = NULL;
|
|
if ( count > 0 ){
|
|
//start again
|
|
ret = _CL_NEWARRAY(TCHAR*,count+1);
|
|
int32_t i=0;
|
|
while ( it->hasMoreElements() ){
|
|
Field* fld=it->nextElement();
|
|
if ( _tcscmp(fld->name(),name)== 0 && fld->stringValue() != NULL ){
|
|
ret[i] = stringDuplicate(fld->stringValue());
|
|
i++;
|
|
}
|
|
}
|
|
ret[count]=NULL;
|
|
}
|
|
_CLDELETE(it);
|
|
return ret;
|
|
}
|
|
CL_NS_END
|