#include "manetGraphML.h"
#include "protoSpace.h"
#include <protoDebug.h>
#include <protoDefs.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#include <libxml/encoding.h>
#include <libxml/xmlwriter.h>
#include <libxml/xmlreader.h>
#define MY_ENCODING "UTF-8"
class Commands
{
public:
enum FileType {NONE, GML};
Commands() : inputFilePath(NULL),inputType(NONE),outputFilePath(NULL),outputType(NONE),doPathCalc(false),doDensityCalc(false),doECDSCalc(false) {}
~Commands() {delete inputFilePath; delete outputFilePath;}
bool ProcessCommands(int argc,char* argv[]);
char* inputFilePath;
FileType inputType;
char* outputFilePath;
FileType outputType;
bool doPathCalc;
bool doDensityCalc;
bool doECDSCalc;
class ECDS
{
public:
ECDS() : usingDensity(false) {}
bool usingDensity;
} ecds;
} theCommands;
class LocalAttributeKey : public ProtoSortedTree::Item
{
public:
bool Init(const char* theIndex,const char* theName)
{
index = new char[sizeof(theIndex)];
strcpy(index,theIndex);
name = new char[sizeof(theName)];
strcpy(name,theName);
if((NULL == index) || (NULL == name))
return false;
return true;
}
~LocalAttributeKey()
{
delete[] index;
delete[] name;
}
char* index;
char* name;
private:
virtual const char* GetKey() const {return index;}
virtual unsigned int GetKeysize() const {return strlen(index);}
};
typedef ProtoSortedTreeTemplate<LocalAttributeKey> KeyList;
class FastReader
{
public:
enum Result {OK, ERROR_, DONE, TIMEOUT};
FastReader(FILE* filePtr);
FastReader::Result Read(char* buffer,
unsigned int* len,
double timeout = -1.0);
FastReader::Result Readline(char* buffer,
unsigned int* len,
double timeout = -1.0);
bool Seek(int offset);
private:
enum {BUFSIZE = 2048};
FILE* file_ptr;
char savebuf[BUFSIZE];
char* saveptr;
unsigned int savecount;
};
void Usage()
{
fprintf(stderr, "Usage: graphExample -ifile graphml <filename> -ofile graphml <filename> <-ecds <id|density>> <-density>\n");
}
const unsigned int MAX_LINE = 256;
class MyCost : public ManetGraph::Cost
{
public:
MyCost() {};
MyCost(double value) : ManetGraph::Cost(value) {};
};
class MyInterface;
class MyLink;
class MyNode: public NetGraph::NodeTemplate<MyInterface>, public ProtoSpace::Node
{
public:
MyNode();
~MyNode();
void SetRtrPriority(int value)
{rtr_priority = value;}
UINT8 GetRtrPriority() const
{return rtr_priority;}
void SetRelayStatus(bool state)
{relay_status = state;}
bool GetRelayStatus() const
{return relay_status;}
void SetVisited(bool state)
{visited = state;}
bool WasVisited() const
{return visited;}
void SetNbrs(int theNbrs)
{nbrs = theNbrs;}
int GetNbrs() const
{return nbrs;}
void SetPosition(double xPos, double yPos)
{
ordinate[0] = xPos;
ordinate[1] = yPos;
}
double GetOrdinateX() const
{return ordinate[0];}
double GetOrdinateY() const
{return ordinate[1];}
unsigned int GetDimensions() const
{return 2;}
double GetOrdinate(unsigned int index) const
{return (ordinate[index]);}
const double* GetOrdinatePtr() const
{return ordinate;}
private:
int rtr_priority;
bool relay_status;
bool visited;
double ordinate[2]; int nbrs;
}; class MyInterface : public NetGraph::InterfaceTemplate<MyCost,MyInterface,MyLink,MyNode>
{
public:
MyInterface(MyNode& theNode, const ProtoAddress& addr)
: NetGraph::InterfaceTemplate<MyCost,MyInterface,MyLink,MyNode>(theNode,addr) {}
MyInterface(MyNode& theNode)
: NetGraph::InterfaceTemplate<MyCost,MyInterface,MyLink,MyNode>(theNode) {}
private:
};
class MyLink : public NetGraph::LinkTemplate<MyCost,MyInterface>
{
public:
private:
};
MyNode::MyNode()
: rtr_priority(0)
{
ordinate[0] = ordinate[1] = 0.0;
}
MyNode::~MyNode()
{
}
class MyManetGraphML : public ManetGraphMLTemplate<MyCost,MyInterface,MyLink,MyNode>
{
public :
int GetId(MyNode &node) const;
KeyList keys;
protected :
bool UpdateKeys(NetGraph& theGraph);
bool UpdateNodeAttributes(NetGraph::Node& theNode);
bool UpdateInterfaceAttributes(NetGraph::Interface& theInterface);
bool UpdateLinkAttributes(NetGraph::Link& theLink);
private :
char* FindIndex(const char* theName);
};
int MyManetGraphML::GetId(MyNode &node) const
{
MyManetGraphML::Interface* iface = node.GetDefaultInterface();
if (NULL != iface)
{
const char* addrPtr = GetString(*iface);
int id=0;
for(int i = 0;i<(int)strlen(addrPtr);i++)
{
(i % 2) ? id += ((int)addrPtr[i]) << 8 : id += addrPtr[i];
}
return id;
}
else
{
ASSERT(0);
return ((int)-1);
}
}
bool MyManetGraphML::UpdateKeys(NetGraph& theGraph)
{
if(theCommands.doECDSCalc)
AddAttributeKey("ecdsrelay","boolean","node",NULL,"false");
if(theCommands.doDensityCalc)
AddAttributeKey("prio","int","node");
AddAttributeKey("weight","double","edge",NULL,"1.0");
return true;
}
bool MyManetGraphML::UpdateNodeAttributes(NetGraph::Node& theNode)
{
bool rv = true;
if(theCommands.doECDSCalc)
{
if((static_cast<MyNode&>(theNode)).GetRelayStatus())
{
rv &= AddAttribute(theNode,"ecdsrelay","true");
} else {
rv &= AddAttribute(theNode,"ecdsrelay","false");
}
}
if(theCommands.doDensityCalc)
{
int prio = (static_cast<MyNode&>(theNode)).GetRtrPriority();
char prioStr[50];
sprintf(prioStr,"%d",prio);
rv &= AddAttribute(theNode,"prio",prioStr);
}
if(!rv)
{
PLOG(PL_ERROR,"MyManetGraphML::UpdateNodeAttributes: Error updating some of the attributes\n");
}
return rv;
}
bool MyManetGraphML::UpdateInterfaceAttributes(NetGraph::Interface& iface)
{
bool rv = true;
return rv;
}
bool MyManetGraphML::UpdateLinkAttributes(NetGraph::Link& theLink)
{
bool rv = true;
char value[100];
sprintf(value,"%f",(static_cast<MyLink&>(theLink)).GetCost().GetValue());
rv &= AddAttribute(theLink,"weight",value);
if(!rv)
{
PLOG(PL_ERROR,"MyManetGraphML::UpdateLinkAttributes: Error updating some of the attributes\n");
}
return rv;
}
char *
MyManetGraphML::FindIndex(const char* theName)
{
KeyList::Iterator kit(keys);
LocalAttributeKey* keyPtr = kit.GetNextItem();
char* index = NULL;
while(keyPtr && (!index))
{
if(!strcmp(keyPtr->name,theName))
{
index = keyPtr->index;
}
keyPtr=kit.GetNextItem();
}
return index;
}
const double RANGE_MAX = 300.0;
inline double CalculateDistance(double x1, double y1, double x2,double y2)
{
double dx = x1 - x2;
double dy = y1 - y2;
return sqrt(dx*dx + dy*dy);
}
bool UpdateGraphFromSpace(MyManetGraphML& graph,
ProtoSpace& space,
ProtoGraph::Vertice::SortedList::ItemPool* sortedVerticeItemPool);
int CalculateFullECDS(MyManetGraphML& graph,
MyManetGraphML::Interface::SimpleList& relayList,
ProtoGraph::Vertice::SortedList::ItemPool* sortedVerticeItemPool);
void CalculateRouterPriority(MyManetGraphML& graph,bool usingDensity);
int CalculatePaths(MyManetGraphML& graph);
int CountPaths(MyManetGraphML::Interface* source, MyManetGraphML::Interface* dest,int depth,int* patharray,int maxdepth); double CalculateDensity(MyManetGraphML& graph);
double X_MIN = -77.028633;
double X_MAX = -77.021267;
double X_SCALE = (X_MAX - X_MIN) / 1600.0;
double Y_MIN = 38.828533;
double Y_MAX = 38.822817;
double Y_SCALE = (Y_MAX - Y_MIN) / 600.0;
int main(int argc, char* argv[])
{
if(!theCommands.ProcessCommands(argc-1,argv+1))
{
Usage();
return -1;
}
MyManetGraphML graph;
if(Commands::GML == theCommands.inputType)
{
printf("reading file\"%s\"\n",theCommands.inputFilePath);
graph.Read(theCommands.inputFilePath);
}
ProtoGraph::Vertice::SortedList::ItemPool sortedVerticeItemPool;
ProtoSpace space;
if(theCommands.doPathCalc)
{
int paths = CalculatePaths(graph);
TRACE("paths = %d\n",paths);
}
MyManetGraphML::Interface::SortedList disconnectedList(&sortedVerticeItemPool);
MyManetGraphML::InterfaceIterator ifaceIterator(graph);
MyManetGraphML::Interface::SimpleList relayList;
if(theCommands.doECDSCalc)
{
CalculateRouterPriority(graph,theCommands.ecds.usingDensity);
MyManetGraphML::Interface::SimpleList relayList;
int relays = CalculateFullECDS(graph, relayList, &sortedVerticeItemPool);
TRACE("graphXMLExample:: E-CDS relays is %d\n",relays);
MyManetGraphML::Interface::SortedList disconnectedList(&sortedVerticeItemPool);
MyManetGraphML::InterfaceIterator ifaceIterator(graph);
MyManetGraphML::Interface* iface;
while (NULL != (iface = ifaceIterator.GetNextInterface()))
{
disconnectedList.Insert(*iface);
}
MyManetGraphML::Interface::SimpleList::Iterator relayIterator(relayList);
MyManetGraphML::Interface* relayIface;
while (NULL != (relayIface = relayIterator.GetNextInterface()))
{
if(relayIface->GetAddress().IsValid())
{
if (NULL != disconnectedList.FindInterface(relayIface->GetAddress()))
disconnectedList.Remove(*relayIface);
} else {
if (NULL != disconnectedList.FindInterfaceByName(relayIface->GetName()))
disconnectedList.Remove(*relayIface);
}
MyManetGraphML::AdjacencyIterator neighborIterator(*relayIface);
MyManetGraphML::Interface* neighborIface;
while (NULL != (neighborIface = neighborIterator.GetNextAdjacency()))
{
if(neighborIface->GetAddress().IsValid())
{
if (NULL != disconnectedList.FindInterface(neighborIface->GetAddress()))
disconnectedList.Remove(*neighborIface);
} else {
if (NULL != disconnectedList.FindInterfaceByName(neighborIface->GetName()))
disconnectedList.Remove(*neighborIface);
}
MyNode& neighborNode = neighborIface->GetNode();
if (!neighborNode.GetRelayStatus())
; }
}
MyManetGraphML::Interface::SortedList::Iterator dcIterator(disconnectedList);
MyManetGraphML::Interface* disconnectedIface;
while (NULL != (disconnectedIface = dcIterator.GetNextInterface()))
{
MyNode& disconnectedNode = disconnectedIface->GetNode();
printf("node %s symbol circle,red,3\n", graph.GetString(disconnectedNode));
}
}
if(theCommands.doDensityCalc)
{
double nodedensity = 0;
nodedensity = CalculateDensity(graph);
TRACE("density is %f\n",nodedensity);
}
if(Commands::GML == theCommands.outputType)
{
graph.Write(theCommands.outputFilePath);
}
fprintf(stderr, "GraphXMLExample: Done.\n");
return 0;
}
bool
Commands::ProcessCommands(int argc,char* argv[])
{
for(int i=0;NULL !=argv[i];i++)
{
if(!strcmp(argv[i],"-ifile"))
{
i++;
if(!strcmp(argv[i],"graphml"))
{
i++;
inputType = GML;
if(NULL == argv[i])
{
PLOG(PL_ERROR,"Commands::ProcessCommands Error no input file path\n");
return false;
}
inputFilePath = new char[strlen(argv[i])];
if(NULL == inputFilePath)
{
PLOG(PL_ERROR,"Commands::ProcessCommands Error allocating space for input file path\n");
return false;
}
memset(inputFilePath,0,strlen(argv[i]));
strcpy(inputFilePath,argv[i]);
} else {
PLOG(PL_ERROR,"Commands::ProcessCommands Error unknown input file format \"%s\"\n",argv[i]);
return false;
}
} else if (!strcmp(argv[i],"-ofile")) {
i++;
if(!strcmp(argv[i],"graphml"))
{
i++;
outputType = GML;
if(NULL == argv[i])
{
PLOG(PL_ERROR,"Commands::ProcessCommands Error no output file path\n");
return false;
}
outputFilePath = new char[strlen(argv[i])];
if(NULL == outputFilePath)
{
PLOG(PL_ERROR,"Commands::ProcessCommands Error allocating space for output file path\n");
return false;
}
memset(outputFilePath,0,strlen(argv[i]));
strcpy(outputFilePath,argv[i]);
} else {
PLOG(PL_ERROR,"Commands::ProcessCommands Error unknown output file format \"%s\"\n",argv[i]);
return false;
}
} else if (!strcmp(argv[i],"-ecds")) {
doECDSCalc = true;
i++;
if(NULL != argv[i]){
if(!strcmp(argv[i],"id")) {
ecds.usingDensity = false;
} else if (!strcmp(argv[i],"density")) {
ecds.usingDensity = true;
} else {
i--;
}
} else {
i--;
}
} else if (!strcmp(argv[i],"-density")) {
doDensityCalc = true;
} else {
PLOG(PL_ERROR,"Commands::ProcessCommands Error Unknown command \"%s\"\n",argv[i]);
return false;
}
}
return true;
}
bool UpdateGraphFromSpace(MyManetGraphML& graph, ProtoSpace& space, ProtoGraph::Vertice::SortedList::ItemPool* sortedVerticeItemPool)
{
MyManetGraphML::InterfaceIterator it(graph);
MyManetGraphML::Interface* iface;
;
unsigned int count = 0;
while (NULL != (iface = it.GetNextInterface()))
{
MyNode& node = iface->GetNode();
MyManetGraphML::Interface::SortedList nbrList(sortedVerticeItemPool);
MyManetGraphML::AdjacencyIterator nbrIterator(*iface);
MyManetGraphML::Interface* nbrIface;
while (NULL != (nbrIface = nbrIterator.GetNextAdjacency()))
{
if (!nbrList.Insert(*nbrIface))
{
PLOG(PL_ERROR, "graphExample: error adding neighbor to temp list\n");
return false;
}
}
ProtoSpace::Iterator sit(space);
if (!sit.Init(node.GetOrdinatePtr()))
{
PLOG(PL_ERROR, "graphExample: error initializing space iterator\n");
return false;
}
MyNode* nbr;
count = 0;
double lastDist = -1.0;
double distance;
while (NULL != (nbr = static_cast<MyNode*>(sit.GetNextNode(&distance))))
{
count++;
ASSERT(lastDist <= distance);
lastDist = distance;
if (nbr == &node)
{
continue;
}
if (distance <= RANGE_MAX)
{
MyManetGraphML::Interface* defaultIface = nbr->GetDefaultInterface();
ASSERT(NULL != defaultIface);
const ProtoAddress& nbrAddr = defaultIface->GetAddress();
nbrIface = nbrList.FindInterface(nbrAddr);
if (NULL == nbrIface)
{
MyManetGraphML::SimpleCostDouble cost(1.0);
if (!graph.Connect(*iface, *defaultIface, cost, true))
{
PLOG(PL_ERROR, "graphExample error: unable to connect interfaces in graph\n");
return false;
}
printf("link %s,%s,green\n", graph.GetString(node), graph.GetString(*nbr));
}
else
{
nbrList.Remove(*nbrIface);
}
}
else
{
if (!nbrList.IsEmpty())
{
MyManetGraphML::Interface::SortedList::Iterator listIterator(nbrList);
while (NULL != (nbrIface = listIterator.GetNextInterface()))
{
graph.Disconnect(*iface, *nbrIface, true);
}
}
break;
}
} } return true;
}
int CalculatePaths(MyManetGraphML& graph)
{
TRACE("in calculate paths\n");
MyManetGraphML::InterfaceIterator it(graph);
MyManetGraphML::Interface* isource;
MyManetGraphML::Interface* idest;
isource = it.GetNextInterface();
idest = it.GetNextInterface();
MyManetGraphML::Node node;
it.Reset();
MyManetGraphML::Interface* interface;
while (NULL != (interface = it.GetNextInterface()))
{
MyNode& node = interface->GetNode();
node.SetVisited(false);
}
MyNode& node1 = isource->GetNode();
MyNode& node2 = idest->GetNode();
TRACE("calculating paths from %s to",graph.GetString(node1));
TRACE(" %s\n",graph.GetString(node2));
int maxdepth = 20;
int* patharray = (int*) malloc (maxdepth*4);
memset(patharray,0,maxdepth*4);
int paths = CountPaths(isource,idest,0,patharray,maxdepth);
for(int i=0;i<maxdepth;i++)
{
TRACE("#paths at depth %d: %d\n",i,patharray[i]);
}
return paths;
}
int CountPaths(MyManetGraphML::Interface* isource,MyManetGraphML::Interface* idest,int depth,int* patharray,int maxdepth)
{
char spaces[255];
memset(spaces,' ',255);
memset(spaces+depth,0,1);
if(depth> maxdepth) exit(0);
if(isource==idest) {
patharray[depth]+=1;
return 1;
}
int paths = 0;
MyNode& node = isource->GetNode();
node.SetVisited(true);
MyManetGraphML::AdjacencyIterator it(*isource);
MyManetGraphML::Interface* inbr;
while(NULL != (inbr = it.GetNextAdjacency()))
{
MyNode& nbrnode = inbr->GetNode();
if(!nbrnode.WasVisited())
{
int ccount = CountPaths(inbr,idest,depth+1,patharray,maxdepth);
paths+= ccount;
}
else
{
}
}
node.SetVisited(false);
return paths;
}
double CalculateDensity(MyManetGraphML& graph)
{
int neighborCount = 0;
int nodeCount = 0;
MyManetGraphML::InterfaceIterator it(graph);
MyManetGraphML::Interface* iface;
it.Reset();
while (NULL != (iface = it.GetNextInterface()))
{
MyNode& node = iface->GetNode();
node.SetNbrs(0.0);
node.SetVisited(false);
}
it.Reset();
while (NULL != (iface = it.GetNextInterface()))
{
MyNode& node = iface->GetNode();
int test = node.GetNbrs()+iface->GetAdjacencyCount();
node.SetNbrs(test);
neighborCount+=iface->GetAdjacencyCount();
if(!node.WasVisited())
{
node.SetVisited(true);
nodeCount++;
}
}
return ((double)neighborCount)/((double)nodeCount);
}
void CalculateRouterPriority(MyManetGraphML& graph,bool usingDensity)
{
if(usingDensity)
CalculateDensity(graph);
MyManetGraphML::InterfaceIterator it(graph);
MyManetGraphML::Interface* iface;
while (NULL != (iface = it.GetNextInterface()))
{
MyNode& node = iface->GetNode();
if(usingDensity)
{
node.SetRtrPriority(node.GetNbrs());
}
else
{
node.SetRtrPriority(0.0);
}
}
}
int CalculateFullECDS(MyManetGraphML& graph,
MyManetGraphML::Interface::SimpleList& relayList,
ProtoGraph::Vertice::SortedList::ItemPool* sortedVerticeItemPool)
{
int numberOfRelays=0;
MyManetGraphML::InterfaceIterator it(graph);
MyManetGraphML::Interface* iface;
while (NULL != (iface = it.GetNextInterface()))
{
MyNode& node = iface->GetNode();
UINT8 priority = node.GetRtrPriority();
if (iface->GetAdjacencyCount() < 2)
{
node.SetRelayStatus(false);
continue;
}
MyManetGraphML::AdjacencyIterator iteratorN1(*iface);
MyManetGraphML::Interface* ifaceN1Max = NULL;
bool isRelay = true; MyManetGraphML::Interface* ifaceN1;
while (NULL != (ifaceN1 = iteratorN1.GetNextAdjacency()))
{
MyNode& nodeN1 = ifaceN1->GetNode();
nodeN1.SetVisited(false); UINT8 priorityN1 = nodeN1.GetRtrPriority();
if (NULL == ifaceN1Max)
{
ifaceN1Max = ifaceN1;
}
else
{
MyNode& nodeN1Max = ifaceN1Max->GetNode();
UINT8 priorityN1Max = nodeN1Max.GetRtrPriority();
if ((priorityN1 > priorityN1Max) ||
((priorityN1 == priorityN1Max) &&
(graph.GetId(nodeN1)>=graph.GetId(nodeN1Max))))
{
ifaceN1Max = ifaceN1;
}
}
if(true == isRelay)
{
if ((priorityN1 > priority) ||
((priorityN1 == priority) && (graph.GetId(nodeN1)>graph.GetId(node))))
{
isRelay = false; }
}
MyManetGraphML::AdjacencyIterator iteratorN2(*ifaceN1);
MyManetGraphML::Interface* ifaceN2;
while (NULL != (ifaceN2 = iteratorN2.GetNextAdjacency()))
{
if (ifaceN2 == iface) continue; if (iface->HasEdgeTo(*ifaceN2)) continue; MyNode& nodeN2 = ifaceN2->GetNode();
nodeN2.SetVisited(false); UINT8 priorityN2 = nodeN2.GetRtrPriority();
if ((priorityN2 > priority) ||
((priorityN2 == priority) &&
(graph.GetId(nodeN2)>graph.GetId(node))))
{
isRelay = false; }
} } if (isRelay)
{
node.SetRelayStatus(true);
numberOfRelays++;
relayList.Append(*iface);
continue;
}
ASSERT(NULL != ifaceN1Max);
MyManetGraphML::Interface::SortedList Q(sortedVerticeItemPool);
if (!Q.Append(*ifaceN1Max))
{
PLOG(PL_ERROR, "graphExample: error adding 'ifaceN1Max' to 'Q'\n");
return -1;
} else {
}
ifaceN1Max->GetNode().SetVisited(true);
MyManetGraphML::Interface* x;
while (NULL != (x = Q.RemoveHead()))
{
bool xIsInN1 = x->HasEdgeTo(*iface);
MyManetGraphML::AdjacencyIterator iteratorX(*x);
MyManetGraphML::Interface* n;
while (NULL != (n = iteratorX.GetNextAdjacency()))
{
if (n == iface) continue; bool nIsInN1 = n->HasEdgeTo(*iface);
if (!xIsInN1 && !nIsInN1) continue; MyNode& nodeNn = n->GetNode();
if (!nodeNn.WasVisited())
{
nodeNn.SetVisited(true);
UINT8 priorityNn = nodeNn.GetRtrPriority();
if ((priorityNn > priority) ||
((priorityNn == priority) &&
(graph.GetId(nodeNn)>graph.GetId(node))))
{
if (!Q.Append(*n))
{
PLOG(PL_ERROR, "graphExample: error adding 'n' to 'Q'\n");
return -1;
} else {
}
}
}
} } bool relayStatus = false;
iteratorN1.Reset();
while (NULL != (ifaceN1 = iteratorN1.GetNextAdjacency()))
{
if (!ifaceN1->GetNode().WasVisited())
{
relayStatus = true;
numberOfRelays++;
break;
}
}
if (relayStatus)
{
relayList.Append(*iface);
}
node.SetRelayStatus(relayStatus);
} return numberOfRelays;
}
FastReader::FastReader(FILE* filePtr)
: file_ptr(filePtr), savecount(0)
{
}
FastReader::Result FastReader::Read(char* buffer,
unsigned int* len,
double timeout)
{
unsigned int want = *len;
if (savecount)
{
unsigned int ncopy = MIN(want, savecount);
memcpy(buffer, saveptr, ncopy);
savecount -= ncopy;
saveptr += ncopy;
buffer += ncopy;
want -= ncopy;
}
while (want)
{
unsigned int result;
#ifndef WIN32
if (timeout >= 0.0)
{
int fd = fileno(file_ptr);
fd_set input;
FD_ZERO(&input);
struct timeval t;
t.tv_sec = (unsigned long)timeout;
t.tv_usec = (unsigned long)((1.0e+06 * (timeout - (double)t.tv_sec)) + 0.5);
FD_SET(fd, &input);
int status = select(fd+1, &input, NULL, NULL, &t);
switch (status)
{
case -1:
if (EINTR != errno)
{
perror("trpr: FastReader::Read() select() error");
return ERROR_;
}
else
{
continue;
}
break;
case 0:
return TIMEOUT;
default:
result = fread(savebuf, sizeof(char), 1, file_ptr);
break;
}
}
else
#endif {
result = fread(savebuf, sizeof(char), BUFSIZE, file_ptr);
if (!isprint(*savebuf) &&
('\t' != *savebuf) &&
('\n' != *savebuf) &&
('\r' != *savebuf))
continue;
}
if (result)
{
unsigned int ncopy= MIN(want, result);
memcpy(buffer, savebuf, ncopy);
savecount = result - ncopy;
saveptr = savebuf + ncopy;
buffer += ncopy;
want -= ncopy;
}
else {
#ifndef WIN32
if (ferror(file_ptr))
{
if (EINTR == errno) continue;
}
#endif *len -= want;
if (*len)
return OK; else
return DONE; }
} return OK;
}
FastReader::Result FastReader::Readline(char* buffer,
unsigned int* len,
double timeout)
{
unsigned int count = 0;
unsigned int length = *len;
char* ptr = buffer;
while (count < length)
{
unsigned int one = 1;
switch (Read(ptr, &one, timeout))
{
case OK:
if (('\n' == *ptr) || ('\r' == *ptr))
{
*ptr = '\0';
*len = count;
return OK;
}
count++;
ptr++;
break;
case TIMEOUT:
if (count)
{
savecount = MIN(count, BUFSIZE);
if (count < BUFSIZE)
{
memcpy(savebuf, buffer, count);
savecount = count;
saveptr = savebuf;
*len = 0;
}
else
{
memcpy(savebuf, buffer+count-BUFSIZE, BUFSIZE);
savecount = BUFSIZE;
saveptr = savebuf;
*len = count - BUFSIZE;
}
}
return TIMEOUT;
case ERROR_:
return ERROR_;
case DONE:
return DONE;
}
}
return ERROR_;
}
bool FastReader::Seek(int offset)
{
bool result = true;
if (offset < 0)
{
if (0 != savecount)
{
int avail = saveptr - savebuf;
if (avail >= abs(offset))
{
savecount += abs(offset);
saveptr -= abs(offset);
offset = 0;
}
else
{
offset -= savecount;
savecount = 0;
}
}
if (0 != offset)
result = (0 == fseek(file_ptr, offset, SEEK_CUR));
}
else if (offset > 0)
{
if ((unsigned int)offset < savecount)
{
savecount -= offset;
saveptr += offset;
}
else
{
if ((unsigned int)offset > savecount)
{
result = (0 == fseek(file_ptr, offset - savecount, SEEK_CUR));
}
savecount = 0;
}
}
return result;
}