2369 lines
60 KiB
C
2369 lines
60 KiB
C
/* WIDE AREA INFORMATION SERVER SOFTWARE:
|
|
Developed by Thinking Machines Corporation and put into the public
|
|
domain with no guarantees or restrictions.
|
|
*/
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
#define _C_WAIS_protocol_
|
|
|
|
#include "wprot.h"
|
|
#include "cutil.h"
|
|
#include "panic.h"
|
|
#include <string.h>
|
|
|
|
#define DefWAISInitResponseSize (size_t)200
|
|
#define DefWAISSearchSize (size_t)3000
|
|
#define DefWAISSearchResponseSize (size_t)6000
|
|
#define DefWAISPresentSize (size_t)1000
|
|
#define DefWAISPresentResponseSize (size_t)6000
|
|
#define DefWAISDocHeaderSize (size_t)500
|
|
#define DefWAISShortHeaderSize (size_t)200
|
|
#define DefWAISLongHeaderSize (size_t)800
|
|
#define DefWAISDocTextSize (size_t)6000
|
|
#define DefWAISDocHeadlineSize (size_t)500
|
|
#define DefWAISDocCodeSize (size_t)500
|
|
|
|
#define RESERVE_SPACE_FOR_WAIS_HEADER(len) \
|
|
if (*len > 0) \
|
|
*len -= header_len;
|
|
|
|
static char* writeUserInfoHeader _AP((data_tag tag,long infoSize,
|
|
long estHeaderSize,char* buffer,
|
|
long* len));
|
|
|
|
static unsigned long userInfoTagSize _AP((data_tag tag,
|
|
unsigned long length));
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
char*
|
|
writeInitInfo(init,buffer,len)
|
|
InitAPDU* init;
|
|
char* buffer;
|
|
long* len;
|
|
{
|
|
char *userInfo, *buf;
|
|
|
|
|
|
|
|
/*!! Clever - set it to Null, and then test it */
|
|
userInfo = NULL;
|
|
|
|
if(userInfo != NULL) {
|
|
buf = writeString(userInfo, DT_UserInformationField, buffer, len);
|
|
return(buf);
|
|
}
|
|
else return buffer;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
static char* readUserInfoHeader _AP((data_tag* tag,unsigned long* num,
|
|
char* buffer));
|
|
|
|
char*
|
|
readInitInfo(info,buffer)
|
|
void** info;
|
|
char* buffer;
|
|
{
|
|
|
|
readString((char **)info, buffer);
|
|
return buffer;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
static unsigned long
|
|
userInfoTagSize(tag,length)
|
|
data_tag tag;
|
|
unsigned long length;
|
|
|
|
{
|
|
unsigned long size;
|
|
|
|
|
|
size = writtenCompressedIntSize(tag);
|
|
size += writtenCompressedIntSize(length);
|
|
|
|
return(size);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
static char*
|
|
writeUserInfoHeader(tag,infoSize,estHeaderSize,buffer,len)
|
|
data_tag tag;
|
|
long infoSize;
|
|
long estHeaderSize;
|
|
char* buffer;
|
|
long* len;
|
|
|
|
{
|
|
long dummyLen = 100;
|
|
char* buf = buffer;
|
|
long realSize = infoSize - estHeaderSize;
|
|
long realHeaderSize = userInfoTagSize(tag,realSize);
|
|
|
|
if (buffer == NULL || *len == 0)
|
|
return(NULL);
|
|
|
|
|
|
buf = writeTag(tag,buf,&dummyLen);
|
|
|
|
|
|
if (estHeaderSize != realHeaderSize)
|
|
{
|
|
CHECK_FOR_SPACE_LEFT(realHeaderSize - estHeaderSize,len);
|
|
memmove(buffer + realHeaderSize,buffer + estHeaderSize,(size_t)(realSize));
|
|
}
|
|
|
|
|
|
writeCompressedInteger(realSize,buf,&dummyLen);
|
|
|
|
|
|
return(buffer + realHeaderSize + realSize);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
static char*
|
|
readUserInfoHeader(tag,num,buffer)
|
|
data_tag* tag;
|
|
unsigned long* num;
|
|
char* buffer;
|
|
|
|
{
|
|
char* buf = buffer;
|
|
buf = readTag(tag,buf);
|
|
buf = readCompressedInteger(num,buf);
|
|
return(buf);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
WAISInitResponse*
|
|
makeWAISInitResponse(chunkCode,
|
|
chunkIDLen,
|
|
chunkMarker,
|
|
highlightMarker,
|
|
deHighlightMarker,
|
|
newLineChars)
|
|
long chunkCode;
|
|
long chunkIDLen;
|
|
char* chunkMarker;
|
|
char* highlightMarker;
|
|
char* deHighlightMarker;
|
|
char* newLineChars;
|
|
|
|
{
|
|
WAISInitResponse* init = (WAISInitResponse*)s_malloc((size_t)sizeof(WAISInitResponse));
|
|
|
|
init->ChunkCode = chunkCode;
|
|
init->ChunkIDLength = chunkIDLen;
|
|
init->ChunkMarker = chunkMarker;
|
|
init->HighlightMarker = highlightMarker;
|
|
init->DeHighlightMarker = deHighlightMarker;
|
|
init->NewlineCharacters = newLineChars;
|
|
|
|
return(init);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
void
|
|
freeWAISInitResponse(init)
|
|
WAISInitResponse* init;
|
|
|
|
{
|
|
if(!init)
|
|
return;
|
|
s_free(init->ChunkMarker);
|
|
s_free(init->HighlightMarker);
|
|
s_free(init->DeHighlightMarker);
|
|
s_free(init->NewlineCharacters);
|
|
s_free(init);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
char*
|
|
writeInitResponseInfo(init,buffer,len)
|
|
InitResponseAPDU* init;
|
|
char* buffer;
|
|
long* len;
|
|
|
|
{
|
|
unsigned long header_len = userInfoTagSize(DT_UserInformationLength,
|
|
DefWAISInitResponseSize);
|
|
char* buf = buffer + header_len;
|
|
WAISInitResponse* info = (WAISInitResponse*)init->UserInformationField;
|
|
unsigned long size;
|
|
|
|
RESERVE_SPACE_FOR_WAIS_HEADER(len);
|
|
|
|
buf = writeNum(info->ChunkCode,DT_ChunkCode,buf,len);
|
|
buf = writeNum(info->ChunkIDLength,DT_ChunkIDLength,buf,len);
|
|
buf = writeString(info->ChunkMarker,DT_ChunkMarker,buf,len);
|
|
buf = writeString(info->HighlightMarker,DT_HighlightMarker,buf,len);
|
|
buf = writeString(info->DeHighlightMarker,DT_DeHighlightMarker,buf,len);
|
|
buf = writeString(info->NewlineCharacters,DT_NewlineCharacters,buf,len);
|
|
|
|
|
|
size = buf - buffer;
|
|
buf = writeUserInfoHeader(DT_UserInformationLength,size,header_len,buffer,len);
|
|
|
|
return(buf);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
char*
|
|
readInitResponseInfo(info,buffer)
|
|
void** info;
|
|
char* buffer;
|
|
|
|
{
|
|
char* buf = buffer;
|
|
unsigned long size;
|
|
unsigned long headerSize;
|
|
data_tag tag;
|
|
long chunkCode,chunkIDLen;
|
|
char* chunkMarker = NULL;
|
|
char* highlightMarker = NULL;
|
|
char* deHighlightMarker = NULL;
|
|
char* newLineChars = NULL;
|
|
|
|
chunkCode = chunkIDLen = UNUSED;
|
|
|
|
buf = readUserInfoHeader(&tag,&size,buf);
|
|
headerSize = buf - buffer;
|
|
|
|
while (buf < (buffer + size + headerSize))
|
|
{ data_tag tag = peekTag(buf);
|
|
switch (tag)
|
|
{ case DT_ChunkCode:
|
|
buf = readNum(&chunkCode,buf);
|
|
break;
|
|
case DT_ChunkIDLength:
|
|
buf = readNum(&chunkIDLen,buf);
|
|
break;
|
|
case DT_ChunkMarker:
|
|
buf = readString(&chunkMarker,buf);
|
|
break;
|
|
case DT_HighlightMarker:
|
|
buf = readString(&highlightMarker,buf);
|
|
break;
|
|
case DT_DeHighlightMarker:
|
|
buf = readString(&deHighlightMarker,buf);
|
|
break;
|
|
case DT_NewlineCharacters:
|
|
buf = readString(&newLineChars,buf);
|
|
break;
|
|
default:
|
|
s_free(highlightMarker);
|
|
s_free(deHighlightMarker);
|
|
s_free(newLineChars);
|
|
REPORT_READ_ERROR(buf); /*does a return */
|
|
break;
|
|
}
|
|
}
|
|
|
|
*info = (void *)makeWAISInitResponse(chunkCode,chunkIDLen,chunkMarker,
|
|
highlightMarker,deHighlightMarker,
|
|
newLineChars);
|
|
return(buf);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
WAISSearch*
|
|
makeWAISSearch(seedWords,
|
|
docs,
|
|
textList,
|
|
dateFactor,
|
|
beginDateRange,
|
|
endDateRange,
|
|
maxDocsRetrieved)
|
|
char* seedWords;
|
|
DocObj** docs;
|
|
char** textList;
|
|
long dateFactor;
|
|
char* beginDateRange;
|
|
char* endDateRange;
|
|
long maxDocsRetrieved;
|
|
|
|
|
|
{
|
|
WAISSearch* query = (WAISSearch*)s_malloc((size_t)sizeof(WAISSearch));
|
|
|
|
query->SeedWords = seedWords;
|
|
query->Docs = docs;
|
|
query->TextList = textList;
|
|
query->DateFactor = dateFactor;
|
|
query->BeginDateRange = beginDateRange;
|
|
query->EndDateRange = endDateRange;
|
|
query->MaxDocumentsRetrieved = maxDocsRetrieved;
|
|
|
|
return(query);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
void
|
|
freeWAISSearch(query)
|
|
WAISSearch* query;
|
|
|
|
|
|
{
|
|
void* ptr = NULL;
|
|
long i;
|
|
|
|
s_free(query->SeedWords);
|
|
|
|
if (query->Docs != NULL)
|
|
for (i = 0,ptr = (void *)query->Docs[i]; ptr != NULL; ptr = (void *)query->Docs[++i])
|
|
freeDocObj((DocObj*)ptr);
|
|
s_free(query->Docs);
|
|
|
|
if (query->TextList != NULL)
|
|
for (i = 0,ptr = (void *)query->TextList[i]; ptr != NULL; ptr = (void *)query->TextList[++i])
|
|
s_free(ptr);
|
|
s_free(query->TextList);
|
|
|
|
s_free(query->BeginDateRange);
|
|
s_free(query->EndDateRange);
|
|
s_free(query);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
DocObj*
|
|
makeDocObjUsingWholeDocument(docID,type) /*!!ALLOC*/
|
|
any* docID;
|
|
char* type;
|
|
|
|
|
|
{
|
|
DocObj* doc = (DocObj*)s_malloc((size_t)sizeof(DocObj));
|
|
doc->DocumentID = docID;
|
|
doc->Type = type;
|
|
doc->ChunkCode = CT_document;
|
|
return(doc);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
DocObj*
|
|
makeDocObjUsingLines(docID,type,start,end) /*!!ALLOC*/
|
|
any* docID;
|
|
char* type;
|
|
long start;
|
|
long end;
|
|
|
|
|
|
{
|
|
DocObj* doc = (DocObj*)s_malloc((size_t)sizeof(DocObj));
|
|
doc->ChunkCode = CT_line;
|
|
doc->DocumentID = docID;
|
|
doc->Type = type;
|
|
doc->ChunkStart.Pos = start;
|
|
doc->ChunkEnd.Pos = end;
|
|
return(doc);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
|
|
DocObj*
|
|
makeDocObjUsingBytes(docID,type,start,end)
|
|
any* docID;
|
|
char* type;
|
|
long start;
|
|
long end;
|
|
|
|
|
|
{
|
|
DocObj* doc = (DocObj*)s_malloc((size_t)sizeof(DocObj));
|
|
doc->ChunkCode = CT_byte;
|
|
doc->DocumentID = docID;
|
|
doc->Type = type;
|
|
doc->ChunkStart.Pos = start;
|
|
doc->ChunkEnd.Pos = end;
|
|
return(doc);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
DocObj*
|
|
makeDocObjUsingParagraphs(docID,type,start,end)
|
|
any* docID;
|
|
char* type;
|
|
any* start;
|
|
any* end;
|
|
|
|
|
|
{
|
|
DocObj* doc = (DocObj*)s_malloc((size_t)sizeof(DocObj));
|
|
doc->ChunkCode = CT_paragraph;
|
|
doc->DocumentID = docID;
|
|
doc->Type = type;
|
|
doc->ChunkStart.ID = start;
|
|
doc->ChunkEnd.ID = end;
|
|
return(doc);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
void
|
|
freeDocObj(doc)
|
|
DocObj* doc;
|
|
|
|
|
|
{
|
|
freeAny(doc->DocumentID);
|
|
s_free(doc->Type);
|
|
if (doc->ChunkCode == CT_paragraph)
|
|
{ freeAny(doc->ChunkStart.ID);
|
|
freeAny(doc->ChunkEnd.ID);
|
|
}
|
|
s_free(doc);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
static char* writeDocObj _AP((DocObj* doc,char* buffer,long* len));
|
|
|
|
static char*
|
|
writeDocObj(doc,buffer,len)
|
|
DocObj* doc;
|
|
char* buffer;
|
|
long* len;
|
|
|
|
|
|
{
|
|
char* buf = buffer;
|
|
|
|
|
|
if (doc->ChunkCode == CT_document)
|
|
buf = writeAny(doc->DocumentID,DT_DocumentID,buf,len);
|
|
else
|
|
buf = writeAny(doc->DocumentID,DT_DocumentIDChunk,buf,len);
|
|
|
|
if (doc->Type != NULL)
|
|
buf = writeString(doc->Type,DT_TYPE,buf,len);
|
|
|
|
switch (doc->ChunkCode)
|
|
{ case CT_document:
|
|
|
|
break;
|
|
case CT_byte:
|
|
case CT_line:
|
|
buf = writeNum(doc->ChunkCode,DT_ChunkCode,buf,len);
|
|
buf = writeNum(doc->ChunkStart.Pos,DT_ChunkStartID,buf,len);
|
|
buf = writeNum(doc->ChunkEnd.Pos,DT_ChunkEndID,buf,len);
|
|
break;
|
|
case CT_paragraph:
|
|
buf = writeNum(doc->ChunkCode,DT_ChunkCode,buf,len);
|
|
buf = writeAny(doc->ChunkStart.ID,DT_ChunkStartID,buf,len);
|
|
buf = writeAny(doc->ChunkEnd.ID,DT_ChunkEndID,buf,len);
|
|
break;
|
|
default:
|
|
panic("Implementation error: unknown chuck type %ld",
|
|
doc->ChunkCode);
|
|
break;
|
|
}
|
|
|
|
return(buf);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
static char* readDocObj _AP((DocObj** doc,char* buffer));
|
|
|
|
static char*
|
|
readDocObj(doc,buffer) /*!!ALLOCS (in doc) */
|
|
DocObj** doc;
|
|
char* buffer;
|
|
|
|
|
|
{
|
|
char* buf = buffer;
|
|
data_tag tag;
|
|
char *retval = NULL;
|
|
|
|
*doc = (DocObj*)s_malloc((size_t)sizeof(DocObj));
|
|
|
|
tag = peekTag(buf);
|
|
buf = readAny(&((*doc)->DocumentID),buf);
|
|
|
|
if (tag == DT_DocumentID)
|
|
{ (*doc)->ChunkCode = CT_document;
|
|
tag = peekTag(buf);
|
|
if (tag == DT_TYPE)
|
|
buf = readString(&((*doc)->Type),buf);
|
|
|
|
}
|
|
else if (tag == DT_DocumentIDChunk)
|
|
{ boolean readParagraphs = false;
|
|
tag = peekTag(buf);
|
|
if (tag == DT_TYPE)
|
|
buf = readString(&((*doc)->Type),buf);
|
|
buf = readNum(&((*doc)->ChunkCode),buf);
|
|
switch ((*doc)->ChunkCode)
|
|
{ case CT_byte:
|
|
case CT_line:
|
|
buf = readNum(&((*doc)->ChunkStart.Pos),buf);
|
|
buf = readNum(&((*doc)->ChunkEnd.Pos),buf);
|
|
break;
|
|
case CT_paragraph:
|
|
readParagraphs = true;
|
|
buf = readAny(&((*doc)->ChunkStart.ID),buf);
|
|
buf = readAny(&((*doc)->ChunkEnd.ID),buf);
|
|
break;
|
|
default:
|
|
freeAny((*doc)->DocumentID);
|
|
if (readParagraphs)
|
|
{ freeAny((*doc)->ChunkStart.ID);
|
|
freeAny((*doc)->ChunkEnd.ID);
|
|
}
|
|
s_free(doc);
|
|
doc = NULL; /* Prevent caller using bad pointer*/
|
|
CLEAN_REPORT_READ_ERROR(buf); /*Returns*/
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{ freeAny((*doc)->DocumentID);
|
|
s_free(*doc);
|
|
doc = NULL; /* Prevent caller using bad pointer*/
|
|
CLEAN_REPORT_READ_ERROR(buf);
|
|
}
|
|
RETURN(buf);
|
|
|
|
cleanup:
|
|
return(retval);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
char*
|
|
writeSearchInfo(query,buffer,len)
|
|
SearchAPDU* query;
|
|
char* buffer;
|
|
long* len;
|
|
|
|
|
|
{
|
|
if (strcmp(query->QueryType,QT_TextRetrievalQuery) == 0)
|
|
{ return(writeAny((any*)query->Query,DT_Query,buffer,len));
|
|
}
|
|
else
|
|
{ unsigned long header_len = userInfoTagSize(DT_UserInformationLength,
|
|
DefWAISSearchSize);
|
|
char* buf = buffer + header_len;
|
|
WAISSearch* info = (WAISSearch*)query->Query;
|
|
unsigned long size;
|
|
long i;
|
|
|
|
RESERVE_SPACE_FOR_WAIS_HEADER(len);
|
|
|
|
buf = writeString(info->SeedWords,DT_SeedWords,buf,len);
|
|
|
|
if (info->Docs != NULL)
|
|
{ for (i = 0; info->Docs[i] != NULL; i++)
|
|
{ buf = writeDocObj(info->Docs[i],buf,len);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
buf = writeNum(info->DateFactor,DT_DateFactor,buf,len);
|
|
buf = writeString(info->BeginDateRange,DT_BeginDateRange,buf,len);
|
|
buf = writeString(info->EndDateRange,DT_EndDateRange,buf,len);
|
|
buf = writeNum(info->MaxDocumentsRetrieved,DT_MaxDocumentsRetrieved,buf,len);
|
|
|
|
|
|
size = buf - buffer;
|
|
buf = writeUserInfoHeader(DT_UserInformationLength,size,header_len,buffer,len);
|
|
|
|
return(buf);
|
|
}
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
char*
|
|
readSearchInfo(info,buffer)
|
|
void** info;
|
|
char* buffer;
|
|
|
|
|
|
{
|
|
data_tag type = peekTag(buffer);
|
|
if (type == DT_Query)
|
|
{ char* buf = buffer;
|
|
any* query = NULL;
|
|
buf = readAny(&query,buf);
|
|
*info = (void *)query;
|
|
return(buf);
|
|
}
|
|
else
|
|
{ char* buf = buffer;
|
|
unsigned long size;
|
|
unsigned long headerSize;
|
|
data_tag tag;
|
|
char* seedWords = NULL;
|
|
char* beginDateRange = NULL;
|
|
char* endDateRange = NULL;
|
|
long dateFactor,maxDocsRetrieved;
|
|
char** textList = NULL;
|
|
DocObj** docIDs = NULL;
|
|
DocObj* doc = NULL;
|
|
long docs = 0;
|
|
long i;
|
|
void* ptr = NULL;
|
|
char *retval;
|
|
|
|
dateFactor = maxDocsRetrieved = UNUSED;
|
|
|
|
buf = readUserInfoHeader(&tag,&size,buf);
|
|
headerSize = buf - buffer;
|
|
|
|
while (buf < (buffer + size + headerSize))
|
|
{ data_tag tag = peekTag(buf);
|
|
switch (tag)
|
|
{ case DT_SeedWords:
|
|
buf = readString(&seedWords,buf);
|
|
break;
|
|
case DT_DocumentID:
|
|
case DT_DocumentIDChunk:
|
|
if (docIDs == NULL)
|
|
{ docIDs = (DocObj**)s_malloc((size_t)sizeof(DocObj*) * 2);
|
|
}
|
|
else
|
|
{ docIDs = (DocObj**)s_realloc((char*)docIDs,(size_t)(sizeof(DocObj*) * (docs + 2)));
|
|
}
|
|
buf = readDocObj(&doc,buf);
|
|
CLEAN_RETURN_ON_NULL(buf);
|
|
docIDs[docs++] = doc;
|
|
docIDs[docs] = NULL;
|
|
break;
|
|
case DT_TextList:
|
|
break;
|
|
case DT_DateFactor:
|
|
buf = readNum(&dateFactor,buf);
|
|
break;
|
|
case DT_BeginDateRange:
|
|
buf = readString(&beginDateRange,buf);
|
|
break;
|
|
case DT_EndDateRange:
|
|
buf = readString(&endDateRange,buf);
|
|
break;
|
|
case DT_MaxDocumentsRetrieved:
|
|
buf = readNum(&maxDocsRetrieved,buf);
|
|
break;
|
|
default:
|
|
CLEAN_REPORT_READ_ERROR(buf);
|
|
break;
|
|
}
|
|
}
|
|
|
|
*info = (void *)makeWAISSearch(seedWords,docIDs,textList,
|
|
dateFactor,beginDateRange,endDateRange,
|
|
maxDocsRetrieved);
|
|
return(buf);
|
|
|
|
cleanup:
|
|
/* Note only cleanup on error success returns pointers to these*/
|
|
s_free(seedWords);
|
|
s_free(beginDateRange);
|
|
s_free(endDateRange);
|
|
if (docIDs != NULL) {
|
|
for (i = 0,ptr = (void *)docIDs[i];
|
|
ptr != NULL;
|
|
ptr = (void *)docIDs[++i])
|
|
freeDocObj((DocObj*)ptr);
|
|
s_free(docIDs);
|
|
}
|
|
return(retval);
|
|
}
|
|
/* Note cleanup is only for else part - if part cleans itself up */
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
WAISDocumentHeader*
|
|
makeWAISDocumentHeader(docID,
|
|
versionNumber,
|
|
score,
|
|
bestMatch,
|
|
docLen,
|
|
lines,
|
|
types,
|
|
source,
|
|
theDate,
|
|
headline,
|
|
originCity)
|
|
any* docID;
|
|
long versionNumber;
|
|
long score;
|
|
long bestMatch;
|
|
long docLen;
|
|
long lines;
|
|
char** types;
|
|
char* source;
|
|
char* theDate;
|
|
char* headline;
|
|
char* originCity;
|
|
|
|
|
|
{
|
|
WAISDocumentHeader* header =
|
|
(WAISDocumentHeader*)s_malloc((size_t)sizeof(WAISDocumentHeader));
|
|
|
|
header->DocumentID = docID;
|
|
header->VersionNumber = versionNumber;
|
|
header->Score = score;
|
|
header->BestMatch = bestMatch;
|
|
header->DocumentLength = docLen;
|
|
header->Lines = lines;
|
|
header->Types = types;
|
|
header->Source = source;
|
|
header->Date = theDate;
|
|
header->Headline = headline;
|
|
header->OriginCity = originCity;
|
|
|
|
return(header);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
void
|
|
freeWAISDocumentHeader(header)
|
|
WAISDocumentHeader* header;
|
|
|
|
{
|
|
freeAny(header->DocumentID);
|
|
doList((void**)header->Types,fs_free);
|
|
s_free(header->Types);
|
|
s_free(header->Source);
|
|
s_free(header->Date);
|
|
s_free(header->Headline);
|
|
s_free(header->OriginCity);
|
|
s_free(header);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
char*
|
|
writeWAISDocumentHeader(header,buffer,len)
|
|
WAISDocumentHeader* header;
|
|
char* buffer;
|
|
long* len;
|
|
{
|
|
unsigned long header_len = userInfoTagSize(DT_DocumentHeaderGroup ,
|
|
DefWAISDocHeaderSize);
|
|
char* buf = buffer + header_len;
|
|
unsigned long size;
|
|
|
|
RESERVE_SPACE_FOR_WAIS_HEADER(len);
|
|
|
|
buf = writeAny(header->DocumentID,DT_DocumentID,buf,len);
|
|
buf = writeNum(header->VersionNumber,DT_VersionNumber,buf,len);
|
|
buf = writeNum(header->Score,DT_Score,buf,len);
|
|
buf = writeNum(header->BestMatch,DT_BestMatch,buf,len);
|
|
buf = writeNum(header->DocumentLength,DT_DocumentLength,buf,len);
|
|
buf = writeNum(header->Lines,DT_Lines,buf,len);
|
|
if (header->Types != NULL)
|
|
{ long size;
|
|
char* ptr = NULL;
|
|
long i;
|
|
buf = writeTag(DT_TYPE_BLOCK,buf,len);
|
|
for (i = 0,size = 0,ptr = header->Types[i]; ptr != NULL; ptr = header->Types[++i])
|
|
{ long typeSize = strlen(ptr);
|
|
size += writtenTagSize(DT_TYPE);
|
|
size += writtenCompressedIntSize(typeSize);
|
|
size += typeSize;
|
|
}
|
|
buf = writeCompressedInteger((unsigned long)size,buf,len);
|
|
for (i = 0,ptr = header->Types[i]; ptr != NULL; ptr = header->Types[++i])
|
|
buf = writeString(ptr,DT_TYPE,buf,len);
|
|
}
|
|
buf = writeString(header->Source,DT_Source,buf,len);
|
|
buf = writeString(header->Date,DT_Date,buf,len);
|
|
buf = writeString(header->Headline,DT_Headline,buf,len);
|
|
buf = writeString(header->OriginCity,DT_OriginCity,buf,len);
|
|
|
|
|
|
size = buf - buffer;
|
|
buf = writeUserInfoHeader(DT_DocumentHeaderGroup,size,header_len,buffer,len);
|
|
|
|
return(buf);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
char*
|
|
readWAISDocumentHeader(header,buffer)
|
|
WAISDocumentHeader** header;
|
|
char* buffer;
|
|
{
|
|
char* buf = buffer;
|
|
unsigned long size;
|
|
unsigned long headerSize;
|
|
data_tag tag;
|
|
any* docID = NULL;
|
|
long versionNumber,score,bestMatch,docLength,lines;
|
|
char** types = NULL;
|
|
char *source = NULL;
|
|
char *theDate = NULL;
|
|
char *headline = NULL;
|
|
char *originCity = NULL;
|
|
char *retval = NULL;
|
|
|
|
versionNumber = score = bestMatch = docLength = lines = UNUSED;
|
|
|
|
buf = readUserInfoHeader(&tag,&size,buf);
|
|
headerSize = buf - buffer;
|
|
|
|
while (buf < (buffer + size + headerSize))
|
|
{ data_tag tag = peekTag(buf);
|
|
switch (tag)
|
|
{ case DT_DocumentID:
|
|
buf = readAny(&docID,buf);
|
|
break;
|
|
case DT_VersionNumber:
|
|
buf = readNum(&versionNumber,buf);
|
|
break;
|
|
case DT_Score:
|
|
buf = readNum(&score,buf);
|
|
break;
|
|
case DT_BestMatch:
|
|
buf = readNum(&bestMatch,buf);
|
|
break;
|
|
case DT_DocumentLength:
|
|
buf = readNum(&docLength,buf);
|
|
break;
|
|
case DT_Lines:
|
|
buf = readNum(&lines,buf);
|
|
break;
|
|
case DT_TYPE_BLOCK:
|
|
{ unsigned long size = -1;
|
|
long numTypes = 0;
|
|
buf = readTag(&tag,buf);
|
|
buf = readCompressedInteger(&size,buf);
|
|
while (size > 0)
|
|
{ char* type = NULL;
|
|
char* originalBuf = buf;
|
|
buf = readString(&type,buf);
|
|
types = (char**)s_realloc(types,(size_t)(sizeof(char*) * (numTypes + 2)));
|
|
types[numTypes++] = type;
|
|
types[numTypes] = NULL;
|
|
size -= (buf - originalBuf);
|
|
}
|
|
}
|
|
case DT_Source:
|
|
buf = readString(&source,buf);
|
|
break;
|
|
case DT_Date:
|
|
buf = readString(&theDate,buf);
|
|
break;
|
|
case DT_Headline:
|
|
buf = readString(&headline,buf);
|
|
break;
|
|
case DT_OriginCity:
|
|
buf = readString(&originCity,buf);
|
|
break;
|
|
default:
|
|
CLEAN_REPORT_READ_ERROR(buf);
|
|
break;
|
|
}
|
|
}
|
|
|
|
*header = makeWAISDocumentHeader(docID,versionNumber,score,bestMatch,
|
|
docLength,lines,types,source,theDate,headline,
|
|
originCity);
|
|
return(buf);
|
|
|
|
cleanup:
|
|
/* Only comes this way on error */
|
|
freeAny(docID);
|
|
s_free(source);
|
|
s_free(theDate);
|
|
s_free(headline);
|
|
s_free(originCity);
|
|
return(retval);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
WAISDocumentShortHeader*
|
|
makeWAISDocumentShortHeader(docID,
|
|
versionNumber,
|
|
score,
|
|
bestMatch,
|
|
docLen,
|
|
lines)
|
|
any* docID;
|
|
long versionNumber;
|
|
long score;
|
|
long bestMatch;
|
|
long docLen;
|
|
long lines;
|
|
|
|
{
|
|
WAISDocumentShortHeader* header =
|
|
(WAISDocumentShortHeader*)s_malloc((size_t)sizeof(WAISDocumentShortHeader));
|
|
|
|
header->DocumentID = docID;
|
|
header->VersionNumber = versionNumber;
|
|
header->Score = score;
|
|
header->BestMatch = bestMatch;
|
|
header->DocumentLength = docLen;
|
|
header->Lines = lines;
|
|
|
|
return(header);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
void
|
|
freeWAISDocumentShortHeader(header)
|
|
WAISDocumentShortHeader* header;
|
|
{
|
|
freeAny(header->DocumentID);
|
|
s_free(header);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
char*
|
|
writeWAISDocumentShortHeader(header,buffer,len)
|
|
WAISDocumentShortHeader* header;
|
|
char* buffer;
|
|
long* len;
|
|
{
|
|
unsigned long header_len = userInfoTagSize(DT_DocumentShortHeaderGroup ,
|
|
DefWAISShortHeaderSize);
|
|
char* buf = buffer + header_len;
|
|
unsigned long size;
|
|
|
|
RESERVE_SPACE_FOR_WAIS_HEADER(len);
|
|
|
|
buf = writeAny(header->DocumentID,DT_DocumentID,buf,len);
|
|
buf = writeNum(header->VersionNumber,DT_VersionNumber,buf,len);
|
|
buf = writeNum(header->Score,DT_Score,buf,len);
|
|
buf = writeNum(header->BestMatch,DT_BestMatch,buf,len);
|
|
buf = writeNum(header->DocumentLength,DT_DocumentLength,buf,len);
|
|
buf = writeNum(header->Lines,DT_Lines,buf,len);
|
|
|
|
|
|
size = buf - buffer;
|
|
buf = writeUserInfoHeader(DT_DocumentShortHeaderGroup,size,header_len,buffer,len);
|
|
|
|
return(buf);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
char*
|
|
readWAISDocumentShortHeader(header,buffer)
|
|
WAISDocumentShortHeader** header;
|
|
char* buffer;
|
|
{
|
|
char* buf = buffer;
|
|
unsigned long size;
|
|
unsigned long headerSize;
|
|
data_tag tag;
|
|
any* docID = NULL;
|
|
long versionNumber,score,bestMatch,docLength,lines;
|
|
|
|
versionNumber = score = bestMatch = docLength = lines = UNUSED;
|
|
|
|
buf = readUserInfoHeader(&tag,&size,buf);
|
|
headerSize = buf - buffer;
|
|
|
|
while (buf < (buffer + size + headerSize))
|
|
{ data_tag tag = peekTag(buf);
|
|
switch (tag)
|
|
{ case DT_DocumentID:
|
|
buf = readAny(&docID,buf);
|
|
break;
|
|
case DT_VersionNumber:
|
|
buf = readNum(&versionNumber,buf);
|
|
break;
|
|
case DT_Score:
|
|
buf = readNum(&score,buf);
|
|
break;
|
|
case DT_BestMatch:
|
|
buf = readNum(&bestMatch,buf);
|
|
break;
|
|
case DT_DocumentLength:
|
|
buf = readNum(&docLength,buf);
|
|
break;
|
|
case DT_Lines:
|
|
buf = readNum(&lines,buf);
|
|
break;
|
|
default:
|
|
freeAny(docID);
|
|
REPORT_READ_ERROR(buf);
|
|
break;
|
|
}
|
|
}
|
|
|
|
*header = makeWAISDocumentShortHeader(docID,versionNumber,score,bestMatch,
|
|
docLength,lines);
|
|
return(buf);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
WAISDocumentLongHeader*
|
|
makeWAISDocumentLongHeader(docID,
|
|
versionNumber,
|
|
score,
|
|
bestMatch,
|
|
docLen,
|
|
lines,
|
|
types,
|
|
source,
|
|
theDate,
|
|
headline,
|
|
originCity,
|
|
stockCodes,
|
|
companyCodes,
|
|
industryCodes)
|
|
any* docID;
|
|
long versionNumber;
|
|
long score;
|
|
long bestMatch;
|
|
long docLen;
|
|
long lines;
|
|
char** types;
|
|
char* source;
|
|
char* theDate;
|
|
char* headline;
|
|
char* originCity;
|
|
char* stockCodes;
|
|
char* companyCodes;
|
|
char* industryCodes;
|
|
|
|
{
|
|
WAISDocumentLongHeader* header =
|
|
(WAISDocumentLongHeader*)s_malloc((size_t)sizeof(WAISDocumentLongHeader));
|
|
|
|
header->DocumentID = docID;
|
|
header->VersionNumber = versionNumber;
|
|
header->Score = score;
|
|
header->BestMatch = bestMatch;
|
|
header->DocumentLength = docLen;
|
|
header->Lines = lines;
|
|
header->Types = types;
|
|
header->Source = source;
|
|
header->Date = theDate;
|
|
header->Headline = headline;
|
|
header->OriginCity = originCity;
|
|
header->StockCodes = stockCodes;
|
|
header->CompanyCodes = companyCodes;
|
|
header->IndustryCodes = industryCodes;
|
|
|
|
return(header);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
void
|
|
freeWAISDocumentLongHeader(header)
|
|
WAISDocumentLongHeader* header;
|
|
{
|
|
freeAny(header->DocumentID);
|
|
doList((void**)header->Types,fs_free);
|
|
s_free(header->Source);
|
|
s_free(header->Date);
|
|
s_free(header->Headline);
|
|
s_free(header->OriginCity);
|
|
s_free(header->StockCodes);
|
|
s_free(header->CompanyCodes);
|
|
s_free(header->IndustryCodes);
|
|
s_free(header);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
char*
|
|
writeWAISDocumentLongHeader(header,buffer,len)
|
|
WAISDocumentLongHeader* header;
|
|
char* buffer;
|
|
long* len;
|
|
{
|
|
unsigned long header_len = userInfoTagSize(DT_DocumentLongHeaderGroup ,
|
|
DefWAISLongHeaderSize);
|
|
char* buf = buffer + header_len;
|
|
unsigned long size;
|
|
|
|
RESERVE_SPACE_FOR_WAIS_HEADER(len);
|
|
|
|
buf = writeAny(header->DocumentID,DT_DocumentID,buf,len);
|
|
buf = writeNum(header->VersionNumber,DT_VersionNumber,buf,len);
|
|
buf = writeNum(header->Score,DT_Score,buf,len);
|
|
buf = writeNum(header->BestMatch,DT_BestMatch,buf,len);
|
|
buf = writeNum(header->DocumentLength,DT_DocumentLength,buf,len);
|
|
buf = writeNum(header->Lines,DT_Lines,buf,len);
|
|
if (header->Types != NULL)
|
|
{ long size;
|
|
char* ptr = NULL;
|
|
long i;
|
|
buf = writeTag(DT_TYPE_BLOCK,buf,len);
|
|
for (i = 0,size = 0,ptr = header->Types[i]; ptr != NULL; ptr = header->Types[++i])
|
|
{ long typeSize = strlen(ptr);
|
|
size += writtenTagSize(DT_TYPE);
|
|
size += writtenCompressedIntSize(typeSize);
|
|
size += typeSize;
|
|
}
|
|
buf = writeCompressedInteger((unsigned long)size,buf,len);
|
|
for (i = 0,ptr = header->Types[i]; ptr != NULL; ptr = header->Types[++i])
|
|
buf = writeString(ptr,DT_TYPE,buf,len);
|
|
}
|
|
buf = writeString(header->Source,DT_Source,buf,len);
|
|
buf = writeString(header->Date,DT_Date,buf,len);
|
|
buf = writeString(header->Headline,DT_Headline,buf,len);
|
|
buf = writeString(header->OriginCity,DT_OriginCity,buf,len);
|
|
buf = writeString(header->StockCodes,DT_StockCodes,buf,len);
|
|
buf = writeString(header->CompanyCodes,DT_CompanyCodes,buf,len);
|
|
buf = writeString(header->IndustryCodes,DT_IndustryCodes,buf,len);
|
|
|
|
|
|
size = buf - buffer;
|
|
buf = writeUserInfoHeader(DT_DocumentLongHeaderGroup,size,header_len,buffer,len);
|
|
|
|
return(buf);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
char*
|
|
readWAISDocumentLongHeader(header,buffer)
|
|
WAISDocumentLongHeader** header;
|
|
char* buffer;
|
|
{
|
|
char* buf = buffer;
|
|
unsigned long size;
|
|
unsigned long headerSize;
|
|
data_tag tag;
|
|
any* docID;
|
|
long versionNumber,score,bestMatch,docLength,lines;
|
|
char **types;
|
|
char *source,*theDate,*headline,*originCity,*stockCodes,*companyCodes,*industryCodes;
|
|
|
|
docID = NULL;
|
|
versionNumber = score = bestMatch = docLength = lines = UNUSED;
|
|
types = NULL;
|
|
source = theDate = headline = originCity = stockCodes = companyCodes = industryCodes = NULL;
|
|
|
|
buf = readUserInfoHeader(&tag,&size,buf);
|
|
headerSize = buf - buffer;
|
|
|
|
while (buf < (buffer + size + headerSize))
|
|
{ data_tag tag = peekTag(buf);
|
|
switch (tag)
|
|
{ case DT_DocumentID:
|
|
buf = readAny(&docID,buf);
|
|
break;
|
|
case DT_VersionNumber:
|
|
buf = readNum(&versionNumber,buf);
|
|
break;
|
|
case DT_Score:
|
|
buf = readNum(&score,buf);
|
|
break;
|
|
case DT_BestMatch:
|
|
buf = readNum(&bestMatch,buf);
|
|
break;
|
|
case DT_DocumentLength:
|
|
buf = readNum(&docLength,buf);
|
|
break;
|
|
case DT_Lines:
|
|
buf = readNum(&lines,buf);
|
|
break;
|
|
case DT_TYPE_BLOCK:
|
|
{ unsigned long size = -1;
|
|
long numTypes = 0;
|
|
buf = readTag(&tag,buf);
|
|
readCompressedInteger(&size,buf);
|
|
while (size > 0)
|
|
{ char* type = NULL;
|
|
char* originalBuf = buf;
|
|
buf = readString(&type,buf);
|
|
types = (char**)s_realloc(types,(size_t)(sizeof(char*) * (numTypes + 2)));
|
|
types[numTypes++] = type;
|
|
types[numTypes] = NULL;
|
|
size -= (buf - originalBuf);
|
|
}
|
|
}
|
|
case DT_Source:
|
|
buf = readString(&source,buf);
|
|
break;
|
|
case DT_Date:
|
|
buf = readString(&theDate,buf);
|
|
break;
|
|
case DT_Headline:
|
|
buf = readString(&headline,buf);
|
|
break;
|
|
case DT_OriginCity:
|
|
buf = readString(&originCity,buf);
|
|
break;
|
|
case DT_StockCodes:
|
|
buf = readString(&stockCodes,buf);
|
|
break;
|
|
case DT_CompanyCodes:
|
|
buf = readString(&companyCodes,buf);
|
|
break;
|
|
case DT_IndustryCodes:
|
|
buf = readString(&industryCodes,buf);
|
|
break;
|
|
default:
|
|
freeAny(docID);
|
|
s_free(source);
|
|
s_free(theDate);
|
|
s_free(headline);
|
|
s_free(originCity);
|
|
s_free(stockCodes);
|
|
s_free(companyCodes);
|
|
s_free(industryCodes);
|
|
REPORT_READ_ERROR(buf);
|
|
break;
|
|
}
|
|
}
|
|
|
|
*header = makeWAISDocumentLongHeader(docID,versionNumber,score,bestMatch,
|
|
docLength,lines,types,source,theDate,headline,
|
|
originCity,stockCodes,companyCodes,
|
|
industryCodes);
|
|
return(buf);
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
WAISSearchResponse*
|
|
makeWAISSearchResponse(seedWordsUsed,
|
|
docHeaders,
|
|
shortHeaders,
|
|
longHeaders,
|
|
text,
|
|
headlines,
|
|
codes,
|
|
diagnostics)
|
|
char* seedWordsUsed;
|
|
WAISDocumentHeader** docHeaders;
|
|
WAISDocumentShortHeader** shortHeaders;
|
|
WAISDocumentLongHeader** longHeaders;
|
|
WAISDocumentText** text;
|
|
WAISDocumentHeadlines** headlines;
|
|
WAISDocumentCodes** codes;
|
|
diagnosticRecord** diagnostics;
|
|
{
|
|
WAISSearchResponse* response = (WAISSearchResponse*)s_malloc((size_t)sizeof(WAISSearchResponse));
|
|
|
|
response->SeedWordsUsed = seedWordsUsed;
|
|
response->DocHeaders = docHeaders;
|
|
response->ShortHeaders = shortHeaders;
|
|
response->LongHeaders = longHeaders;
|
|
response->Text = text;
|
|
response->Headlines = headlines;
|
|
response->Codes = codes;
|
|
response->Diagnostics = diagnostics;
|
|
|
|
return(response);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
void
|
|
freeWAISSearchResponse(response)
|
|
WAISSearchResponse* response;
|
|
{
|
|
void* ptr = NULL;
|
|
long i;
|
|
|
|
s_free(response->SeedWordsUsed);
|
|
|
|
if (response->DocHeaders != NULL)
|
|
for (i = 0,ptr = (void *)response->DocHeaders[i]; ptr != NULL; ptr = (void *)response->DocHeaders[++i])
|
|
freeWAISDocumentHeader((WAISDocumentHeader*)ptr);
|
|
s_free(response->DocHeaders);
|
|
|
|
if (response->ShortHeaders != NULL)
|
|
for (i = 0,ptr = (void *)response->ShortHeaders[i]; ptr != NULL; ptr = (void *)response->ShortHeaders[++i])
|
|
freeWAISDocumentShortHeader((WAISDocumentShortHeader*)ptr);
|
|
s_free(response->ShortHeaders);
|
|
|
|
if (response->LongHeaders != NULL)
|
|
for (i = 0,ptr = (void *)response->LongHeaders[i]; ptr != NULL; ptr = (void *)response->LongHeaders[++i])
|
|
freeWAISDocumentLongHeader((WAISDocumentLongHeader*)ptr);
|
|
s_free(response->LongHeaders);
|
|
|
|
if (response->Text != NULL)
|
|
for (i = 0,ptr = (void *)response->Text[i]; ptr != NULL; ptr = (void *)response->Text[++i])
|
|
freeWAISDocumentText((WAISDocumentText*)ptr);
|
|
s_free(response->Text);
|
|
|
|
if (response->Headlines != NULL)
|
|
for (i = 0,ptr = (void *)response->Headlines[i]; ptr != NULL; ptr = (void *)response->Headlines[++i])
|
|
freeWAISDocumentHeadlines((WAISDocumentHeadlines*)ptr);
|
|
s_free(response->Headlines);
|
|
|
|
if (response->Codes != NULL)
|
|
for (i = 0,ptr = (void *)response->Codes[i]; ptr != NULL; ptr = (void *)response->Codes[++i])
|
|
freeWAISDocumentCodes((WAISDocumentCodes*)ptr);
|
|
s_free(response->Codes);
|
|
|
|
if (response->Diagnostics != NULL)
|
|
for (i = 0,ptr = (void *)response->Diagnostics[i]; ptr != NULL; ptr = (void *)response->Diagnostics[++i])
|
|
freeDiag((diagnosticRecord*)ptr);
|
|
s_free(response->Diagnostics);
|
|
|
|
s_free(response);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
char*
|
|
writeSearchResponseInfo(query,buffer,len)
|
|
SearchResponseAPDU* query;
|
|
char* buffer;
|
|
long* len;
|
|
{
|
|
unsigned long header_len = userInfoTagSize(DT_UserInformationLength,
|
|
DefWAISSearchResponseSize);
|
|
char* buf = buffer + header_len;
|
|
WAISSearchResponse* info = (WAISSearchResponse*)query->DatabaseDiagnosticRecords;
|
|
unsigned long size;
|
|
void* header = NULL;
|
|
long i;
|
|
|
|
RESERVE_SPACE_FOR_WAIS_HEADER(len);
|
|
|
|
buf = writeString(info->SeedWordsUsed,DT_SeedWordsUsed,buf,len);
|
|
|
|
|
|
if (info->DocHeaders != NULL)
|
|
{ for (i = 0,header = (void *)info->DocHeaders[i]; header != NULL; header = (void *)info->DocHeaders[++i])
|
|
buf = writeWAISDocumentHeader((WAISDocumentHeader*)header,buf,len);
|
|
}
|
|
|
|
if (info->ShortHeaders != NULL)
|
|
{ for (i = 0,header = (void *)info->ShortHeaders[i]; header != NULL; header = (void *)info->ShortHeaders[++i])
|
|
buf = writeWAISDocumentShortHeader((WAISDocumentShortHeader*)header,buf,len);
|
|
}
|
|
|
|
if (info->LongHeaders != NULL)
|
|
{ for (i = 0,header = (void *)info->LongHeaders[i]; header != NULL; header = (void *)info->LongHeaders[++i])
|
|
buf = writeWAISDocumentLongHeader((WAISDocumentLongHeader*)header,buf,len);
|
|
}
|
|
|
|
if (info->Text != NULL)
|
|
{ for (i = 0,header = (void *)info->Text[i]; header != NULL; header = (void *)info->Text[++i])
|
|
buf = writeWAISDocumentText((WAISDocumentText*)header,buf,len);
|
|
}
|
|
|
|
if (info->Headlines != NULL)
|
|
{ for (i = 0,header = (void *)info->Headlines[i]; header != NULL; header = (void *)info->Headlines[++i])
|
|
buf = writeWAISDocumentHeadlines((WAISDocumentHeadlines*)header,buf,len);
|
|
}
|
|
|
|
if (info->Codes != NULL)
|
|
{ for (i = 0,header = (void *)info->Codes[i]; header != NULL;header = (void *)info->Codes[++i])
|
|
buf = writeWAISDocumentCodes((WAISDocumentCodes*)header,buf,len);
|
|
}
|
|
|
|
if (info->Diagnostics != NULL)
|
|
{ for (i = 0, header = (void *)info->Diagnostics[i]; header != NULL; header = (void *)info->Diagnostics[++i])
|
|
buf = writeDiag((diagnosticRecord*)header,buf,len);
|
|
}
|
|
|
|
|
|
size = buf - buffer;
|
|
buf = writeUserInfoHeader(DT_UserInformationLength,size,header_len,buffer,len);
|
|
|
|
return(buf);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
static void
|
|
cleanUpWaisSearchResponse _AP((char* buf,char* seedWordsUsed,
|
|
WAISDocumentHeader** docHeaders,
|
|
WAISDocumentShortHeader** shortHeaders,
|
|
WAISDocumentLongHeader** longHeaders,
|
|
WAISDocumentText** text,
|
|
WAISDocumentHeadlines** headlines,
|
|
WAISDocumentCodes** codes,
|
|
diagnosticRecord**diags));
|
|
|
|
static void
|
|
cleanUpWaisSearchResponse (buf,seedWordsUsed,docHeaders,shortHeaders,
|
|
longHeaders,text,headlines,codes,diags)
|
|
char* buf;
|
|
char* seedWordsUsed;
|
|
WAISDocumentHeader** docHeaders;
|
|
WAISDocumentShortHeader** shortHeaders;
|
|
WAISDocumentLongHeader** longHeaders;
|
|
WAISDocumentText** text;
|
|
WAISDocumentHeadlines** headlines;
|
|
WAISDocumentCodes** codes;
|
|
diagnosticRecord** diags;
|
|
|
|
{
|
|
void* ptr = NULL;
|
|
long i;
|
|
|
|
if (buf == NULL)
|
|
{ s_free(seedWordsUsed);
|
|
if (docHeaders != NULL)
|
|
for (i = 0,ptr = (void *)docHeaders[i]; ptr != NULL;
|
|
ptr = (void *)docHeaders[++i])
|
|
freeWAISDocumentHeader((WAISDocumentHeader*)ptr);
|
|
s_free(docHeaders);
|
|
if (shortHeaders != NULL)
|
|
for (i = 0,ptr = (void *)shortHeaders[i]; ptr != NULL;
|
|
ptr = (void *)shortHeaders[++i])
|
|
freeWAISDocumentShortHeader((WAISDocumentShortHeader*)ptr);
|
|
s_free(shortHeaders);
|
|
if (longHeaders != NULL)
|
|
for (i = 0,ptr = (void *)longHeaders[i]; ptr != NULL;
|
|
ptr = (void *)longHeaders[++i])
|
|
freeWAISDocumentLongHeader((WAISDocumentLongHeader*)ptr);
|
|
s_free(longHeaders);
|
|
if (text != NULL)
|
|
for (i = 0,ptr = (void *)text[i]; ptr != NULL; ptr = (void *)text[++i])
|
|
freeWAISDocumentText((WAISDocumentText*)ptr);
|
|
s_free(text);
|
|
if (headlines != NULL)
|
|
for (i = 0,ptr = (void *)headlines[i]; ptr != NULL;
|
|
ptr = (void *)headlines[++i])
|
|
freeWAISDocumentHeadlines((WAISDocumentHeadlines*)ptr);
|
|
s_free(headlines);
|
|
if (codes != NULL)
|
|
for (i = 0,ptr = (void *)codes[i]; ptr != NULL;
|
|
ptr = (void *)codes[++i])
|
|
freeWAISDocumentCodes((WAISDocumentCodes*)ptr);
|
|
s_free(codes);
|
|
if (diags != NULL)
|
|
for (i = 0,ptr = (void *)diags[i]; ptr != NULL;
|
|
ptr = (void *)diags[++i])
|
|
freeDiag((diagnosticRecord*)ptr);
|
|
s_free(diags);
|
|
}
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
char*
|
|
readSearchResponseInfo(info,buffer)
|
|
void** info;
|
|
char* buffer;
|
|
{
|
|
char* buf = buffer;
|
|
unsigned long size;
|
|
unsigned long headerSize;
|
|
data_tag tag;
|
|
void* header = NULL;
|
|
WAISDocumentHeader** docHeaders = NULL;
|
|
WAISDocumentShortHeader** shortHeaders = NULL;
|
|
WAISDocumentLongHeader** longHeaders = NULL;
|
|
WAISDocumentText** text = NULL;
|
|
WAISDocumentHeadlines** headlines = NULL;
|
|
WAISDocumentCodes** codes = NULL;
|
|
long numDocHeaders,numLongHeaders,numShortHeaders,numText,numHeadlines;
|
|
long numCodes;
|
|
char* seedWordsUsed = NULL;
|
|
diagnosticRecord** diags = NULL;
|
|
diagnosticRecord* diag = NULL;
|
|
long numDiags = 0;
|
|
|
|
numDocHeaders = numLongHeaders = numShortHeaders = numText = numHeadlines = numCodes = 0;
|
|
|
|
buf = readUserInfoHeader(&tag,&size,buf);
|
|
headerSize = buf - buffer;
|
|
|
|
while (buf < (buffer + size + headerSize))
|
|
{ data_tag tag = peekTag(buf);
|
|
switch (tag)
|
|
{ case DT_SeedWordsUsed:
|
|
buf = readString(&seedWordsUsed,buf);
|
|
break;
|
|
case DT_DatabaseDiagnosticRecords:
|
|
if (diags == NULL)
|
|
{ diags = (diagnosticRecord**)s_malloc((size_t)sizeof(diagnosticRecord*) * 2);
|
|
}
|
|
else
|
|
{ diags = (diagnosticRecord**)s_realloc((char*)diags,(size_t)(sizeof(diagnosticRecord*) * (numDiags + 2)));
|
|
}
|
|
buf = readDiag(&diag,buf);
|
|
diags[numDiags++] = diag;
|
|
diags[numDiags] = NULL;
|
|
break;
|
|
case DT_DocumentHeaderGroup:
|
|
if (docHeaders == NULL)
|
|
{ docHeaders = (WAISDocumentHeader**)s_malloc((size_t)sizeof(WAISDocumentHeader*) * 2);
|
|
}
|
|
else
|
|
{ docHeaders = (WAISDocumentHeader**)s_realloc((char*)docHeaders,(size_t)(sizeof(WAISDocumentHeader*) * (numDocHeaders + 2)));
|
|
}
|
|
buf = readWAISDocumentHeader((WAISDocumentHeader**)&header,buf);
|
|
cleanUpWaisSearchResponse(buf,seedWordsUsed,docHeaders,shortHeaders,longHeaders,text,headlines,codes,diags);
|
|
RETURN_ON_NULL(buf);
|
|
docHeaders[numDocHeaders++] =
|
|
(WAISDocumentHeader*)header;
|
|
docHeaders[numDocHeaders] = NULL;
|
|
break;
|
|
case DT_DocumentShortHeaderGroup:
|
|
if (shortHeaders == NULL)
|
|
{ shortHeaders = (WAISDocumentShortHeader**)s_malloc((size_t)sizeof(WAISDocumentShortHeader*) * 2);
|
|
}
|
|
else
|
|
{ shortHeaders = (WAISDocumentShortHeader**)s_realloc((char*)shortHeaders,(size_t)(sizeof(WAISDocumentShortHeader*) * (numShortHeaders + 2)));
|
|
}
|
|
buf = readWAISDocumentShortHeader((WAISDocumentShortHeader**)&header,buf);
|
|
cleanUpWaisSearchResponse(buf,seedWordsUsed,docHeaders,shortHeaders,longHeaders,text,headlines,codes,diags);
|
|
RETURN_ON_NULL(buf);
|
|
shortHeaders[numShortHeaders++] =
|
|
(WAISDocumentShortHeader*)header;
|
|
shortHeaders[numShortHeaders] = NULL;
|
|
break;
|
|
case DT_DocumentLongHeaderGroup:
|
|
if (longHeaders == NULL)
|
|
{ longHeaders = (WAISDocumentLongHeader**)s_malloc((size_t)sizeof(WAISDocumentLongHeader*) * 2);
|
|
}
|
|
else
|
|
{ longHeaders = (WAISDocumentLongHeader**)s_realloc((char*)longHeaders,(size_t)(sizeof(WAISDocumentLongHeader*) * (numLongHeaders + 2)));
|
|
}
|
|
buf = readWAISDocumentLongHeader((WAISDocumentLongHeader**)&header,buf);
|
|
cleanUpWaisSearchResponse(buf,seedWordsUsed,docHeaders,shortHeaders,longHeaders,text,headlines,codes,diags);
|
|
RETURN_ON_NULL(buf);
|
|
longHeaders[numLongHeaders++] =
|
|
(WAISDocumentLongHeader*)header;
|
|
longHeaders[numLongHeaders] = NULL;
|
|
break;
|
|
case DT_DocumentTextGroup:
|
|
if (text == NULL)
|
|
{ text = (WAISDocumentText**)s_malloc((size_t)sizeof(WAISDocumentText*) * 2);
|
|
}
|
|
else
|
|
{ text = (WAISDocumentText**)s_realloc((char*)text,(size_t)(sizeof(WAISDocumentText*) * (numText + 2)));
|
|
}
|
|
buf = readWAISDocumentText((WAISDocumentText**)&header,buf);
|
|
cleanUpWaisSearchResponse(buf,seedWordsUsed,docHeaders,shortHeaders,longHeaders,text,headlines,codes,diags);
|
|
RETURN_ON_NULL(buf);
|
|
text[numText++] =
|
|
(WAISDocumentText*)header;
|
|
text[numText] = NULL;
|
|
break;
|
|
case DT_DocumentHeadlineGroup:
|
|
if (headlines == NULL)
|
|
{ headlines = (WAISDocumentHeadlines**)s_malloc((size_t)sizeof(WAISDocumentHeadlines*) * 2);
|
|
}
|
|
else
|
|
{ headlines = (WAISDocumentHeadlines**)s_realloc((char*)headlines,(size_t)(sizeof(WAISDocumentHeadlines*) * (numHeadlines + 2)));
|
|
}
|
|
buf = readWAISDocumentHeadlines((WAISDocumentHeadlines**)&header,buf);
|
|
cleanUpWaisSearchResponse(buf,seedWordsUsed,docHeaders,shortHeaders,longHeaders,text,headlines,codes,diags);
|
|
RETURN_ON_NULL(buf);
|
|
headlines[numHeadlines++] =
|
|
(WAISDocumentHeadlines*)header;
|
|
headlines[numHeadlines] = NULL;
|
|
break;
|
|
case DT_DocumentCodeGroup:
|
|
if (codes == NULL)
|
|
{ codes = (WAISDocumentCodes**)s_malloc((size_t)sizeof(WAISDocumentCodes*) * 2);
|
|
}
|
|
else
|
|
{ codes = (WAISDocumentCodes**)s_realloc((char*)codes,(size_t)(sizeof(WAISDocumentCodes*) * (numCodes + 2)));
|
|
}
|
|
buf = readWAISDocumentCodes((WAISDocumentCodes**)&header,buf);
|
|
cleanUpWaisSearchResponse(buf,seedWordsUsed,docHeaders,shortHeaders,longHeaders,text,headlines,codes,diags);
|
|
RETURN_ON_NULL(buf);
|
|
codes[numCodes++] =
|
|
(WAISDocumentCodes*)header;
|
|
codes[numCodes] = NULL;
|
|
break;
|
|
default:
|
|
cleanUpWaisSearchResponse(buf,seedWordsUsed,docHeaders,shortHeaders,longHeaders,text,headlines,codes,diags);
|
|
REPORT_READ_ERROR(buf);
|
|
break;
|
|
} /*switch*/
|
|
}/*while*/
|
|
|
|
*info = (void *)makeWAISSearchResponse(seedWordsUsed,docHeaders,shortHeaders,
|
|
longHeaders,text,headlines,codes,diags);
|
|
return(buf);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
WAISDocumentText*
|
|
makeWAISDocumentText(docID,versionNumber,documentText)
|
|
any* docID;
|
|
long versionNumber;
|
|
any* documentText;
|
|
{
|
|
WAISDocumentText* docText = (WAISDocumentText*)s_malloc((size_t)sizeof(WAISDocumentText));
|
|
|
|
docText->DocumentID = docID;
|
|
docText->VersionNumber = versionNumber;
|
|
docText->DocumentText = documentText;
|
|
|
|
return(docText);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
void
|
|
freeWAISDocumentText(docText)
|
|
WAISDocumentText* docText;
|
|
{
|
|
freeAny(docText->DocumentID);
|
|
freeAny(docText->DocumentText);
|
|
s_free(docText);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
char*
|
|
writeWAISDocumentText(docText,buffer,len)
|
|
WAISDocumentText* docText;
|
|
char* buffer;
|
|
long* len;
|
|
{
|
|
unsigned long header_len = userInfoTagSize(DT_DocumentTextGroup,
|
|
DefWAISDocTextSize);
|
|
char* buf = buffer + header_len;
|
|
unsigned long size;
|
|
|
|
RESERVE_SPACE_FOR_WAIS_HEADER(len);
|
|
|
|
buf = writeAny(docText->DocumentID,DT_DocumentID,buf,len);
|
|
buf = writeNum(docText->VersionNumber,DT_VersionNumber,buf,len);
|
|
buf = writeAny(docText->DocumentText,DT_DocumentText,buf,len);
|
|
|
|
|
|
size = buf - buffer;
|
|
buf = writeUserInfoHeader(DT_DocumentTextGroup,size,header_len,buffer,len);
|
|
|
|
return(buf);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
char*
|
|
readWAISDocumentText(docText,buffer)
|
|
WAISDocumentText** docText;
|
|
char* buffer;
|
|
{
|
|
char* buf = buffer;
|
|
unsigned long size;
|
|
unsigned long headerSize;
|
|
data_tag tag;
|
|
any *docID,*documentText;
|
|
long versionNumber;
|
|
|
|
docID = documentText = NULL;
|
|
versionNumber = UNUSED;
|
|
|
|
buf = readUserInfoHeader(&tag,&size,buf);
|
|
headerSize = buf - buffer;
|
|
|
|
while (buf < (buffer + size + headerSize))
|
|
{ data_tag tag = peekTag(buf);
|
|
switch (tag)
|
|
{ case DT_DocumentID:
|
|
buf = readAny(&docID,buf);
|
|
break;
|
|
case DT_VersionNumber:
|
|
buf = readNum(&versionNumber,buf);
|
|
break;
|
|
case DT_DocumentText:
|
|
buf = readAny(&documentText,buf);
|
|
break;
|
|
default:
|
|
freeAny(docID);
|
|
freeAny(documentText);
|
|
REPORT_READ_ERROR(buf);
|
|
break;
|
|
}
|
|
}
|
|
|
|
*docText = makeWAISDocumentText(docID,versionNumber,documentText);
|
|
return(buf);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
WAISDocumentHeadlines*
|
|
makeWAISDocumentHeadlines(docID,
|
|
versionNumber,
|
|
source,
|
|
theDate,
|
|
headline,
|
|
originCity)
|
|
any* docID;
|
|
long versionNumber;
|
|
char* source;
|
|
char* theDate;
|
|
char* headline;
|
|
char* originCity;
|
|
{
|
|
WAISDocumentHeadlines* docHeadline =
|
|
(WAISDocumentHeadlines*)s_malloc((size_t)sizeof(WAISDocumentHeadlines));
|
|
|
|
docHeadline->DocumentID = docID;
|
|
docHeadline->VersionNumber = versionNumber;
|
|
docHeadline->Source = source;
|
|
docHeadline->Date = theDate;
|
|
docHeadline->Headline = headline;
|
|
docHeadline->OriginCity = originCity;
|
|
|
|
return(docHeadline);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
void
|
|
freeWAISDocumentHeadlines(docHeadline)
|
|
WAISDocumentHeadlines* docHeadline;
|
|
{
|
|
freeAny(docHeadline->DocumentID);
|
|
s_free(docHeadline->Source);
|
|
s_free(docHeadline->Date);
|
|
s_free(docHeadline->Headline);
|
|
s_free(docHeadline->OriginCity);
|
|
s_free(docHeadline);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
char*
|
|
writeWAISDocumentHeadlines(docHeadline,buffer,len)
|
|
WAISDocumentHeadlines* docHeadline;
|
|
char* buffer;
|
|
long* len;
|
|
{
|
|
unsigned long header_len = userInfoTagSize(DT_DocumentHeadlineGroup,
|
|
DefWAISDocHeadlineSize);
|
|
char* buf = buffer + header_len;
|
|
unsigned long size;
|
|
|
|
RESERVE_SPACE_FOR_WAIS_HEADER(len);
|
|
|
|
buf = writeAny(docHeadline->DocumentID,DT_DocumentID,buf,len);
|
|
buf = writeNum(docHeadline->VersionNumber,DT_VersionNumber,buf,len);
|
|
buf = writeString(docHeadline->Source,DT_Source,buf,len);
|
|
buf = writeString(docHeadline->Date,DT_Date,buf,len);
|
|
buf = writeString(docHeadline->Headline,DT_Headline,buf,len);
|
|
buf = writeString(docHeadline->OriginCity,DT_OriginCity,buf,len);
|
|
|
|
|
|
size = buf - buffer;
|
|
buf = writeUserInfoHeader(DT_DocumentHeadlineGroup,size,header_len,buffer,len);
|
|
|
|
return(buf);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
char*
|
|
readWAISDocumentHeadlines(docHeadline,buffer)
|
|
WAISDocumentHeadlines** docHeadline;
|
|
char* buffer;
|
|
{
|
|
char* buf = buffer;
|
|
unsigned long size;
|
|
unsigned long headerSize;
|
|
data_tag tag;
|
|
any* docID;
|
|
long versionNumber;
|
|
char *source,*theDate,*headline,*originCity;
|
|
|
|
docID = NULL;
|
|
versionNumber = UNUSED;
|
|
source = theDate = headline = originCity = NULL;
|
|
|
|
buf = readUserInfoHeader(&tag,&size,buf);
|
|
headerSize = buf - buffer;
|
|
|
|
while (buf < (buffer + size + headerSize))
|
|
{ data_tag tag = peekTag(buf);
|
|
switch (tag)
|
|
{ case DT_DocumentID:
|
|
buf = readAny(&docID,buf);
|
|
break;
|
|
case DT_VersionNumber:
|
|
buf = readNum(&versionNumber,buf);
|
|
break;
|
|
case DT_Source:
|
|
buf = readString(&source,buf);
|
|
break;
|
|
case DT_Date:
|
|
buf = readString(&theDate,buf);
|
|
break;
|
|
case DT_Headline:
|
|
buf = readString(&headline,buf);
|
|
break;
|
|
case DT_OriginCity:
|
|
buf = readString(&originCity,buf);
|
|
break;
|
|
default:
|
|
freeAny(docID);
|
|
s_free(source);
|
|
s_free(theDate);
|
|
s_free(headline);
|
|
s_free(originCity);
|
|
REPORT_READ_ERROR(buf);
|
|
break;
|
|
}
|
|
}
|
|
|
|
*docHeadline = makeWAISDocumentHeadlines(docID,versionNumber,source,theDate,
|
|
headline,originCity);
|
|
return(buf);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
WAISDocumentCodes*
|
|
makeWAISDocumentCodes(docID,
|
|
versionNumber,
|
|
stockCodes,
|
|
companyCodes,
|
|
industryCodes)
|
|
any* docID;
|
|
long versionNumber;
|
|
char* stockCodes;
|
|
char* companyCodes;
|
|
char* industryCodes;
|
|
{
|
|
WAISDocumentCodes* docCodes = (WAISDocumentCodes*)s_malloc((size_t)sizeof(WAISDocumentCodes));
|
|
|
|
docCodes->DocumentID = docID;
|
|
docCodes->VersionNumber = versionNumber;
|
|
docCodes->StockCodes = stockCodes;
|
|
docCodes->CompanyCodes = companyCodes;
|
|
docCodes->IndustryCodes = industryCodes;
|
|
|
|
return(docCodes);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
void
|
|
freeWAISDocumentCodes(docCodes)
|
|
WAISDocumentCodes* docCodes;
|
|
{
|
|
freeAny(docCodes->DocumentID);
|
|
s_free(docCodes->StockCodes);
|
|
s_free(docCodes->CompanyCodes);
|
|
s_free(docCodes->IndustryCodes);
|
|
s_free(docCodes);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
char*
|
|
writeWAISDocumentCodes(docCodes,buffer,len)
|
|
WAISDocumentCodes* docCodes;
|
|
char* buffer;
|
|
long* len;
|
|
{
|
|
unsigned long header_len = userInfoTagSize(DT_DocumentCodeGroup ,
|
|
DefWAISDocCodeSize);
|
|
char* buf = buffer + header_len;
|
|
unsigned long size;
|
|
|
|
RESERVE_SPACE_FOR_WAIS_HEADER(len);
|
|
|
|
buf = writeAny(docCodes->DocumentID,DT_DocumentID,buf,len);
|
|
buf = writeNum(docCodes->VersionNumber,DT_VersionNumber,buf,len);
|
|
buf = writeString(docCodes->StockCodes,DT_StockCodes,buf,len);
|
|
buf = writeString(docCodes->CompanyCodes,DT_CompanyCodes,buf,len);
|
|
buf = writeString(docCodes->IndustryCodes,DT_IndustryCodes,buf,len);
|
|
|
|
|
|
size = buf - buffer;
|
|
buf = writeUserInfoHeader(DT_DocumentCodeGroup,size,header_len,buffer,len);
|
|
|
|
return(buf);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
char*
|
|
readWAISDocumentCodes(docCodes,buffer)
|
|
WAISDocumentCodes** docCodes;
|
|
char* buffer;
|
|
{
|
|
char* buf = buffer;
|
|
unsigned long size;
|
|
unsigned long headerSize;
|
|
data_tag tag;
|
|
any* docID;
|
|
long versionNumber;
|
|
char *stockCodes,*companyCodes,*industryCodes;
|
|
|
|
docID = NULL;
|
|
versionNumber = UNUSED;
|
|
stockCodes = companyCodes = industryCodes = NULL;
|
|
|
|
buf = readUserInfoHeader(&tag,&size,buf);
|
|
headerSize = buf - buffer;
|
|
|
|
while (buf < (buffer + size + headerSize))
|
|
{ data_tag tag = peekTag(buf);
|
|
switch (tag)
|
|
{ case DT_DocumentID:
|
|
buf = readAny(&docID,buf);
|
|
break;
|
|
case DT_VersionNumber:
|
|
buf = readNum(&versionNumber,buf);
|
|
break;
|
|
case DT_StockCodes:
|
|
buf = readString(&stockCodes,buf);
|
|
break;
|
|
case DT_CompanyCodes:
|
|
buf = readString(&companyCodes,buf);
|
|
break;
|
|
case DT_IndustryCodes:
|
|
buf = readString(&industryCodes,buf);
|
|
break;
|
|
default:
|
|
freeAny(docID);
|
|
s_free(stockCodes);
|
|
s_free(companyCodes);
|
|
s_free(industryCodes);
|
|
REPORT_READ_ERROR(buf);
|
|
break;
|
|
}
|
|
}
|
|
|
|
*docCodes = makeWAISDocumentCodes(docID,versionNumber,stockCodes,
|
|
companyCodes,industryCodes);
|
|
return(buf);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
char*
|
|
writePresentInfo(present,buffer,len)
|
|
PresentAPDU* present;
|
|
char* buffer;
|
|
long* len;
|
|
{
|
|
|
|
return(buffer);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
char*
|
|
readPresentInfo(info,buffer)
|
|
void** info;
|
|
char* buffer;
|
|
{
|
|
|
|
*info = NULL;
|
|
return(buffer);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
char*
|
|
writePresentResponseInfo(response,buffer,len)
|
|
PresentResponseAPDU* response;
|
|
char* buffer;
|
|
long* len;
|
|
{
|
|
|
|
return(buffer);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
char*
|
|
readPresentResponseInfo(info,buffer)
|
|
void** info;
|
|
char* buffer;
|
|
{
|
|
|
|
*info = NULL;
|
|
return(buffer);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
#define BYTE "wb"
|
|
#define LINE "wl"
|
|
#define PARAGRAPH "wp"
|
|
#define DATA_TYPE "wt"
|
|
|
|
|
|
|
|
static query_term** makeWAISQueryTerms _AP((DocObj** docs));
|
|
|
|
static query_term**
|
|
makeWAISQueryTerms(docs)
|
|
DocObj** docs;
|
|
|
|
{
|
|
query_term** terms = NULL;
|
|
long numTerms = 0;
|
|
DocObj* doc = NULL;
|
|
long i;
|
|
|
|
if (docs == NULL)
|
|
return((query_term**)NULL);
|
|
|
|
terms = (query_term**)s_malloc((size_t)(sizeof(query_term*) * 1));
|
|
terms[numTerms] = NULL;
|
|
|
|
|
|
for (i = 0,doc = docs[i]; doc != NULL; doc = docs[++i])
|
|
{ any* type = NULL;
|
|
|
|
if (doc->Type != NULL)
|
|
type = stringToAny(doc->Type);
|
|
|
|
if (doc->ChunkCode == CT_document)
|
|
{ terms = (query_term**)s_realloc((char*)terms,
|
|
(size_t)(sizeof(query_term*) *
|
|
(numTerms + 3 + 1)));
|
|
terms[numTerms++] = makeAttributeTerm(SYSTEM_CONTROL_NUMBER,
|
|
EQUAL,IGNORE,IGNORE,
|
|
IGNORE,IGNORE,doc->DocumentID);
|
|
if (type != NULL)
|
|
{ terms[numTerms++] = makeAttributeTerm(DATA_TYPE,EQUAL,
|
|
IGNORE,IGNORE,IGNORE,
|
|
IGNORE,type);
|
|
terms[numTerms++] = makeOperatorTerm(AND);
|
|
}
|
|
terms[numTerms] = NULL;
|
|
}
|
|
else
|
|
{ char chunk_att[ATTRIBUTE_SIZE];
|
|
any* startChunk = NULL;
|
|
any* endChunk = NULL;
|
|
|
|
terms = (query_term**)s_realloc((char*)terms,
|
|
(size_t)(sizeof(query_term*) *
|
|
(numTerms + 7 + 1)));
|
|
|
|
switch (doc->ChunkCode)
|
|
{ case CT_byte:
|
|
case CT_line:
|
|
{ char start[20],end[20];
|
|
(doc->ChunkCode == CT_byte) ?
|
|
strncpy(chunk_att,BYTE,ATTRIBUTE_SIZE) :
|
|
strncpy(chunk_att,LINE,ATTRIBUTE_SIZE);
|
|
sprintf(start,"%ld",doc->ChunkStart.Pos);
|
|
startChunk = stringToAny(start);
|
|
sprintf(end,"%ld",doc->ChunkEnd.Pos);
|
|
endChunk = stringToAny(end);
|
|
}
|
|
break;
|
|
case CT_paragraph:
|
|
strncpy(chunk_att,PARAGRAPH,ATTRIBUTE_SIZE);
|
|
startChunk = doc->ChunkStart.ID;
|
|
endChunk = doc->ChunkEnd.ID;
|
|
break;
|
|
default:
|
|
|
|
break;
|
|
}
|
|
|
|
terms[numTerms++] = makeAttributeTerm(SYSTEM_CONTROL_NUMBER,
|
|
EQUAL,IGNORE,IGNORE,
|
|
IGNORE,
|
|
IGNORE,doc->DocumentID);
|
|
if (type != NULL)
|
|
{ terms[numTerms++] = makeAttributeTerm(DATA_TYPE,EQUAL,IGNORE,
|
|
IGNORE,IGNORE,IGNORE,
|
|
type);
|
|
terms[numTerms++] = makeOperatorTerm(AND);
|
|
}
|
|
terms[numTerms++] = makeAttributeTerm(chunk_att,
|
|
GREATER_THAN_OR_EQUAL,
|
|
IGNORE,IGNORE,IGNORE,
|
|
IGNORE,
|
|
startChunk);
|
|
terms[numTerms++] = makeOperatorTerm(AND);
|
|
terms[numTerms++] = makeAttributeTerm(chunk_att,LESS_THAN,
|
|
IGNORE,IGNORE,IGNORE,
|
|
IGNORE,
|
|
endChunk);
|
|
terms[numTerms++] = makeOperatorTerm(AND);
|
|
terms[numTerms] = NULL;
|
|
|
|
if (doc->ChunkCode == CT_byte || doc->ChunkCode == CT_line)
|
|
{ freeAny(startChunk);
|
|
freeAny(endChunk);
|
|
}
|
|
}
|
|
|
|
freeAny(type);
|
|
|
|
if (i != 0)
|
|
{ terms = (query_term**)s_realloc((char*)terms,
|
|
(size_t)(sizeof(query_term*) *
|
|
(numTerms + 1 + 1)));
|
|
terms[numTerms++] = makeOperatorTerm(OR);
|
|
terms[numTerms] = NULL;
|
|
}
|
|
}
|
|
|
|
return(terms);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
static DocObj** makeWAISQueryDocs _AP((query_term** terms));
|
|
|
|
static DocObj**
|
|
makeWAISQueryDocs(terms)
|
|
query_term** terms;
|
|
|
|
{
|
|
query_term* docTerm = NULL;
|
|
query_term* fragmentTerm = NULL;
|
|
DocObj** docs = NULL;
|
|
DocObj* doc = NULL;
|
|
long docNum,termNum;
|
|
|
|
docNum = termNum = 0;
|
|
|
|
docs = (DocObj**)s_malloc((size_t)(sizeof(DocObj*) * 1));
|
|
docs[docNum] = NULL;
|
|
|
|
|
|
while (true)
|
|
{
|
|
query_term* typeTerm = NULL;
|
|
char* type = NULL;
|
|
long startTermOffset;
|
|
|
|
docTerm = terms[termNum];
|
|
|
|
if (docTerm == NULL)
|
|
break; ;
|
|
|
|
typeTerm = terms[termNum + 1];
|
|
|
|
if (strcmp(typeTerm->Use,DATA_TYPE) == 0)
|
|
{ startTermOffset = 3;
|
|
type = anyToString(typeTerm->Term);
|
|
}
|
|
else
|
|
{ startTermOffset = 1;
|
|
typeTerm = NULL;
|
|
type = NULL;
|
|
}
|
|
|
|
|
|
docs = (DocObj**)s_realloc((char*)docs,(size_t)(sizeof(DocObj*) *
|
|
(docNum + 1 + 1)));
|
|
|
|
|
|
fragmentTerm = terms[termNum + startTermOffset];
|
|
if (fragmentTerm != NULL && fragmentTerm->TermType == TT_Attribute)
|
|
{
|
|
query_term* startTerm = fragmentTerm;
|
|
query_term* endTerm = terms[termNum + startTermOffset + 2];
|
|
|
|
if (strcmp(startTerm->Use,BYTE) == 0)
|
|
doc = makeDocObjUsingBytes(duplicateAny(docTerm->Term),
|
|
type,
|
|
anyToLong(startTerm->Term),
|
|
anyToLong(endTerm->Term));
|
|
else if (strcmp(startTerm->Use,LINE) == 0)
|
|
doc = makeDocObjUsingLines(duplicateAny(docTerm->Term),
|
|
type,
|
|
anyToLong(startTerm->Term),
|
|
anyToLong(endTerm->Term));
|
|
else if (strcmp(startTerm->Use,PARAGRAPH) == 0)
|
|
|
|
doc = makeDocObjUsingParagraphs(duplicateAny(docTerm->Term),
|
|
type,
|
|
duplicateAny(startTerm->Term),
|
|
duplicateAny(endTerm->Term));
|
|
termNum += (startTermOffset + 4);
|
|
}
|
|
else
|
|
{
|
|
doc = makeDocObjUsingWholeDocument(duplicateAny(docTerm->Term),
|
|
type);
|
|
termNum += startTermOffset;
|
|
}
|
|
|
|
docs[docNum++] = doc;
|
|
|
|
docs[docNum] = NULL;
|
|
|
|
|
|
if (terms[termNum] != NULL)
|
|
termNum++;
|
|
else
|
|
break;
|
|
}
|
|
|
|
return(docs);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
any*
|
|
makeWAISTextQuery(docs)
|
|
DocObj** docs;
|
|
|
|
{
|
|
any *buf = NULL;
|
|
query_term** terms = NULL;
|
|
|
|
terms = makeWAISQueryTerms(docs);
|
|
buf = writeQuery(terms);
|
|
|
|
doList((void**)terms,freeTerm);
|
|
s_free(terms);
|
|
|
|
return(buf);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
#if !defined(IN_RMG) && !defined(PFS_THREADS)
|
|
DocObj**
|
|
readWAISTextQuery(buf)
|
|
any* buf;
|
|
|
|
{
|
|
query_term** terms = NULL;
|
|
DocObj** docs = NULL;
|
|
|
|
terms = readQuery(buf);
|
|
docs = makeWAISQueryDocs(terms);
|
|
|
|
doList((void**)terms,freeTerm);
|
|
s_free(terms);
|
|
|
|
return(docs);
|
|
}
|
|
#endif
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
void
|
|
CSTFreeWAISInitResponse(init)
|
|
WAISInitResponse* init;
|
|
|
|
{
|
|
s_free(init);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
void
|
|
CSTFreeWAISSearch(query)
|
|
WAISSearch* query;
|
|
|
|
{
|
|
s_free(query);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
void
|
|
CSTFreeDocObj(doc)
|
|
DocObj* doc;
|
|
|
|
{
|
|
s_free(doc);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
void
|
|
CSTFreeWAISDocumentHeader(header)
|
|
WAISDocumentHeader* header;
|
|
{
|
|
s_free(header);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
void
|
|
CSTFreeWAISDocumentShortHeader(header)
|
|
WAISDocumentShortHeader* header;
|
|
{
|
|
s_free(header);
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
void
|
|
CSTFreeWAISDocumentLongHeader(header)
|
|
WAISDocumentLongHeader* header;
|
|
{
|
|
s_free(header);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
void
|
|
CSTFreeWAISSearchResponse(response)
|
|
WAISSearchResponse* response;
|
|
{
|
|
s_free(response);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
void
|
|
CSTFreeWAISDocumentText(docText)
|
|
WAISDocumentText* docText;
|
|
{
|
|
s_free(docText);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
void
|
|
CSTFreeWAISDocumentHeadlines(docHeadline)
|
|
WAISDocumentHeadlines* docHeadline;
|
|
{
|
|
s_free(docHeadline);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
void
|
|
CSTFreeWAISDocumentCodes(docCodes)
|
|
WAISDocumentCodes* docCodes;
|
|
{
|
|
s_free(docCodes);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
void
|
|
CSTFreeWAISTextQuery(query)
|
|
any* query;
|
|
{
|
|
freeAny(query);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
|