binarytermreader.c
来自「SRI international 发布的OAA框架软件」· C语言 代码 · 共 542 行 · 第 1/2 页
C
542 行
#ifdef _WINDOWS
#include <windows.h>
#include <winsock.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h> /* close */
#include <sys/time.h> /* For polling time */
#endif
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <stdio.h>
#include "binarytermreader.h"
#include "javadistoglib.h"
#include "binarytermtypes.h"
#include "libicl.h"
#include "libicl_private.h"
#include "glib.h"
#include "liboaa.h"
#ifdef _WINDOWS
// VC++ does not support const ints inside of array
// sizes. The following is an "enum hack" to get around
// this bug.
enum { INITBUFFERSZ = 8388608 };
enum { AMOUNTTOREAD = 8192 };
#else
static const int INITBUFFERSZ = 8388608;
static const int AMOUNTTOREAD = 8192;
#endif
struct BinaryTermReaderStruct
{
TermReader* superReader;
GByteArray* currentBuffer;
}
;
void binaryTermReader_cleanup(TermReader*);
ICLTerm* binaryTermReader_getNext(TermReader*, double);
ICLTerm* binaryTermReader_parseBuffer(BinaryTermReader* br);
void binaryTermReader_fillData(BinaryTermReader* br, double timeout);
void binaryTermReader_addToCurrentBuffer(BinaryTermReader* br, char* buf, ssize_t len);
void binaryTermReader_cleanupTermList(GQueue*);
BinaryTermReader* binaryTermReader_create(TermReader* t, gint listenSocket)
{
BinaryTermReader* r = (BinaryTermReader*)malloc(sizeof(BinaryTermReader));
r->superReader = t;
r->currentBuffer = g_byte_array_new();
termReader_setReaderSpecificData(t, r);
termReader_setSocket(t, listenSocket);
termReader_setType(t, BINARYTERMREADERTYPE);
termReader_setGetNextCallback(t, binaryTermReader_getNext);
termReader_setCleanupCallback(t, binaryTermReader_cleanup);
termReader_setError(t, TERMREADER_OKAY);
return r;
}
void binaryTermReader_cleanup(TermReader* reader)
{
BinaryTermReader* br = (BinaryTermReader*)termReader_getReaderSpecificData(reader);
if(br->currentBuffer != NULL) {
free(br->currentBuffer);
}
if(br != NULL) {
free(br);
}
}
ICLTerm* binaryTermReader_getNext(TermReader* reader, double timeout)
{
ICLTerm* nextEvent = NULL;
gboolean done = FALSE;
gboolean timedOut = FALSE;
gboolean hadOldData = FALSE;
gboolean forceFill = FALSE;
BinaryTermReader* br = (BinaryTermReader*)termReader_getReaderSpecificData(reader);
while(!done) {
termReader_setError(reader, TERMREADER_OKAY);
if((br->currentBuffer->len == 0) || forceFill) {
binaryTermReader_fillData(br, timeout);
if(termReader_getError(reader) == TERMREADER_TIMEOUT) {
timedOut = TRUE;
}
}
else {
forceFill = FALSE;
hadOldData = TRUE;
}
if((termReader_getError(reader) != TERMREADER_OKAY) &&
!timedOut) {
if(termReader_getError(reader) != TERMREADER_NOCONN) {
// Don't report an error for NOCONN...typically
// a client has simply disconnected cleanly.
fprintf(stderr,
"binaryTermReader_getNext() [%s %i] bad read: %i\n",
__FILE__, __LINE__, termReader_getError(reader));
}
return NULL;
}
if(br->currentBuffer->len > 0) {
CHECK_LEAKS();
nextEvent = binaryTermReader_parseBuffer(br);
CHECK_LEAKS();
if(nextEvent == NULL) {
/* If there was no event in the buffer, check for a timeout */
if(timedOut) {
nextEvent = icl_NewTermFromString("event(timeout)");
return nextEvent;
}
else if(termReader_getError(reader) == TERMREADER_BINNOTENOUGHDATA) {
forceFill = TRUE;
hadOldData = FALSE;
termReader_setError(reader, TERMREADER_OKAY);
/*printf("Not enough data in buffer--continue\n");*/
continue;
}
else if(termReader_getError(reader) != TERMREADER_OKAY) {
fprintf(stderr, "error in binarytermreader\n");
return NULL;
}
else if(hadOldData) {
forceFill = TRUE;
hadOldData = FALSE;
continue;
}
else {
continue;
}
}
else {
//char* finalTerm;
//finalTerm = icl_NewStringFromTerm(nextEvent);
/* printf("binaryTermReader_getNext() found next [%s]\n", finalTerm); */
//icl_stFree(finalTerm);
return nextEvent;
}
}
else if(timedOut) {
nextEvent = icl_NewTermFromString("event(timeout)");
return nextEvent;
}
else {
continue;
}
}
return NULL;
}
void binaryTermReader_cleanupTermList(GQueue* termList)
{
ICLTerm* t;
while(!g_queue_is_empty(termList)) {
t = (ICLTerm*)g_queue_pop_tail(termList);
icl_Free(t);
}
g_queue_free(termList);
}
ICLTerm* binaryTermReader_parseBuffer(BinaryTermReader* br)
{
GQueue* termList = g_queue_new();
gboolean done = FALSE;
gint32 type;
gint32 numArgs;
gint32 dataLen;
ICLTerm* newTerm;
gint64 inIclInt = 0;
double inIclFloat = 0;
char* inString = NULL;
char* inData = NULL;
char* currPos = br->currentBuffer->data;
size_t bufLen = br->currentBuffer->len;
size_t offset = 0;
size_t offsetIncr = 0;
size_t strLen = 0;
char starter = 0;
ICLTerm* args;
int i;
/* printf("binaryTermReader_parseBuffer()\n"); */
while(!done) {
offsetIncr = javadistoglib_readJavaInt(currPos + offset, bufLen, &type);
if(offsetIncr == 0) {
/* printf("binaryTermReader_parseBuffer() not enough data for int (type) at offset %i\n", offset); */
termReader_setError(br->superReader, TERMREADER_BINNOTENOUGHDATA);
binaryTermReader_cleanupTermList(termList);
return NULL;
}
offset += offsetIncr;
bufLen -= offsetIncr;
numArgs = 0;
dataLen = 0;
newTerm = NULL;
switch(type) {
case BTT_SENTINEL:
/* printf("binaryTermReader_parseBuffer() hit sentinel\n"); */
done = TRUE;
newTerm = (ICLTerm*)g_queue_pop_tail(termList);
if(!g_queue_is_empty(termList)) {
fprintf(stderr, "binaryTermReader_parseBuffer() encountered sentinel but termList not empty\n");
termReader_setError(br->superReader, TERMREADER_BINUNEXPECTEDSENTINEL);
binaryTermReader_cleanupTermList(termList);
return NULL;
}
else {
GByteArray* oldBuf = br->currentBuffer;
br->currentBuffer = g_byte_array_sized_new(br->currentBuffer->len - offset);
g_byte_array_append(br->currentBuffer, oldBuf->data + offset, oldBuf->len - offset);
g_byte_array_free(oldBuf, TRUE);
binaryTermReader_cleanupTermList(termList);
return newTerm;
}
case BTT_ICLINT:
/* printf("binaryTermReader_parseBuffer() hit IclInt\n"); */
offsetIncr = javadistoglib_readJavaLong(currPos + offset, bufLen, &inIclInt);
if(offsetIncr == 0) {
/* printf("binaryTermReader_parseBuffer() not enough data for long (int)\n"); */
termReader_setError(br->superReader, TERMREADER_BINNOTENOUGHDATA);
binaryTermReader_cleanupTermList(termList);
return NULL;
}
offset += offsetIncr;
bufLen -= offsetIncr;
newTerm = icl_NewInt(inIclInt);
break;
case BTT_ICLFLOAT:
/* printf("binaryTermReader_parseBuffer() hit IclFloat at offset %i\n", offset); */
offsetIncr = javadistoglib_readJavaDouble(currPos + offset, bufLen, &inIclFloat);
if(offsetIncr == 0) {
/* printf("binaryTermReader_parseBuffer() not enough data for double (float)\n"); */
termReader_setError(br->superReader, TERMREADER_BINNOTENOUGHDATA);
binaryTermReader_cleanupTermList(termList);
return NULL;
}
offset += offsetIncr;
bufLen -= offsetIncr;
newTerm = icl_NewFloat(inIclFloat);
break;
case BTT_ICLVAR:
/* printf("binaryTermReader_parseBuffer() hit IclVar\n"); */
offsetIncr = javadistoglib_readJavaInt(currPos + offset, bufLen, &dataLen);
if(offsetIncr == 0) {
/* printf("binaryTermReader_parseBuffer() not enough data for int (dataLen for Var)\n"); */
termReader_setError(br->superReader, TERMREADER_BINNOTENOUGHDATA);
binaryTermReader_cleanupTermList(termList);
return NULL;
}
offset += offsetIncr;
bufLen -= offsetIncr;
if(dataLen < 0) {
fprintf(stderr, "binaryTermReader_parseBuffer() ICLVAR has datalen < 0\n");
termReader_setError(br->superReader, TERMREADER_BINBADICLVAR);
binaryTermReader_cleanupTermList(termList);
return NULL;
}
if(dataLen == 0) {
newTerm = icl_NewVar("_");
}
else {
inString = (char*)malloc((dataLen + 1) * sizeof(char));
offsetIncr = javadistoglib_readJavaChars(currPos + offset, bufLen, dataLen, dataLen + 1, inString);
if(offsetIncr == 0) {
/* printf("binaryTermReader_parseBuffer() not enough data for chars (var)\n"); */
termReader_setError(br->superReader, TERMREADER_BINNOTENOUGHDATA);
free(inString);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?